异常处理中间件和页面

时间:2017-06-27 22:57:44

标签: c# exception-handling asp.net-core asp.net-core-mvc asp.net-core-middleware

我是中间件概念的新手,目前正在努力处理我的MVC核心项目中处理异常的正确方法。

我想要发生的事情是捕获,记录异常,然后将用户发送到带有消息的友好错误页面。起初,我试图在中间件中管理所有这些,但意识到我可能没有正确地做到这一点。

所以如果我想要这个流程发生,我应该使用我的Exception-logging中间件和app.UseExceptionHandler(“/ Error”),以便中间件重新抛出页面的异常?如果是这样,我如何在错误页面中获取异常详细信息?我想首先拦截的异常处理机制应该是Configure中的最后一个吗?

这是正确的吗?

我发现的所有示例都严格处理HTTP状态码错误,如404;我正在寻找处理实际的异常(及其子类)。这样,在我的View页面中,我可以在适用的情况下抛出自己的异常(例如,如果为必填字段提供了一个null,则为空。)

Startup.cs片段:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
                      ILoggerFactory loggerFactory, LoanDbContext context) {
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseStatusCodePages();
    if (env.IsDevelopment() || env.IsEnvironment("qa")) {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    } else {
        app.UseExceptionHandler("/Error");
    }
    app.UseMiddleware<MyExceptionHandler>(loggerFactory);
    // ... rest of Configure is irrelevant to this issue

MyExceptionHandler.cs

using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace MyCompany.MyProject.Helpers
{
    /// <summary>
    /// A custom Exception Handler Middleware which can be re-used in other projects.
    /// </summary>
    public sealed class MyExceptionHandler
    {
        private readonly RequestDelegate _next;
        private readonly ILogger _logger;

        public MyExceptionHandler(RequestDelegate next, ILoggerFactory loggerFactory) {
            _next = next;
            _logger = loggerFactory.CreateLogger<MyExceptionHandler>();
        }

        public async Task Invoke(HttpContext context) {
            try {
                await _next(context);
            } catch (Exception ex) {
                HandleException(ex);
            }
        }

        // I realize this function looks pointless, but it will have more meat to it eventually.
        public void HandleException(Exception ex) {
            if (ex is ArgumentException argEx) {
                _logger.LogError(0, argEx, argEx.Message);
            } else if (ex is InvalidOperationException ioEx) {
                _logger.LogError(0, ioEx, "An Invalid Operation Exception occurred. This is usually caused by a database call that expects "
                    + "one result, but receives none or more than one.");
            } else if (ex is SqlException sqlEx) {
                _logger.LogError(0, sqlEx, $"A SQL database exception occurred. Error Number {sqlEx.Number}");
            } else if (ex is NullReferenceException nullEx) {
                _logger.LogError(0, nullEx, $"A Null Reference Exception occurred. Source: {nullEx.Source}.");
            } else if (ex is DbUpdateConcurrencyException dbEx) {
                _logger.LogError(0, dbEx, "A database error occurred while trying to update your item. This is usually due to someone else modifying the item since you loaded it.");
            } else {
                _logger.LogError(0, ex, "An unhandled exception has occurred.")
            }
        }
    }
}

1 个答案:

答案 0 :(得分:10)

  

我应该同时使用我的异常日志记录中间件和import shutil #import csv files from folder path = r'data/US/market/merged_data' allFiles = glob.glob(path + "/*.csv") with open('someoutputfile.csv', 'wb') as outfile: for i, fname in enumerate(allFiles): with open(fname, 'rb') as infile: if i != 0: infile.readline() # Throw away header on all but first file # Block copy rest of file from input to output without parsing shutil.copyfileobj(infile, outfile) print(fname + " has been imported.") ,以便中间件将异常重新抛出到页面中吗?

仅使用您示例的片段。

app.UseExceptionHandler("/Error")

以上内容将在记录之后重新抛出原始错误,以便管道中的其他处理程序捕获它并进行开箱即用处理。

来源Error Handling in ASP.NET Core

  

如何在错误页面中获取异常详细信息?

使用public async Task Invoke(HttpContext context) { try { await _next(context); } catch (Exception ex) { HandleException(ex); // re -throw the original exception // after logging the information throw; } } 获取例外和路径

IExceptionHandlerPathFeature

来源Adding Global Error Handling and Logging in ASP.NET Core with IExceptionHandlerPathFeature

在上面的示例中,他们提到在视图中进行日志记录,但您已经在自定义处理程序中完成了该操作。

在渲染错误视图时要特别注意这个小注释。

  

无论你做什么,都要小心抓住任何例外情况,否则你最终会得到一个空白页并投掷500

通过插入管道,您可以避免重新发明框架已经提供的功能,并且还可以管理跨领域的问题。