我想在我的 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); 时已经关闭 所以它抛出异常无法访问关闭的流。

当我在浏览器中加载页面然后刷新 之前很容易观察到这种奇怪的行为

我想知道:
  • 为什么会发生这种情况?
  • 如何防止呢?
  • 是我的解决方案一个好主意还是有另一种方法来替换响应流?
  • 最佳答案

    异常不是来自您的 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 - 替换 ASP.NET Core 1.0 中间件中的响应流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38285623/

    10-11 11:41