如何让用 ASP.Net Core 2.0 编写的自定义异常处理程序在 Core 3.1 ASP.Net 工作?



在完成了Pluralsight课程(Erik Dahl的.NET Logging Done Right: An Opinionated Approach Using Serilog(之后,我开始在我自己的 ASP.Net Core 3.1 MVC项目中实现类似的解决方案。作为初步的概念证明,我从课程中下载了他的完整示例代码,并将他的记录器类库集成到我的项目中,看看它是否有效。

不幸的是,除了一个关键因素之外,一切似乎都在工作。在我的项目的 Startup.cs 文件的 Configure 方法中,而不是我现在app.UseCustomExceptionHandler("MyAppName", "Core MVC", "/Home/Error");app.UseExceptionHandler("/Home/Error");- 理论上,这意味着命中一些自定义中间件,传入一些额外的数据以进行错误日志记录,然后像普通的异常处理程序一样运行并命中错误处理路径。实际上,它不会命中错误处理路径,并且向用户显示浏览器的错误页面。

中间件代码的注释说这段代码是:

// based on Microsoft's standard exception middleware found here:
// https://github.com/aspnet/Diagnostics/tree/dev/src/
//         Microsoft.AspNetCore.Diagnostics/ExceptionHandler

此链接不再有效。我找到了新链接,但它在 GitHub 存档中,它没有告诉我任何有用的东西。

我知道 .Net Core 2.0 和 3.1 之间的路由工作方式发生了变化,但我不确定这些是否会导致我遇到的问题。我认为问题不在于下面从 Startup.cs 调用的代码。

public static class CustomExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseCustomExceptionHandler(
this IApplicationBuilder builder, string product, string layer, 
string errorHandlingPath)
{
return builder.UseMiddleware<CustomExceptionHandlerMiddleware>
(product, layer, Options.Create(new ExceptionHandlerOptions
{
ExceptionHandlingPath = new PathString(errorHandlingPath)
}));
}
}

我相信问题可能出在实际自定义异常中间件中的调用方法中.cs如下所示:

public sealed class CustomExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ExceptionHandlerOptions _options;
private readonly Func<object, Task> _clearCacheHeadersDelegate;
private string _product, _layer;
public CustomExceptionHandlerMiddleware(string product, string layer,
RequestDelegate next,
ILoggerFactory loggerFactory,
IOptions<ExceptionHandlerOptions> options,
DiagnosticSource diagSource)
{
_product = product;
_layer = layer;
_next = next;
_options = options.Value;
_clearCacheHeadersDelegate = ClearCacheHeaders;
if (_options.ExceptionHandler == null)
{
_options.ExceptionHandler = _next;
}
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
WebHelper.LogWebError(_product, _layer, ex, context);
PathString originalPath = context.Request.Path;
if (_options.ExceptionHandlingPath.HasValue)
{
context.Request.Path = _options.ExceptionHandlingPath;
}
context.Response.Clear();
var exceptionHandlerFeature = new ExceptionHandlerFeature()
{
Error = ex,
Path = originalPath.Value,
};
context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);
context.Response.StatusCode = 500;
context.Response.OnStarting(_clearCacheHeadersDelegate, context.Response);
await _options.ExceptionHandler(context);
return;
}
}
private Task ClearCacheHeaders(object state)
{
var response = (HttpResponse)state;
response.Headers[HeaderNames.CacheControl] = "no-cache";
response.Headers[HeaderNames.Pragma] = "no-cache";
response.Headers[HeaderNames.Expires] = "-1";
response.Headers.Remove(HeaderNames.ETag);
return Task.CompletedTask;
}
}

任何建议将不胜感激,在过去的几天里,我已经陷入了很多兔子洞,试图让它工作无济于事,除了我自己的项目之外,我很想能够对 Pluralsight 课程发表评论给任何其他试图这样做的人,以挽救他们不得不经历与我相同的挣扎。

我实际上推荐了一种比我最初在 .NET Logging Done Right 课程中展示的方法更简单的方法(该课程大部分是围绕 .NET Framework 构建的,ASP.NET Core 模块是在原始发布后添加的(。 执行 ASP.NET 核心日志记录的更好方法是 ASP.NET 核心中较新的有效日志记录。 但是,与其简单地把你送到另一门课程观看,不如让我回答你的问题。

我认为您应该使用UseExceptionHandler(string path)中间件。 您可以自由地在错误代码(控制器或剃须刀页面代码(中记录异常。 您可以在此代码存储库中具体看到这一点:

https://github.com/dahlsailrunner/aspnetcore-effective-logging

具体看看 BookClub.UI 项目中的这些文件:

  • 启动.cs(Configure方法(
  • Pages/Error.cshtml
  • Pages/Error.cshtml.cs

这将使您的自定义代码保持在最低限度(总是一件好事(。

呵呵

可以尝试重置自定义异常处理程序中间件中的终结点和路由值,如下所示。

try
{
context.Response.Clear();
context.SetEndpoint(endpoint: null);
var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
routeValuesFeature?.RouteValues?.Clear();
var exceptionHandlerFeature = new ExceptionHandlerFeature()
{
Error = ex,
Path = originalPath.Value,
};
//...

有关更多信息,请查看 github 中ExceptionHandlerMiddleware的源代码:

https://github.com/dotnet/aspnetcore/blob/5e575a3e64254932c1fd4937041a4e7426afcde4/src/Middleware/Diagnostics/src/ExceptionHandler/ExceptionHandlerMiddleware.cs#L107

相关内容

  • 没有找到相关文章

最新更新