You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 ActionFilter大请求体连续请求时内容混合及读取异常问题

问题:大体积XML请求体多次读取后内容损坏及并发读取异常

我们实现了自定义XmlValidationActionFilter,用于在控制器动作执行前对请求体执行XSD校验,确保XML格式合法。同时编写了HttpRequest扩展方法读取请求体,保证请求体可被多次读取。

当请求体未超过30KB阈值(不写入磁盘)时,XML校验正常;但当请求体超过该阈值时,首次请求可正常处理,后续对同一端点的请求内容出现损坏:部分XML被截断,有时会出现前一次请求的部分内容拼接下一次完整请求内容的情况。

现象示例

首次请求体

<?xml version="1.0" encoding="UTF-8"?>
<TestXML>
   <Node1>Node1</Node1>
   <Node2>
      <CNode>Hello</CNode>
   </Node2
</TestXML>

后续请求1(内容截断)

<?xml version="1.0" encoding="UTF-8"?>
<TestXML>
   <Node1>Node1</Node1>
   <Node2>
      <CNode>Hello</CNode>

后续请求2(内容拼接)

<?xml version="1.0" encoding="UTF-8"?>
<TestXML>
   <Node1>Node1</Node1>
   <Node2>
      <CNode>Hello</CNode><?xml version="1.0" encoding="UTF-8"?>
<TestXML>
   <Node1>Node1</Node1>
   <Node2>
      <CNode>Hello</CNode>
   </Node2
</TestXML>

相关代码

Startup.cs

services.AddScoped<XmlValidationActionFilter>();
app.Use(next => context =>
{
    context.Request.EnableBuffering();
    return next(context);
});

HttpRequest扩展方法

public static async Task<string> GetRequestBodyAsync(this HttpRequest request)
{
    string requestBody = null;

    // IMPORTANT: Ensure the requestBody can be read multiple times.
    request.EnableBuffering();

    // IMPORTANT: Leave the body open so the next middleware/filter/action can read it.
    using (var reader = new StreamReader(
        request.Body,
        Encoding.UTF8,
        detectEncodingFromByteOrderMarks: false,
        leaveOpen: true))
    {
        requestBody = await reader.ReadToEndAsync();

        // IMPORTANT: Reset the request body stream position so the next middleware/filter/action can read it
        request.Body.Position = 0;
    }

    return requestBody;
}

控制器使用示例

[ServiceFilter(typeof(XmlValidationActionFilter))]
public async Task<IActionResult> SetRecord([FromHeader(Name = "SerialNumber")] string serialNumber)
{
    var payload = await HttpContext.Request.GetRequestBodyAsync();
    // 后续处理逻辑
}

补充异常信息

运行过程中还出现以下异常:

System.InvalidOperationException: Reading is already in progress.
   at System.IO.Pipelines.ThrowHelper.ThrowInvalidOperationException_AlreadyReading()
   at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
   at System.IO.Pipelines.Pipe.ReadAsync(CancellationToken token)
   at System.IO.Pipelines.Pipe.DefaultPipeReader.ReadAsync(CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadAsync(Memory`1 memory, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.IIS.Core.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadToEndAsyncInternal()


Exception Info: System.InvalidOperationException: Concurrent reads or writes are not supported.
   at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
   at System.IO.Pipelines.Pipe.GetReadAsyncResult()
   at System.IO.Pipelines.Pipe.DefaultPipeReader.GetResult(Int16 token)
   at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ReadAsync(Memory`1 memory, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.IIS.Core.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.IIS.Core.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadBufferAsync(CancellationToken cancellationToken)
   at System.IO.StreamReader.ReadToEndAsyncInternal()
   at System.IO.StreamReader.ReadToEndAsyncInternal()

内容的提问来源于stack exchange,提问作者Kaizer69

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:32:02