我们在 Web API 中有中间件,我们用它来过滤来自控制器的响应主体在将我们的服务更新到 .net 5 后,替换输出失败为
System.InvalidOperationException: Headers already sent.
at Microsoft.AspNetCore.Server.HttpSys.Response.CheckResponseStarted()
at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.ConsiderEnablingResponseCache()
at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.OnResponseStart()
at Microsoft.AspNetCore.Server.HttpSys.FeatureContext.CompleteAsync()
at Microsoft.AspNetCore.Server.HttpSys.RequestContext.Execute()
at Microsoft.AspNetCore.Server.HttpSys.RequestContext.Execute()
我们过滤输出的中间件看起来像这样
internal class FilterOutput : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var originalBodyStream = context.Response.Body;
var tempResponseBody = new MemoryStream();
context.Response.Body = tempResponseBody;
context.Response.OnStarting(async state =>
{
await FilterResponse(context, tempResponseBody, originalBodyStream);
}, context);
await next(context);
}
private async Task FilterResponse(HttpContext context, MemoryStream tempResponseBody, Stream originalBodyStream)
{
if (context.Response.StatusCode == 200)
{
var output = Encoding.UTF8.GetString(tempResponseBody.GetBuffer());
var newOutput = output.Filter(null);
var updatedStream = GenerateStreamFromString(newOutput);
await updatedStream.CopyToAsync(originalBodyStream);
context.Response.Body = originalBodyStream;
return;
}
await tempResponseBody.CopyToAsync(originalBodyStream);
}
public static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
}
我意识到 net 5 可能更异步并且更早发送标头有没有办法阻止它,所以我可以修改中间件中的输出主体?