Как регистрировать запрос входного потока с помощью HttpModule, затем reset Позиция InputStream

Я пытаюсь зарегистрировать содержимое http-запроса, используя IHttpModule, например:

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);, но не работал.

Ответ 1

Я решил проблему: я думаю, что вызов dispose на StreamReader также должен убивать 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)
    }
}

Ответ 2

Да StreamReader закроет предоставленный поток.

Если вы находитесь нa > v4.5, используйте конструктор StreamReader, который оставляет поток открытым.

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

Ответ 3

Вам нужно использовать фильтр запросов. Напишите класс, полученный из Stream и зарегистрируйте его как фильтр.

Ответ 4

этот ответ не сработал. он возвращает массив, содержащий нулевые значения.

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

потому что потребляемый входной поток.

Ответ 5

Мне пришлось немного подправить ответ, предоставленный "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);

Ответ 6

sometime, RequestFilter не запускаются в метод Read. Кажется, W3WP не читает содержимое httprequest обычным способом.

Если вы развертываете WEbservice на сервер. Затем используйте IHttpModule для его улова. Добавить RequestFilter.

Но метод Read() RequestFilter не запускается: P