¿Por qué son necesarios los atributos FromBody
y FromUri
en ASP.NET Web API`?
¿Cuáles son las diferencias entre usar los atributos y no usarlos?
¿Por qué son necesarios los atributos FromBody
y FromUri
en ASP.NET Web API`?
¿Cuáles son las diferencias entre usar los atributos y no usarlos?
Respuestas:
Cuando la API web ASP.NET llama a un método en un controlador, debe establecer valores para los parámetros, un proceso llamado enlace de parámetros .
De forma predeterminada, la API web utiliza las siguientes reglas para enlazar parámetros:
Si el parámetro es de tipo "simple" , la API web intenta obtener el valor del URI . Los tipos simples incluyen los tipos primitivos .NET (int, bool, double, etc.), más TimeSpan, DateTime, Guid, decimal y string, más cualquier tipo con un convertidor de tipos que se pueda convertir de una cadena.
Para los tipos complejos , la API web intenta leer el valor del cuerpo del mensaje , utilizando un formateador de tipo multimedia.
Por lo tanto, si desea anular el comportamiento predeterminado anterior y obligar a la API web a leer un tipo complejo del URI, agregue el [FromUri]
atributo al parámetro. Para obligar a la API web a leer un tipo simple del cuerpo de la solicitud, agregue el [FromBody]
atributo al parámetro.
Entonces, para responder a su pregunta, la necesidad de los atributos [FromBody]
y [FromUri]
en la API web es simplemente anular, si es necesario, el comportamiento predeterminado como se describió anteriormente. Tenga en cuenta que puede usar ambos atributos para un método de controlador, pero solo para diferentes parámetros, como se demuestra aquí .
Hay mucha más información en la web si buscas en Google "enlace de parámetros de API web".
JustGetIt
que tenga el mismo propósito de agregar múltiples atributos como [FromBody, FromQuery]
etc.
El comportamiento predeterminado es:
Si el parámetro es un primitivo tipo ( int
, bool
, double
, ...), intentos de API Web para obtener el valor de la URI de la petición HTTP.
Para los tipos complejos (su propio objeto, por ejemplo:) Person
, la API web intenta leer el valor del cuerpo de la solicitud HTTP.
Entonces, si tienes:
... entonces no tiene que agregar ningún atributo (ni [FromBody]
tampoco [FromUri]
).
Pero, si tiene un tipo primitivo en el cuerpo , entonces debe agregar [FromBody]
delante de su parámetro de tipo primitivo en su método de controlador WebAPI. (Porque, de forma predeterminada, WebAPI está buscando tipos primitivos en el URI de la solicitud HTTP).
O, si tiene un tipo complejo en su URI , entonces debe agregar [FromUri]
. (Porque, de forma predeterminada, WebAPI está buscando tipos complejos en el cuerpo de la solicitud HTTP de forma predeterminada).
Tipos primitivos:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post([FromBody]int id)
{
}
// api/users/id
public HttpResponseMessage Post(int id)
{
}
}
Tipos complejos:
public class UsersController : ApiController
{
// api/users
public HttpResponseMessage Post(User user)
{
}
// api/users/user
public HttpResponseMessage Post([FromUri]User user)
{
}
}
Esto funciona siempre que envíe solo un parámetro en su solicitud HTTP. Al enviar múltiples , debe crear un modelo personalizado que tenga todos sus parámetros como este:
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;
}
De la documentación de Microsoft para el enlace de parámetros en la API web ASP.NET :
Cuando un parámetro tiene [FromBody], la API web usa el encabezado Content-Type para seleccionar un formateador. En este ejemplo, el tipo de contenido es "application / json" y el cuerpo de la solicitud es una cadena JSON sin formato (no un objeto JSON). Como máximo, se permite leer un parámetro del cuerpo del mensaje.
Esto debería funcionar:
public HttpResponseMessage Post([FromBody] string name) { ... }
Esto no funcionará:
// Caution: This won't work! public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
El motivo de esta regla es que el cuerpo de la solicitud puede almacenarse en una secuencia no almacenada en el búfer que solo se puede leer una vez.
Solo adición a las respuestas anteriores.
[FromUri] también se puede usar para enlazar tipos complejos a partir de parámetros uri en lugar de pasar parámetros desde la cadena de consulta
Por ej.
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) { ... }
}
Se puede llamar como:
http://localhost/api/values/47.678558/-122.130989
Cuando un parámetro tiene [FromBody], la API web usa el encabezado Content-Type para seleccionar un formateador. En este ejemplo, el tipo de contenido es "application / json" y el cuerpo de la solicitud es una cadena JSON sin formato (no un objeto JSON).
Como máximo, se permite leer un parámetro del cuerpo del mensaje. Entonces esto no funcionará:
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
La razón de esta regla es que el cuerpo de la solicitud puede almacenarse en una secuencia no almacenada en el búfer que solo se puede leer una vez
Visite el sitio web para obtener más detalles: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api