Owin WebApi服务忽略ExceptionFilter



堆栈,

出于某种原因,我的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中注册了它,它对我很有效。

最新更新