在中间件 asp.net 核心 2 中设置捕获错误的主体

Setting Body of caught error in Middleware asp.net core 2

我已关注以下link;

Custom HttpResponseException Middleware Asp.Net Core 2.0

我现在想在响应正文中添加一条消息,为异常提供上下文。

中间件Invoke方法我修改如下;

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (HttpStatusCodeException exception)
        {
            context.Response.StatusCode = (int)exception.StatusCode;
            // byte[] data = Encoding.UTF8.GetBytes(exception.Message);
            // await context.Response.Body.WriteAsync(data, 0, data.Length);
            await context.Response.WriteAsync(exception.Message);
            context.Response.Headers.Clear();
        }
    }

然而,当将 WriteAsync 行添加到方法时,我没有从 Api 得到响应(我正在通过邮递员进行测试)。

任何人都可以指出我在这里做错的正确方向吗?

class 和中间件的完整代码如下;

namespace Services.WebApi.Middleware
{
    public class HttpErrorHandlerMiddleware
    {

        private readonly RequestDelegate _next;

        public HttpErrorHandlerMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (HttpStatusCodeException exception)
            {
                context.Response.StatusCode = (int)exception.StatusCode;
                // byte[] data = Encoding.UTF8.GetBytes(exception.Message);
                // await context.Response.Body.WriteAsync(data, 0, data.Length);
                await context.Response.WriteAsync(exception.Message);
                context.Response.Headers.Clear();
            }
        }
    }

    public static class HttpErrorHandlerMiddlewareExtensions
    {
        public static IApplicationBuilder UseHttpErrorHandlerMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<HttpErrorHandlerMiddleware>();
        }
    }
}

HttpStatusCodeExceptionclass如下;

    public class HttpStatusCodeException : Exception
{
    public HttpStatusCode StatusCode { get; set; }

    public HttpStatusCodeException(HttpStatusCode statusCode)
    {
        StatusCode = statusCode;
    }

    public HttpStatusCodeException(HttpStatusCode statusCode, string message) : base(message)
    {
        StatusCode = statusCode;
    }

}

这个

await context.Response.WriteAsync(exception.Message);
context.Response.Headers.Clear();

不会起作用,因为在您发送响应后(通过 Response.WriteAsync)- headers 不能是 changed\cleared,因为 headers 在响应之前发送body等此时已经发送给客户端。只需像这样更改顺序:

context.Response.Headers.Clear();
await context.Response.WriteAsync(exception.Message);

它应该按预期工作。还值得检查此时响应尚未开始:

if (!context.Response.HasStarted) {
    context.Response.Headers.Clear();
    await context.Response.WriteAsync(exception.Message);
}

还要确保在注册其他中间件之前注册您的中间件。右:

app.UseHttpErrorHandlerMiddleware();
app.UseMvc();

错误

app.UseMvc();
app.UseHttpErrorHandlerMiddleware();