Тело запроса на чтение в ASP.NET - PullRequest
12 голосов
/ 01 сентября 2011

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

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

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

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

Ответы [ 5 ]

4 голосов
/ 01 сентября 2011

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

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

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

Обновление

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

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

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

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

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

2 голосов
/ 11 марта 2014

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

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

По сути, суть этого вопроса заключалась в следующем: «Как я могу передать более крупный и более сложный критерий поиска ресурсу, чтобы получить отфильтрованный список объектов?»И все закончилось двумя вариантами:

  1. Набор параметров строки запроса GET
  2. POST с DTO в теле запроса

Первый вариант не идеален, потому что реализация уродлива и URL-адрес, вероятно, превысит максимальную длину в какой-то момент.Второй вариант, хотя и функциональный, просто не подходил мне в смысле «RESTful».В конце концов, я ПОЛУЧАЮ данных, верно?

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

Это чисто семантическая разница, но безусловно важная.Потому что, проще всего, это означает, что я могу с комфортом использовать POST для выдачи этих критериев поиска на сервер.Ответ - это данные, которые я получаю, поэтому я «получаю» данные.Но я не «ПОЛУЧАЮ» данные в том смысле, что я фактически выполняю акт творения, создавая новый экземпляр списка объектов, который, как оказалось, состоит из уже существующих элементов.

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

1 голос
/ 02 января 2013

Помимо проблемы GET / POST, я обнаружил, что вам нужно установить позицию Request.InputStream обратно в начало.Благодаря этому ответу я нашел.

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

Request.InputStream // убедитесь, что сброс позиции после чтения или последующего чтения может завершиться неудачей

Который я перевел на

Request.InputStream.Seek(0,0)
0 голосов
/ 07 января 2015

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

/*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);
}
0 голосов
/ 01 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...