ASP.NET Web APIでFromBody
とFromUri
属性が必要なのはなぜですか?
属性を使用することと使用しないことの違いは何ですか?
ASP.NET Web APIでFromBody
とFromUri
属性が必要なのはなぜですか?
属性を使用することと使用しないことの違いは何ですか?
回答:
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]
属性の必要性は、必要に応じて、上記のデフォルトの動作をオーバーライドすることです。実証されたように、あなたが、唯一異なるパラメータのため、コントローラのメソッドの両方の属性を使用できることに注意してくださいここで。
JustGetIt
ように複数の属性を追加する同じ目的に役立つと呼ばれる属性を作成できるかどうか疑問に思います[FromBody, FromQuery]
デフォルトの動作は次のとおりです。
パラメータがある場合は、プリミティブタイプ(int
、bool
、double
、...)、ウェブAPIから値を取得しようとURI HTTPリクエストの。
複合型(たとえば、独自のオブジェクトPerson
)の場合、Web API はHTTPリクエストの本文から値を読み取ろうとします。
だから、あなたが持っているなら:
...属性を追加する必要はありません([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) { ... }
このルールの理由は、リクエストの本文が、一度だけ読み取ることができるバッファリングされていないストリームに格納される可能性があるためです。
上記の答えに加えて..
[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
パラメーターに[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