2012-09-19 18 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個の特性を持っている場合ことを意味最初の要求(で送信/変更された「何のプロパティ」を見つけ出します

{ 

    "FirstName": null, 
    "LastName": null, 
    "id": 21 
} 

期待される最終結果は

次のとおりです。そして私は、私は、2つのプロパティのみでこのような何かを送信し、オブジェクトをそれらの2つだけを更新したいです

答えて

88

設計上、ASP.NET Web APIの本文コンテンツは、一度だけ読み取れる順方向ストリームとして扱われます。

ウェブAPIがモデルをバインドしているときに初めてが何も返されない場合、最初の読み込みが行われています。

あなたは、あなたのアクションパラメータから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はURLパラメータです。 – Marty

+1

Modelバインディングが実行される前に、リクエストコンテンツにLoadIntoBuffer()を呼び出すMessageHandlerを作成できるかどうかは疑問です。 –

+0

@DarrelMiller ASP.NET Web APIがまだモデルをバインドするかどうかはわかりません。 – tpeczek

-5

すべての要求の内容を読み込むための最も簡単な方法は、通常、あなたすべてローカルトラフィック(プラス完全な要求 - ヘッダなど)を示すの巨大な利点を持っているfiddler

ようなHTTPプロキシを使用することで、特定のコントローラ内の特定のアクションの中でリクエストコンテンツを読んでいる他の多くのリクエストはあなたに表示されません。 401/404など

また、フィドラーの作曲家を使用して、ゼロからテストリクエストを作成したり、以前のリクエストを変更したりすることもできます。

何らかの理由でプロキシを使用することはできませんか、Webアプリケーション内からのリクエストを表示しなければならない場合、this answerあなたは、次のアプローチを使用してCONTACTパラメータを保つことができる賢明な

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

として発見します。

モデルをメソッドのパラメータとして使用する場合は、コンテンツをバッファリングする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 Milleranswerに基づいています。

このようにして、すべてのリクエストがバッファされます。

+0

私はそれが私のサーバーのperfをタンクするかもしれないと思う...しかし、それは便利になる可能性があります。 –

関連する問題