bartonm
bartonm

Reputation: 1650

Owin WebApi service ignoring ExceptionFilter

Stack,

For some reason my Owin WebApi service is ignoring our custom exception handler. I'm following documentation for asp.net exception handling. Here are the simplified implementation details (scrubbed out business proprietary stuff).

Can you someone point out what I'm overlooking?

Custom exception filter:

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...");
   }
}

During startup:

var filter = new CustomExceptionFilter();
config.Filters.Add(filter);
appBuilder.UseWebApi(config);

Test controller:

[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.
    }
}

Upvotes: 2

Views: 2052

Answers (2)

In my case I didn't need to register filters both in Startup.cs and by applying attribute above the Controller class. I ended up registering it just in the Startup.cs and it worked for me.

Upvotes: 0

jumuro
jumuro

Reputation: 1532

You can try to implement Global Error Handling in ASP.NET Web API 2. This way you will get a global error handler for Web API middleware, but not for other middlewares in OWIN pippeline, like authorization one.

If you want to implement a globlal error handling middleware, this, this and this links could orientate you.

I hope it helps.

EDIT

Regarding on @t0mm13b's comment, I'll give a little explanation based on the first this link from Khanh TO.

For global error handling you can write a custom and simple middleware that just pass the execution flow to the following middleware in the pipeline but inside a try block.

If there is an unhandled exception in one of the following middlewares in the pipeline, it will be captured in the catch block:

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
        }
    }
}

In the Startup.Configuration() method, add the middleware in first place to the pipeline if you want to handle exceptions for all other middlewares.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use<GlobalExceptionMiddleware>();
        //Register other middlewares
    }
}

As pointed by Tomas Lycken in the second this link, you can use this to handle exceptions generated in Web API middleware creating a class that implements IExceptionHandler that just throws the captured exception, this way the global exception handler middleware will catch it:

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();
    }
}

And don't forget to replace the IExceptionHandler during the Web API middleware configuration:

config.Services.Replace(typeof(IExceptionHandler), new PassthroughExceptionHandler());

Upvotes: 3

Related Questions