Подтвердить что ты не робот

Тело запроса чтения в ASP.NET

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

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

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

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

4b9b3361

Ответ 1

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

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

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

Update

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

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

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

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

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

Ответ 2

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

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

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

  • Связка параметров строки запроса GET
  • POST с DTO в теле запроса

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

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

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

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

Ответ 3

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

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

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

Что я перевел на

Request.InputStream.Seek(0,0)

Ответ 4

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

Ответ 5

Прямое чтение из 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);
}