如何优雅地从的WebAPI消息处理程序
我在我的mvc具有全球ExceptionFilter返回例外\的WebAPI申请注册为:如何优雅地从的WebAPI消息处理程序
public virtual void RegisterHttpFilters(HttpConfiguration config)
{
config.Filters.Add(new MyExceptionFilter(_exceptionHandler));
}
其中MyExceptionFilter是:
public class MyExceptionFilter : ExceptionFilterAttribute
{
private readonly IMyExceptionHandler m_exceptionHandler;
public MyExceptionFilter(IMyExceptionHandler exceptionHandler)
{
m_exceptionHandler = exceptionHandler;
}
public override void OnException(HttpActionExecutedContext context)
{
Exception ex = context.Exception;
if (ex != null)
{
object response = null;
HttpStatusCode statusCode = m_exceptionHandler != null
? m_exceptionHandler.HandleException(ex, out response)
: HttpStatusCode.InternalServerError;
context.Response = context.Request.CreateResponse(statusCode, response ?? ex);
}
base.OnException(context);
}
}
该过滤器返回的所有异常作为json对象,并允许一些IMyExceptionHandler实现来定制返回的对象。
这一切都很好。直到我有我的一些消息处理程序的异常:
public class FooMessageHandler : DelegatingHandler
{
private readonly Func<IBar> _barFactory;
public FooMessageHandler(Func<IBar> barFactory)
{
_barFactory = varFactory;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Properties["MY_BAR"] = _barFactory();
return base.SendAsync(request, cancellationToken);
}
}
正如你可以看到这个处理程序创建的一些组件,并把它放到当前的HTTP请求消息。 当FuncOfIBar发生异常时,我会得到死亡黄色屏幕。我的ExceptionFilter没有被调用。
我想专门捕获在消息处理异常,并返回HttpResponseException,但它不会改变任何东西 - 仍然得到YSOD:
public class XApplicationInitializerMessageHandler : DelegatingHandler
{
private readonly Func<IXCoreApplication> _appFactory;
private readonly IXExceptionHandler m_exceptionHandler;
public XApplicationInitializerMessageHandler(Func<IXCoreApplication> appFactory, IXExceptionHandler exceptionHandler)
{
ArgumentValidator.EnsureArgumentNotNull(appFactory, "appFactory");
_appFactory = appFactory;
m_exceptionHandler = exceptionHandler;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
request.SetApplication(_appFactory());
}
catch (Exception ex)
{
object resultObject = null;
HttpStatusCode statusCode = m_exceptionHandler != null
? m_exceptionHandler.HandleException(ex, out resultObject)
: HttpStatusCode.InternalServerError;
HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex);
throw new HttpResponseException(responseMessage);
}
return base.SendAsync(request, cancellationToken);
}
}
}
我想我的应用程序的行为是无论发生什么异常:在ApiController或消息处理程序中。
如何做到这一点?
我知道Application_Error,但我想保持HttpApplication定制不可触摸。
不是引发HttpResponseException
我应该只是返回的HttpResponseMessage
:
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
request.SetApplication(_appFactory());
}
catch (Exception ex)
{
object resultObject = null;
HttpStatusCode statusCode = m_exceptionHandler != null
? m_exceptionHandler.HandleException(ex, out resultObject)
: HttpStatusCode.InternalServerError;
HttpResponseMessage responseMessage = request.CreateResponse(statusCode, resultObject ?? ex);
return Task<HttpResponseMessage>.Factory.StartNew(() => responseMessage);
}
return base.SendAsync(request, cancellationToken);
}
我有更迭做的是使用基于属性的方法。你把一个自定义属性上的每一个应该使用异常处理的行动:
[ExceptionHandling]
public IEnumerable<string> Get()
您的自定义异常处理属性来实现这样的:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{}
正如你可以看到你,自定义属性从ExceptionFilterAttribute继承。然后您只需重写OnException方法。然后,您可以查看异常的类型,并根据业务规则处理它或满足您的需求。在某些情况下,您可能会吞服服务器上的异常。如果你想通知客户端,你可以抛出一个HttpResponseException,它可以容纳所有相关信息,如消息,调用堆栈,内部异常等。
欲了解更多灵感,请看这个伟大的博客文章:ASP.NET Web API Exception Handling
我与全局异常过滤器没有运行相同的问题。解决方案是Web API异常过滤器必须配置在与ASP.NET MVC异常过滤器不同的全局集合中。
所以要配置ASP。NET MVC的错误处理,你可以运行:
System.Web.Mvc.GlobalFilters.Filters.Add(new MyMvcExceptionFilter());
但对Web API的错误处理,你必须运行:
System.Web.Http.GlobalConfiguration.Configuration.Filters.Add(new MyWebApiExceptionFilter());
从我用的Web API经验有限这种情况是典型的:表面上使用的图案将非常类似于ASP.NET MVC,因此很快就熟悉了。这就产生了这样的错觉:编写一段代码会对两个框架产生影响,但实际上它们的实现在很大程度上或完全独立,您需要编写两个非常相似的代码版本工作。基于Web API异常处理
很好的参考:http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling
在startup.cs:
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
我发现,使用GlobalExceptionHandler能赶上在委托处理异常,并返回定制JSON对象。
我发现这个博客有很好的例子: http://nodogmablog.bryanhogan.net/2016/07/getting-web-api-exception-details-from-a-httpresponsemessage/
我采用了一些更新的代码:使用
if ((int)response.StatusCode >= 400)
{
exceptionResponse = JsonConvert.DeserializeObject<ExceptionResponse>(LogRequisicao.CorpoResposta);
LogRequisicao.CorpoResposta = exceptionResponse.ToString() ;
if (exceptionResponse.InnerException != null)
LogRequisicao.CorpoResposta += "\r\n InnerException: " + exceptionResponse.ToString();
}
对象:
public class ExceptionResponse
{
public string Message { get; set; }
public string ExceptionMessage { get; set; }
public string ExceptionType { get; set; }
public string StackTrace { get; set; }
public ExceptionResponse InnerException { get; set; }
public override String ToString()
{
return "Message: " + Message + "\r\n "
+ "ExceptionMessage: " + ExceptionMessage + "\r\n "
+ "ExceptionType: " + ExceptionType + " \r\n "
+ "StackTrace: " + StackTrace + " \r\n ";
}
}
http://stackoverflow.com /问题/ 13013973/ASP网的Web-API的默认错误信息 – Timeless 2015-11-18 16:19:11