如何获取HttpRequestMessage数据

68

我有一个MVC API控制器,其中包含以下操作。

我不明白如何读取“Message”的实际数据/正文内容?

[HttpPost]
public void Confirmation(HttpRequestMessage request)
{
    var content = request.Content;
}

2
你从 request.Content 中得到什么? - Mansfield
我看到了所有的头部和内容长度,但数据在哪里? - user1615362
你可以在这里查看多个示例:http://www.codingfusion.com/Post/How-to-Get-HttpRequestMessage-Data-in-NET-MVC - MaxPayne
4个回答

94

来自这个答案:

[HttpPost]
public void Confirmation(HttpRequestMessage request)
{
    var content = request.Content;
    string jsonContent = content.ReadAsStringAsync().Result;
}

注意: 正如评论中所述,这段代码可能会导致死锁,不应使用。请参阅此博客文章获取更多详细信息。


2
从开发者的角度来看,如果您想要调试或等待操作完成以查看数据,则使用异步可能不是更好的选择。 - Kurkula
3
请注意,不要在生产环境中使用这段代码,@ToddMenier的评论已经提醒过了。我们曾在代码中使用过它,结果导致了死锁。 - makhdumi
4
为什么这可能导致死锁的详细信息,请参阅:http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html - Thomas Schreiter
1
这不是正确的解决方案。请看@Zebing Lin的答案。 - Miro J.
1
那么应该如何编辑这个答案以避免死锁呢?请更新答案,而不是将读者引用到外部网站。 - Björn Larsson
显示剩余2条评论

31
using System.IO;

string requestFromPost;
using( StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream) )
{
    reader.BaseStream.Position = 0;
    requestFromPost = reader.ReadToEnd();
}

Request.Content 是一个流。根据你的代码运行的时间,该流可能已经被消耗完毕。 - stannius
2
这适用于MVC,而Web Api的被接受答案不同。 - Sel
BaseStream.Position = 0 这句话让我意识到,如果内容被框架吃掉以填充 HttpPost 方法的参数,流可能会被重置。结果也确实如此。谢谢。 - Rangoric
这对我也有效,应该被采纳为答案。 - John Spax

15

我建议您不要像这样操作。行为方法应该设计成易于单元测试。在这种情况下,您不应直接从请求中访问数据,因为如果您这样做,当您想要对该代码进行单元测试时,您必须构造一个HttpRequestMessage

您应该这样做,让MVC为您完成所有模型绑定:

[HttpPost]
public void Confirmation(YOURDTO yourobj)//assume that you define YOURDTO elsewhere
{
        //your logic to process input parameters.

}

如果您确实需要访问请求,您只需访问控制器的 Request 属性(而不是通过参数)。像这样:

[HttpPost]
public void Confirmation()
{
    var content = Request.Content.ReadAsStringAsync().Result;
}
在MVC中,Request属性实际上是一个围绕.NET HttpRequest的包装器,并从一个基类继承而来。当您需要进行单元测试时,也可以模拟此对象。

如果你有 HttpGet 呢?如果我使用 Request.Content.ReadAsStringAsync().Result; 它不起作用! - ayasha
@ayasha:使用HttpGet时,参数应该来自查询字符串而不是请求正文。 - Khanh TO
@ayasha:我也更新了答案。刚意识到之前它没有起作用。 - Khanh TO

3

如果您想转换为一个类而不仅仅是一个字符串:

YourClass model = await request.Content.ReadAsAsync<YourClass>();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接