Aller au contenu principal

19-3 Route imbriquée et contrôleur

Rappel routes REST

On se souvient qu'on essaie lorsque possible de se coller sur le format de routes de type REST:

Verbe HTTPCheminController#Action
GET/controller controller#Index
GET/controller/newcontroller#New
POST/controller controller#Create
GET/controller/{id}controller#Show
GET/controller/{id}/editcontroller#Edit
PATCH/PUT/controller/{id}controller#Update
DELETE/controller/{id} controller#Delete

Il serait tout indiqué pour les questions d'avoir des routes comme:

  • GET /questions/new (formulaire)
  • POST /questions (création)
  • ...

Mais en suivant ce format, comment est-ce qu'on saura pour quel événement on poser la question?

On pourrait essayer de passer une référence au ViewModel associé à chaque fois, mais à l'origine, il nous faut une façon d'établir sur quel événement on ajoute la question.

La même question se pose pour l'utilisateur, mais ce dernier est connecté et son contexte est disponible à l'application en tout temps, donc bien différent.

De plus, imaginez qu'on développe une API et qu'on respecte le format de routes REST... comment est-ce que je fournis le id de l'événement?

On pourrait utiliser un Query string, comme GET /questions/new?evenementId=3 et j'en conviens, cela fonctionne.

Cependant, il existe une autre alternative beaucoup plus descriptive, soit d'utiliser les routes et contrôleurs imbriqués.

On pourrait plutôt définir une route de base comme: /evenements/{evenementId}/questions.

Les questions sont des ressources associées aux événements, ils ne peuvent exister indépendamment, donc cette approche est tout à fait logique. Cela oblige aussi d'avoir un id d'événement pour créer une question puisque la route pour arriver aux questions dépend des événements!

Créer le contrôleur QuestionsController

Dans le projet Web.Mvc, ajoutez un contrôleur dans le dossier Controllers via Add -> Controller.

Nommez ce contrôleur QuestionsController et vous pouvez pour le moment retirer l'action Index créée par défaut.

Snowfall.Web.Mvc/Controllers/QuestionsController.cs
using Microsoft.AspNetCore.Mvc;

namespace Snowfall.Web.Mvc.Controllers;

public class QuestionsController : Controller
{

}

Définir la route imbriquée

Pour définir la route de base du contrôleur, cela n'est pas tellement différent qu'à l'habitude. Cependant, un paramètre de base, soit le id de l'événement, sera inclus dans la route!

Snowfall.Web.Mvc/Controllers/QuestionsController.cs
[Route("evenements/{evenementId:int}/[controller]")]
public class QuestionsController : Controller
{

}
info

Cela aura pour effet de créer la route de base du contrôleur sous la forme: /evenements/{id}/questions

Par exemple, /evenements/3/questions/new.

La route est très descriptive et de cette façon, on obtiendra automatiquement le id de l'événement, car il fait partie de la route! 🎉

Constructeur du contrôleur

Profitons-en pour créer le constructeur du contrôleur afin d'obtenir les dépendances requises. Le contrôleur aura besoin de:

  • QuestionService

Nous aurions aussi pu avoir besoin de UserManager, mais puisque nous avons modifié l'authentification pour qu'elle ajoute des Claims supplémentaires, comme le Id de l'utilisateur, il ne sera pas nécessaire.

Snowfall.Web.Mvc/Controllers/QuestionsController.cs
[Route("evenements/{evenementId:int}/[controller]")]
public class QuestionsController : Controller
{
private readonly IQuestionService _questionService;

public QuestionsController(IQuestionService questionService)
{
_questionService = questionService;
}
}