Захват необработанных данных HTTP POST во время исключения - PullRequest
7 голосов
/ 25 мая 2009

У меня есть служба WCF, размещенная в IIS / ASP.NET, которая принимает HTTP Post ( not form post ) сериализованных объектов.

Если клиент отправляет некорректные запросы (например, они не сериализуют объект правильно), я бы хотел зарегистрировать отправленное сообщение.

Мы уже используем ELMAH для захвата необработанных исключений, поэтому проще всего подключить данные поста.

Я могу получить текущий HttpContext во время исключения, однако он содержит только информацию заголовка HTTP.

У меня такой вопрос: есть ли способ захвата исходного тела HTTP-запроса POST? Или, если это не удастся - лучший способ (без обратного прокси-сервера) перехватить ввод, вызвавший ошибку?

Редактировать: Просто для пояснения, запуск захвата на уровне пакетов не всегда подходит. Мне нужно решение, которое я могу развернуть на производственных серверах и которое будет иметь клиентов вне нашего контроля или возможности мониторинга.

Редактирование # 2: было предложено получить доступ к Request.InputStream - это не сработает, если вы пытаетесь читать после того, как WCF прочитал запрос из потока.

Пример кода, чтобы увидеть, как я пытался использовать это здесь.

        StringBuilder log = new StringBuilder();

        var request = HttpContext.Current.Request;

        if (request.InputStream != null)
        {
            log.AppendLine(string.Format("request.InputStream.Position = \"{0}\"", request.InputStream.Position));
            if (request.InputStream.Position != 0)
            {
                request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
            }

            using (StreamReader sr = new StreamReader(request.InputStream))
            {
                log.AppendLine(string.Format("Original Input: \"{0}\"", sr.ReadToEnd()));
            }
        }
        else
        {
            log.AppendLine("request.Inputstream = null");
        }


        log.ToString();

Выход log.ToString ():

    request.InputStream.Position = "0"
    Original Input: ""

Ответы [ 4 ]

3 голосов
/ 25 мая 2009

К тому времени, как оно поступит к вам, запрос будет обработан и вам недоступен.

Однако ... вы можете прикрепить инспектор сообщений . Инспекторы сообщений позволяют вам возиться с сообщением до того, как оно достигнет ваших реализаций операций. Вы можете создать буферизованную копию сообщения и скопировать ее в OperationContext.Current.

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

0 голосов
/ 03 января 2013

из-под ASP.NET (веб-сервис ASP под IIS) помогает следующий код:

if (request.InputStream.Position != 0)
{
  request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
}

WCF может быть другим (то есть он удаляет InputStream после его прочтения)

0 голосов
/ 25 мая 2009

Вы смотрели на свойство System.Web.Request.InputStream? Он должен иметь именно то, что вы хотите.

Как «перемотать» свойство InputStream.

    if (Request.InputStream.Position != 0)
    {
        Request.InputStream.Seek(0, System.IO.SeekOrigin.Begin);
    }

Другой вариант, на который вы должны обратить внимание, - это захват этой информации с помощью HTTPModule для события BeginRequest. Данные должны присутствовать в событии BeginRequest, поскольку я не верю, что WCF принимает запрос до тех пор, пока не будет завершено PostAuthenticateEvent.

0 голосов
/ 25 мая 2009

Использовать скрипач. Бесплатно от MS. Прекрасно работает.

...