gpt4 book ai didi

c# - WebAPI 强制反序列化不同于 Controller 方法中定义的对象

转载 作者:太空宇宙 更新时间:2023-11-03 15:17:16 25 4
gpt4 key购买 nike

我试图以这样一种方式引入自动映射器,即对于 WebAPI,所有 DTO 都是透明的,所以基本上我想在运行时映射对象,并在它们到达 Controller 方法之前将它们转换为域对象。

我有automapper过滤器属性

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class AutoMapAttribute : ActionFilterAttribute
{
private readonly Type _sourceType;
private readonly Type _destType;

public AutoMapAttribute(Type sourceType, Type destType)
{
_sourceType = sourceType;
_destType = destType;
}

#region Overrides of ActionFilterAttribute

/// <summary>Occurs before the action method is invoked.</summary>
/// <param name="actionContext">The action context.</param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
var mapper = ServiceLocator.Locator.GetInstance<IMapper>();
var jsonObject = actionContext.ActionArguments.FirstOrDefault(x => x.Value.GetType() == typeof(Newtonsoft.Json.Linq.JObject));
var dto = JsonConvert.DeserializeObject(jsonObject.Value.ToString(), _sourceType);
object model = mapper.Map(dto, _sourceType, _destType);

actionContext.ActionArguments[jsonObject.Key] = model;

base.OnActionExecuting(actionContext);
}

#endregion

#region Overrides of ActionFilterAttribute

/// <summary>Occurs after the action method is invoked.</summary>
/// <param name="actionExecutedContext">The action executed context.</param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
base.OnActionExecuted(actionExecutedContext);
}

#endregion

public Type SourceType
{
get { return _sourceType; }
}

public Type DestType
{
get { return _destType; }
}
}

和 Controller 方法:

    [HttpPost]
[Route("")]
[AutoMap(typeof(Public.Dto.Product), typeof(Domain.Model.Product))]
public IHttpActionResult Post(object product)
{
_productBusinessLogic.Create(product);
return Ok();
}

它工作得很好,因为 controlr 方法中的产品变量实际上是我的域产品。 现在我想在 Controller 方法定义中将对象类型更改为具体的 Domain.Product 类型。不幸的是,WebAPI 试图立即将来自 Request 的对象反序列化为该对象类型,这打破了整个想法。

如果有帮助,我可以使用 OWIN。

最佳答案

关键是 Action 过滤器的处理发生在模型绑定(bind)之后 Web API request stack .

使用 OWIN我们可以读取原始主体作为源类型,然后将其映射到目标类型:

  1. 覆盖 OnActionExecutingAsync方法:

    public override async Task OnActionExecutingAsync(HttpActionContext actionContext,
    CancellationToken cancellationToken)
    {
    var argumentKey = actionContext.ActionArguments.FirstOrDefault().Key;

    var owinContext = (OwinContext) actionContext.Request.Properties["MS_OwinContext"];

    owinContext.Request.Body.Seek(0, SeekOrigin.Begin);

    var source = await actionContext.Request.Content.ReadAsAsync(_sourceType, cancellationToken);

    actionContext.ActionArguments[argumentKey] = Mapper.Map(source, _sourceType, _destType);

    await base.OnActionExecutingAsync(actionContext, cancellationToken);
    }
  2. 要在操作过滤器中重新读取请求的内容,我们需要在 OWIN 中的管道中添加一些处理程序。启动类:

    public class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    var config = new HttpConfiguration();

    app.Use(async (context, next) =>
    {
    var content = context.Request.Body;

    if (content == Stream.Null)
    {
    await next();
    }
    else
    {
    using (var stream = new MemoryStream())
    {
    await content.CopyToAsync(stream);

    stream.Position = 0;

    context.Request.Body = stream;

    await next();
    }

    context.Request.Body = content;
    }
    });

    app.UseWebApi(config);
    }
    }

关于c# - WebAPI 强制反序列化不同于 Controller 方法中定义的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38583264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com