Search code examples
.net-coreasp.net-core-mvc

How to pass the exception from exception handling middleware to ErrorController in ASP.NET Core MVC web application?


I developed a global exception handling middleware and tried to pass my exception to the ErrorCotroller in my ASP.NET Core MVC application.

Middleware:

public class GlobalExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;         

    public GlobalExceptionHandlingMiddleware(RequestDelegate request)
    {
        _next = request; 
    }

    public async Task Invoke(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch(Exception ex)
        {
            await HandleExceptionAsync(httpContext, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext httpContext, Exception ex)
    {           
        httpContext.Response.Redirect("/Error/Error");
        httpContext.Items["exception"] = ex;
    }
} 

ErrorController:

public class ErrorController : Controller
{
    private readonly ILogger<ErrorController> _logger;

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

    [Route("/Error/Error")]
    public IActionResult Error()
    {
        Exception exec = (Exception)HttpContext.Items["exception"];
        ViewData["message"] = exec.Message;
        _logger.LogError(exec, "Internal server error");
        return View("Error");
    }  
}

I tried to use HttpContext.Items["exception"] to pass the exception to the ErrorController, but that was not successful.

How can I achieve this?


Solution

  • Change your middleware like below, it works for me.

    And I am not familiar with your logic, you can modify it as you needed.

    Test Result

    enter image description here

    GlobalExceptionHandlingMiddleware.cs

    namespace AspCore7_Web_Identity
    {
        public class GlobalExceptionHandlingMiddleware
        {
            private readonly RequestDelegate _next;
    
            public GlobalExceptionHandlingMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            public async Task Invoke(HttpContext httpContext)
            {
                try
                {
                    // Just for testing in my local
                    //await HandleExceptionAsync(httpContext, new Exception("test exceptions"));
                    await _next(httpContext);
                }
                catch (Exception ex)
                {
                    await HandleExceptionAsync(httpContext, ex);
                }
            }
    
            private async Task HandleExceptionAsync(HttpContext httpContext, Exception ex)
            {
                httpContext.Items["exception"] = ex;
    
                PathString originalPath = httpContext.Request.Path;
                QueryString originalQueryString = httpContext.Request.QueryString;
    
                try
                {
                    httpContext.Request.Path = "/Error/Error";
                    httpContext.Request.QueryString = QueryString.Empty;
    
                    await _next(httpContext);
                }
                finally
                {
                    httpContext.Request.Path = originalPath;
                    httpContext.Request.QueryString = originalQueryString;
                }
            }
        }
    
    }
    

    Register middlware here

    enter image description here