5

In my ASP.NET Core 3.1 application, there's code like this in the Startup class:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseStatusCodePagesWithReExecute("/error/{0}");
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error/500");
        app.UseHsts();
    }

    // ...
}

The ErrorController has an action like this:

public IActionResult Index(int id)
{
    var context = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
    var exception = context?.Error;
    if (exception != null)
    {
        logger.LogCritical(exception, $"Unhandled exception in request {HttpContext.TraceIdentifier}: {exception.GetRecursiveMessage()}");
    }
    else
    {
        logger.LogCritical(exception, $"Unhandled exception in request {HttpContext.TraceIdentifier}, no exception available");
    }

    // ...
}

From what I've read, this should give me the unhandled exception that occurred in another action. But it doesn't. The exception object is null. I also tried using the other feature of type IExceptionHandlerFeature but it's just the same. No exception anywhere.

How can I get the exception in the error handler?

Please note that I'm using the re-execute feature because I hate forwarding the user to a different URL in case of an error. That only makes things worse because reloading the page to "try again" will certainly never resolve any problem (it's the error page, after all, it can only ever show errors).

0

3 Answers 3

4

To get the exception object you could use IExceptionHandlerFeature

public IActionResult Error()
{
   // Retrieve error information in case of internal errors
   var error = HttpContext
          .Features
          .Get<IExceptionHandlerFeature>();

   if (error == null)
     ...

  // Use the information about the exception 
  var exception = error.Error;
   ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

you tried to get an instance of IExceptionHandlerPathFeature. But in my example, I got an instance of IExceptionHandlerFeature
You haven't read my question. I mention it there.
2

The StatusCodePages middleware runs only if the response generated so far has no body.

If you want to catch exception in action, you could use a custom ExceptionHandler.

public class CustomExceptionHandler
{
    private readonly IWebHostEnvironment _environment;

    public CustomExceptionHandler(IWebHostEnvironment environment)
    {
        _environment = environment;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        var feature = httpContext.Features.Get<IExceptionHandlerFeature>();
        var error = feature?.Error;

        if (error != null)
        {
            //LogError
        }

        await Task.CompletedTask;
    }
}

startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseExceptionHandler(new ExceptionHandlerOptions
    {
        ExceptionHandler = new CustomExceptionHandler(env).Invoke
    });

    //...
}

Comments

1

This is a bug in .NET, up to .NET 7.

If you use app.UseDeveloperExceptionPage(), then context.HttpContext.Features.Get<IExceptionHandlerFeature>() will return null.

This appears to be fixed in .NET 8.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.