C# 在WebApi控制器中读取HttpContent

C# 在WebApi控制器中读取HttpContent,c#,asp.net-mvc,asp.net-web-api,httpcontent,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; ... 我在这里得到空字符串:( 我需要做的是:找出在初始请求中修改/发送了“哪些属

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

[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
    var httpContent = Request.Content;
    var asyncContent = httpContent.ReadAsStringAsync().Result;
...
我在这里得到空字符串:(

我需要做的是:找出在初始请求中修改/发送了“哪些属性”(这意味着,如果
联系人
对象有10个属性,而我只想更新其中的2个,那么我只发送和发送两个属性的对象,类似这样:

{

    "FirstName": null,
    "LastName": null,
    "id": 21
}
预期的最终结果是

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

通过设计,ASP.NET Web API中的正文内容被视为只能读取一次的仅转发流

案例中的第一次读取是在Web API绑定模型时进行的,之后,
请求将不会返回任何内容

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

[HttpPut]
公共httpresponsemessageput(int accountId)
{
HttpContent requestContent=Request.Content;
字符串jsonContent=requestContent.ReadAsStringAsync().Result;
CONTACT=JsonConvert.DeserializeObject(jsonContent);
...
}

这应该可以做到(假设
accountId
是URL参数,因此它不会被视为内容读取)。

您可以使用以下方法保留联系人参数:

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表示,因此我可以将其用于异常处理和日志记录


被认为是公认的答案

尽管这个解决方案看起来很明显,但我只是想把它贴在这里,这样下一个家伙就能更快地用谷歌搜索它

如果仍然希望将模型作为方法中的参数,可以创建
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;
    }
}
此解决方案基于


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

Thanx。是的,帐户id是一个url参数。我想知道您是否可以创建一个名为LoadIntoBuffer()的MessageHandler在模型绑定器启动之前请求内容。@DarrelMiller我不确定ASP.NET Web API是否仍会绑定模型-需要测试。这会导致死锁吗?@Airn5475,可能会。您应该将操作签名切换为async并使用Wait。我想这可能会影响我的服务器性能…但它可能会派上用场。
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());