【问题标题】:Asp .Net Core How to handle error pages in areaAsp .Net Core 如何处理区域内的错误页面
【发布时间】:2020-12-19 13:08:35
【问题描述】:
if (env.IsDevelopment())
{ 
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Administration/Error");
    app.UseExceptionHandler("/Production/Error");
}

如何为剃须刀页面上的不同区域定义 2 个错误处理页面?

【问题讨论】:

    标签: c# asp.net-core


    【解决方案1】:

    自定义异常处理程序页面的替代方法是向 UseExceptionHandler 提供 lambda。使用 lambda 允许在返回响应之前访问出错的请求的路径。

    以下是使用 lambda 进行异常处理的示例:

    app.UseExceptionHandler(errorApp =>
    {
        errorApp.Run(async context =>
        {
            var exceptionHandlerPathFeature =
                context.Features.Get<IExceptionHandlerPathFeature>();
    
            // Use exceptionHandlerPathFeature to process the exception (for example, 
            // logging), but do NOT expose sensitive error information directly to 
            // the client.
    
            if (exceptionHandlerPathFeature.Path.Contains("/Administration/"))
            {
                context.Response.Redirect("/Administration/Error");
            }
    
            if(exceptionHandlerPathFeature.Path.Contains("/Production/"))
            {
                context.Response.Redirect("/Production/Error");
            }
        });
    });
    

    您可以参考Handle errors in ASP.NET Core: Exception handler lambda

    【讨论】:

      【解决方案2】:

      我不知道通过配置实现此目的的任何方法。但是,您可以在错误处理程序中识别原始路径:

      if (env.IsDevelopment())
      {          
          app.UseDeveloperExceptionPage();
      }
      else
      {
          app.UseExceptionHandler("/Home/Error");
      }
      

      发生错误时,.NET 会向 Request 对象添加一个 IExceptionHandlerPathFeature 对象。您可以使用它来获取路径:

      public class HomeController : BaseController
      {
          [Route("Error")]
          public IActionResult Error()
          {
              var exceptionPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
      
              var path = exceptionPathFeature.Path;
      
              if(path.Contains("/Administration/"))
                  return View("AdministrationErrorPage");
      
              if(path.Contains("/Production/"))
                  return View("ProductionErrorPage");
      
              return View("GenericErrorPage");
          }
      }
      

      【讨论】:

      • 我试过了,调试时没有碰到控制器
      • @Jackal 这可能是因为异常处理程序仅在不在开发环境中时才被注册。
      【解决方案3】:

      更新了我第一次弄错的评论。 根据这个link,您应该能够指定一个 ExceptionHandler 委托作为调用的一部分。我没试过,但可能会解决你的问题。

       if (env.IsDevelopment())
       {          
            app.UseDeveloperExceptionPage();
       }
       else
       {
                  ExceptionHandlerOptions options;
                  options.ExceptionHandler = new RequestDelegate();
                  app.UseExceptionHandler(options);
       }
      

      您可能还想查看Areas 作为可能的解决方案。它们允许您定义实现不同行为的应用程序的子部分。

      【讨论】:

      • 我承认我弄错了。我已经用 ExceptionHandler 委托更新了我的回复,这可能会对您有所帮助。在委托中,您可以检查路径并做出适当的响应。
      【解决方案4】:

      实现所需行为的另一种方法是使用 UseWhen,如下所示:

      if (env.IsDevelopment())
      { 
          app.UseDeveloperExceptionPage();
      }
      else
      {
          app.UseWhen(
              context => context.Request.Path.StartsWithSegments("/Administration", StringComparison.OrdinalIgnoreCase)),
              appBuilder => appBuilder.UseExceptionHandler("/Administration/Error"));
      
          app.UseWhen(
              context => context.Request.Path.StartsWithSegments("/Production", StringComparison.OrdinalIgnoreCase)),
              appBuilder => appBuilder.UseExceptionHandler("/Production/Error"));
      
          // the catch-all is a bit tricky and is needs to be updated if you add a new area.
          app.UseWhen(
              context => !context.Request.Path.StartsWithSegments("/Administration", StringComparison.OrdinalIgnoreCase)) &&
                         !context.Request.Path.StartsWithSegments("/Production", StringComparison.OrdinalIgnoreCase)),
              appBuilder => appBuilder.UseExceptionHandler("/Error"));
      }
      

      【讨论】:

        【解决方案5】:

        假设您已将您的区域映射为路线值,请在 Configure 中添加以下内容:

        app.UseStatusCodePages(context =>
        {
            var area = context.HttpContext.Request.RouteValues["area"]?.ToString();
            var statusCode = context.HttpContext.Response.StatusCode;
        
            var location = (area, statusCode) switch {
                (string a, 404) => $"/{a}/page-not-found",
                (string a, int s) => $"/{a}/error/{s}",
                (null, 404) => "/page-not-found",
                (null, int s) => $"/error/{s}",
            };
        
            context.HttpContext.Response.Redirect(location);
            return Task.CompletedTask;
        });
        

        【讨论】:

        • 对不起,我认为这实际上并没有回答原始问题,因为它不能处理异常情况。我现在正在研究 ExceptionHandlerMiddleware 并期待一个类似的简单解决方案。
        猜你喜欢
        • 1970-01-01
        • 2020-07-03
        • 2018-10-03
        • 2019-01-04
        • 2020-07-01
        • 2016-06-22
        • 2020-10-04
        • 2020-12-21
        • 2020-03-12
        相关资源
        最近更新 更多