khellang / Middleware

Various ASP.NET Core middleware
MIT License
806 stars 110 forks source link

Add the possibility to chose whether to handle the exception or not #179

Closed PhenX closed 2 years ago

PhenX commented 2 years ago

This change add the possibility to forward the not handled exception to the net middleware, if we don't want problemDetails Object result, for example to let the "Developer Exception Page" display the details.

khellang commented 2 years ago

Isn't this already supported by returning null when mapping an exception?

https://github.com/khellang/Middleware/blob/88154dca6bd41bf18416f891eba0c15c9f1458f5/src/ProblemDetails/ProblemDetailsMiddleware.cs#L122

khellang commented 2 years ago

There's even a specific method to ignore exceptions of certain types; https://github.com/khellang/Middleware/blob/84658c260afa5bac34f4ba5d5667a773dbeb52a6/src/ProblemDetails/ProblemDetailsOptions.cs#L154-L162

PhenX commented 2 years ago

Ok, I tried that but didn't find a way to handle the "common" case when not ignoring the exception, as the exception handling doesn't depend on the exception itself, but on the HTTP request :

options.Map<Exception>((context, exception) =>
    {
        if (context.Request.Whatever())
        {
            return null;
        }

        return ???
    }
);

How can I achieve this ?

PhenX commented 2 years ago

Hello, @khellang do you need more information ? Is there another possibility to do what I need ?

PhenX commented 2 years ago

Hello, sorry to bother you again, can I add more information on my use case ? I couldn't figure another way to do what I want to achieve.

Is it the way we have "hybrid" controllers with API-like (Ajax) and MVC (with Razor) routes in the same controller such a bad practice ?

khellang commented 2 years ago

Sorry for the late reply @PhenX 😞

If you just want to map Exception in some cases, you can use the predicate-based overload:

options.Map<Exception>((ctx, ex) => ctx.Request.Whatever(), (ctx, ex) => null);

I guess this could be made into an .IgnoreWhen<Exception>(predicate) method.

khellang commented 2 years ago

Ah, I see what you're trying to accomplish now. You want to re-throw exceptions given a specific predicate?

You could just call

options.Rethrow<Exception>((ctx, ex) => ctx.Request.Whatever())
PhenX commented 2 years ago

Well, it does not work as intented, because the probleme details are already outputted and the next middleware will not output anything in this condition, like your middleware, by the way :

image

In red the outputting code, the green arrow is when we rethrow

khellang commented 2 years ago

For rethrowing, yes, but did you try conditional mapping? We should probably move the ClearResponse call inside the null check as well.

PhenX commented 2 years ago

Do you mean this by conditional mapping ?

options.Map<Exception>(
    (context, exception) => context.Request.Headers.Accept.Any(_ => _.Contains("html")), 
    (context, exception) => null
);

It works if I put it first among all other mappings, thank you very much ! It was not easy :)