Захват необработанных данных HTTP POST во время исключения

StackOverflow https://stackoverflow.com/questions/906788

Вопрос

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

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

Мы уже используем 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: ""
Это было полезно?

Решение

К тому моменту, когда он попадает в вашу службу, запрос уже обработан и недоступен для вас.

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

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

Другие советы

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

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

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

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

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

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

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

Используйте скрипач.Бесплатно от МС.Прекрасно работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top