如何在不重定向用户的情况下在 mvc 启动中使用 UseExceptionHandler?

How to use UseExceptionHandler in the mvc startup without redirecting the user?

我有一个 ASP.NET Core 2.1 MVC 应用程序,我正试图在发生异常时 return 一个单独的 html 视图。这样做的原因是,如果有错误,我们不希望 google 将重定向注册到我们的 SEO 的错误页面(我省略了开发设置以清除问题)。

我们的启动包含这个:

app.UseExceptionHandler("/Error/500"); // this caused a redirect because some of our middleware.
app.UseStatusCodePagesWithReExecute("/error/{0}"); 

但是我们想阻止重定向,所以我们需要更改 UseExceptionHandler。 我尝试使用 question 中的答案,如下所示:

app.UseExceptionHandler(
            options =>
            {
                options.Run(
                    async context =>
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        context.Response.ContentType = "text/html";
                        await context.Response.WriteAsync("sumtin wrong").ConfigureAwait(false);

                    });
            });

但这会产生一个非常丑陋的页面,没有任何样式。我们尝试使用的另一个解决方案是创建一个错误处理中间件,但是我们 运行 遇到了同样的问题,我们无法添加视图。

如何在不重定向用户的情况下 return 样式化视图?

编辑:UseExceptionHandler 不会导致重定向,它是由我们的某些中间件中的错误引起的。

How can I return a styled view in case of an exception, without redirecting the user?

你快到了。您可以重写(而不是重定向)路径,然后根据当前路径提供 HTML。

假设您的 wwwroot/ 文件夹中有一个样式良好的 sth-wrong.html 页面。更改代码如下:

app.UseExceptionHandler(appBuilder=>
{
    // override the current Path
    appBuilder.Use(async (ctx, next)=>{
        ctx.Request.Path = "/sth-wrong.html";
        await next();
    });
    // let the staticFiles middleware to serve the sth-wrong.html
    appBuilder.UseStaticFiles();
});

[编辑]

Is there anyway where I can make use of my main page layout?

是的。但是因为页面布局是属于MVC的View Feature,所以你可以在这里启用另一个MVC分支

  1. 首先创建一个Controllers/ErrorController.cs文件:

    public class ErrorController: Controller
    {
        public IActionResult Index() => View();
    }
    

    和一个相关的 Views/Error/Index.cshtml 文件:

    Ouch....Something bad happens........
    
  2. 在中间件管道中添加一个 MVC 分支:

    app.UseExceptionHandler(appBuilder=>
    {
        appBuilder.Use(async (ctx, next)=>{
            ctx.Request.Path = "/Error/Index";
            await next();
        });
        appBuilder.UseMvc(routes =>{
            routes.MapRoute(
                name: "sth-wrong",
                template: "{controller=Error}/{action=Index}");
        });
    });
    

演示: