替换 ASP.NET Core 1.0 中间件中的响应流
Replacing response stream in ASP.NET Core 1.0 middleware
我想在我的 ASP.NET Core 1.0 项目中编写自定义中间件,它将把原来框架的 Http Response Stream 替换为我自己的,这样我就可以对其执行读/查找/写操作(首先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);
所以它抛出异常 无法访问已关闭的流。
当我在浏览器中加载页面然后刷新时,在它完全加载之前。
很容易观察到这种奇怪的行为
我想知道:
- 为什么会这样?
- 如何预防?
- 我的解决方案是个好主意还是有另一种方法来替换响应流?
异常并非来自您的 CopyToAsync
。它来自您的代码调用者之一:
您没有恢复 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!");
});
我想在我的 ASP.NET Core 1.0 项目中编写自定义中间件,它将把原来框架的 Http Response Stream 替换为我自己的,这样我就可以对其执行读/查找/写操作(首先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);
所以它抛出异常 无法访问已关闭的流。
当我在浏览器中加载页面然后刷新时,在它完全加载之前。
很容易观察到这种奇怪的行为我想知道:
- 为什么会这样?
- 如何预防?
- 我的解决方案是个好主意还是有另一种方法来替换响应流?
异常并非来自您的 CopyToAsync
。它来自您的代码调用者之一:
您没有恢复 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!");
});