84

MVC webApi コントローラー アクションで PUT 要求の内容を読み取るにはどうすればよいですか。

[HttpPut]
public HttpResponseMessage Put(int accountId, Contact contact)
{
    var httpContent = Request.Content;
    var asyncContent = httpContent.ReadAsStringAsync().Result;
...

ここで空の文字列を取得します:(

私がする必要があるのは、最初のリクエストで「どのプロパティ」が変更/送信されたかを把握することです(つまり、Contactオブジェクトに10個のプロパティがあり、そのうちの2つだけを更新したい場合、2つのプロパティだけでオブジェクトを送信し、このようなもの:

{

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

予想される最終結果は

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

3 に答える 3

155

設計上、ASP.NET Web APIの本文コンテンツは、1回だけ読み取ることができる転送専用ストリームとして扱われます。

あなたの場合の最初の読み取りは、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パラメーターであると仮定すると、コンテンツの読み取りとして扱われません)。

于 2012-09-19T12:32:28.227 に答える
4

この解決策は明白に思えるかもしれませんが、次の人がもっと早くググってくれるように、ここに投稿したかっただけです。

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 Millerによる回答に基づいています。

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

于 2016-09-28T12:56:19.287 に答える