如何使用HttpModule记录请求输入流,然后重置InputStream位置

问题描述 投票:0回答:7

我正在尝试使用 IHttpModule 来记录 http 请求的内容,如下所示:

public class LoggingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += ContextBeginRequest;
    }

    private void ContextBeginRequest(object sender, EventArgs e)
    {
        var request = ((HttpApplication)sender).Request;
        string content;

        using (var reader = new StreamReader(request.InputStream))
        {
            content = reader.ReadToEnd();
        }

        LogRequest(content)
    }
}

问题是,读完输入流后,InputStream似乎消失了,或更可能的是,光标位于流的末尾。

我已经尝试过

request.InputStream.Position = 0;
request.InputStream.Seek(0, SeekOrigin.Begin);
,但都不起作用。

.net httpmodule inputstream
7个回答
48
投票

我已经解决了这个问题:我认为在 StreamReader 上调用 dispose 也一定会杀死 InputStream。

我没有使用 StreamReader,而是执行了以下操作:

        var bytes = new byte[request.InputStream.Length];
        request.InputStream.Read(bytes, 0, bytes.Length);
        request.InputStream.Position = 0;
        string content = Encoding.ASCII.GetString(bytes);

完整代码:

public class LoggingModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += ContextBeginRequest;
    }

    private void ContextBeginRequest(object sender, EventArgs e)
    {
        var request = ((HttpApplication)sender).Request;

        var bytes = new byte[request.InputStream.Length];
        request.InputStream.Read(bytes, 0, bytes.Length);
        request.InputStream.Position = 0;
        string content = Encoding.ASCII.GetString(bytes);

        LogRequest(content)
    }
}

23
投票

是的,StreamReader 将关闭提供的流。

如果您使用的是 >v4.5,请使用 StreamReader 构造函数使流保持打开状态。

using (var reader = new StreamReader(request.InputStream, Encoding.UTF8, true, 1024, true))
{
    content = reader.ReadToEnd();
}

3
投票

我不得不对“cbp”提供的答案进行一些小小的调整。 当使用他的代码时我只得到零。 我将位置设置为读取上方的 0,现在它可以工作了。

 var bytes = new byte[Request.InputStream.Length];
 Request.InputStream.Position = 0;
 Request.InputStream.Read(bytes, 0, bytes.Length);
 string content = Encoding.ASCII.GetString(bytes);

2
投票

这个答案不起作用。它返回一个包含空值的数组。

 var bytes = new byte[request.InputStream.Length];
        request.InputStream.Read(字节, 0, 字节.Length);
        请求.InputStream.Position = 0;
        字符串内容 = Encoding.ASCII.GetString(bytes);

因为输入流被消耗了。


1
投票

您需要使用请求过滤器。编写一个从 Stream 派生的类并将其注册为过滤器。


0
投票

我只是将这一行放在使用部分的前面: 请求.InputStream.Position = 0;

让我很开心...


-1
投票

有时,

RequestFilter
不会运行到方法Read。看来 W3WP 无法通过正常方式读取
httprequest
的内容。

如果您将

WEbservice
部署到服务器。然后使用 IHttpModule 来捕获它。添加
RequestFilter

但是RequestFilter的方法

Read()
没有运行:P

© www.soinside.com 2019 - 2024. All rights reserved.