asp.net-web-api - open - asp.net web api tutorial
ASP.net Core RC2 Web API POST: ¿Cuándo usar Crear, CreatedAtAction, vs. CreatedAtRoute? (1)
Aquí hay algunas preguntas diferentes que probablemente deberían dividirse, pero creo que esto cubre la mayor parte de sus problemas.
¿Por qué crear nombres para acciones y rutas? ¿Cuál es la diferencia entre los nombres de acción y los nombres de ruta?
En primer lugar, las acciones y rutas son muy diferentes.
Una acción vive en un controlador. Una ruta especifica un punto final completo que consiste en un Controlador, y Acción y potencialmente otros parámetros de ruta adicionales.
Puede asignar un nombre a una ruta, lo que le permite consultarla en su aplicación. por ejemplo
routes.MapRoute(
name: "MyRouteName",
url: "SomePrefix/{action}/{id}",
defaults: new { controller = "Section", action = "Index" }
);
El motivo de los nombres de acción se trata en esta pregunta: Propósito de ActionName
Le permite iniciar su acción con un número o incluir cualquier carácter que .net no permita en un identificador. - La razón más común es que le permite tener dos Acciones con la misma firma (vea las acciones de GET / POST Delete de cualquier controlador de andamio)
¿Cuáles son las diferencias fundamentales de esas funciones?
Todas estas 3 funciones realizan esencialmente la misma función: devolver una respuesta 201 Created
, con un encabezado de Location
apunta a la url para la respuesta recién creada y el objeto en sí en el cuerpo. La url debe ser la url en la que una solicitud GET devolvería la url del objeto. Esto se consideraría el comportamiento ''correcto'' en un sistema RESTful.
Para el código de publicación de ejemplo en su pregunta, realmente desearía utilizar CreatedAtAction
.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff);
}
Suponiendo que tiene configurada la ruta predeterminada, esto agregará un encabezado de ubicación que apunta a la acción MyStuff
en el mismo controlador.
Si quisiera que la URL de la ubicación apunte a una ruta específica (como lo definimos anteriormente, podría usar, por ejemplo,
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}
¿Puedo usar esta variante y proporcionar una URL falsa y devolver el objeto que quiero y hacerlo de una vez por todas?
Si realmente no quieres usar un CreatedResult
, puedes usar un simple StatusCodeResult
, que devolverá un 201, sin el encabezado o el cuerpo de la Location
.
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return StatusCode(201);
}
¿Cuáles son las diferencias fundamentales de esas funciones? Lo único que sé es que los tres resultados en un 201, que es apropiado para una solicitud POST exitosa.
Solo sigo los ejemplos que veo en línea, pero en realidad no explican por qué están haciendo lo que están haciendo.
Se supone que debemos proporcionar un nombre para nuestro GET (1 registro por id):
[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
return new ObjectResult(new MyStuff(id));
}
¿Cuál es el propósito de nombrar esta función de obtención, además de que es "probablemente" necesario para la función POST a continuación:
[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
// actual insertion code left out
return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}
CreatedAtRoute
que CreatedAtRoute
también tiene una sobrecarga que no toma el nombre de la ruta.
También hay CreatedAtAction
que toma en parámetros similares. ¿Por qué existe esta variante?
También se Created
que espera una URL y el objeto que queremos devolver. ¿Puedo usar esta variante y proporcionar una URL falsa y devolver el objeto que quiero y hacerlo de una vez por todas?
No estoy seguro de por qué hay tantas variantes para poder devolver un 201 al cliente. En la mayoría de los casos, todo lo que quiero hacer es devolver el ID exclusivo "asignado por la aplicación" (probablemente de una base de datos) o una versión de mi entidad que tenga información mínima.
Creo que en última instancia, una respuesta 201 "debería" crear un encabezado de ubicación que tenga la URL del recurso recién creado, que creo que los 3 y sus sobrecargas terminan haciendo. ¿Por qué siempre debería devolver un encabezado de ubicación? Mis clientes de JavaScript, dispositivos móviles nativos y aplicaciones de escritorio nunca lo usan. Si emito un HTTP POST, por ejemplo, para crear estados de cuenta y enviarlos a los usuarios, ¿cuál sería esa URL de ubicación? (Mis disculpas por no profundizar en la historia de Internet para encontrar una respuesta para esto).
¿Por qué crear nombres para acciones y rutas? ¿Cuál es la diferencia entre los nombres de acción y los nombres de ruta?
Estoy confundido acerca de esto, así que recurrí a devolver el Ok()
, que devuelve 200, lo cual no es apropiado para POST.