提问人:Premchandra Singh 提问时间:6/11/2014 更新时间:1/25/2017 访问量:1814
Owin 中间件 vs ExceptionHandler 与 HttpMessageHandler (DelegatingHandler)
Owin Middleware vs ExceptionHandler vs HttpMessageHandler (DelegatingHandler)
问:
请任何人告诉我以下三个模块如何在 asp.net Web API 2.1 中协同工作
- Owin 中间件
- HttpMessageHandler(或 DelegatingHandler)
- ExceptionHandler (异常处理程序)
我正在尝试做的是开发一个 Web API,它将提供恒定格式的 json 数据,这意味着如果实际数据是
{"Id":1,"UserName":"abc","Email":"[email protected]"}
然后我喜欢将 json 作为
{__d:{"Id":1,"UserName":"abc","Email":"[email protected]"}, code:200, somekey: "somevalue"}
为此,我尝试使用自定义 ActionFilterAttribute,但我觉得(仍然无法确认)在代码遇到异常的情况下,这无法提供类似格式的数据
请给我最好的方向。
这是我的自定义属性的简短代码片段。还建议我是自定义属性是好的目的
[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;
}
}
}
答:
0赞
alltej
1/25/2017
#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 中消失了)。如何包装 Web API 响应(在 .net core 中)以保持一致性?
评论
HttpMessageHandler
并且是 WebAPI 的一部分。 是管道的一部分,仅当使用 OWIN 时才可用。与您一起靠近您的控制器。您甚至可以访问实际实例。OWIN 中间件甚至在你进入 Web API 框架之前就已经存在了。这意味着您无权访问它的服务等。ExceptionHandler
OwinMiddleware
ActionFilters