首页 > 解决方案 > ASP.NET Core 3.0 将 HTTP 4XX 和 5XX 请求重定向到自定义错误页面,同时保留错误代码

问题描述

我希望将带有 4XX 或 5XX 错误代码的 HTTP 请求重定向到自定义错误页面,同时将错误代码保持在请求级别。我还想将异常重定向到自定义错误页面,错误代码为 500。

为此,我在启动文件中使用了“app.UseStatusCodePagesWithReExecute("/error/{0}"); app.UseExceptionHandler("/error/500");" 与错误控制器相关联。

关于异常的部分效果很好。我还设法将不存在的路由重定向到我的自定义页面,同时保持 404 错误。

但是,我无法将以下操作重定向到我的自定义错误页面:

实现这一目标的技术解决方案是什么?

这是我的启动文件的配置功能:

app.UseStatusCodePagesWithReExecute("/error/{0}");
app.UseExceptionHandler("/error/500");

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "Error-StatusCode-Route",
        pattern: "error/{statusCode}",
        defaults: new { controller = "Error", action = "InternalServerError" }
);

endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

标签: asp.net-core

解决方案


您可以自定义中间件来处理它:

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();
    //...
}

对于您的错误控制器:

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

推荐阅读