【问题标题】:Owin Middleware vs ExceptionHandler vs HttpMessageHandler (DelegatingHandler)Owin Middleware vs ExceptionHandler vs HttpMessageHandler (DelegatingHandler)
【发布时间】:2014-08-01 03:39:18
【问题描述】:

请任何人告诉我以下三个模块如何在 asp.net Web API 2.1 中协同工作

  • Owin 中间件
  • HttpMessageHandler(或 DelegatingHandler)
  • 异常处理程序

我要做的是开发一个 web api,它将提供一个恒定格式的 json 数据,这意味着如果实际数据是

{"Id":1,"UserName":"abc","Email":"abc@xyz.com"}

那我喜欢传递json为

{__d:{"Id":1,"UserName":"abc","Email":"abc@xyz.com"}, code:200, somekey: "somevalue"}

为此,我尝试使用自定义 ActionFilterAttribute,但我觉得(仍然无法确认)如果代码遇到异常,则无法提供类似格式的数据

请建议我最好的方向。

这是我的自定义属性的简短代码sn-p。还建议我自定义属性是否适合目的

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class ResponseNormalizationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
            base.OnActionExecuted(actionExecutedContext);
            var response = actionExecutedContext.Response;
            object contentValue;
            if (response.TryGetContentValue(out contentValue))
            {
                var nval = new { data=contentValue, status = 200 };


                var newResponse = new HttpResponseMessage { Content = new ObjectContent(nval.GetType(), nval, new JsonMediaTypeFormatter()) };
                newResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                actionContext.Response = newResponse;
            }
     }
}

【问题讨论】:

  • 当状态码已经是响应本身的一部分时,为什么还要将其作为响应正文的一部分返回?我也觉得这是很糟糕的设计。想想一年后你什么时候回到你的代码。是否易于阅读,并且易于了解正在发生的事情?为什么不创建一个与您想要的输出相对应的模型并将其返回到您的控制器中。
  • HttpMessageHandlerExceptionHandler 是 WebAPI 的一部分。 OwinMiddleware 是管道的一部分,仅当您使用 OWIN 时才可用。使用ActionFilters,您离控制器很近。您甚至可以访问实际实例。 OWIN 中间件甚至早于您使用 Web API 框架。这意味着您无权访问它的服务等。

标签: asp.net json asp.net-web-api


【解决方案1】:

如果您没有使用 Owin 中间件,您可以全局包装所有响应,以便使用委托处理程序返回您的常量格式 json 数据。

编写一个继承自 DelegatingHandler 的自定义处理程序:

public class ApiResponseHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        return BuildResponse(request, response);
    }

    private static HttpResponseMessage BuildResponse(HttpRequestMessage request, HttpResponseMessage response)
    {
        object content;
        string errorMessage = null;

        if (response.TryGetContentValue(out content) && !response.IsSuccessStatusCode)
        {
            HttpError error = content as HttpError;

            if (error != null)
            {
                content = null;
                errorMessage = error.Message;
            }
        }

        var newResponse = request.CreateResponse(response.StatusCode, new ApiResponse((int)response.StatusCode, content, errorMessage));

        foreach (var header in response.Headers)
        {
            newResponse.Headers.Add(header.Key, header.Value);
        }

        return newResponse;
    }
}

//ApiResponse is your constant json response
public class ApiResponse
{

    public ApiResponse(int statusCode, object content, string errorMsg)
    {
        Code = statusCode;
        Content = content;
        Error = errorMsg;
        Id = Guid.NewGuid().ToString();
    }

    public string Error { get; set; }

    //your actual data is mapped to the Content property
    public object Content { get; set; }
    public int Code { get; private set; }
    public string Id { get; set; }
}

WebApiConfig.cs注册处理程序:

    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();
        ...

        config.MessageHandlers.Add(new ApiResponseHandler());

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        ...
    }

我在 SO 中发布了类似的答案,但这是在 .NET Core 中并作为 OWIN 中间件实现(因为 DelegatingHandler 在 .NET Core 中消失了)。 How can I wrap Web API responses(in .net core) for consistency?

【讨论】:

    猜你喜欢
    • 2016-12-07
    • 2013-09-10
    • 2017-07-06
    • 2015-08-30
    • 1970-01-01
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    相关资源
    最近更新 更多