asp.net 倒带请求正文流



asp.net core owin (3)

刚找到一个解决方案。 用包含数据的新流替换原始流。

    public override Task Invoke(IOwinContext context)
    {
        return Task.Run(() => {
            string body = new StreamReader(context.Request.Body).ReadToEnd();
            // log body

            byte[] requestData = Encoding.UTF8.GetBytes(body);
            context.Request.Body = new MemoryStream(requestData);
            this.Next.Invoke(context);
        });
    }

如果您正在处理大量数据,我确信FileStream也可以作为替代品。

我正在重新实现一个请求记录器作为Owin Middleware,它记录了所有传入请求的请求URL和正文。 我能够读取正文,但如果我在控制器中执行body参数为null。

我猜它是空的,因为流的位置在末尾,因此在尝试反序列化主体时没有什么可读的。 我在以前版本的Web API中遇到了类似的问题,但是能够将Stream位置设置回0.这个特定的流抛出了一个This stream does not support seek operations异常。

在最新版本的Web API 2.0中,我可以在我的请求记录器中调用Request.HttpContent.ReadAsStringAsync() ,并且主体仍然可以到达控制器。

如何在阅读后回放流?

要么

如何在不消费的情况下阅读请求体?

public class RequestLoggerMiddleware : OwinMiddleware
{
    public RequestLoggerMiddleware(OwinMiddleware next)
        : base(next)
    {
    }

    public override Task Invoke(IOwinContext context)
    {
        return Task.Run(() => {
            string body = new StreamReader(context.Request.Body).ReadToEnd();
            // log body

            context.Request.Body.Position = 0; // cannot set stream position back to 0
            Console.WriteLine(context.Request.Body.CanSeek); // prints false
            this.Next.Invoke(context);
        });
    }
}
public class SampleController : ApiController 
{
    public void Post(ModelClass body)
    {
        // body is now null if the middleware reads it
    }
}

Answer #1

我知道这是旧的,但只是为了帮助遇到这个的人。 你需要在流上寻找: context.Request.Body.Seek(0, SeekOrigin.Begin);


Answer #2

这是Despertar对第一个答案的一个小改进,这对我帮助很大,但在处理二进制数据时遇到了一个问题 将流提取为字符串然后使用Encoding.UTF8.GetBytes(body)将其放回字节数组的中间步骤会混淆二进制内容(除非是UTF8编码的字符串,否则内容将会更改)。 这是我使用Stream.CopyTo()修复:

    public override async Task Invoke(IOwinContext context)
    {
        // read out body (wait for all bytes)
        using (var streamCopy = new MemoryStream())
        {
            context.Request.Body.CopyTo(streamCopy);
            streamCopy.Position = 0; // rewind

            string body = new StreamReader(streamCopy).ReadToEnd();
            // log body

            streamCopy.Position = 0; // rewind again
            context.Request.Body = streamCopy; // put back in place for downstream handlers

            await this.Next.Invoke(context);
        }
    }

此外, MemoryStream很不错,因为您可以在记录完整正文之前检查流的长度(这是我不想做的事情,以防有人上传大文件)。





owin-middleware