UseExceptionHandler Blazor服务器端

时间:2020-01-30 10:11:57

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

有人可以确认app.UseExceptionHandler()对服务器端的服务器不起作用吗?

我已经看到几种情况,我的自定义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实现。

2 个答案:

答案 0 :(得分:2)

实际上,许多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 中放置一个断点,您会注意到,一旦context参数用于路径“ / _blazor”,您就不会进一步。

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

答案 1 :(得分:0)

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

只需3个步骤:

1.创建一个ExceptionMiddleware:

 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.in配置中将此中间件用作第一个中间件:

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

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

请参见Outputwindow登录vs:

enter image description here