关于c#:设置中间件asp.net核心2中捕获的错误的主体

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

我关注了以下链接;

自定义HttpResponseException中间件Asp.Net Core 2.0

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

我如下修改了中间件调用方法;??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    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的响应(我正在通过邮递员进行测试)。

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

以下是该类和中间件的完整代码;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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>();
        }
    }
}

HttpStatusCodeException类如下;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    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;
    }

}


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

不起作用,因为在您发送了Respose之后(通过Response.WriteAsync)-无法更改头文件,无法清除标头,因为标头是在响应主体之前发送的,因此此时已经发送给客户端。只需像这样更改顺序:

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

它应该可以正常工作。还值得检查的是,此时响应尚未开始:

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

还要确保您先注册中间件,然后再注册其他中间件。右:

1
2
app.UseHttpErrorHandlerMiddleware();
app.UseMvc();

错误

1
2
app.UseMvc();
app.UseHttpErrorHandlerMiddleware();