ASP.Net Core 异常处理中间件

Posted

技术标签:

【中文标题】ASP.Net Core 异常处理中间件【英文标题】:ASP.Net Core exception handling middleware 【发布时间】:2019-11-12 15:02:08 【问题描述】:

我正在尝试在我的 ASP.Net Core 3.0 Web API 项目中使用中间件进行异常处理:

public class ErrorHandlingMiddleware

    private readonly RequestDelegate next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    
        this.next = next;
    

    public async Task Invoke(HttpContext context)
    
        try
        
            await next(context);
        
        catch (Exception ex)
        
            await HandleException(context, ex);
        
    

    private static Task HandleException(HttpContext context, Exception ex)
    
        HttpStatusCode code = HttpStatusCode.InternalServerError; // 500 if unexpected

        // Specify different custom exceptions here
        if (ex is CustomException) code = HttpStatusCode.BadRequest;

        string result = JsonConvert.SerializeObject(new  error = ex.Message );

        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;

        return context.Response.WriteAsync(result);
    

startup.cs

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    
        // Add controllers with a route prefix
        services.AddControllers(x =>  x.UseGeneralRoutePrefix($"api/vConfiguration["APIVersion"]"); );
        services.AddSwaggerGen(c =>
        
            c.SwaggerDoc("v0.1", new OpenApiInfo  Title = "My API", Version = "v0.1" );
        );
    

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        app.UseHttpsRedirection();

        app.UseSwagger();
        app.UseSwaggerUI(c =>
        
            c.SwaggerEndpoint("/swagger/v0.1/swagger.json", "My API V1");
        );

        app.UseMiddleware(typeof(ErrorHandlingMiddleware));

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllers();
        );
    

控制器

[HttpPost]
public ActionResult Method()

    if (condition)
        throw new CustomException();
    else
        return Ok();

但是在控制器中抛出的异常并没有被中间件处理。使用中间件的正确方法是什么?

【问题讨论】:

那么会发生什么?你看到了什么? @KirkLarkin 如果条件不满足,则抛出异常,应用程序刚刚崩溃。来自中间件的HandleException() 方法永远不会被调用。 你看到UseDeveloperExceptionPage的结果了吗?显示错误、堆栈跟踪等的漂亮 html 响应? 错误处理中间件应尽早在管道中注册。 参考Handle errors in ASP.NET Core 【参考方案1】:

好像

app.UseDeveloperExceptionPage();

阻止异常处理中间件捕获异常。删除它可以解决问题。

【讨论】:

这是有道理的,猜测您试图在环境变量设置为“开发”的情况下在本地进行调试。可能最好将其包装在条件中。我认为它实际上就像那个 OOTB。 这把我从一个整体中挖出来试图达到刹车点但不能导致数据库页面妨碍【参考方案2】:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        app.UseCors(ApiConstantVars.AZURE_POLICY);
        app.UseCors(ApiConstantVars.CORS_POLICY_NAME);
        app.UseAuthentication();
        app.UseMvc();

        app.Run(
               async context =>
               
                   var handler = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>();
                   if (handler != null && handler.Error != null)
                   
                       var errorModel = new OperationResult
                       
                           IsSuccess = false,
                       ;
                        //Handle the JSON request to respond in its origin format
                       if (context.Request.ContentType.ToUpper().IndexOf("JSON") != -1)
                       
                           context.Response.ContentType = "application/json";
                           context.Response.StatusCode = 400; //Set the Status Code to responde JSON Failed requests
                           await context.Response
                           .WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(new  error = "Unhandled internal error", success = false, origin = context.Request.Path ))
                           .ConfigureAwait(false);
                       
                       else
                       
                           context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
                           await context.Response.WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(handler.Error.Message))
                               .ConfigureAwait(false);
                       
                   
                   else
                   
                       context.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
                       await context.Response
                           .WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(new  message = "Unhandled internal error" ))
                           .ConfigureAwait(false);
                   
               );
    

【讨论】:

【参考方案3】:
app.UseMiddleware<ErrorHandlingMiddleware>();

我认为你应该这样使用它。 将此行添加到 Configure 方法中

【讨论】:

以上是关于ASP.Net Core 异常处理中间件的主要内容,如果未能解决你的问题,请参考以下文章

异常处理中间件不处理异常 - 调用 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware (ASP.NET Core WebAPI)

使用中间件的全局异常处理在 ASP.Net Core 应用程序中不起作用

从零写一个Asp.net core手脚架 (异常处理)

Error Handling in ASP.NET Core

理解ASP.NET Core

处理asp.net核心中的异常?