19-3 Route imbriquée et contrôleur
REST
On se souvient qu'on essaie lorsque possible de se coller sur le format de routes de type REST
:
Verbe HTTP | Chemin | Controller#Action |
---|---|---|
GET | /controller | controller#Index |
GET | /controller/new | controller#New |
POST | /controller | controller#Create |
GET | /controller/{id} | controller#Show |
GET | /controller/{id}/edit | controller#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.
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!
[Route("evenements/{evenementId:int}/[controller]")]
public class QuestionsController : Controller
{
}
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.
[Route("evenements/{evenementId:int}/[controller]")]
public class QuestionsController : Controller
{
private readonly IQuestionService _questionService;
public QuestionsController(IQuestionService questionService)
{
_questionService = questionService;
}
}