2009-05-25 2 views
7

У меня есть служба WCF, размещенная в IIS/ASP.NET, которая принимает HTTP-сообщение (не формирует сообщение) сериализованных объектов.Захват необработанных HTTP-данных 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: "" 
+1

"Использование" с StreamReader приведет к System.Web.Request.InputStream находится (что означает, что данные теряются). – Jeff

+0

Данные уже потеряны. – 2009-05-26 00:57:16

ответ

3

К моменту получения вашей услуги запрос обрабатывается и недоступен для вас.

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

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

+0

Спасибо - это не очень замечательное решение, но жертвуя некоторой памятью, возможно, стоит того. – 2009-05-26 00:56:21

-2

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

+1

Я говорю об ошибках, которые произошли, когда нет Fiddler, Wireshark или что-то бегущее для его захвата. , например, на сервере Production или Staging, где не всегда возможно выполнять захват пакетов. – 2009-05-25 13:49:11

-1

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

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

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

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

+1

Я просмотрел это свойство - к сожалению, этот поток содержит только непрочитанные данные. К моменту возникновения исключения входные данные уже были прочитаны WCF. Вы не можете перемотать или сбросить позицию. – 2009-05-25 14:12:19

+0

См. Мое обновление ... Так как Request.InputStream.CanSeek верен, вы можете вернуть позицию обратно в 0 с помощью метода Seek. – Jeff

+0

Благодарим за обновление - CanSeek прав, однако в потоке ничего не читать. См. Обновленный текст, например, о том, что я сделал, чтобы попробовать и проверить это. – 2009-05-25 16:52:25

-1

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

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

WCF, может отличаться (то есть он распоряжается InputStream после прочтения)

+0

Это тот же ответ, что и Джефф. Он также не работает, поскольку поток не доступен для поиска. – 2013-01-03 21:45:34