3
votes

I am trying to catch routing errors in a ASP.NET Core Web API project.

To be specific, by routing error, I mean for example: In the controller I only have:

// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
    return "value";
}

But a request is:

api/values/5/6

A 404 is returned automatically, but I would like to be able to handle this in code (i.e. invoke some kind of exception handling routine).

I have tried three different approaches without success:

In ConfigureServices(IServiceCollection services), I added:

services.AddMvc(config =>
{
    config.Filters.Add(typeof(CustomExceptionFilter));
});

This captures errors that occur within the controller (e.g. if I put a throw() in the Get(id) method above), but not routing errors. I assume this is because no matching controller method was found so the error propagates up the middleware pipeline.

In an attempt to handle errors further up the pipeline I tried...

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseExceptionHandler(
        options =>
        {
            options.Run(
            async context =>
            {
                var ex = context.Features.Get<IExceptionHandlerFeature>();
                // handle exception here
            });
        });

    app.UseApplicationInsightsRequestTelemetry();
    app.UseApplicationInsightsExceptionTelemetry();
    app.UseMvc();
}

I also tried:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.Use(async (ctx, next) =>
        {
            try
            {
                await next();
            }
            catch (Exception ex)
            {
                // handle exception here
            }
        });

    app.UseApplicationInsightsRequestTelemetry();
    app.UseApplicationInsightsExceptionTelemetry();
    app.UseMvc();
}

Neither of the above appears to be invoked when a routing error occurs. Am I taking the wrong approach? Or should one of these approaches actually work?

Any suggestions would be really appreciated.

Thanks

Chris

PS. I am relatively new to ASP.NET Web API, so please excuse where I may be using slightly the wrong terms.

1

1 Answers

4
votes

You can use UseStatusCodePages extension method:

 app.UseStatusCodePages(new StatusCodePagesOptions()
 {
     HandleAsync = (ctx) =>
     {
          if (ctx.HttpContext.Response.StatusCode == 404)
          {
               //handle
          }

          return Task.FromResult(0);
     }
 });

Edit

 app.UseExceptionHandler(options =>
 {
       options.Run( async context =>
       {
             var ex = context.Features.Get<IExceptionHandlerFeature>();
             // handle
             await Task.FromResult(0);
       });
 });
 app.UseStatusCodePages(new StatusCodePagesOptions()
 {
     HandleAsync = (ctx) =>
     {
          if (ctx.HttpContext.Response.StatusCode == 404)
          {
               // throw new YourException("<message>");
          }

          return Task.FromResult(0);
     }
 });