ASP.Net MVC中的全局错误记录6

swa*_*nee 9 asp.net asp.net-web-api asp.net-core-mvc

我正在测试一个MVC 6 Web Api,并希望实现登录到全局错误处理程序.只是保证在没有记录的情况下没有错误退出系统.我创建了一个ExceptionFilterAttribute并在启动时全局添加它:

public class AppExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        //Notice pulling from HttpContext Application Svcs -- don't like that
        var loggerFactory = (ILoggerFactory)context.HttpContext.ApplicationServices.GetService(typeof (ILoggerFactory));

        var logger = loggerFactory.Create("MyWeb.Web.Api");
        logger.WriteError(2, "Error Occurred", context.Exception);

        context.Result = new JsonResult(
            new
            {
                context.Exception.Message,
                context.Exception.StackTrace
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在启动时,我正在添加此过滤器:

services.Configure<MvcOptions>(options =>
{
    options.Filters.Add(new AppExceptionFilterAttribute());
});
Run Code Online (Sandbox Code Playgroud)

这一切似乎都是一种蛮力...有没有更好的方法来使用MVC 6?

我不喜欢或不确定这种方法的事情:

  1. 不喜欢从http上下文中提取DI
  2. 没有太多关于发起错误的控制器的上下文(也许我可以通过某种方式从上下文中获取它).

我能想到的另一个选择是拥有一个基本控制器,它接受所有控制器继承的ILoggerFactory.

想知道是否有某种诊断中间件允​​许插入日志...

Kir*_*lla 11

你的问题有2个部分.1)DI可注射过滤器2)全局错误处理.

关于#1:您可以ServiceFilterAttribute为此目的使用.例:

//Modify your filter to be like this to get the logger factory DI injectable.
public class AppExceptionFilterAttribute : ExceptionFilterAttribute
{
    private readonly ILogger _logger;
    public AppExceptionFilterAttribute(ILoggerFactory loggerfactory)
    {
       _logger = loggerFactory.CreateLogger<AppExceptionFilterAttribute>();
    }
    public override void OnException(ExceptionContext context)
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)
//Register your filter as a service (Note this filter need not be an attribute as such)
services.AddTransient<AppExceptionFilterAttribute>();
Run Code Online (Sandbox Code Playgroud)
//On the controller/action where you want to apply this filter,
//decorate them like
[ServiceFilter(typeof(AppExceptionFilterAttribute))]
public class HomeController : Controller
{
....
}
Run Code Online (Sandbox Code Playgroud)

您应该能够从ExceptionContext传递的控制器中获取控制器的详细信息.

关于#2:从你之前的帖子看起来你正在玩ExceptionHandlerMiddleware(来源扩展源)......如何使用它?...有关它的一些信息:

  • 这个中间件是通用的,适用于在它之后注册的任何中间件,因此控制器/动作信息之类的任何概念都是特定于MVC的,中间件不会知道.
  • 此中间件不处理格式化程序写入异常.您可以编写自己的缓冲中间件,您可以将响应主体修改为缓冲流(MemoryStream),并让MVC层将响应写入其中.在格式化程序写入异常的情况下,您可以捕获它并发送带有详细信息的500错误响应.