c# - ASP.NET Core MVC(以前的 MVC 6)Razor 错误未被异常过滤器捕获

标签 c# razor asp.net-core asp.net-core-mvc

背景:使用 Dapper 和存储库模式的 ASP.NET 5 (ASP.NET Core 1.0) MVC 6 应用程序

显然,与所有其他网站/应用程序一样,我正在努力消除网站中弹出的大部分/所有异常。

我实现了一个 ExceptionFilter 以捕获所有未处理的异常,如下所示:

public class UnhandledExceptionFilter : ActionFilterAttribute, IExceptionFilter
{
    private readonly IErrorRepo _errorRepo;

    public UnhandledExceptionFilter(IErrorRepo errorRepo)
    {
        _errorRepo = errorRepo;
    }

    public void OnException(ExceptionContext context)
    {
        try
        {
            _errorRepo.SaveException(context.Exception);
        }
        catch { }
    }
}

当错误来自 C# 代码时,这非常有用。但是我故意在我的 razor View (cshtml 文件)中加入了错误,并且这些错误没有被这个过滤器捕获。

我是否需要继承额外的属性/接口(interface)才能捕获 razor 异常?

更新:

此处是指定过滤器属性的位置,在 ConfigureServices 方法的 startup.cs 文件中。

    services.AddMvc(options =>
    {
        options.Filters.Add(new UnhandledExceptionFilter(new ErrorRepo(Configuration)));
    });

最佳答案

这样做的诀窍不在于属性 - 它是通过添加中间件提供者。一旦您的中间件在管道中,您将能够捕获任何时候抛出的异常(因此您的属性将不再需要)。

记录器

这是实际要记录错误的东西。我已经复制了我从您的 IErrorRepo 接口(interface)中看到的内容,但是您当然可以修改它以包含传递到下面的 Log 方法中的任何附加信息。

public class UnhandledExceptionLogger : ILogger
{
    private readonly IErrorRepo _repo;

    public UnhandledExceptionLogger(IErrorRepo repo)
    {
        _repo = repo;
    }
    public IDisposable BeginScopeImpl(object state) =>
        new NoOpDisposable();

    public bool IsEnabled(LogLevel logLevel) =>
        logLevel == LogLevel.Critical || logLevel == LogLevel.Error;

    public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
    {
        if (IsEnabled(logLevel))
        {
            _repo.SaveException(exception);
        }
    }

    private sealed class NoOpDisposable : IDisposable
    {
        public void Dispose()
        {
        }
    }
}

提供商

这是将创建记录器的工厂。它只会被实例化一次,并且会在它通过管道时创建所有记录器。

public class UnhandledExceptionLoggerProvider : ILoggerProvider
{
    private readonly IErrorRepo _repo;

    public UnhandledExceptionLoggerProvider(IErrorRepo repo)
    {
        _repo = repo;
    }

    public ILogger CreateLogger(string categoryName) =>
        new UnhandledExceptionLogger(_repo);

    public void Dispose()
    {
    }
}

注册提供者

一旦添加到 ILoggerFactory,它将在管道中的每个请求上被调用。这通常是通过自定义扩展方法完成的,但我们已经有了很多新代码,所以我将省略那部分。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddProvider(new UnhandledExceptionLoggerProvider(new ErrorRepo()));
    // the rest

关于c# - ASP.NET Core MVC(以前的 MVC 6)Razor 错误未被异常过滤器捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36920742/

相关文章:

c# - 使用反射获取元组的值

c# - 如果我从代码创建文本 block ,如何计算加载时的文本框高度和宽度?

c# - Roslyn - 从内存中程序集创建元数据引用

c# - Entity Framework 核心 : SqlException: A transport-level error has occurred when receiving results from the server

asp.net-core - .NET Core 3 rc1 至最终升级 : missing from Visual Studio 2019

c# - Asp.net MVC3 Razor View 引擎,使用 "Multiline @:"转义几行文本?

asp.net - 如何从 @using (Html.BeginForm(

asp.net - ASP.NET MVC 3 Razor 是否输出缓冲区 View ?

asp.net-mvc - MVC CheckBoxFor 导致绕过不引人注目的验证

c# - 远程机器中的日期文化问题