hakanviv
hakanviv

Reputation: 253

Using "UseDeveloperExceptionPage" together with "UseExceptionHandler"

I want to show the developer exception page when there is an unhandled exception but I also want to add logging to it. But when I use app.UseDeveloperExceptionPage together with app.UseExceptionHandler, only the last one I add works. How can I make the two work together?

Upvotes: 10

Views: 2066

Answers (3)

somethingRandom
somethingRandom

Reputation: 1157

In my case, I wanted to get the developer exception page when the request is sent with the text/html header to make debugging a bit easier.

SpiritBob's answer worked but it changed the route shown in the developer page to the error handling endpoint

Developer exception page with wrong route

I fixed this by registering the exception handler middleware using a branching request pipeline. Instead of just registering the exception handler like this:

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
else
{
    app.UseExceptionHandler("/Error-Development");
}

You change it to this:

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
else
{
    app.UseWhen(
        context =>
        {
            RequestHeaders headers = context.Request.GetTypedHeaders();
            MediaTypeHeaderValue mediaTypeHeaderValue = new("text/html");

            return !headers.Accept.Any(h => h.IsSubsetOf(mediaTypeHeaderValue));
        },
        applicationBuilder => applicationBuilder.UseExceptionHandler("/Error-Development"));
}

This will use the exception handler middleware unless you include text/html in the accept header. In which case, it will allow the exception to bubble up to the developer exception page middleware and return a nicely formatted exception page.

Upvotes: 0

SpiritBob
SpiritBob

Reputation: 2672

You don't need to move your logic to an exception filter.

You can simply re-throw the exception received from the IExceptionHandlerFeature you used (IExceptionHandlerFeature/IExceptionHandlerPathFeature)

For example:

var exceptionFeature = context.Features.Get<IExceptionHandlerFeature>();
throw exceptionFeature.Error;

Then your DeveloperExceptionPage will catch the exception down the pipeline.

Upvotes: 3

Camilo Terevinto
Camilo Terevinto

Reputation: 32068

The default ExceptionHandler does not work with the DeveloperExceptionPage because it catches the Exception.
What you can do is add an ExceptionFilter, log the Exception and let it be caught by the DeveloperExceptionPage:

public class ExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        Log.Error(context.Exception, $"{context.ActionDescriptor.DisplayName}");

        // the important bit here
        context.ExceptionHandled = false;
    }
}

And then add it to the filters:

services.AddMvc(setup => { /* ... */ setup.Filters.Add<ExceptionFilter>(); });

Upvotes: 4

Related Questions