在ASP.NET中读取请求主体

时间:2011-09-01 18:09:05

标签: asp.net rest httpwebrequest

如何在ASP.NET中读取请求正文?我正在使用Firefox的REST客户端插件为我在本地托管的网站上的资源形成GET请求,而在请求正文中我只是将字符串“test”试图读取它服务器。

在服务器代码中(这是一个非常简单的MVC动作)我有这个:

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

但是当我调试它时,inputString总是空的。我不确定如何(例如在FireBug中)确认请求正文确实正确发送,我想我只是假设附加组件正确地执行了此操作。也许我错误地读了这个值?

5 个答案:

答案 0 :(得分:4)

也许我错误地记住了我的学业,但我认为GET请求实际上没有一个团体。 This page states

  

HTML规范在技术上定义了“GET”和“POST”之间的区别,因此前者意味着表单数据将被(通过浏览器)编码为URL,而后者意味着表单数据将出现在消息体。

所以也许你正确地做事,但你必须发布数据才能有一个消息体?

更新

在回复您的评论时,最“正确”的RESTful方式是将每个值作为自己的参数发送:

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

如果你给它一个相同名称的数组参数,你的动作将自动绑定这些:

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

或者,如果你是一个受虐狂,你可以尝试一次从Request.QueryString中提取一个值。

答案 1 :(得分:2)

我最近想起了这个老问题,并希望根据我自己工作中最近的实现添加另一个完整性的答案。

最近参考I've blogged on the subject

基本上,这个问题的核心是,#34;我如何将更大,更复杂的搜索条件传递给资源以获取过滤的对象列表?"它最终沸腾到两个选择:

  1. 一堆GET查询字符串参数
  2. 请求正文中包含DTO的POST
  3. 第一个选项并不理想,因为实现很难看,并且URL在某些时候可能会超过最大长度。第二种选择,虽然功能齐全,但并没有和我一起坐在" RESTful"感。毕竟,我 GETting 数据,对吧?

    但是,请记住,我只是 GETting数据。我创建对象列表。每个对象都已存在,但列表本身并不存在。它是一个全新的东西,通过向服务器上的完整对象存储库发出搜索/过滤条件来创建。 (毕竟,请记住,对象集合本身仍然是一个对象。)

    它纯粹是语义上的差异,但却是一个非常重要的差异。因为,最简单的是,这意味着我可以轻松地使用POST将这些搜索条件发布到服务器。回复是我收到的数据,所以我得到了#34;数据。但我不是" GETting"我实际上在执行创作行为的意义上的数据,创建了一个恰好由预先存在的元素组成的对象列表的新实例。

    我完全承认这种限制从来都不是技术性的,只是语义上的。它永远不会正确地坐在"与我一起。非技术问题需要非技术解决方案,在这种情况下是语义解决方案。从稍微不同的语义观点来看问题导致了一个更清晰的解决方案,这恰好是我最初使用的解决方案。

答案 2 :(得分:1)

除了GET / POST问题之外,我确实发现您需要将Request.InputStream位置设置回到开头。感谢this answer我找到了。

特别是评论

  

Request.InputStream //确保在读取后重置位置或稍后读取可能失败

我将其翻译成

Request.InputStream.Seek(0,0)

答案 3 :(得分:0)

我会尝试使用HttpClient(可通过Nuget获得)来执行此类操作。它比System.Net对象

容易得多

答案 4 :(得分:0)

从Request.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);
}