web-dev-qa-db-fra.com

ASP.net Core RC2 Web API POST - Quand utiliser Create, CreatedAtAction, vs. CreatedAtRoute?

Quelles sont les différences fondamentales de ces fonctions? Tout ce que je sais, c'est que les trois aboutissent à un 201, ce qui est approprié pour une demande POST POST réussie.

Je ne fais que suivre des exemples que je vois en ligne, mais ils n'expliquent pas vraiment pourquoi ils font ce qu'ils font.

Nous sommes censés fournir un nom pour notre GET (1 enregistrement par id):

[HttpGet("{id}", Name="MyStuff")]
public async Task<IActionResult> GetAsync(int id)
{
     return new ObjectResult(new MyStuff(id));
}

Quel est le but de nommer cette fonction get, outre qu'elle est "probablement" requise pour la fonction POST ci-dessous:

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{
     // actual insertion code left out

     return CreatedAtRoute("MyStuff", new { id = myStuff.Id }, myStuff);
}

Je remarque que CreatedAtRoute a également une surcharge qui n'accepte pas le nom de la route.

Il existe également CreatedAtAction qui accepte des paramètres similaires. Pourquoi cette variante existe-t-elle?

Il y a aussi Created qui attend une URL et l'objet que nous voulons retourner. Puis-je simplement utiliser cette variante et fournir une URL fausse et retourner l'objet que je veux et le faire et ainsi de suite?

Je ne sais pas pourquoi il y a tant de variantes juste pour pouvoir retourner un 201 au client. Dans la plupart des cas, tout ce que je veux faire, c'est renvoyer l'ID unique "attribué par l'application" (très probablement à partir d'une base de données) ou une version de mon entité qui contient un minimum d'informations.

Je pense qu'en fin de compte, une réponse 201 "devrait" créer un en-tête d'emplacement qui a l'URL de la ressource nouvellement créée, ce que je crois que les 3 et leurs surcharges finissent par faire. Pourquoi devrais-je toujours retourner un en-tête d'emplacement? Mes clients JavaScript, les applications mobiles natives et les applications de bureau ne l'utilisent jamais. Si j'émets un HTTP POST, par exemple, pour créer des relevés de facturation et les envoyer aux utilisateurs, quelle serait une telle URL de localisation? (Mes excuses pour ne pas avoir approfondi l'histoire d'Internet pour trouver une réponse à cela.)

Pourquoi créer des noms pour les actions et les itinéraires? Quelle est la différence entre les noms d'action et les noms de route?

Je suis confus à ce sujet, j'ai donc eu recours à la fonction Ok(), qui renvoie 200, ce qui est inapproprié pour POST.

38
Mickael Caruso

Il y a ici quelques questions différentes qui devraient probablement être divisées, mais je pense que cela couvre la majeure partie de vos problèmes.

Pourquoi créer des noms pour les actions et les itinéraires? Quelle est la différence entre les noms d'action et les noms de route?

Tout d'abord, les actions et les itinéraires sont très différents.

Une action vit sur un contrôleur. Une route spécifie un point final complet qui se compose d'un contrôleur, d'une action et éventuellement d'autres paramètres de route supplémentaires.

Vous pouvez donner un nom à un itinéraire, ce qui vous permet de le référencer dans votre application. par exemple

routes.MapRoute(
  name: "MyRouteName",
  url: "SomePrefix/{action}/{id}",
  defaults: new { controller = "Section", action = "Index" }
);

La raison des noms d'action est abordée dans cette question: But de ActionName

Il vous permet de commencer votre action avec un nombre ou d'inclure tout caractère que .net n'autorise pas dans un identifiant. - La raison la plus courante est qu'il vous permet d'avoir deux Actions avec la même signature ( voir les actions GET/POST Delete de tout contrôleur échafaudé)

Quelles sont les différences fondamentales de ces fonctions?

Ces 3 fonctions remplissent toutes essentiellement la même fonction - renvoyer un 201 Created réponse, avec un en-tête Location pointant vers l'url de la réponse nouvellement créée et l'objet lui-même dans le corps. L'URL doit être l'URL à laquelle une demande GET retournerait l'URL de l'objet. Cela serait considéré comme le comportement "correct" dans un système RESTful.

Pour l'exemple de code postal dans votre question, vous souhaitez réellement utiliser CreatedAtAction.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
   // actual insertion code left out

   return CreatedAtAction("MyStuff", new { id = myStuff.Id }, myStuff);
}

En supposant que la route par défaut est configurée, cela ajoutera un en-tête Location pointant vers l'action MyStuff sur le même contrôleur.

Si vous souhaitez que l'URL de l'emplacement pointe vers un itinéraire spécifique (comme nous l'avons défini précédemment, vous pouvez utiliser par exemple.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
   // actual insertion code left out

   return CreatedAtRoute("MyRouteName", new { id = myStuff.Id }, myStuff);
}

Puis-je simplement utiliser cette variante et fournir une URL bidon et renvoyer l'objet que je veux et le terminer?

Si vous ne voulez vraiment pas utiliser un CreatedResult, vous pouvez utiliser un simple StatusCodeResult, qui renverra un 201, sans l'en-tête ou le corps Location.

[HttpPost]
public async Task<IActionResult> PostAsync([FromBody]MyStuff myStuff)
{  
  // actual insertion code left out

  return StatusCode(201);
}
40
Sock