Прочитать тело запроса в ASP.NET

Как читать тело запроса в ASP.NET? Я использую надстройку клиента REST для Firefox, чтобы сформировать запрос GET для ресурса на сайте, который я размещаю локально, и в теле запроса я просто помещаю строку "test", чтобы попытаться прочитать ее на сервере.

в коде сервера (который является очень простым действием MVC) у меня есть это:

var reader = new StreamReader(Request.InputStream);
var inputString = reader.ReadToEnd();

но когда я отладить его, inputString всегда есть пуста. Я не уверен, как еще (например, в FireBug) подтвердить, что тело запроса действительно отправляется правильно, я думаю, я просто предполагаю, что дополнение делает это правильно. Может быть, я неправильно читаю значение?

5 ответов


возможно, я неправильно помню свое обучение, но я думаю, что запросы GET на самом деле не есть тело. страницы.

спецификации HTML технически определяют разницу между" GET "и" POST", так что первый означает, что данные формы должны быть закодированы (браузером) в URL-адрес, а последний означает, что данные формы должны отображаться в теле сообщения.

Так что, может быть, вы делаете все правильно, но вы должны публиковать данные, чтобы иметь тело сообщения?

обновление

в ответ на ваш комментарий, самым "правильным" способом RESTful было бы отправить каждое из значений в качестве собственного параметра:

site.com/MyController/MyAction?id=1&id=2&id=3...

тогда ваше действие автоматически свяжет их, если вы дадите ему параметр массива с тем же именем:

public ActionResult MyAction(int[] id) {...}

или если вы мазохист, вы можете попробовать вытащить значения из Request.QueryString одному за раз.


недавно мне напомнили об этом старом вопросе, и я хотел добавить еще один ответ для полноты, основанный на более поздних реализациях в моей собственной работе.

Для справки:Я вел блог на эту тему недавно.

по сути, суть этого вопроса была: "как я могу передать большие и более сложные критерии поиска ресурсу, чтобы получить отфильтрованный список объектов?"И в итоге все свелось к двум вариантам:

  1. куча Получить параметры строки запроса
  2. сообщение с DTO в теле запроса

первый вариант не идеален, потому что реализация уродлива, и URL-адрес, вероятно, превысит максимальную длину в какой-то момент. Второй вариант, хотя и функциональный, просто не сидел прямо со мной в "спокойном" смысле. В конце концов, я ... --15-->начало данные, верно?

Однако имейте в виду, что я не просто получение данных. Я создания список объектов. Каждый объект уже существует, но список сам не делает. Это совершенно новая вещь, созданная путем выдачи критериев поиска/фильтра в полный репозиторий объектов на сервере. (В конце концов, помните, что коллекция объектов по-прежнему сама по себе является объектом.)

Это чисто семантическое различие, но решительно важное. Потому что, в простейшем случае, это означает, что я могу удобно использовать POST для выдачи этих поисков критерии для сервера. Ответ-это данные, которые я получаю, поэтому я "получаю" данные. Но я не" получаю " данные в том смысле, что я фактически выполняю акт создания, создавая новый экземпляр списка объектов, который состоит из ранее существовавших элементов.

Я полностью признаю, что ограничение никогда не было техническим, оно было просто семантическим. Он просто никогда не "сидела" со мной. Нетехническая проблема требует нетехнического решения, в данном случае семантического. Взгляд на проблему с несколько иной семантической точки зрения привел к гораздо более чистому решению, которое оказалось решением, которое я использовал в первую очередь.


помимо проблемы GET / POST, я обнаружил, что вам нужно установить запрос.InputStream позиция обратно в начало. Спасибо ответ Я нашел.

в частности комментарий

запрос.InputStream / / обязательно сбросьте позицию после чтения или более поздних чтений может произойти сбой

который я перевел в

Request.InputStream.Seek(0,0)

Я бы попытался использовать HttpClient (доступный через Nuget) для выполнения этого типа вещей. Это намного проще, чем System.Net объекты


прямое чтение из запроса.InputStream опасен, потому что при повторном чтении будет получать null, даже если данные существуют. Это проверено на практике. Надежное считывание выполняется следующим образом:

/*Returns a string representing the content of the body 
of the HTTP-request.*/
public static string GetFromBodyString(this HttpRequestBase request)
{
    string result = string.Empty;

    if (request == null || request.InputStream == null)
        return result;

    request.InputStream.Position = 0;

    /*create a new thread in the memory to save the original 
    source form as may be required to read many of the 
    body of the current HTTP- request*/
    using (MemoryStream memoryStream = new MemoryStream())
    {
        request.InputStream.CopyToMemoryStream(memoryStream);
        using (StreamReader streamReader = new StreamReader(memoryStream))
        {
            result = streamReader.ReadToEnd();
        }
    }
    return result;
}

/*Copies bytes from the given stream MemoryStream and writes 
them to another stream.*/
public static void CopyToMemoryStream(this Stream source, MemoryStream destination)
{
    if (source.CanSeek)
    {
        int pos = (int)destination.Position;
        int length = (int)(source.Length - source.Position) + pos;
        destination.SetLength(length);

        while (pos < length)
            pos += source.Read(destination.GetBuffer(), pos, length - pos);
    }
    else
        source.CopyTo((Stream)destination);
}