Search code examples
c#asp.net-coremodel-view-controller.net-8.0

Global Exception Handling (IExceptionHandler) : show error page without redirection


I'm using the new IExceptionHandler for GlobalExceptionHandling introduced in ASP.NET Core 8 in an MVC application.

I have seen many examples where TryHandleAsync writes a JSON response, but I'm in an MVC environment and want to return an HTML page. I have an Error action in my HomeController that shows a generic error page to my users (e.g., "Please contact XXX if the problem persists...").

I could simply do the following:

internal sealed class GlobalExceptionHandler : IExceptionHandler
{

private readonly ILogger<GlobalExceptionHandler> _logger;

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

public async ValueTask<bool> TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
{
    /* Doing some logic here depending on the exception type */
    var message = ....;
    
    /* Logging the exception */
    _logger.LogError(exception, message);

    httpContext.Response.Redirect("/Home/Error");

    return true;
}

}

But my problem is that I don't want to use a redirect, as the user would see "/Home/Error" in their browser, and if they hit F5, they'd be stuck on that page. I thought it would be simple to invoke the view result of the Error action directly, but that doesn't seem so straightforward.

I’ve been trying to call the Razor engine to get the html string of my Error View, similar to what is shown here: https://weblog.west-wind.com/posts/2022/Jun/21/Back-to-Basics-Rendering-Razor-Views-to-String-in-ASPNET-Core. But how to achieve this in TryHandleAsync method ? Getting ActionContext etc ...

Thanks in advance !


Solution

  • If you want render a complete razor view on an exception you can simply use app.UseExceptionHandler in the request pipeline instead of using a custom IExceptionHandler. For example you can use app.UseExceptionHandler("/error/500") in the request pipeline and create a view that will be shown on this route. The exception that triggered this can be accessed through HttpContext.Features.Get<IExceptionHandlerPathFeature>().Error. Exception handling like this is also done in the default ASP.NET MVC template in Visual Studio. This blog post explains shows it also https://joonasw.net/view/custom-error-pages.