我经常发现写入
HttpContext.Response.Body
流是一种不好的做法(或者使用 PushStreamContent
或 StreamContent
作为 HttpMessageResponse 的一部分),因为如果发生错误,您将无法更改 HTTP 状态代码。
是否有任何解决方法可以实际执行
async
写入输出流,同时能够更改HTTP状态代码以防操作出错?
是的。最佳实践是编写中间件。例如:
public class ErrorWrappingMiddleware
{
private readonly RequestDelegate next;
public ErrorWrappingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next.Invoke(context);
}
catch (Exception exception)
{
context.Response.StatusCode = 500;
await context.Response.WriteAsync(...); // change you response body if needed
}
}
}
并将它们注入您的管道
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
{
...
app.UseMiddleware<ErrorWrappingMiddleware>();
...
}
当然,您可以根据需要更改中间件中的逻辑,包括根据需要更改响应代码。另外,您可以抛出自己的异常类型,例如
MyOwnException
,然后在中间件中捕获并调用与异常相关的您自己的逻辑。
接下来不要打电话。将响应发送到客户端后调用。响应开始后对 HttpResponse 进行更改,引发异常。
例如,设置标头和状态代码等更改会引发异常。调用 next 后写入响应正文可能会导致协议违规,即写入的内容超出 Content-Length 标头中指定的内容。
它可能会破坏正文格式,就像将 HTML 页脚写入 CSS 文件一样。
HasStarted
是一个有用的提示,指示是否已发送标头或是否已写入正文。