我想在我的ASP.NET Core 1.0项目中编写自定义中间件,它将取代原始框架的Http响应流到我自己的,所以我将能够对它执行读/寻/写操作(首先在进一步的代码中,即在“动作”或“过滤器”中,原始流上无法实现2。
我已经开始使用以下代码:
public class ReplaceStreamMiddleware
{
protected RequestDelegate NextMiddleware;
public ReplaceStreamMiddleware(RequestDelegate next)
{
NextMiddleware = next;
}
public async Task Invoke(HttpContext httpContext)
{
using (var responseStream = new MemoryStream())
{
var fullResponse = httpContext.Response.Body;
httpContext.Response.Body = responseStream;
await NextMiddleware.Invoke(httpContext);
responseStream.Seek(0, SeekOrigin.Begin);
await responseStream.CopyToAsync(fullResponse);
}
}
}
以下代码的问题是,在调用fullResponse
时有时 await responseStream.CopyToAsync(fullResponse);
流已关闭,因此它会引发异常无法访问已关闭的流。
当我在浏览器中加载页面然后在完全加载之前刷新时,很容易发现这种奇怪的行为。
我想知道:
答案 0 :(得分:7)
例外不是来自HttpContext
。它来自您的一个代码的来电者:
您没有在MemoryStream
中恢复原始回复流。因此,无论谁调用您的中间件,都会收回已关闭的app.Use(async (httpContext, next) =>
{
using (var memoryResponse = new MemoryStream())
{
var originalResponse = httpContext.Response.Body;
try
{
httpContext.Response.Body = memoryResponse;
await next.Invoke();
memoryResponse.Seek(0, SeekOrigin.Begin);
await memoryResponse.CopyToAsync(originalResponse);
}
finally
{
// This is what you're missing
httpContext.Response.Body = originalResponse;
}
}
});
app.Run(async (context) =>
{
context.Response.ContentType = "text/other";
await context.Response.WriteAsync("Hello World!");
});
。
这是一些有效的代码:
{{1}}