AspNetCore.Docs icon indicating copy to clipboard operation
AspNetCore.Docs copied to clipboard

The section about IExceptionHandler is misleading.

Open voroninp opened this issue 1 year ago • 3 comments

Description

The article creates an impression that it's enough to add custom implementation of IExceptionHandler. However, I had to call UseExceptionHanlder middleware.

This comment is a confirmation that the former does not work without the latter.

However, there are more surprises:

If I call:

app.UseExceptionHandler();

I get the following exception:

System.InvalidOperationException: 'An error occurred when configuring the exception handler middleware. Either the 'ExceptionHandlingPath' or the 'ExceptionHandler' property must be set in 'UseExceptionHandler()'. Alternatively, set one of the aforementioned properties in 'Startup.ConfigureServices' as follows: 'services.AddExceptionHandler(options => { ... });' or configure to generate a 'ProblemDetails' response in 'service.AddProblemDetails()'.'

If I call it like this:

app.UseExceptionHandler(c => {});

custom exception handler is called, but I see two log entries about the error despite my handler returns true:

"Category": "Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware",

and then from my handler:

"Category": "ExceptionHandler"

I'd appreciate if this WTF behavior was properly explained.

the 'ExceptionHandler' property must be set in 'UseExceptionHandler()'.

Why do I need to call it, if I called builder.Services.AddExceptionHandler<ExceptionHandler>();

Here's the code I use:

using Microsoft.AspNetCore.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
// Add services to the container.

builder.Services.AddExceptionHandler<ExceptionHandler>();
builder.Services.AddControllers();
builder.Logging.AddJsonConsole(c =>
{
    c.UseUtcTimestamp = true;
    c.IncludeScopes = true;
    c.JsonWriterOptions = new()
    {
        Indented = true,
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseExceptionHandler(c => {});

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

internal sealed class ExceptionHandler : IExceptionHandler
{
    private readonly ILogger<ExceptionHandler> _logger;

    public ExceptionHandler(ILogger<ExceptionHandler> logger)
    {
        _logger = logger;
    }

    public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        _logger.LogError(exception, "You will see it twice");

        return true;
    }
}

Page URL

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-8.0

Content source URL

https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/fundamentals/error-handling.md

Document ID

38515dfb-91a5-b395-db9d-084bbaf095c8

Article author

@tdykstra

voroninp avatar Apr 12 '24 14:04 voroninp

I'd also mention that currently ExceptionHandlerMiddleware logs exception as unhandled despite IExceptionHandler returns true.

There was a request to disable logging

but dev team rejected the proposal.

But this is so wrong regarding the expectations of the developer.

Kestrel logs uncaught (!) exceptions with Error level. - That's fine.

However, ExceptionHandlerMiddleware logs exception anyway, but it does not pass it to Kestrel, if IExceptionHanlder says it handled the exception.

It's better to clarify in documentation, how to disable logging error from the middleware:

None for Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware

voroninp avatar Apr 12 '24 15:04 voroninp

I'd propose @adityamandaleeka to reconsider.

voroninp avatar Apr 12 '24 15:04 voroninp

Update:

If I use middleware this way:

app.UseExceptionHandler(c => {});

and exception is thrown, I see this in the logs:

The exception handler configured on ExceptionHandlerOptions produced a 404 status response. This InvalidOperationException containing the original exception was thrown since this is often due to a misconfigured ExceptionHandlingPath. If the exception handler is expected to return 404 status responses then set AllowStatusCode404Response to true.

voroninp avatar Aug 16 '24 20:08 voroninp