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.
3 Réponses :
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 -
MyControllerBase
[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 { }
Route
, j'ai également supprimé l'attribut [ApiController]
de la classe. Cet attribut force l'utilisateur à utiliser Route
au lieu du routage de carte. 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]
:)
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.
Microsoft.AspNetCore.Mvc.Versioning
Configurer dans Startup.cs
[Route("api/v{version:apiVersion}/[controller]/[action]")] [ApiController] public class ValuesController : ControllerBase { [HttpGet] public IActionResult Hello() { return Ok("Test"); } }
ApiController
services.AddApiVersioning(opt => { opt.DefaultApiVersion = new ApiVersion(1,0); //this is your version v1 });
Url de la demande: https: // localhost: 44369 / api / v1 / values / hello
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
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/";
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 ...