84

如何在 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

3 回答 3

155

通过设计,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 参数,因此它不会被视为内容读取)。

于 2012-09-19T12:32:28.227 回答
20

您可以使用以下方法保留您的 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 表示形式,因此我可以将其用于异常处理和日志记录。

在此处找到已接受的答案

于 2016-03-02T17:00:40.833 回答
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());

该解决方案基于Darrel Miller回答

这样所有的请求都会被缓冲。

于 2016-09-28T12:56:19.287 回答