在WebApi控制器中读取HttpContent

时间:2012-09-19 11:46:27

标签: c# asp.net-mvc asp.net-web-api httpcontent

如何在MVC webApi控制器操作中读取PUT请求中的内容。

[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
    var httpContent = Request.Content;
    var asyncContent = httpContent.ReadAsStringAsync().Result;
...

我在这里得到空字符串:(

我需要做的是:弄清楚在初始请求中修改/发送了什么属性(意味着如果Contact对象有10个属性,并且我只想更新其中的2个,我发送和对象只有两个属性,如下所示:

{

    "FirstName": null,
    "LastName": null,
    "id": 21
}

预期的最终结果是

List<string> modified_properties = {"FirstName", "LastName"}

4 个答案:

答案 0 :(得分:117)

按照设计,ASP.NET Web API中的正文内容被视为只能读取一次的仅向前流。

您的案例中的第一次读取是在Web API绑定模型时完成的,之后Request.Content将不会返回任何内容。

您可以从操作参数中删除contact,获取内容并将其手动反序列化为对象(例如使用Json.NET):

[HttpPut]
public HttpResponseMessage Put(int accountId)
{
    HttpContent requestContent = Request.Content;
    string jsonContent = requestContent.ReadAsStringAsync().Result;
    CONTACT contact = JsonConvert.DeserializeObject<CONTACT>(jsonContent);
    ...
}

应该这样做(假设accountId是URL参数,因此不会将其视为内容读取)。

答案 1 :(得分:18)

您可以使用以下方法保留您的CONTACT参数:

using (var stream = new MemoryStream())
{
    var context = (HttpContextBase)Request.Properties["MS_HttpContext"];
    context.Request.InputStream.Seek(0, SeekOrigin.Begin);
    context.Request.InputStream.CopyTo(stream);
    string requestBody = Encoding.UTF8.GetString(stream.ToArray());
}

为我返回参数对象的json表示,因此我可以将它用于异常处理和日志记录。

找到已接受的答案here

答案 2 :(得分:4)

即使这个解决方案看起来很明显,我只是想在这里发布,以便下一个人能更快地进行谷歌搜索。

如果您仍希望将模型作为方法中的参数,则可以创建DelegatingHandler来缓冲内容。

internal sealed class BufferizingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        await request.Content.LoadIntoBufferAsync();
        var result = await base.SendAsync(request, cancellationToken);
        return result;
    }
}

并将其添加到全局消息处理程序:

configuration.MessageHandlers.Add(new BufferizingHandler());

此解决方案基于answerDarrel Miller

这样就可以缓冲所有请求。

答案 3 :(得分:-6)

阅读任何请求内容的最简单方法通常是使用fiddler之类的http代理

这具有向您显示所有本地流量(加上完整请求 - 标头等)以及在特定控制器中的特定操作内读取请求内容的许多其他请求的巨大优势告诉你 - 例如401/404等。

您还可以使用fiddler的编辑器从头开始创建测试请求或修改以前的请求。

如果由于某种原因无法使用代理或必须从网络应用中查看请求,那么this answer看起来很合理