在WebApi控制器中读取HttpContent

Mar*_*rty 67 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;
...
Run Code Online (Sandbox Code Playgroud)

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

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

{

    "FirstName": null,
    "LastName": null,
    "id": 21
}
Run Code Online (Sandbox Code Playgroud)

预期的最终结果是

List<string> modified_properties = {"FirstName", "LastName"}
Run Code Online (Sandbox Code Playgroud)

tpe*_*zek 128

根据设计,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);
    ...
}
Run Code Online (Sandbox Code Playgroud)

这应该做的伎俩(假设这accountId是URL参数,所以它不会被视为内容读取).

  • @ Airn5475可能是这样。您应该将动作签名切换为异步并使用await。 (2认同)

Any*_*toe 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());
}
Run Code Online (Sandbox Code Playgroud)

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

在这里找到接受的答案


der*_*asp 5

尽管这个解决方案看起来很明显,但我只是想将其发布在这里,以便下一个人可以更快地用谷歌搜索它。

如果您仍然希望将模型作为方法中的参数,则可以创建一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

configuration.MessageHandlers.Add(new BufferizingHandler());
Run Code Online (Sandbox Code Playgroud)

该解决方案基于Darrel Miller回答

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