对我而言,我无法弄清楚。
我有一些中间件抛出异常,即
public class SubscriptionMiddleware
{
private readonly RequestDelegate _next;
...
public SubscriptionMiddleware(RequestDelegate next, ...)
{
_next = next;
...
}
public async Task Invoke(HttpContext context, ...)
{
await _next(context); // Exception may occur here
...
}
}
标准分子量。但是当await _next()
部分发生异常时,它永远不会记录在任何地方...
我的控制器如下:
[ApiController]
[Authorize]
[Route("api/[controller]")]
public class SubscriptionsController : Controller
{
[MiddlewareFilter(typeof(SubscriptionMiddlewareFilter))]
[HttpPost("test")]
public async Task<IActionResult> TestMethod(...)
{
...
return Ok(jsonResult);
}
}
您可能已经注意到的中间件过滤器看起来像这样(如果有所不同):
public class SubscriptionMiddlewareFilter
{
public void Configure(IApplicationBuilder app) => app.UseMiddleware<SubscriptionMiddleware>();
}
所有在控制器方法中发生的异常都被记录下来,并且代码500自动返回。但是,返回400(错误请求)的异常(即某些JSON格式问题)都被吞没了...从未在任何地方记录过。我对它的印象是ApiController
-s应该可以自动运行。
Program.cs
代码也很标准:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.ConfigureAppConfiguration(config =>
{
...
})
.SuppressStatusMessages(true)
.UseKestrel(opts =>
{
...
})
.UseStartup<Startup>();
我尝试使用的是UseExceptionHandler
,但我认为使用的不正确。我在网上能找到的所有解决方案都可以将异常详细信息打印到一些HTML页面或JSON输出中-我只需要将它们记录下来,什么都不需要。
这是我的最新尝试,不过该代理从未被调用:
var exHandlerOpts = new ExceptionHandlerOptions
{
ExceptionHandler = ctx =>
{
var ex = ctx.Features.Get<IExceptionHandlerFeature>().Error;
... log? ...
return Task.CompletedTask;
}
};
app
.UseExceptionHandler(exHandlerOpts)
.UseHsts()
.UseHttpsRedirection()
.UseAuthentication()
.UseMvc()
...
我对此感到困惑,因为整个Asp.Net Core中的异常日志记录看起来非常优雅并且几乎是自动的,我的后台服务,范围服务,控制器等都很好地记录了它们。但是,错误的请求异常...在服务器端甚至都没有被提及?
仅放置.UseExceptionHandler()
会抛出一个异常:
'An error occurred when configuring the exception handler middleware. Either the 'ExceptionHandlingPath' or the 'ExceptionHandler' option must be set in 'UseExceptionHandler()'.'
拜托!因此,尽管文档说:
在管道中添加一个可以捕获异常的中间件,记录它们,然后在备用管道中重新执行请求。
我想指出的是,只要控制器类用[ApiController]
装饰,控制器使用的中间件中的所有异常都会被捕获而不被重发,例如
public async Task Invoke(HttpContext context, SubscriptionRequestData data)
{
try
{
await _next(context);
}
catch (Exception ex)
{
// this will never happen
}
}
我注意到无论我叫.UseExceptionHandler
还是.UseExceptionMiddleware
,情况都是如此。因此,捕获异常并检查异常的唯一方法是在调试器中(配置了异常设置)。
在我的特定情况下,错误的请求是由JSON格式异常引起的,我希望将其记录在某处。像这样:
Newtonsoft.Json.JsonSerializationException:'无法创建类型为PushService.Abstractions.Subscription.ICriterion的实例。类型是接口或抽象类,无法实例化。路径'Criteria [0] .FieldName',第1行,位置63。'
一旦我能够阅读此代码,便很容易发现该错误,但在生产中,我的WebApi不会记录此信息。我只会看到有一个错误的请求,仅此而已,没有更多信息。