【问题标题】:When and how StreamReader should be disposed if underlying Stream should not be disposed?如果不应该处置底层 Stream,应该何时以及如何处置 StreamReader?
【发布时间】:2026-02-13 20:05:02
【问题描述】:

我想在 asp.net core 3.0 应用程序中反序列化 httpRequest.Body 两次:一次在中间件内部,第二次在模型绑定期间。

这是中间件的代码

 var streamReader = new StreamReader(httpRequest.Body)
 var body = streamReader.ReadToEndAsync();
 //some body processing

与我的绑定代码中的完全相同

根据最佳实践,我需要在此处处理 StreamReader 对象。 但是如果我在中间件中处理它,我会在绑定过程中遇到异常 - Cannot access a disposed object. 因为StreamReader 也会处理使用过的Stream

那么我应该在这里做什么?不处置StreamReader,让GC以后做?

也许这是众所周知且微不足道的事情,但我完全糊涂了......

【问题讨论】:

  • 我认为你做不到。我不认为流是缓冲的,客户端只会发送一次正文。
  • @Damien_The_Unbeliever,那么您建议在中间件代码中做什么?我看到的唯一选择是不要处理 StreamReader 但它有难闻的气味......
  • 原来你可以开启缓冲。你可以试试this example
  • @Damien_The_Unbeliever,哇,看起来有效!非常感谢!

标签: c# asp.net-core .net-core stream middleware


【解决方案1】:

感谢@Damien_The_Unbeliever 提供的帮助和链接,以下代码将允许我们处理StreamReader 并避免Stream 在模型绑定中处理和跟踪异常。

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
    context.Request.EnableBuffering();

    // Leave the body open so the next middleware can read it.
    using (var reader = new StreamReader(
        context.Request.Body,
        encoding: Encoding.UTF8,
        detectEncodingFromByteOrderMarks: false,
        bufferSize: bufferSize,
        leaveOpen: true))
{
    var body = await reader.ReadToEndAsync();
    // Do some processing with body…

    // Reset the request body stream position so the next middleware can read it
    context.Request.Body.Position = 0;
}

// Call the next delegate/middleware in the pipeline
await next(context);

}

【讨论】: