2012-09-19 91 views
46

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

[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"} 

回答

88

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

+0

Thanx。是的,帐户ID是一个网址参数。 – Marty

+1

我不知道是否可以在模型绑定器启动之前创建一个名为LoadIntoBuffer()的请求内容的MessageHandler。 –

+0

@DarrelMiller我不确定ASP.NET Web API是否仍然绑定模型 - 需要测试。 – tpeczek

-5

阅读通常任何请求的内容,最简单的方法是使用HTTP代理像fiddler

这已显示你所有本地流量的巨型的好处(加上完整的请求 - 头等等)和读取特定控制器中特定操作内的请求内容的许多其他请求不会显示给您,例如401/404等

您还可以使用fiddler的作曲家从头创建测试请求或修改以前的请求。

如果您由于某种原因不能使用代理服务器或必须在Web应用程序中查看请求,然后this answer看上去很聪明

11

你可以保持下列方法处理您的联系参数:

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

3

即使这个解决方案似乎是显而易见的,我只是想在这里发布这样下次家伙会更快google一下。

如果您仍希望将模型作为方法中的参数,则可以创建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()); 

该解决方案是基于answer通过Darrel Miller

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

+0

我认为这可能会让我的服务器性能下降......但它可以派上用场。 –