ASP.Net Core 2 错误处理:如何在 Http Response 中返回格式化的异常详细信息?

Posted

技术标签:

【中文标题】ASP.Net Core 2 错误处理:如何在 Http Response 中返回格式化的异常详细信息?【英文标题】:ASP.Net Core 2 error handling: How to return formatted exception details in Http Response? 【发布时间】:2018-07-15 09:37:15 【问题描述】:

我正在寻找一种方法来返回调用我的 Web API 的方法时发生的任何异常的详细信息。

在生产环境中,默认情况下,错误500“Internal Server Error”是API返回的唯一信息。

它是一个私有API,不通过互联网发布,调用者应用程序需要获取并存储所有细节以防异常。

异常详情可以是 JSON 格式的 HttpResponse 内容,允许调用者读取 Message属性,以及异常的 StackTraceString 属性(没有像 UseDeveloperExceptionPage 配置那样的 HTTP 页面)。

目前默认的启动配置方式为:

public class Startup
   
    [...]

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory)
    
        loggerFactory.AddNLog();
        env.ConfigureNLog(Path.Combine(AppContext.BaseDirectory, "nlog.config"));

        if ( env.IsDevelopment() )
            app.UseDeveloperExceptionPage();
        else
            app.UseStatusCodePages();

        app.UseMvc();
    

【问题讨论】:

【参考方案1】:

您可以编写一个自定义中间件,它会拦截所有异常并将它们返回给调用者:

public class ExceptionHandler

    private readonly RequestDelegate _next;

    public ExceptionHandler(RequestDelegate next)
    
        _next = next;
    

    public async Task Invoke(HttpContext context)
    
        try
        
            await _next.Invoke(context);
        
        catch (Exception ex)
        
            await HandleExceptionAsync(context, ex);
        
    

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    
        var response = context.Response;
        response.ContentType = "application/json";
        response.StatusCode = (int)HttpStatusCode.InternalServerError;
        await response.WriteAsync(JsonConvert.SerializeObject(new
        
            // customize as you need
            error = new
            
                message = exception.Message,
                exception = exception.GetType().Name
            
        ));
    

并在您的启动配置方法中注册它:

if (env.IsDevelopment())
    app.UseDeveloperExceptionPage();
else
   app.UseMiddleware<ExceptionHandler>();

【讨论】:

完美运行,+1。我们应该在docs.microsoft.com/en-us/aspnet/core/fundamentals/… 中有这样的例子 @CommonGuy - 你会在哪里存储这个类?你把它放在模型目录中还是推荐的做法是什么? 取决于您如何构建项目。我个人对每一层都有文件夹(Controller、Repository、...),所以我把这个类放在一个 Middleware 文件夹中 @CommonGuy - 所以你有一个名为“Middleware”的文件夹,里面有这个 - 看起来很合理。我确实为每个层、控制器、存储库、服务都有一个文件夹,但我没有 Middleware 文件夹。【参考方案2】:

除了中间件,您可以创建 ActionFilterAttribute 并更改 IActionResult

这是一个简单的示例属性,对于所有未处理的异常,使用 Exception 方法返回 400 Bad request。

public class MyUnhandledExceptionFilter : ActionFilterAttribute, IExceptionFilter
        
    public void OnException(ExceptionContext context)
               
        context.Result = new BadRequestObjectResult(context.Exception.Message);
    

然后像这样在启动的 ConfigureServices 方法中注册它

services.AddMvc(options =>
        
            options.Filters.Add(typeof(MyUnhandledExceptionFilter));
        )

这只会捕获到达 MVC 的异常,这在大多数情况下是您需要的

【讨论】:

不错的解决方案 +1,它有效。但是我们怎样才能让这种行为依赖于环境呢? @abreneliere,只需将 IHostingEnvironment 注入 Startup 的构造函数并保存引用即可。或者您可以使用基于环境的启动类。查看此文档以获取更多信息docs.microsoft.com/en-us/aspnet/core/fundamentals/environments【参考方案3】:

记得在 UseMvc(或 .Net Core 3 中的 UseRouting)之前添加它,因为顺序很重要!!!!!

        app.UseRouting ();
        app.UseMiddleware (typeof (ErrorHandlingMiddleware));

【讨论】:

以上是关于ASP.Net Core 2 错误处理:如何在 Http Response 中返回格式化的异常详细信息?的主要内容,如果未能解决你的问题,请参考以下文章

Error Handling in ASP.NET Core

如何使用 ASP.NET Core 显示错误

ASP.NET Core 无法在 IIS 下运行:HTTP 错误 500.0 - ANCM 进程内处理程序加载失败

ASP.NET Core 无法在 IIS 下运行:HTTP 错误 500.0 - ANCM 进程内处理程序加载失败

ASP.NET Core MediatR 错误:向容器注册处理程序

用VSCode开发一个asp.net core 2.0+angular 5项目: Angular5全局错误处理