堆栈,
出于某种原因,我的Owin WebApi服务忽略了我们的自定义异常处理程序。下面是关于asp.net异常处理的文档。以下是简化的实现细节(去掉了业务专有内容)。
你能指出我忽略了什么吗?
自定义异常过滤器:
public class CustomExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
actionExecutedContext.Response.StatusCode = HttpStatusCode.NotFound;
actionExecutedContext.Response.Content = new StringContent("...my custom business...message...here...");
}
}
启动期间:
var filter = new CustomExceptionFilter();
config.Filters.Add(filter);
appBuilder.UseWebApi(config);
测试控制器:
[CustomExceptionFilter]
public class TestController: ApiController
{
public void Get()
{
throw new Exception(); // This is a simplification.
// This is really thrown in buried
// under layers of implementation details
// used by the controller.
}
}
您可以尝试在ASP.NET Web API 2中实现全局错误处理。通过这种方式,您将获得Web API中间件的全局错误处理程序,但不适用于OWIN pippeline中的其他中间件,如授权中间件。
如果你想实现一个globlal错误处理中间件,this、this和this链接可以为你定位。
我希望它能有所帮助。
编辑
关于@t0mm13b的评论,我将根据Khanh TO的第一个这个链接给出一点解释。
对于全局错误处理,您可以编写一个自定义的简单中间件,只需将执行流传递给管道中但位于try
块内的以下中间件。
如果管道中的以下中间件中有一个未处理的异常,它将在catch
块中捕获:
public class GlobalExceptionMiddleware : OwinMiddleware
{
public GlobalExceptionMiddleware(OwinMiddleware next) : base(next)
{ }
public override async Task Invoke(IOwinContext context)
{
try
{
await Next.Invoke(context);
}
catch (Exception ex)
{
// your handling logic
}
}
}
在Startup.Configuration()
方法中,如果您想处理所有其他中间件的异常,请首先将中间件添加到管道中。
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<GlobalExceptionMiddleware>();
//Register other middlewares
}
}
正如Tomas Lycken在第二个这个链接中所指出的,您可以使用它来处理Web API中间件中生成的异常,该中间件创建了一个实现IExceptionHandler
的类,该类只抛出捕获的异常,这样全局异常处理器中间件就会捕获它:
public class PassthroughExceptionHandler : IExceptionHandler
{
public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
{
// don't just throw the exception; that will ruin the stack trace
var info = ExceptionDispatchInfo.Capture(context.Exception);
info.Throw();
}
}
在Web API中间件配置过程中,不要忘记替换IExceptionHandler
:
config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler());
在我的例子中,我不需要在Startup.cs中注册过滤器,也不需要在Controller类上应用属性。我最终只在Startup.cs中注册了它,它对我很有效。