Dlaczego atrybuty FromBody
i są FromUri
potrzebne w interfejsie ASP.NET Web API?
Jakie są różnice między używaniem atrybutów a ich nieużywaniem?
Dlaczego atrybuty FromBody
i są FromUri
potrzebne w interfejsie ASP.NET Web API?
Jakie są różnice między używaniem atrybutów a ich nieużywaniem?
Odpowiedzi:
Gdy interfejs API sieci Web ASP.NET wywołuje metodę na kontrolerze, musi ustawić wartości parametrów, czyli proces nazywany powiązaniem parametrów .
Domyślnie interfejs API sieci Web używa następujących reguł do powiązania parametrów:
Jeśli parametr jest „prostym” typem , interfejs API sieci Web próbuje pobrać wartość z identyfikatora URI . Typy proste obejmują typy pierwotne .NET (int, bool, double itd.), A także TimeSpan, DateTime, Guid, decimal i string, a także dowolny typ z konwerterem typów, który można konwertować z ciągu.
W przypadku typów złożonych interfejs API sieci Web próbuje odczytać wartość z treści wiadomości przy użyciu programu formatującego typu nośnika.
Jeśli więc chcesz zastąpić powyższe domyślne zachowanie i wymusić odczytanie typu złożonego z identyfikatora URI przez interfejs API sieci Web, dodaj [FromUri]
atrybut do parametru. Aby zmusić interfejs API sieci Web do odczytu prostego typu z treści żądania, dodaj [FromBody]
atrybut do parametru.
Tak więc, aby odpowiedzieć na Twoje pytanie, potrzebą atrybutu [FromBody]
i [FromUri]
w interfejsie API sieci Web jest po prostu zastąpienie, jeśli to konieczne, domyślnego zachowania opisanego powyżej. Zauważ, że możesz użyć obu atrybutów dla metody kontrolera, ale tylko dla różnych parametrów, jak pokazano tutaj .
W internecie jest o wiele więcej informacji, jeśli wpiszesz w google „wiązanie parametrów interfejsu API sieci Web”.
JustGetIt
, który służy temu samemu celowi dodawania wiele atrybutów jak [FromBody, FromQuery]
etc
Domyślne zachowanie to:
Jeżeli parametr jest prymitywny typ ( int
, bool
, double
, ...), próbuje Web API, aby uzyskać wartość z URI żądania HTTP.
W przypadku typów złożonych (na przykład własny obiekt Person
:) interfejs API sieci Web próbuje odczytać wartość z treści żądania HTTP.
Więc jeśli masz:
... wtedy nie musisz dodawać żadnych atrybutów (ani [FromBody]
ani [FromUri]
).
Ale jeśli masz prymitywny typ w organizmie , to trzeba dodać [FromBody]
przed swoim prymitywnym parametru typu w metodzie kontrolera WebAPI. (Ponieważ domyślnie interfejs WebAPI szuka typów pierwotnych w identyfikatorze URI żądania HTTP).
Lub, jeśli masz złożony typ w identyfikatorze URI , musisz dodać [FromUri]
. (Ponieważ domyślnie interfejs WebAPI domyślnie szuka w treści żądania HTTP typów złożonych).
Typy pierwotne:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post([FromBody]int id)
{
}
// api/users/id
public HttpResponseMessage Post(int id)
{
}
}
Złożone typy:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post(User user)
{
}
// api/users/user
public HttpResponseMessage Post([FromUri]User user)
{
}
}
Działa to tak długo, jak długo wysyłasz tylko jeden parametr w żądaniu HTTP. Wysyłając wiele , musisz stworzyć niestandardowy model, który ma wszystkie parametry, takie jak:
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;
}
Z dokumentacji firmy Microsoft dotyczącej wiązania parametrów w ASP.NET Web API :
Gdy parametr ma [FromBody], interfejs API sieci Web używa nagłówka Content-Type do wybrania programu formatującego. W tym przykładzie typ zawartości to „application / json”, a treść żądania to nieprzetworzony ciąg JSON (nie obiekt JSON). Z treści wiadomości można odczytać co najwyżej jeden parametr.
To powinno działać:
public HttpResponseMessage Post([FromBody] string name) { ... }
To nie zadziała:
// Caution: This won't work! public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
Powodem tej reguły jest to, że treść żądania może być przechowywana w niebuforowanym strumieniu, który można odczytać tylko raz.
Tylko dodatek do powyższych odpowiedzi ...
[FromUri] może również służyć do wiązania typów złożonych z parametrów uri zamiast przekazywania parametrów z kwerendy
Dla Ex ...
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) { ... }
}
Można go nazwać:
http://localhost/api/values/47.678558/-122.130989
Gdy parametr ma [FromBody], interfejs API sieci Web używa nagłówka Content-Type do wybrania programu formatującego. W tym przykładzie typ zawartości to „application / json”, a treść żądania to nieprzetworzony ciąg JSON (nie obiekt JSON).
Z treści wiadomości można odczytać co najwyżej jeden parametr. Więc to nie zadziała:
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
Powodem tej reguły jest to, że treść żądania może być przechowywana w niebuforowanym strumieniu, który można odczytać tylko raz
Więcej informacji można znaleźć na stronie internetowej: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api