Por que precisamos especificar FromBody e FromUri?

Por que os atributos FromUri e FromUri são necessários na API da Web do ASP.NET?

Quais são as diferenças entre usar os atributos e não usá-los?

Quando o ASP.NET Web API chama um método em um controlador, ele deve definir valores para os parâmetros, um processo chamado binding de parâmetro .

Por padrão, a API da Web usa as seguintes regras para vincular parâmetros:

  • Se o parâmetro for um tipo “simples” , a API da Web tentará obter o valor do URI . Os tipos simples incluem os tipos primitivos do .NET (int, bool, double e assim por diante), além de TimeSpan, DateTime, Guid, decimal e string, além de qualquer tipo com um conversor de tipos que possa converter de uma string.

  • Para tipos complexos , a API da Web tenta ler o valor do corpo da mensagem , usando um formatador do tipo de mídia.

Portanto, se você quiser replace o comportamento padrão acima e forçar a API da Web a ler um tipo complexo do URI, adicione o atributo [FromUri] ao parâmetro. Para forçar a API da Web a ler um tipo simples do corpo da solicitação, adicione o atributo [FromBody] ao parâmetro.

Portanto, para responder à sua pergunta, a necessidade dos [FromBody] e [FromUri] na API da Web é simplesmente replace, se necessário, o comportamento padrão, conforme descrito acima. Observe que você pode usar os dois atributos para um método do controlador, mas apenas para parâmetros diferentes, conforme demonstrado aqui .

Há muito mais informações na web se você usar o google “web api parameter binding”.

O comportamento padrão é:

  1. Se o parâmetro for um tipo primitivo ( int , bool , double , …), a API da Web tentará obter o valor do URI da solicitação HTTP.

  2. Para tipos complexos (seu próprio object, por exemplo: Person ), a API da Web tenta ler o valor do corpo da solicitação HTTP.

Então, se você tem:

  • um tipo primitivo no URI, ou
  • um tipo complexo no corpo

… então você não precisa adicionar nenhum atributo (nem [FromBody] nem [FromUri] ).

Mas, se você tiver um tipo primitivo no corpo , será necessário adicionar [FromBody] à frente do parâmetro de tipo primitivo no método do controlador WebAPI. (Porque, por padrão, o WebAPI está procurando por tipos primitivos no URI da solicitação HTTP.)

Ou, se você tiver um tipo complexo em seu URI , deverá adicionar [FromUri] . (Por padrão, o WebAPI está procurando tipos complexos no corpo da solicitação HTTP por padrão).

Tipos primitivos:

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

Tipos complexos:

 public class UsersController : ApiController { // api/users public HttpResponseMessage Post(User user) { } // api/users/user public HttpResponseMessage Post([FromUri]User user) { } } 

Isso funciona desde que você envie apenas um parâmetro em sua solicitação HTTP. Ao enviar múltiplos , você precisa criar um modelo personalizado que tenha todos os seus parâmetros assim:

 public class MyModel { public string MyProperty { get; set; } public string MyProperty2 { get; set; } } [Route("search")] [HttpPost] public async Task Search([FromBody] MyModel model) { // model.MyProperty; // model.MyProperty2; } 

Da documentação da Microsoft para binding de parâmetros na API da Web do ASP.NET :

Quando um parâmetro tem [FromBody], a API da Web usa o header Content-Type para selecionar um formatador. Neste exemplo, o tipo de conteúdo é “application / json” e o corpo da solicitação é uma string JSON bruta (não um object JSON). No máximo, um parâmetro pode ser lido no corpo da mensagem.

Isso deve funcionar:

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

Isso não funcionará:

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

O motivo dessa regra é que o corpo da solicitação pode ser armazenado em um stream sem buffer que só pode ser lido uma vez.

Quando um parâmetro tem [FromBody], a API da Web usa o header Content-Type para selecionar um formatador. Neste exemplo, o tipo de conteúdo é “application / json” e o corpo da solicitação é uma string JSON bruta (não um object JSON).

No máximo, um parâmetro pode ser lido no corpo da mensagem. Então isso não vai funcionar:

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

O motivo dessa regra é que o corpo da solicitação pode ser armazenado em um stream sem buffer que só pode ser lido uma vez

Por favor, vá até o site para mais detalhes: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Apenas além de respostas acima ..

[FromUri] também pode ser usado para ligar tipos complexos de parâmetros uri em vez de passar parâmetros de querystring

Por 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) { ... } } 

Pode ser chamado como:

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