Shr*_*ike 13 c# asp.net-web-api
我在我的Mvc\WebApi应用程序中有一个全局ExceptionFilter,注册为:
public virtual void RegisterHttpFilters(HttpConfiguration config)
{
config.Filters.Add(new MyExceptionFilter(_exceptionHandler));
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
Run Code Online (Sandbox Code Playgroud)
此过滤器将所有异常作为json-objects返回,并允许某些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);
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,此处理程序创建了一些组件并将其放入当前的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);
}
}
Run Code Online (Sandbox Code Playgroud)
}
无论异常发生在哪里,我都希望我的应用程序的行为相同:在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);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我所取得的成功是使用基于属性的方法.您在应该使用异常处理的每个操作上放置一个自定义属性:
[ExceptionHandling]
public IEnumerable<string> Get()
Run Code Online (Sandbox Code Playgroud)
您的自定义异常处理属性实现如下:
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{}
Run Code Online (Sandbox Code Playgroud)
如您所见,自定义属性继承自ExceptionFilterAttribute.然后,您只需重写OnException方法.您可以做的是查看异常的类型,并根据业务规则或任何符合您需求的处理它.在某些情况下,您可能只是吞下服务器上的异常.如果要通知客户端,可以抛出HttpResponseException,它可以保存所有相关信息,例如消息,调用堆栈,内部异常等.
有关更多灵感,请查看这篇精彩的博文:ASP.NET Web API异常处理
我遇到了与未运行的全局异常过滤器相同的问题.解决方案是必须在与ASP.NET MVC异常过滤器不同的全局集合中配置Web API异常过滤器.
因此,要配置ASP.NET MVC错误处理,您将运行:
System.Web.Mvc.GlobalFilters.Filters.Add(new MyMvcExceptionFilter());
Run Code Online (Sandbox Code Playgroud)
但是对于Web API错误处理,您必须运行:
System.Web.Http.GlobalConfiguration.Configuration.Filters.Add(new MyWebApiExceptionFilter());
Run Code Online (Sandbox Code Playgroud)
根据我对Web API的有限经验,这种情况很典型:表面上使用的模式与ASP.NET MVC非常相似,因此很容易熟悉.这给人一种错觉,即编写一段代码会对两个框架产生影响,但实际上它们下面的实现都是大部分或完全独立的,你需要编写两个非常相似的代码版本工作.
关于Web API异常处理的优秀参考:http://www.asp.net/web-api/overview/web-api-routing-and-actions/exception-handling