2012-09-19 121 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

我認爲這可能會讓我的服務器性能下降......但它可以派上用場。 –