1
votes

Composez le modèle de route dans le contrôleur AspNetCore.Mvc

Mon contrôleur:

app.UseMvc(routes =>
   {
       routes.MapRoute(name: "api", template: "api/v1/{controller}/{action}/");
   });

Mon startup.cs Configure ():

[Route("Categories")]
[ApiController]
public class CategoriesController : ControllerBase
{
    [HttpGet]
    [Route("My")]
    public string[] My()
    {
        return new[]
        {
            "Is the Microwave working?",
            "Where can i pick the washing machine from?",
        };
    }
}

Cela ne fonctionne que si j'appuie sur l'URL " https: // localhost: 44325 / categories / my "

J'en ai besoin " https: // localhost: 44325 / api / v1 / categories / my ".

Que dois-je définir différemment?

J'ai essayé quelque chose comme l'attribut [Route ("[api] / Categories")] sur le contrôleur pour composer l'itinéraire souhaité, mais cela n'a pas fonctionné ... p>

J'ai:

Les erreurs suivantes se sont produites avec les informations de routage des attributs:

Erreur 1: pour l'action: 'historyAccounts.WebApi.Controllers.CategoriesController.My (historyAccounts.WebApi) 'Erreur: lors du traitement du modèle '[api] / Categories / My', une valeur de remplacement pour le jeton 'api' pourrait pas être trouvé. Jetons disponibles: 'action, contrôleur'. Pour utiliser un '[' ou ']' comme chaîne littérale dans une route ou dans une contrainte, utilisez '[[' ou ']]' à la place.


2 commentaires

n'est-ce pas [Route ("api / v1 / [controller]")]?


Je veux éviter d'écrire "api / v1" explicitement dans chaque contrôleur, car quand viendra le temps de passer à la v2, je devrai tous les mettre à jour ...


3 Réponses :


3
votes

Solution avec routage d'attributs

Au lieu d'utiliser MapRoute dans Startup , créez une classe de base personnalisée -

app.UseMvc(routes =>
{
   routes.MapRoute(name: "api", template: "api/v1/{controller}/{action}/");
});

Maintenant dérivez tous vos contrôleurs de cette classe de base au lieu de ControllerBase -

public class CategoriesController : ControllerBase
{
   [HttpGet]
   public string[] My()
   {
       return new[]
       {
           "Is the Microwave working?",
           "Where can i pick the washing machine from?",
       };
   }
}

De cette façon, toutes vos exigences sont remplies -

  1. Vos informations de version se trouvent au même endroit MyControllerBase
  2. Conservé [ApiController] et donc toutes les fonctionnalités qu'il fournit

Ancienne solution

En fonction de vos besoins, si vous supprimez simplement l'attribut Route de vos contrôleurs, cela devrait fonctionner comme vous le souhaitez vous le voulez -

public class CategoriesController : MyControllerBase
{
    [HttpGet]
    public string[] My()
    {
        return new[]
        {
            "Is the Microwave working?????",
            "Where can i pick the washing machine from?",
        };
    }
}

Garder votre carte d'itinéraire telle quelle -

[Route("api/v1/[controller]/[action]")]
[ApiController]
public class MyControllerBase : ControllerBase { }
  • Si vous remarquez, en plus de supprimer les attributs Route , j'ai également supprimé l'attribut [ApiController] de la classe. Cet attribut force l'utilisateur à utiliser Route au lieu du routage de carte.
  • De plus, le routage d'attributs a son propre avantages . Et comme je l'ai mentionné plus tôt, "En fonction de vos besoins", si vous n'utilisez aucune des fonctionnalités du routage attribué, vous pouvez utiliser cette approche.


4 commentaires

Si je supprime les attrs de route, j'obtiens l'exception "Action '... Mon ()' n'a pas de route d'attribut. Les méthodes d'action sur les contrôleurs annotés avec ApiControllerAttribute doivent être routées par attribut."


@cnom J'ai mis à jour ma réponse, vous devez également supprimer l'attribut [ApiController] .


merci, mais la suppression de l'attribut [ApiController] n'est pas recommandée.


J'ai mis à jour ma réponse avec une meilleure conservation [ApiController] :)



2
votes

Pour la route de conversation MVC et la route d'attribut, la route d'attribut remplacera la route de conversation.

Pour la solution de @Gaurav Mathur, tout le contrôleur devra ajouter api / v1 à la requête url.

En fonction de votre scénario, si vous souhaitez activer la version pour l'API, vous pouvez essayer la fonctionnalité de version de l'API Web au lieu de configurer l'itinéraire dans la converstaion mvc.

  1. Installer le package Microsoft.AspNetCore.Mvc.Versioning
  2. Configurer dans Startup.cs

    [Route("api/v{version:apiVersion}/[controller]/[action]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet]
        public IActionResult Hello()
        {
            return Ok("Test");
        }
    }
    
  3. ApiController

    services.AddApiVersioning(opt => {
        opt.DefaultApiVersion = new ApiVersion(1,0); //this is your version v1
    });
    
  4. Url de la demande: https: // localhost: 44369 / api / v1 / values ​​/ hello


2 commentaires

mais cela ne peut pas couvrir le cas où nous devons renommer la partie "api". c'est-à-dire / myapi / v1


@cnom Si vous préférez changer une autre chaîne statique, veuillez suivre la suggestion de Gaurav Mathur



0
votes

J'ai déjà accepté une réponse précédente, mais une autre approche possible est une constante globale (c'est-à-dire déclarée au démarrage):

[Route(Startup.BaseUrl + "[controller]")]
[ApiController]
public class CategoriesController : ControllerBase

et

public const string BaseUrl = "/api/v1/"; 


0 commentaires