asp.net web api - route - ¿Por qué tenemos que especificar FromBody y FromUri?
web api route name (4)
¿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?
Cuando ASP.NET Web API llama a un método en un controlador, debe establecer valores para los parámetros, un proceso llamado enlace de parámetros .
De manera predeterminada, la API web usa las siguientes reglas para vincular 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.), además de TimeSpan, DateTime, Guid, decimal y string, más cualquier tipo con un convertidor de tipo que puede convertir desde una cadena.
Para tipos complejos , Web API intenta leer el valor del cuerpo del mensaje , utilizando un formateador de tipo de medio.
Por lo tanto, si desea anular el comportamiento predeterminado anterior y forzar que la API web lea un tipo complejo del URI, agregue el atributo [FromUri]
al parámetro. Para obligar a la API web a leer un tipo simple del cuerpo de la solicitud, agregue el atributo [FromBody]
al parámetro.
Entonces, para responder a su pregunta, la necesidad de los [FromBody]
y [FromUri]
en Web API es simplemente anular, si es necesario, el comportamiento predeterminado como se describe arriba. Tenga en cuenta que puede usar ambos atributos para un método de controlador, pero solo para diferentes parámetros, como se demuestra here .
Hay mucha more information en la web si googleas "enlace de parámetro web api".
Cuando un parámetro tiene [FromBody], Web API 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 que un parámetro lea del cuerpo del mensaje. Entonces esto no funcionará
// Caution: Will not work!
public HttpResponseMessage Post([FromBody] int id, [FromBody] string name) { ... }
El motivo de esta regla es que el cuerpo de la solicitud se puede almacenar en una secuencia no protegida que solo se puede leer una vez
Visite el sitio web para obtener más información: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
El comportamiento predeterminado es:
Si el parámetro es un tipo primitivo (
int
,bool
,double
, ...), Web API intenta obtener el valor del URI de la solicitud 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:
- un tipo primitivo en el URI, o
- un tipo complejo en el cuerpo
... entonces no tiene que agregar ningún atributo (ni [FromBody]
ni [FromUri]
).
Pero, si tiene un tipo primitivo en el cuerpo , entonces tiene que 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 bien, si tiene un tipo complejo en su URI , debe agregar [FromUri]
. (Porque, de forma predeterminada, WebAPI busca 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 , necesita crear un modelo personalizado que tenga todos sus parámetros de esta manera:
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 ASP.NET Web API :
Cuando un parámetro tiene [FromBody], Web API 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 que un parámetro lea 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 se puede almacenar en una secuencia no protegida que solo se puede leer una vez.
Solo además de las respuestas anteriores ...
[FromUri] también se puede usar para vincular tipos complejos a partir de parámetros uri en lugar de pasar parámetros desde la cadena de consulta
Por ejemplo ...
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 así:
http://localhost/api/values/47.678558/-122.130989