C
C#14mo ago
TempleOS

❔ OnActionExecuted exception filter runs before exception is thrown and is never called

I'm having a bit of an issue where I'm following the guide from https://learn.microsoft.com/en-us/aspnet/core/web-api/handle-errors?view=aspnetcore-7.0#use-exceptions-to-modify-the-response The goal is to modify the status code when an exception is thrown, I know there are alternative ways to do this, but this is the most straightforward. I already have an expected exception, I built the filter, then deployed it onto builder.Services.AddControllers options.Filters, but it doesn't quite work as expected. When using the debugger I noticed that the onActionExecuted is running before the exception is thrown. The exception then continues, gets thrown, but then the status code is never changed. This was how my original implementation was supposed to behave, but after just trying to copy/paste the exact example from the docs, it didn't work either. Could someone lead me in the right direction on figuring out why OnActionExecuted is not running for when the exception is thrown? There is one thing to keep in mind, the app is very monorepo like, with many sub-repositories. The startup is in /api & the exception and exception filter are declared, but used in /services. But I don't know why this would cause any issues.
Handle errors in ASP.NET Core web APIs
Learn about error handling with ASP.NET Core web APIs.
14 Replies
TempleOS
TempleOSOP14mo ago
So I found a bit of an issue. I tried testing out throwing the error in the controller directly and it worked. However, the actual code passes through three layers. httpService -> documentGenerator -> downloadCommand -> controller All while the http service passes a stream down, and each layer passes the stream. So, it's almost as if /api doesn't ever get the thrown exception in this process. Which is strange to me.
return ToActionResult(result, r => {
return new FileCallbackResult(
new MediaTypeHeaderValue(MedaiTypes.PDF);
async (response, _) => {
try {
await (r.Result?.Invoke(responseBodyWriter.AsStream()) ?? Task.CompletedTask);
}
catch (Exception e) {
throw e;
}
}
);
});
return ToActionResult(result, r => {
return new FileCallbackResult(
new MediaTypeHeaderValue(MedaiTypes.PDF);
async (response, _) => {
try {
await (r.Result?.Invoke(responseBodyWriter.AsStream()) ?? Task.CompletedTask);
}
catch (Exception e) {
throw e;
}
}
);
});
In this process, the exception is caught here, but it is never detected by asp, and never runs the exception filter. So, I'm not sure how to fix this. (The rethrow was just to see if it did throw and was detectable here, but I'm lost on why asp doesn't detect this)
Nox
Nox14mo ago
@TempleOS It looks like you're handling the response a little weird here You're using the wrong tool if it's running before the exception happens
Nox
Nox14mo ago
You specifically need exception filters
TempleOS
TempleOSOP14mo ago
How are these two things functionally different?
Nox
Nox14mo ago
There's a pipeline that the filters get executed in An exception might be an entirely different pipeline I recommend reading that entire page to understand what tool you're using before trying to use it You might have also configured exception handling elsewhere that prevents your filter from getting it
TempleOS
TempleOSOP14mo ago
Do you mind explaining this a bit further. The concept of different pipelines? It seems strange that if I throw the exception directly in the controller (just immediately, not in the same fashion as shown above), that it doesn't bubble to the other filter implementation.
You might have also configured exception handling elsewhere that prevents your filter from getting it
I'm kind of doubting it, but it's not impossible. It's a large app, but idk
Nox
Nox14mo ago
No description
Nox
Nox14mo ago
Filters can prevent other filters from running
TempleOS
TempleOSOP14mo ago
So by pipeline you're meaning only the filter pipeline, not some "magical term" in asp that I've never heard of
Nox
Nox14mo ago
Uhh yes, I believe so Basically if you're throwing an exception in a controller, and you've registered a filter appropriately, and the filter isn't being called something else is handling that exception. I believe if you enable trace-level logging you'll see which components are being executed to handle it.
TempleOS
TempleOSOP14mo ago
I removed the other filter as a test, no change, I modified to be an exception filter and still no change. The stack trace has some information, but still doesn't quite help me solve the core issue. The stack trace ends at the downloadCommand step. So I've found a bit more information about how the app is working. There was a custom class called FileCallbackResult inside of that class, it overwrites the ExecuteResultAsync. This indicates that the code that I'm expecting to throw an error r.Result?.Invoke(responseBodyWriter.AsStream()) ?? Task.CompletedTask at the result stage, but this explains why each of the other filter types would fail, and an exception filter didn't work either. The issue now is managing to get the error and handle the error before the response is sent to the client. This is an issue I am not sure how to solve.
Accord
Accord14mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server