简体   繁体   English

ASP.Net Core 异常处理中间件

[英]ASP.Net Core exception handling middleware

I am trying to use middleware for exception handling in my ASP.Net Core 3.0 Web API project:我正在尝试在我的 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启动.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/v{Configuration["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();
        });
    }
}

Controller Controller

[HttpPost]
public ActionResult Method()
{
    if (condition)
        throw new CustomException();
    else
        return Ok();
}

but the exception thrown in the controller doesn't get handled by the middleware.但是 controller 中抛出的异常不会被中间件处理。 What would be the correct way to use the middleware?使用中间件的正确方法是什么?

It seems that看起来

app.UseDeveloperExceptionPage();

was preventing the exception handling middleware from catching exceptions.正在阻止异常处理中间件捕获异常。 Removing it solves the problem.删除它可以解决问题。

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);
                   }
               });
    }
app.UseMiddleware<ErrorHandlingMiddleware>();

I think you should use it this way.我认为您应该以这种方式使用它。 Add this line to the Configure method将此行添加到 Configure 方法

public class ExceptionHandlerMiddleware{
        private readonly RequestDelegate _next;

        public ExceptionHandlerMiddleware(RequestDelegate next)
        {
            _next = next;

        }


        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context).ConfigureAwait(false);
            }
            catch (Exception)
            {
                await HandleExceptionAsync(context).ConfigureAwait(false);
            }
        }

        private static Task HandleExceptionAsync(HttpContext context)
        {
            var result = JsonConvert.SerializeObject(new
            {
                StatusCode = 500,
                Message = "Internal Server Error",
                Data = string.Empty,
                Status = "Failed"

            });
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = 500;
            return context.Response.WriteAsync(result);
        }
    }

// for extension method
 public static class ExceptionHandlerMiddlewareExtensions
    {

        public static void UseExceptionHandlerMiddleware(this IApplicationBuilder app)
        {
            app.UseMiddleware<ExceptionHandlerMiddleware>();
        }
    }


// use it like below

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
           
            // your code
            if (env.IsDevelopment()) // if want to use in development too
            {
                app.UseExceptionHandlerMiddleware();
            }
            else
            {

                app.UseExceptionHandlerMiddleware();
            }
     // your code
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM