[英]Read Request Body in ASP.NET
如何读取ASP.NET中的请求主体? 我正在使用Firefox的REST客户端插件为我在本地托管的网站上的资源形成GET请求,而在请求正文中我只是将字符串“test”试图读取它服务器。
在服务器代码(这是一个非常简单的MVC动作)我有这个:
var reader = new StreamReader(Request.InputStream);
var inputString = reader.ReadToEnd();
但是当我调试它时, inputString
总是为空。 我不确定如何(例如在FireBug中)确认请求正文确实正确发送,我想我只是假设附加组件正确地执行了此操作。 也许我读错了价值?
也许我错误地记得我的学业,但我认为GET请求实际上没有一个机构。 这个页面说明 。
HTML规范在技术上定义了“GET”和“POST”之间的区别,因此前者意味着表单数据将被(通过浏览器)编码为URL,而后者意味着表单数据将出现在消息正文中。
所以也许你正在做的事情,但你必须POST数据,以便有一个消息体?
在回应您的评论时,最“正确”的RESTful方式是将每个值作为自己的参数发送:
site.com/MyController/MyAction?id=1&id=2&id=3...
然后,如果您使用相同的名称为其指定数组参数,则您的操作将自动绑定它们:
public ActionResult MyAction(int[] id) {...}
或者如果你是一个受虐狂,你可以尝试一次从Request.QueryString
提取值。
我最近想起了这个老问题,并希望根据我自己工作中最近的实现添加另一个完整性的答案。
作为参考, 我最近在博客上发表了这个主题 。
从本质上讲,这个问题的核心是,“如何将更大,更复杂的搜索条件传递给资源,以获取过滤的对象列表?” 它最终沸腾到两个选择:
第一个选项并不理想,因为实现很难看,并且URL在某些时候可能会超过最大长度。 第二个选项,虽然功能齐全,但并没有让我坐在“RESTful”意义上。 毕竟,我正在获取数据,对吧?
但是,请记住,我不仅仅是获取数据。 我正在创建一个对象列表。 每个对象都已存在,但列表本身不存在。 这是一个全新的事情,通过向服务器上的完整对象存储库发出搜索/过滤条件来创建。 (毕竟,请记住,对象集合本身仍然是一个对象。)
这是纯粹的语义差异,但却是一个非常重要的差异。 因为,最简单的是,这意味着我可以轻松地使用POST将这些搜索条件发布到服务器。 响应是我收到的数据,因此我“获取”数据。 但我并没有“获取”数据,因为我实际上正在执行创建行为,创建一个恰好由预先存在的元素组成的对象列表的新实例。
我完全承认,限制从来都不是技术性的,只是语义上的。 它永远不会和我“坐在一起”。 非技术问题需要非技术解决方案,在这种情况下是语义解决方案。 从稍微不同的语义观点来看问题导致了一个更清晰的解决方案,这恰好是我最终使用的解决方案。
除了GET / POST问题,我确实发现你需要将Request.InputStream位置设置回到开头。 感谢这个答案,我找到了。
特别是评论
Request.InputStream //确保在读取后重置位置或稍后读取可能失败
我把它翻译成了
Request.InputStream.Seek(0,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);
}
我会尝试使用HttpClient(可通过Nuget获得)来做这种事情。 它比System.Net对象容易得多
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.