12

I have in startup

(UPDATE: the solution was to move UseRouting under the /api/error routes)

app.UseRouting();

if (env.IsDevelopment()) {               
    app.UseExceptionHandler("/api/error/error-local-development"); 
    SwaggerConfig.Configure(app);              
}
else {             
    app.UseExceptionHandler("/api/error/error");
}

 app.UseCors();
 app.UseHttpsRedirection();
 app.UseDefaultFiles();
 app.UseSpaStaticFiles(); 
 app.UseAuthentication();
 app.UseAuthorization();
 app.UseRequestLocalization(options);
  app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHub<ResultHub>("/hubs/resultHub");
            });


            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "wwwroot";
            });

But when throw new Exception() in a controller action, the Error controller Methods are never called.

[Route("api/error")]
[ApiController]
[ApiExplorerSettings(IgnoreApi = true)]
public class ErrorController : OwnBaseController
{
    public ErrorController(IApplicationUserService applicationUserService, ILogger<ErrorController> logger, IDiagnosticContext diagnosticContext) : base(applicationUserService, logger, diagnosticContext)
    {
    }

    [Route("error")]
    public IActionResult Error()
    {
        return Problem(); 
    }

    [Route("error-local-development")]
    public IActionResult ErrorLocalDevelopment([FromServices] IWebHostEnvironment webHostEnvironment)
    {
       var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
       return Problem(
            detail: context.Error.StackTrace,
            title: context.Error.Message);
    }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
edelwater
  • 2,650
  • 8
  • 39
  • 67

3 Answers3

11

It might seem strange but ordering matters.

UseExceptionHandler and UseRouting are both registering middlewares under the hood.

The firstly registered will be the outer most middleware. So if the inner throws exception the outer can catch it and can handle (and/or log) it.

middleware ordering Source

MSDN has some warnings about this, for example:

If an endpoint within the app is specified, create an MVC view or Razor page for the endpoint. Ensure UseStatusCodePagesWithReExecute is placed before UseRouting so the request can be rerouted to the status page.

UseExceptionHandler is the first middleware component added to the pipeline. Therefore, the Exception Handler Middleware catches any exceptions that occur in later calls.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • I was really hoping this simple solution would have fixed my case. My called to UseExceptionHandler is called first, but the unhandled exception still does not call the error handling controller. There must be other causes for this issue. – Matthew MacFarland Sep 06 '21 at 20:52
  • Hi @MatthewMacFarland, could you please share further details in order to be able to help you? (If needed please create a new question and paste here the link) – Peter Csala Sep 07 '21 at 07:15
  • 1
    Hi @PeterCsala, Certainly. I will put my details together and post them soon. – Matthew MacFarland Sep 07 '21 at 13:00
  • 2
    Hi @PeterCsala, I discovered my problem while getting ready to post details here. I was running in development mode and the call to `app.UseExceptionHandler()` was only active for when `IsDevelopmentMode = false`. Silly mistake. Everything works perfectly now. – Matthew MacFarland Sep 08 '21 at 20:12
  • Hi @MatthewMacFarland it happens to everyone, no worries. I'm glad that you could solve it on your own. – Peter Csala Sep 08 '21 at 20:25
2

It didn't help for me so, I changed this

app.UseExceptionHandler("Home/Error");

to this

app.UseExceptionHandler("/Error");

and aldo added an attribute route on the action

[Route("/Error")]
public IActionResult Error()
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
miri l.
  • 141
  • 6
0

For me it was the route name was not the same as the usEexceptionHandler:

I had

[Route("/errors")]
public IActionResult Error()

and in my program.cs:

app.UseExceptionHandler("/error");

both names must be the same for it to work

Mo D Genesis
  • 5,187
  • 1
  • 21
  • 32