FromBodyとFromUriを指定する必要があるのはなぜですか?


157

ASP.NET Web APIでFromBodyFromUri属性が必要なのはなぜですか?

属性を使用することと使用しないことの違いは何ですか?


11
[FromBody]アノテーションを使用すると便利な場合のヒントを提供します。たとえば、URL内にエンコードされたパラメーターとしてユーザー名/パスワードなどの静的な資格情報を送信することは不適切です。SSL暗号化により、サードパーティがURL内のパラメーターへの読み取りアクセスを取得できなくなる可能性がありますが、これらの資格情報はブラウザーのログと同等のものに保存される可能性があるため、依然として不適切な方法です。そのような場合、[FromBody]アノテーションを使用して、HTTPメッセージの本文内にパラメーターを強制的に格納し、高値を導入することができます
Chris

回答:


193

ASP.NET Web APIがコントローラーのメソッドを呼び出すとき、パラメーターの値を設定する必要があります。これは、パラメーターバインディングと呼ばれるプロセスです。

デフォルトでは、Web APIは次のルールを使用してパラメーターをバインドします。

  • パラメータが「シンプル」タイプの場合、Web API はURIから値を取得しようとします。単純型には、.NETプリミティブ型(int、bool、doubleなど)、TimeSpan、DateTime、Guid、decimal、string、および文字列から変換できる型コンバーターを備えた任意の型が含まれます。

  • 複合型の場合、Web APIはメディアタイプフォーマッタを使用して、メッセージ本文から値を読み取ろうとします。

したがって、上記のデフォルトの動作をオーバーライドして、Web APIにURIから複合型を読み取らせる場合は、[FromUri]属性をパラメーターに追加します。Web APIにリクエストの本文から単純なタイプを読み取らせるには、[FromBody]属性をパラメーターにします。

したがって、質問に答えるために、Web APIの[FromBody]および[FromUri]属性の必要性は、必要に応じて、上記のデフォルトの動作をオーバーライドすることです。実証されたように、あなたが、唯一異なるパラメータのため、コントローラのメソッドの両方の属性を使用できることに注意してくださいここで

ある多くの より多くの 情報あなたが「結合パラメータのWeb APIを」Googleの場合は、Web上で。


2
@ user3510527:デフォルトの振る舞いに従う限り、使用しない場合はこれらの属性を使用する必要はありません。デフォルトの動作を変更したい場合は、それらを使用する必要があります。
ジカイ14

1
デフォルトの動作をしている場合、なぜovverideが必要なのか、そしてこの属性について言及した場合にどのような利点があるのでしょうか?
Rajneesh 14

1
@ user3510527 オーバーライドする必要ありません。デフォルトの動作をそのまま使用できます。誰かがオーバーライドする可能性がある1つの例は、リクエストの本文に単純な整数を提供したい場合です。これは、デフォルトで、URIでそれを見つけることを期待しているためです。基本的に、必要に応じてデフォルトの動作をそのまま使用することも、オーバーライドすることもできます。これは、単なるオプションです。混乱の意味がわかりません。
ジカイ14

form属性を使用する場合、内部の作業プロセスを知りたいだけなので、直接値が取得され、uriやformbodyはチェックされません...
Rajneesh

7
などのJustGetItように複数の属性を追加する同じ目的に役立つと呼ばれる属性を作成できるかどうか疑問に思います[FromBody, FromQuery]
Muffin Man

93

デフォルトの動作は次のとおりです。

  1. パラメータがある場合は、プリミティブタイプ(intbooldouble、...)、ウェブAPIから値を取得しようとURI HTTPリクエストの。

  2. 複合型(たとえば、独自のオブジェクトPerson)の場合、Web API はHTTPリクエストの本文から値を読み取ろうとします。

だから、あなたが持っているなら:

  • URIのプリミティブ型、または
  • 体内の複合型

...属性を追加する必要はありません([FromBody]また、[FromUri])。

しかし、ボディにプリミティブ型がある場合は、追加する必要があります[FromBody]あなたのWebAPIのコントローラの方法であなたのプリミティブ型パラメータの前に。(デフォルトでは、WebAPIはHTTPリクエストのURIでプリミティブ型を探しているためです。)

あなたが持っている場合は、複合型をあなたにURI、あなたが追加する必要があります[FromUri]。(デフォルトでは、WebAPIはデフォルトでHTTPリクエストの本文で複合型を探しているためです。)

プリミティブタイプ:

public class UsersController : ApiController
{
    // api/users
    public HttpResponseMessage Post([FromBody]int id)
    {

    }
    // api/users/id
    public HttpResponseMessage Post(int id)
    {

    }       
}

複合型:

public class UsersController : ApiController
{       
    // api/users
    public HttpResponseMessage Post(User user)
    {

    }

    // api/users/user
    public HttpResponseMessage Post([FromUri]User user)
    {

    }       
}

これは、HTTPリクエストでパラメータ 1つだけ送信する限り機能します。複数を送信するときは、次のようなすべてのパラメーターを持つカスタムモデルを作成する必要があります。

public class MyModel
{
    public string MyProperty { get; set; }
    public string MyProperty2 { get; set; }
}

[Route("search")]
[HttpPost]
public async Task<dynamic> Search([FromBody] MyModel model)
{
    // model.MyProperty;
    // model.MyProperty2;
}

ASP.NET Web APIのパラメーターバインディングに関するMicrosoftのドキュメントから:

パラメーターに[FromBody]がある場合、Web APIはContent-Typeヘッダーを使用してフォーマッターを選択します。この例では、コンテンツタイプは「application / json」で、リクエストの本文は未加工のJSON文字列です(JSONオブジェクトではありません)。メッセージ本文からの読み取りが許可されているパラメーターは1つだけです。

これはうまくいくはずです:

public HttpResponseMessage Post([FromBody] string name) { ... }

これは機能しません:

// Caution: This won't work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

このルールの理由は、リクエストの本文が、一度だけ読み取ることができるバッファリングされていないストリームに格納される可能性があるためです。


5
「最大で1つのパラメータがメッセージ本文からの読み取りを許可されている」は、特に役立つ情報でした
Ryan

15

上記の答えに加えて..

[FromUri]を使用して、クエリ文字列からパラメーターを渡す代わりに、uriパラメーターから複合型をバインドすることもできます

例:

public class GeoPoint
{
    public double Latitude { get; set; } 
    public double Longitude { get; set; }
}

[RoutePrefix("api/Values")]
public ValuesController : ApiController
{
    [Route("{Latitude}/{Longitude}")]
    public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}

次のように呼び出すことができます:

http://localhost/api/values/47.678558/-122.130989

12

パラメーターに[FromBody]がある場合、Web APIはContent-Typeヘッダーを使用してフォーマッターを選択します。この例では、コンテンツタイプは「application / json」で、リクエストの本文は未加工のJSON文字列です(JSONオブジェクトではありません)。

メッセージ本文からの読み取りが許可されているパラメーターは1つだけです。したがって、これは機能しません:

 // Caution: Will not work!    
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }

このルールの理由は、リクエストの本文がバッファリングされていないストリームに保存される可能性があるためです。

詳細については、Webサイトにアクセスしてください。http//www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.