locked
ASP.NET Core 3.0 Redirect HTTP 4XX and 5XX requests to customized error pages while keeping the error code RRS feed

  • Question

  • User-326091563 posted

    Hello,
    I'm looking to redirect HTTP requests with 4XX or 5XX error code to a custom error page, while keeping the error code at the request level. I also want to redirect exceptions to a custom error page, with an error code 500.

    For that I used in my Startup.cs file
    "app.UseStatusCodePagesWithReExecute("/error/{0}");
    app.UseExceptionHandler("/error/500");"
    associated with an Error controller.

    The part about exceptions works well.
    I also manage to redirect non-existent routes to my custom page while keeping the 404 error.

    However, I can't redirect the following actions to my custom error pages:
    - return NotFound()
    - return BadRequest()
    - return StatusCode(404)

    What would be the technical solution applied to accomplish this?

    Thursday, November 7, 2019 10:28 AM

All replies

  • User475983607 posted

    However, I can't redirect the following actions to my custom error pages:
    - return NotFound()
    - return BadRequest()
    - return StatusCode(404)

    Correct and expected as you are specifically returning an HTTP response from the action method.  

    What would be the technical solution applied to accomplish this?

    Return a RedirectToAction() or RedirectToPageResult().  

    Thursday, November 7, 2019 11:13 AM
  • User711641945 posted

    Hi a0umi,

    You could custom middleware to deal with it:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {            
        app.UseStatusCodePagesWithReExecute("/error/{0}");
        app.UseExceptionHandler("/error/500");
        app.Use(async (context, next) =>
        {
            await next();
            var code = context.Response.StatusCode; 
    
            var newPath = new PathString("/error/"+code);
            var originalPath = context.Request.Path;
            var originalQueryString = context.Request.QueryString;
            context.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
            {
                OriginalPathBase = context.Request.PathBase.Value,
                OriginalPath = originalPath.Value,
                OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
            });
    
            // An endpoint may have already been set. Since we're going to re-invoke the middleware pipeline we need to reset
            // the endpoint and route values to ensure things are re-calculated.
            context.SetEndpoint(endpoint: null);
            var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
            routeValuesFeature?.RouteValues?.Clear();
    
            context.Request.Path = newPath;
            try
            {
                await next();
            }
            finally
            {
                context.Request.QueryString = originalQueryString;
                context.Request.Path = originalPath;
                context.Features.Set<IStatusCodeReExecuteFeature>(null);
            }              
        });
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        app.UseRouting();
        app.UseAuthorization();
        //...
    }

    For your ErrorController:

    public class ErrorController : Controller
    {
        // GET: /<controller>/
        public IActionResult InternalServerError()
        {
            return View();
        }
        [Route("error/404")]
        public IActionResult StatusCode404()
        {
            return View();
        }
        [Route("error/400")]
        public IActionResult StatusCode400()
        {
            return View();
        }
    }

    Result:

    Best Regards,

    Rena

    Friday, November 8, 2019 4:36 AM