【问题标题】:UseExceptionHandler Blazor server-sideUseExceptionHandler Blazor 服务器端
【发布时间】:2020-05-15 22:10:56
【问题描述】:

有人可以确认app.UseExceptionHandler() 不适用于服务器端 blazor 吗?

我见过几种情况,我的自定义 ErrorHandler 没有捕捉到我的应用程序抛出的异常。示例代码

Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
    ...
    app.UseExceptionHandler(new ExceptionHandlerOptions { ExceptionHandler = ErrorHandler.HandleError });
    ...
}

ErrorHandler.cs:

public static async Task HandleError(HttpContext context)
{
    var error = context.Features.Get<IExceptionHandlerFeature>()?.Error;
    var message = error?.Message ?? "[EXCEPTION NOT FOUND]";        
    return;
}

一个例子是当我的存储库抛出异常时: The instance of entity type cannot be tracked because another instance with the same key value for {'Id'} is already being tracked

我的 MVC 解决方案正在捕获所有异常,并且它使用类似的 ErrorHandling 实现。

【问题讨论】:

    标签: c# .net asp.net-core .net-core blazor


    【解决方案1】:

    确实,许多 ASP Core 中间件方案无法在服务器端 Blazor 应用程序中完全运行。 这是因为 Blazor 与 SignalR 和 Blazor Hub 配合使用。

    您会看到,在启动 Blazor 应用程序时,首先有几个 HTTP 请求将通过管道直到结束。 (在大多数情况下,这些是初始页面加载,然后是协商阶段)。 但随后出现了对“/_blazor”的请求,此时连接保持打开状态以继续通过 websocket 进行通信。 如果您在此阶段之后出现异常,它将不会进入您的异常处理程序。

    您可以通过创建一个小型中间件类来观察这一点,该类通过 IApplicationBuilder 上的 UseMiddleware 扩展方法注册。 这样的中间件类需要像这样的 Invoke 方法,例如:

    .....
    public class TestMiddleware
    {
        private readonly RequestDelegate _next;
        public TestMiddleware(RequestDelegate next)
        {
           _next = next
        }
    
        public async Task Invoke(HttpContext context)
        {
           await _next(context);
        }
    ....
    

    如果您在Invoke 中放置断点,您会注意到一旦上下文参数用于路径“/_blazor”,您将不会再进一步​​。

    这是另一个讨论类似问题的链接,与异常处理程序不同,但也与 ASP.NET 中间件有关: https://github.com/aspnet/SignalR/issues/1334

    【讨论】:

      【解决方案2】:

      感谢@reno的回答,我刚刚完成了他的回答

      只需 3 个步骤:

      1.创建一个异常中间件:

       public class ExceptionMiddleware
      {
          public readonly RequestDelegate _next;
          string _path;
          private readonly ILogger<ExceptionMiddleware> _logger;
      
          public ExceptionMiddleware(ILogger<ExceptionMiddleware> logger, RequestDelegate next,string Path)
          {
              _next = next;
              _path = Path;
              _logger = logger;
          }
      
          public async Task InvokeAsync(HttpContext context)
          {
              try
              {
                  await _next(context);
              }
              catch (System.Exception ex)
              {
                  _logger.LogError(ex,$"RequsetPath: {context.Request.Path}",default);
                  context.Response.Redirect(_path);
      
              }
          }
      
      }
      

      2.创建自定义MiddlewareExtension:

      public static class MiddlewareExtensions
      {
          public static IApplicationBuilder UsemycustomException(
              this IApplicationBuilder builder,string path)
          {
              return builder.UseMiddleware<ExceptionMiddleware>(path);
          }
      }
      

      3.在配置中使用这个中间件作为第一个中间件:

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
      {
        app.UsemycustomException("/Error");
        .
        .
        .
      }
      

      注意:Pages 中的Error.razor 文件必须具有路由路径: @page "/error"

      查看输出窗口登录 vs:

      【讨论】:

        猜你喜欢
        • 2021-05-28
        • 1970-01-01
        • 2020-09-19
        • 2020-04-14
        • 2020-09-26
        • 2020-09-30
        • 1970-01-01
        • 2020-03-25
        • 2020-12-29
        相关资源
        最近更新 更多