Routage vers les actions du contrôleur dans ASP.NET CoreRouting to controller actions in ASP.NET Core

Par Ryan Nowak, Kirk Larkinet Rick AndersonBy Ryan Nowak, Kirk Larkin, and Rick Anderson

Les contrôleurs de ASP.NET Core utilisent l' intergiciel (middleware ) de routage pour faire correspondre les URL des demandes entrantes et les mapper aux actions.ASP.NET Core controllers use the Routing middleware to match the URLs of incoming requests and map them to actions. Itinéraires des modèles :Routes templates:

  • Sont définis dans le code de démarrage ou les attributs.Are defined in startup code or attributes.
  • Décrivez comment les chemins d’URL sont mis en correspondance avec les actions.Describe how URL paths are matched to actions.
  • Sont utilisées pour générer des URL pour les liens.Are used to generate URLs for links. Les liens générés sont généralement retournés dans les réponses.The generated links are typically returned in responses.

Les actions sont soit de façon conventionnelle, soit routées par attribut.Actions are either conventionally-routed or attribute-routed. Le fait de placer un itinéraire sur le contrôleur ou l' action le rend positionné par attribut.Placing a route on the controller or action makes it attribute-routed. Pour plus d’informations, consultez Routage mixte.See Mixed routing for more information.

Ce document :This document:

  • Explique les interactions entre MVC et le routage :Explains the interactions between MVC and routing:
    • Comment les applications MVC classiques utilisent les fonctionnalités de routage.How typical MVC apps make use of routing features.
    • Couvre les deux :Covers both:
    • Consultez routage pour plus d’informations sur le routage avancé.See Routing for advanced routing details.
  • Fait référence au système de routage par défaut ajouté dans ASP.NET Core 3,0, appelé routage de point de terminaison.Refers to the default routing system added in ASP.NET Core 3.0, called endpoint routing. Il est possible d’utiliser des contrôleurs avec la version précédente du routage pour des raisons de compatibilité.It's possible to use controllers with the previous version of routing for compatibility purposes. Pour obtenir des instructions, consultez le Guide de migration 2.2-3.0 .See the 2.2-3.0 migration guide for instructions. Reportez-vous à la version 2,2 de ce document pour obtenir des documents de référence sur le système de routage hérité.Refer to the 2.2 version of this document for reference material on the legacy routing system.

Configurer l’itinéraire conventionnelSet up conventional route

Startup.Configurea généralement un code similaire à ce qui suit lors de l’utilisation du routage conventionnel:Startup.Configure typically has code similar to the following when using conventional routing:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

À l’intérieur de l’appel à UseEndpoints , MapControllerRoute est utilisé pour créer un itinéraire unique.Inside the call to UseEndpoints, MapControllerRoute is used to create a single route. L’itinéraire unique est nommé default route.The single route is named default route. La plupart des applications avec contrôleurs et vues utilisent un modèle de routage similaire à l' default itinéraire.Most apps with controllers and views use a route template similar to the default route. Les API REST doivent utiliser le routage d’attributs.REST APIs should use attribute routing.

Le modèle de routage "{controller=Home}/{action=Index}/{id?}" :The route template "{controller=Home}/{action=Index}/{id?}":

  • Correspond à un chemin d’URL comme/Products/Details/5Matches a URL path like /Products/Details/5

  • Extrait les valeurs d’itinéraire { controller = Products, action = Details, id = 5 } en tokenant le chemin d’accès.Extracts the route values { controller = Products, action = Details, id = 5 } by tokenizing the path. L’extraction des valeurs de route aboutit à une correspondance si l’application possède un contrôleur nommé ProductsController et une Details action :The extraction of route values results in a match if the app has a controller named ProductsController and a Details action:

    public class ProductsController : Controller
    {
        public IActionResult Details(int id)
        {
            return ControllerContext.MyDisplayRouteInfo(id);
        }
    }
    

    MyDisplayRouteInfo est fourni par le package NuGet Rick. docs. Samples. RouteInfo et affiche des informations sur l’itinéraire.MyDisplayRouteInfo is provided by the Rick.Docs.Samples.RouteInfo NuGet package and displays route information.

  • /Products/Details/5le modèle lie la valeur de id = 5 pour définir le id paramètre sur 5 ./Products/Details/5 model binds the value of id = 5 to set the id parameter to 5. Pour plus d’informations, consultez liaison de modèle .See Model Binding for more details.

  • {controller=Home}définit Home comme valeur par défaut controller .{controller=Home} defines Home as the default controller.

  • {action=Index}définit Index comme valeur par défaut action .{action=Index} defines Index as the default action.

  • Le ? caractère dans {id?} définit id comme étant facultatif.The ? character in {id?} defines id as optional.

  • Les paramètres de route par défaut et facultatifs n’ont pas besoin d’être présents dans le chemin d’URL pour qu’une correspondance soit établie.Default and optional route parameters don't need to be present in the URL path for a match. Pour une description détaillée de la syntaxe du modèle de route, consultez Informations de référence sur le modèle de route.See Route Template Reference for a detailed description of route template syntax.

  • Correspond au chemin d’accès de l’URL / .Matches the URL path /.

  • Produit les valeurs de route { controller = Home, action = Index } .Produces the route values { controller = Home, action = Index }.

Les valeurs pour controller et action utilisent les valeurs par défaut.The values for controller and action make use of the default values. idne produit pas de valeur, car il n’existe pas de segment correspondant dans le chemin d’accès de l’URL.id doesn't produce a value since there's no corresponding segment in the URL path. /correspond uniquement s’il existe une HomeController Index action et :/ only matches if there exists a HomeController and Index action:

public class HomeController : Controller
{
  public IActionResult Index() { ... }
}

À l’aide de la définition de contrôleur et du modèle de routage précédents, l' HomeController.Index action est exécutée pour les chemins d’URL suivants :Using the preceding controller definition and route template, the HomeController.Index action is run for the following URL paths:

  • /Home/Index/17
  • /Home/Index
  • /Home
  • /

Le chemin d’accès de l’URL / utilise les Home contrôleurs et l’action du modèle de routage par défaut Index .The URL path / uses the route template default Home controllers and Index action. Le chemin d’accès de l’URL /Home utilise l’action par défaut du modèle de routage Index .The URL path /Home uses the route template default Index action.

La méthode pratique MapDefaultControllerRoute :The convenience method MapDefaultControllerRoute:

endpoints.MapDefaultControllerRoute();

RemplaceReplaces:

endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");

Important

Le routage est configuré à l’aide de et de l' UseRouting UseEndpoints intergiciel (middleware).Routing is configured using the UseRouting and UseEndpoints middleware. Pour utiliser des contrôleurs :To use controllers:

Routage conventionnelConventional routing

Le routage conventionnel est utilisé avec les contrôleurs et les vues.Conventional routing is used with controllers and views. La route default :The default route:

endpoints.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

est un exemple de routage conventionnel.is an example of a conventional routing. Il s’agit du routage conventionnel , car il établit une Convention pour les chemins d’URL :It's called conventional routing because it establishes a convention for URL paths:

  • Le premier segment de chemin d’accès, {controller=Home} , correspond au nom du contrôleur.The first path segment, {controller=Home}, maps to the controller name.
  • Le deuxième segment, {action=Index} , correspond au nom de l' action .The second segment, {action=Index}, maps to the action name.
  • Le troisième segment, {id?} est utilisé pour un facultatif id .The third segment, {id?} is used for an optional id. Le ? dans le {id?} rend facultatif.The ? in {id?} makes it optional. idest utilisé pour mapper à une entité de modèle.id is used to map to a model entity.

À l’aide de cet default itinéraire, le chemin d’accès de l’URL :Using this default route, the URL path:

  • /Products/Listcorrespond à l' ProductsController.List action./Products/List maps to the ProductsController.List action.
  • /Blog/Article/17est mappé à BlogController.Article et en général, le modèle lie le id paramètre à 17./Blog/Article/17 maps to BlogController.Article and typically model binds the id parameter to 17.

Ce mappage :This mapping:

  • Est basé uniquementsur les noms de contrôleur et d' action .Is based on the controller and action names only.
  • N’est pas basé sur des espaces de noms, des emplacements de fichiers sources ou des paramètres de méthode.Isn't based on namespaces, source file locations, or method parameters.

L’utilisation du routage conventionnel avec l’itinéraire par défaut permet de créer l’application sans avoir à trouver un nouveau modèle d’URL pour chaque action.Using conventional routing with the default route allows creating the app without having to come up with a new URL pattern for each action. Pour une application avec des actions de style CRUD , avec cohérence des URL entre les contrôleurs :For an app with CRUD style actions, having consistency for the URLs across controllers:

  • Permet de simplifier le code.Helps simplify the code.
  • Rend l’interface utilisateur plus prévisible.Makes the UI more predictable.

Avertissement

Le id dans le code précédent est défini comme facultatif par le modèle de routage.The id in the preceding code is defined as optional by the route template. Les actions peuvent s’exécuter sans l’ID facultatif fourni dans le cadre de l’URL.Actions can execute without the optional ID provided as part of the URL. En règle générale, lorsque id est omis de l’URL :Generally, whenid is omitted from the URL:

  • ida la valeur 0 par liaison de modèle.id is set to 0 by model binding.
  • Aucune entité n’a été trouvée dans la correspondance de base de données id == 0 .No entity is found in the database matching id == 0.

Le routage d’attributs fournit un contrôle affiné pour rendre l’ID requis pour certaines actions et non pour d’autres.Attribute routing provides fine-grained control to make the ID required for some actions and not for others. Par Convention, la documentation comprend des paramètres facultatifs tels que le id moment où ils sont susceptibles d’apparaître dans une utilisation correcte.By convention, the documentation includes optional parameters like id when they're likely to appear in correct usage.

La plupart des applications doivent choisir un schéma de routage de base et descriptif pour que les URL soient lisibles et explicites.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. La route conventionnelle par défaut {controller=Home}/{action=Index}/{id?} :The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Prend en charge un schéma de routage de base et descriptif.Supports a basic and descriptive routing scheme.
  • Est un point de départ pratique pour les applications basées sur une interface utilisateur.Is a useful starting point for UI-based apps.
  • Est le seul modèle de routage nécessaire pour de nombreuses applications d’interface utilisateur Web.Is the only route template needed for many web UI apps. Pour les applications d’interface utilisateur Web plus volumineuses, un autre itinéraire utilise des zones si tout cela est nécessaire.For larger web UI apps, another route using Areas if frequently all that's needed.

MapControllerRouteet MapAreaRoute :MapControllerRoute and MapAreaRoute :

  • Assigner automatiquement une valeur de commande à leurs points de terminaison en fonction de l’ordre dans lequel ils sont appelés.Automatically assign an order value to their endpoints based on the order they are invoked.

Routage des points de terminaison dans ASP.NET Core 3,0 et versions ultérieures :Endpoint routing in ASP.NET Core 3.0 and later:

  • N’a pas de concept d’itinéraires.Doesn't have a concept of routes.
  • Ne fournit pas de garantie de classement pour l’exécution de l’extensibilité, tous les points de terminaison sont traités à la fois.Doesn't provide ordering guarantees for the execution of extensibility, all endpoints are processed at once.

Activez la journalisation pour voir comment les implémentations de routage intégrées, comme Route, établissent des correspondances avec les requêtes.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Le routage des attributs est expliqué plus loin dans ce document.Attribute routing is explained later in this document.

Plusieurs itinéraires conventionnelsMultiple conventional routes

Vous pouvez ajouter plusieurs itinéraires conventionnels dans UseEndpoints en ajoutant des appels à MapControllerRoute et MapAreaControllerRoute .Multiple conventional routes can be added inside UseEndpoints by adding more calls to MapControllerRoute and MapAreaControllerRoute. Cela permet de définir plusieurs conventions ou d’ajouter des itinéraires conventionnels dédiés à une actionspécifique, par exemple :Doing so allows defining multiple conventions, or to adding conventional routes that are dedicated to a specific action, such as:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

L' blog itinéraire dans le code précédent est un itinéraire conventionnel dédié.The blog route in the preceding code is a dedicated conventional route. Il s’agit d’un itinéraire conventionnel dédié, car :It's called a dedicated conventional route because:

Étant donné que controller et action n’apparaissent pas dans le modèle de routage "blog/{*article}" en tant que paramètres :Because controller and action don't appear in the route template "blog/{*article}" as parameters:

  • Ils peuvent uniquement avoir les valeurs par défaut { controller = "Blog", action = "Article" } .They can only have the default values { controller = "Blog", action = "Article" }.
  • Cet itinéraire est toujours mappé à l’action BlogController.Article .This route always maps to the action BlogController.Article.

/Blog, /Blog/Article et /Blog/{any-string} sont les seuls chemins d’URL qui correspondent à l’itinéraire du blog./Blog, /Blog/Article, and /Blog/{any-string} are the only URL paths that match the blog route.

L’exemple précédent :The preceding example:

  • blogl’itinéraire a une priorité plus élevée pour les correspondances que l' default itinéraire, car il est d’abord ajouté.blog route has a higher priority for matches than the default route because it is added first.
  • Est un exemple de routage de style Slug dans lequel il est courant d’avoir un nom d’article dans le cadre de l’URL.Is and example of Slug style routing where it's typical to have an article name as part of the URL.

Avertissement

Dans ASP.NET Core 3,0 et versions ultérieures, le routage ne suit pas :In ASP.NET Core 3.0 and later, routing doesn't:

  • Définissez un concept appelé itinéraire.Define a concept called a route. UseRoutingAjoute la correspondance d’itinéraire au pipeline de l’intergiciel (middleware).UseRouting adds route matching to the middleware pipeline. L' UseRouting intergiciel examine l’ensemble des points de terminaison définis dans l’application et sélectionne la meilleure correspondance de point de terminaison en fonction de la demande.The UseRouting middleware looks at the set of endpoints defined in the app, and selects the best endpoint match based on the request.
  • Fournir des garanties sur l’ordre d’exécution de l’extensibilité comme IRouteConstraint ou IActionConstraint .Provide guarantees about the execution order of extensibility like IRouteConstraint or IActionConstraint.

Consultez routage pour obtenir des documents de référence sur le routage.See Routing for reference material on routing.

Ordre de routage conventionnelConventional routing order

Le routage conventionnel correspond uniquement à une combinaison d’action et de contrôleur définie par l’application.Conventional routing only matches a combination of action and controller that are defined by the app. Cela vise à simplifier les cas où les itinéraires conventionnels se chevauchent.This is intended to simplify cases where conventional routes overlap. L’ajout d’itinéraires à l’aide de MapControllerRoute , MapDefaultControllerRoute et MapAreaControllerRoute assigne automatiquement une valeur de commande à leurs points de terminaison en fonction de l’ordre dans lequel ils sont appelés.Adding routes using MapControllerRoute, MapDefaultControllerRoute, and MapAreaControllerRoute automatically assign an order value to their endpoints based on the order they are invoked. Les correspondances d’un itinéraire qui apparaît précédemment ont une priorité plus élevée.Matches from a route that appears earlier have a higher priority. Le routage conventionnel est dépendant de l’ordre.Conventional routing is order-dependent. En général, les itinéraires avec des zones doivent être placés plus tôt, car ils sont plus spécifiques que les itinéraires sans zone.In general, routes with areas should be placed earlier as they're more specific than routes without an area. Les itinéraires conventionnels dédiés avec des paramètres d’itinéraire Catch-All comme {*article} peuvent rendre une route trop gourmande, ce qui signifie qu’elle correspond aux URL que vous avez prévues pour être mises en correspondance par d’autres itinéraires.Dedicated conventional routes with catch-all route parameters like {*article} can make a route too greedy, meaning that it matches URLs that you intended to be matched by other routes. Mettez les itinéraires gourmands plus tard dans la table de routage pour empêcher les correspondances gourmandes.Put the greedy routes later in the route table to prevent greedy matches.

Avertissement

Un paramètre catch-all peut faire correspondre les itinéraires de manière incorrecte en raison d’un bogue dans le routage.A catch-all parameter may match routes incorrectly due to a bug in routing. Les applications affectées par ce bogue présentent les caractéristiques suivantes :Apps impacted by this bug have the following characteristics:

  • Un itinéraire de rattrapage, par exemple,{**slug}"A catch-all route, for example, {**slug}"
  • L’itinéraire catch-all ne parvient pas à faire correspondre les demandes auxquelles il doit correspondre.The catch-all route fails to match requests it should match.
  • La suppression d’autres itinéraires rend le fonctionnement de l’itinéraire de rattrapage.Removing other routes makes catch-all route start working.

Consultez les bogues GitHub 18677 et 16579 pour obtenir des exemples de cas qui rencontrent ce bogue.See GitHub bugs 18677 and 16579 for example cases that hit this bug.

Un correctif d’abonnement pour ce bogue est contenu dans .net Core 3.1.301 SDK et versions ultérieures.An opt-in fix for this bug is contained in .NET Core 3.1.301 SDK and later. Le code suivant définit un commutateur interne qui corrige ce bogue :The following code sets an internal switch that fixes this bug:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

Résolution des actions ambiguësResolving ambiguous actions

Lorsque deux points de terminaison correspondent au routage, le routage doit effectuer l’une des opérations suivantes :When two endpoints match through routing, routing must do one of the following:

  • Choisissez le meilleur candidat.Choose the best candidate.
  • Levée d'une exception.Throw an exception.

Par exemple :For example:

    public class Products33Controller : Controller
    {
        public IActionResult Edit(int id)
        {
            return ControllerContext.MyDisplayRouteInfo(id);
        }

        [HttpPost]
        public IActionResult Edit(int id, Product product)
        {
            return ControllerContext.MyDisplayRouteInfo(id, product.name);
        }
    }
}

Le contrôleur précédent définit deux actions qui correspondent :The preceding controller defines two actions that match:

  • Chemin de l’URL/Products33/Edit/17The URL path /Products33/Edit/17
  • Acheminer les données { controller = Products33, action = Edit, id = 17 } .Route data { controller = Products33, action = Edit, id = 17 }.

Il s’agit d’un modèle classique pour les contrôleurs MVC :This is a typical pattern for MVC controllers:

  • Edit(int)affiche un formulaire pour modifier un produit.Edit(int) displays a form to edit a product.
  • Edit(int, Product)traite le formulaire publié.Edit(int, Product) processes the posted form.

Pour résoudre le routage correct :To resolve the correct route:

  • Edit(int, Product)est sélectionné lorsque la requête est HTTP POST .Edit(int, Product) is selected when the request is an HTTP POST.
  • Edit(int)est sélectionné lorsque le verbe http est autre chose.Edit(int) is selected when the HTTP verb is anything else. Edit(int)est généralement appelé via GET .Edit(int) is generally called via GET.

Le HttpPostAttribute , [HttpPost] , est fourni au routage afin qu’il puisse choisir en fonction de la méthode http de la requête.The HttpPostAttribute, [HttpPost], is provided to routing so that it can choose based on the HTTP method of the request. Le HttpPostAttribute fournit Edit(int, Product) une meilleure correspondance que Edit(int) .The HttpPostAttribute makes Edit(int, Product) a better match than Edit(int).

Il est important de comprendre le rôle des attributs comme HttpPostAttribute .It's important to understand the role of attributes like HttpPostAttribute. Des attributs similaires sont définis pour d’autres verbes HTTP.Similar attributes are defined for other HTTP verbs. Dans le cadre d’un routage conventionnel, il est courant que des actions utilisent le même nom d’action lorsqu’elles font partie d’un formulaire d’affichage, envoyer un flux de travail de formulaire.In conventional routing, it's common for actions to use the same action name when they're part of a show form, submit form workflow. Par exemple, consultez examiner les deux méthodes d’action de modification.For example, see Examine the two Edit action methods.

Si le routage ne peut pas choisir un meilleur candidat, une AmbiguousMatchException exception est levée et répertorie les différents points de terminaison correspondants.If routing can't choose a best candidate, an AmbiguousMatchException is thrown, listing the multiple matched endpoints.

Noms de routes conventionnelsConventional route names

Les chaînes "blog" et "default" dans les exemples suivants sont des noms de route conventionnels :The strings "blog" and "default" in the following examples are conventional route names:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

Les noms de routes donnent un nom logique à l’itinéraire.The route names give the route a logical name. L’itinéraire nommé peut être utilisé pour la génération d’URL.The named route can be used for URL generation. L’utilisation d’un itinéraire nommé simplifie la création d’URL lorsque l’ordonnancement des itinéraires peut compliquer la génération d’URL.Using a named route simplifies URL creation when the ordering of routes could make URL generation complicated. Les noms de routes doivent être uniques à l’ensemble de l’application.Route names must be unique application wide.

Noms des itinéraires :Route names:

  • N’ont aucun impact sur la correspondance d’URL ou la gestion des demandes.Have no impact on URL matching or handling of requests.
  • Sont utilisés uniquement pour la génération d’URL.Are used only for URL generation.

Le concept de nom d’itinéraire est représenté dans le routage en tant que IEndpointNameMetadata.The route name concept is represented in routing as IEndpointNameMetadata. Nom de l' itinéraire et nom du point de terminaison:The terms route name and endpoint name:

  • Sont interchangeables.Are interchangeable.
  • Celui qui est utilisé dans la documentation et le code dépend de l’API qui est décrite.Which one is used in documentation and code depends on the API being described.

Routage d’attribut pour les API RESTAttribute routing for REST APIs

Les API REST doivent utiliser le routage d’attributs pour modéliser les fonctionnalités de l’application sous la forme d’un ensemble de ressources où les opérations sont représentées par des verbes HTTP.REST APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs.

Le routage par attributs utilise un ensemble d’attributs pour mapper les actions directement aux modèles de routes.Attribute routing uses a set of attributes to map actions directly to route templates. Le StartUp.Configure code suivant est courant pour une API REST et est utilisé dans l’exemple suivant :The following StartUp.Configure code is typical for a REST API and is used in the next sample:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Dans le code précédent, MapControllers est appelé dans UseEndpoints pour mapper les contrôleurs routés d’attribut.In the preceding code, MapControllers is called inside UseEndpoints to map attribute routed controllers.

Dans l’exemple suivant :In the following example:

  • La Configure méthode précédente est utilisée.The preceding Configure method is used.
  • HomeControllercorrespond à un ensemble d’URL similaires à ce que la route conventionnelle par défaut {controller=Home}/{action=Index}/{id?} correspond.HomeController matches a set of URLs similar to what the default conventional route {controller=Home}/{action=Index}/{id?} matches.
public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

L' HomeController.Index action est exécutée pour tous les chemins d’accès d’URL / ,, /Home /Home/Index ou /Home/Index/3 .The HomeController.Index action is run for any of the URL paths /, /Home, /Home/Index, or /Home/Index/3.

Cet exemple met en évidence une différence de programmation clé entre le routage d’attributs et le routage conventionnel.This example highlights a key programming difference between attribute routing and conventional routing. Le routage des attributs requiert plus d’entrée pour spécifier un itinéraire.Attribute routing requires more input to specify a route. L’itinéraire par défaut conventionnel gère les routes de façon plus succincte.The conventional default route handles routes more succinctly. Toutefois, le routage d’attributs permet et requiert un contrôle précis des modèles de routage qui s’appliquent à chaque action.However, attribute routing allows and requires precise control of which route templates apply to each action.

Avec le routage d’attributs, les noms de contrôleur et d’action ne jouent aucun rôle dans lequel l’action est mise en correspondance, sauf si le remplacement de jeton est utilisé.With attribute routing, the controller and action names play no part in which action is matched, unless token replacement is used. L’exemple suivant correspond aux mêmes URL que l’exemple précédent :The following example matches the same URLs as the previous example:

public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Le code suivant utilise le remplacement de jeton pour action et controller :The following code uses token replacement for action and controller:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("[controller]/[action]")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("[controller]/[action]")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Le code suivant s’applique [Route("[controller]/[action]")] au contrôleur :The following code applies [Route("[controller]/[action]")] to the controller:

[Route("[controller]/[action]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Dans le code précédent, les Index modèles de méthode doivent précéder / ou ~/ atteindre les modèles de routage.In the preceding code, the Index method templates must prepend / or ~/ to the route templates. Les modèles de routes appliqués à une action qui commencent par / ou ~/ ne sont pas combinés avec les modèles de routes appliqués au contrôleur.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.

Pour plus d’informations sur la sélection d’un modèle de routage, consultez priorité des modèles de routage .See Route template precedence for information on route template selection.

Noms de routage réservésReserved routing names

Les mots clés suivants sont des noms de paramètres d’itinéraire réservés lors de l’utilisation de contrôleurs ou de Razor pages :The following keywords are reserved route parameter names when using Controllers or Razor Pages:

  • action
  • area
  • controller
  • handler
  • page

L’utilisation de page comme paramètre d’itinéraire avec routage d’attribut est une erreur courante.Using page as a route parameter with attribute routing is a common error. Cela entraîne un comportement incohérent et confus avec la génération d’URL.Doing that results in inconsistent and confusing behavior with URL generation.

public class MyDemo2Controller : Controller
{
    [Route("/articles/{page}")]
    public IActionResult ListArticles(int page)
    {
        return ControllerContext.MyDisplayRouteInfo(page);
    }
}

Les noms de paramètres spéciaux sont utilisés par la génération d’URL pour déterminer si une opération de génération d’URL fait référence à une Razor page ou à un contrôleur.The special parameter names are used by the URL generation to determine if a URL generation operation refers to a Razor Page or to a Controller.

Modèles de verbe HTTPHTTP verb templates

ASP.NET Core a les modèles de verbe HTTP suivants :ASP.NET Core has the following HTTP verb templates:

Modèles de routageRoute templates

ASP.NET Core contient les modèles d’itinéraire suivants :ASP.NET Core has the following route templates:

Routage d’attribut avec attributs de verbe httpAttribute routing with Http verb attributes

Prenons le contrôleur suivant :Consider the following controller:

[Route("api/[controller]")]
[ApiController]
public class Test2Controller : ControllerBase
{
    [HttpGet]   // GET /api/test2
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int/{id:int}")] // GET /api/test2/int/3
    public IActionResult GetIntProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
    public IActionResult GetInt2Product(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Dans le code précédent :In the preceding code:

  • Chaque action contient l' [HttpGet] attribut, qui limite la correspondance aux requêtes http obtient uniquement.Each action contains the [HttpGet] attribute, which constrains matching to HTTP GET requests only.
  • L' GetProduct action comprend le "{id}" modèle. par conséquent, id est ajouté au "api/[controller]" modèle sur le contrôleur.The GetProduct action includes the "{id}" template, therefore id is appended to the "api/[controller]" template on the controller. Le modèle de méthode est "api/[controller]/"{id}"" .The methods template is "api/[controller]/"{id}"". Par conséquent, cette action correspond uniquement aux demandes d’extraction de pour le formulaire /api/test2/xyz ,, /api/test2/123 /api/test2/{any string} , etc.Therefore this action only matches GET requests of for the form /api/test2/xyz,/api/test2/123,/api/test2/{any string}, etc.
    [HttpGet("{id}")]   // GET /api/test2/xyz
    public IActionResult GetProduct(string id)
    {
       return ControllerContext.MyDisplayRouteInfo(id);
    }
    
  • L' GetIntProduct action contient le "int/{id:int}") modèle.The GetIntProduct action contains the "int/{id:int}") template. La :int partie du modèle limite les id valeurs d’itinéraire aux chaînes qui peuvent être converties en un entier.The :int portion of the template constrains the id route values to strings that can be converted to an integer. Une demande d’accès à /api/test2/int/abc :A GET request to /api/test2/int/abc:
    • Ne correspond pas à cette action.Doesn't match this action.
    • Retourne une erreur 404 introuvable .Returns a 404 Not Found error.
      [HttpGet("int/{id:int}")] // GET /api/test2/int/3
      public IActionResult GetIntProduct(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      
  • L' GetInt2Product action contient {id} dans le modèle, mais ne contraint pas les id valeurs qui peuvent être converties en entier.The GetInt2Product action contains {id} in the template, but doesn't constrain id to values that can be converted to an integer. Une demande d’accès à /api/test2/int2/abc :A GET request to /api/test2/int2/abc:
    • Correspond à cet itinéraire.Matches this route.
    • La liaison de modèle ne peut pas être convertie abc en entier.Model binding fails to convert abc to an integer. Le id paramètre de la méthode est un entier.The id parameter of the method is integer.
    • Retourne une demande 400 incorrecte , car la liaison de modèle n’a pas pu être convertie abc en entier.Returns a 400 Bad Request because model binding failed to convertabc to an integer.
      [HttpGet("int2/{id}")]  // GET /api/test2/int2/3
      public IActionResult GetInt2Product(int id)
      {
          return ControllerContext.MyDisplayRouteInfo(id);
      }
      

Le routage d’attribut peut utiliser des HttpMethodAttribute attributs tels que HttpPostAttribute , HttpPutAttribute et HttpDeleteAttribute .Attribute routing can use HttpMethodAttribute attributes such as HttpPostAttribute, HttpPutAttribute, and HttpDeleteAttribute. Tous les attributs de verbe http acceptent un modèle d’itinéraire.All of the HTTP verb attributes accept a route template. L’exemple suivant montre deux actions qui correspondent au même modèle de routage :The following example shows two actions that match the same route template:

[ApiController]
public class MyProductsController : ControllerBase
{
    [HttpGet("/products3")]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpPost("/products3")]
    public IActionResult CreateProduct(MyProduct myProduct)
    {
        return ControllerContext.MyDisplayRouteInfo(myProduct.Name);
    }
}

Utilisation du chemin d’accès de l’URL /products3 :Using the URL path /products3:

  • L' MyProductsController.ListProducts action s’exécute lorsque le verbe http est GET .The MyProductsController.ListProducts action runs when the HTTP verb is GET.
  • L' MyProductsController.CreateProduct action s’exécute lorsque le verbe http est POST .The MyProductsController.CreateProduct action runs when the HTTP verb is POST.

Lors de la création d’une API REST, il est rare que vous deviez utiliser [Route(...)] sur une méthode d’action, car l’action accepte toutes les méthodes http.When building a REST API, it's rare that you'll need to use [Route(...)] on an action method because the action accepts all HTTP methods. Il est préférable d’utiliser l’attribut de verbe http plus spécifique pour préciser ce que votre API prend en charge.It's better to use the more specific HTTP verb attribute to be precise about what your API supports. Les clients des API REST doivent normalement connaître les chemins et les verbes HTTP qui correspondent à des opérations logiques spécifiques.Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Les API REST doivent utiliser le routage d’attributs pour modéliser les fonctionnalités de l’application sous la forme d’un ensemble de ressources où les opérations sont représentées par des verbes HTTP.REST APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs. Cela signifie que de nombreuses opérations, par exemple, obtenir et poster sur la même ressource logique, utilisent la même URL.This means that many operations, for example, GET and POST on the same logical resource use the same URL. Le routage d’attributs fournit le niveau de contrôle nécessaire pour concevoir avec soin la disposition des points de terminaison publics d’une API.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Dans la mesure où une route d’attribut s’applique à une action spécifique, il est facile de placer les paramètres nécessaires dans la définition du modèle de route.Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. Dans l’exemple suivant, id est obligatoire dans le cadre du chemin d’accès de l’URL :In the following example, id is required as part of the URL path:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

L' Products2ApiController.GetProduct(int) action :The Products2ApiController.GetProduct(int) action:

  • Est exécuté avec un chemin d’URL comme/products2/3Is run with URL path like /products2/3
  • N’est pas exécuté avec le chemin d’accès de l’URL /products2 .Isn't run with the URL path /products2.

L’attribut [Consommed] permet à une action de limiter les types de contenu de demande pris en charge.The [Consumes] attribute allows an action to limit the supported request content types. Pour plus d’informations, consultez définir les types de contenu de demande pris en charge avec l’attribut consomme.For more information, see Define supported request content types with the Consumes attribute.

Consultez Routage pour obtenir une description complète des modèles de routes et des options associées.See Routing for a full description of route templates and related options.

Pour plus d’informations sur [ApiController] , consultez attribut ApiController.For more information on [ApiController], see ApiController attribute.

Nom de l’itinéraireRoute name

Le code suivant définit un nom de routeProducts_List :The following code defines a route name of Products_List:

[ApiController]
public class Products2ApiController : ControllerBase
{
    [HttpGet("/products2/{id}", Name = "Products_List")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Les noms de routes peuvent être utilisés pour générer une URL basée sur une route spécifique.Route names can be used to generate a URL based on a specific route. Noms des itinéraires :Route names:

  • N’ont aucun impact sur le comportement de correspondance d’URL du routage.Have no impact on the URL matching behavior of routing.
  • Sont utilisés uniquement pour la génération d’URL.Are only used for URL generation.

Les noms de routes doivent être unique à l’échelle de l’application.Route names must be unique application-wide.

Comparez le code précédent avec l’itinéraire par défaut conventionnel, qui définit le id paramètre comme facultatif ( {id?} ).Contrast the preceding code with the conventional default route, which defines the id parameter as optional ({id?}). La possibilité de spécifier avec précision les API présente des avantages, tels que l’autorisation /products et la /products/5 distribution à des actions différentes.The ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

Combinaison d’itinéraires d’attributsCombining attribute routes

Pour rendre le routage par attributs moins répétitif, les attributs de route sont combinés avec des attributs de route sur les actions individuelles.To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. Les modèles de routes définis sur le contrôleur sont ajoutés à des modèles de routes sur les actions.Any route templates defined on the controller are prepended to route templates on the actions. Placer un attribut de route sur le contrôleur a pour effet que toutes les actions du contrôleur utilisent le routage par attributs.Placing a route attribute on the controller makes all actions in the controller use attribute routing.

[ApiController]
[Route("products")]
public class ProductsApiController : ControllerBase
{
    [HttpGet]
    public IActionResult ListProducts()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]
    public IActionResult GetProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Dans l'exemple précédent :In the preceding example:

  • Le chemin d’accès de l’URL /products peut correspondreProductsApi.ListProductsThe URL path /products can match ProductsApi.ListProducts
  • Le chemin d’accès de l’URL /products/5 peut correspondre ProductsApi.GetProduct(int) .The URL path /products/5 can match ProductsApi.GetProduct(int).

Ces deux actions correspondent uniquement à HTTP GET , car elles sont marquées avec l' [HttpGet] attribut.Both of these actions only match HTTP GET because they're marked with the [HttpGet] attribute.

Les modèles de routes appliqués à une action qui commencent par / ou ~/ ne sont pas combinés avec les modèles de routes appliqués au contrôleur.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. L’exemple suivant correspond à un ensemble de chemins d’URL similaires à l’itinéraire par défaut.The following example matches a set of URL paths similar to the default route.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]
    [Route("Index")]
    [Route("/")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [Route("About")]
    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Le tableau suivant décrit les [Route] attributs dans le code précédent :The following table explains the [Route] attributes in the preceding code:

AttributAttribute Est combiné avec[Route("Home")]Combines with [Route("Home")] Définit le modèle de routageDefines route template
[Route("")] OuiYes "Home"
[Route("Index")] OuiYes "Home/Index"
[Route("/")] NonNo ""
[Route("About")] OuiYes "Home/About"

Ordre de routage des attributsAttribute route order

Le routage génère une arborescence et met en correspondance tous les points de terminaison simultanément :Routing builds a tree and matches all endpoints simultaneously:

  • Les entrées d’itinéraire se comportent comme si elles étaient placées dans un ordre idéal.The route entries behave as if placed in an ideal ordering.
  • Les itinéraires les plus spécifiques ont une chance de s’exécuter avant les itinéraires plus généraux.The most specific routes have a chance to execute before the more general routes.

Par exemple, un itinéraire d’attribut comme blog/search/{topic} est plus spécifique qu’un itinéraire d’attribut comme blog/{*article} .For example, an attribute route like blog/search/{topic} is more specific than an attribute route like blog/{*article}. L' blog/search/{topic} itinéraire a une priorité plus élevée, par défaut, car il est plus spécifique.The blog/search/{topic} route has higher priority, by default, because it's more specific. En utilisant le routage conventionnel, le développeur est chargé de placer les routes dans l’ordre souhaité.Using conventional routing, the developer is responsible for placing routes in the desired order.

Les routes d’attribut peuvent configurer une commande à l’aide de la Order propriété.Attribute routes can configure an order using the Order property. Tous les attributs d’itinéraire fournis par l’infrastructure incluent Order .All of the framework provided route attributes include Order . Les routes sont traitées selon un ordre croissant de la propriété Order.Routes are processed according to an ascending sort of the Order property. L’ordre par défaut est 0.The default order is 0. La définition d’un itinéraire à l’aide de Order = -1 s’exécute avant les itinéraires qui ne définissent pas de commande.Setting a route using Order = -1 runs before routes that don't set an order. La définition d’un itinéraire à l’aide de Order = 1 s’exécute après l’ordonnancement par défaut.Setting a route using Order = 1 runs after default route ordering.

Évitez de dépendre de Order .Avoid depending on Order. Si l’espace URL d’une application exige que les valeurs d’ordre explicites soient routées correctement, il est probable que les clients soient également déroutants.If an app's URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. En général, le routage des attributs sélectionne l’itinéraire correct avec la correspondance d’URL.In general, attribute routing selects the correct route with URL matching. Si l’ordre par défaut utilisé pour la génération d’URL ne fonctionne pas, l’utilisation d’un nom d’itinéraire comme remplacement est généralement plus simple que l’application de la Order propriété.If the default order used for URL generation isn't working, using a route name as an override is usually simpler than applying the Order property.

Considérez les deux contrôleurs suivants qui définissent la correspondance d’itinéraire /home :Consider the following two controllers which both define the route matching /home:

public class HomeController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult Index(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult About(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}
public class MyDemoController : Controller
{
    [Route("")]
    [Route("Home")]
    [Route("Home/Index")]
    [Route("Home/Index/{id?}")]
    public IActionResult MyIndex(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    [Route("Home/About")]
    [Route("Home/About/{id?}")]
    public IActionResult MyAbout(int? id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

/homeLa demande avec le code précédent lève une exception semblable à la suivante :Requesting /home with the preceding code throws an exception similar to the following:

AmbiguousMatchException: The request matched multiple endpoints. Matches:

 WebMvcRouting.Controllers.HomeController.Index
 WebMvcRouting.Controllers.MyDemoController.MyIndex

OrderL’ajout de à l’un des attributs de route résout l’ambiguïté :Adding Order to one of the route attributes resolves the ambiguity:

[Route("")]
[Route("Home", Order = 2)]
[Route("Home/MyIndex")]
public IActionResult MyIndex()
{
    return ControllerContext.MyDisplayRouteInfo();
}

Avec le code précédent, /home exécute le HomeController.Index point de terminaison.With the preceding code, /home runs the HomeController.Index endpoint. Pour accéder à la MyDemoController.MyIndex requête, /home/MyIndex .To get to the MyDemoController.MyIndex, request /home/MyIndex. Remarque :Note:

  • Le code précédent est un exemple ou une conception de routage médiocre.The preceding code is an example or poor routing design. Il a été utilisé pour illustrer la Order propriété.It was used to illustrate the Order property.
  • La Order propriété ne résout que l’ambiguïté, ce modèle ne peut pas être mis en correspondance.The Order property only resolves the ambiguity, that template cannot be matched. Il serait préférable de supprimer le [Route("Home")] modèle.It would be better to remove the [Route("Home")] template.

Pour plus d’informations sur l’ordre des itinéraires avec les pages Razor , consultez conventions des applications et des itinéraires de routage Razor .See Razor Pages route and app conventions: Route order for information on route order with Razor Pages.

Dans certains cas, une erreur HTTP 500 est retournée avec des itinéraires ambigus.In some cases, an HTTP 500 error is returned with ambiguous routes. Utilisez la journalisation pour voir quels points de terminaison ont provoqué le AmbiguousMatchException .Use logging to see which endpoints caused the AmbiguousMatchException.

Remplacement de jetons dans les modèles de routage [contrôleur], [action], [zone]Token replacement in route templates [controller], [action], [area]

Pour plus de commodité, les itinéraires d’attributs prennent en charge le remplacement de jeton pour les paramètres d’itinéraire réservés en plaçant un jeton dans l’un des éléments suivants :For convenience, attribute routes support token replacement for reserved route parameters by enclosing a token in one of the following:

  • Crochets :[]Square brackets: []
  • Accolades :{}Curly braces: {}

Les jetons [action] , [area] et [controller] sont remplacés par les valeurs du nom d’action, du nom de la zone et du nom de contrôleur de l’action dans laquelle l’itinéraire est défini :The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined:

[Route("[controller]/[action]")]
public class Products0Controller : Controller
{
    [HttpGet]
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }


    [HttpGet("{id}")]
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Dans le code précédent :In the preceding code:

[HttpGet]
public IActionResult List()
{
    return ControllerContext.MyDisplayRouteInfo();
}
  • Correspond/Products0/ListMatches /Products0/List
[HttpGet("{id}")]
public IActionResult Edit(int id)
{
    return ControllerContext.MyDisplayRouteInfo(id);
}
  • Correspond/Products0/Edit/{id}Matches /Products0/Edit/{id}

Le remplacement des jetons se produit à la dernière étape de la création des routes d’attribut.Token replacement occurs as the last step of building the attribute routes. L’exemple précédent se comporte de la même façon que le code suivant :The preceding example behaves the same as the following code:

public class Products20Controller : Controller
{
    [HttpGet("[controller]/[action]")]  // Matches '/Products20/List'
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("[controller]/[action]/{id}")]   // Matches '/Products20/Edit/{id}'
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Si vous lisez ce code dans une langue autre que l’anglais, faites-le nous savoir dans ce numéro de discussion GitHub si vous souhaitez afficher les commentaires de code dans votre langue maternelle.If you are reading this in a language other than English, let us know in this GitHub discussion issue if you'd like to see the code comments in your native language.

Les routes d’attribut peuvent aussi être combinées avec l’héritage.Attribute routes can also be combined with inheritance. Il s’agit d’une puissante combinaison avec le remplacement des jetons.This is powerful combined with token replacement. Le remplacement des jetons s’applique aussi aux noms de routes définis par des routes d’attribut.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")]génère un nom d’itinéraire unique pour chaque action :[Route("[controller]/[action]", Name="[controller]_[action]")]generates a unique route name for each action:

[ApiController]
[Route("api/[controller]/[action]", Name = "[controller]_[action]")]
public abstract class MyBase2Controller : ControllerBase
{
}

public class Products11Controller : MyBase2Controller
{
    [HttpGet]                      // /api/products11/
    public IActionResult List()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    [HttpGet("{id}")]             //    /api/products11/edit/3
    public IActionResult Edit(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Le remplacement des jetons s’applique aussi aux noms de routes définis par des routes d’attribut.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] génère un nom de route unique pour chaque action.generates a unique route name for each action.

Pour faire correspondre le délimiteur littéral de remplacement de jetons [ ou ], placez-le en échappement en répétant le caractère ([[ ou ]]).To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

Utiliser un transformateur de paramètre pour personnaliser le remplacement des jetonsUse a parameter transformer to customize token replacement

Le remplacement des jetons peut être personnalisé à l’aide d’un transformateur de paramètre.Token replacement can be customized using a parameter transformer. Un transformateur de paramètre implémente IOutboundParameterTransformer et transforme la valeur des paramètres.A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. Par exemple, un SlugifyParameterTransformer transformateur de paramètre personnalisé remplace la SubscriptionManagement valeur d’itinéraire par subscription-management :For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management:

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        return Regex.Replace(value.ToString(),
                             "([a-z])([A-Z])",
                             "$1-$2",
                             RegexOptions.CultureInvariant,
                             TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
    }
}

RouteTokenTransformerConvention est une convention de modèle d’application qui :The RouteTokenTransformerConvention is an application model convention that:

  • Applique un transformateur de paramètre à toutes les routes d’attribut dans une application.Applies a parameter transformer to all attribute routes in an application.
  • Personnalise les valeurs de jeton de route d’attribut quand elles sont remplacées.Customizes the attribute route token values as they are replaced.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")]
    public IActionResult ListAll()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

La ListAll méthode précédente correspond à /subscription-management/list-all .The preceding ListAll method matches /subscription-management/list-all.

RouteTokenTransformerConvention est inscrit en tant qu’option dans ConfigureServices.The RouteTokenTransformerConvention is registered as an option in ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews(options =>
    {
        options.Conventions.Add(new RouteTokenTransformerConvention(
                                     new SlugifyParameterTransformer()));
    });
}

Consultez la documentation Web MDN sur Slug pour connaître la définition de Slug.See MDN web docs on Slug for the definition of Slug.

Avertissement

Lorsque vous System.Text.RegularExpressions utilisez pour traiter une entrée non fiable, transmettez un délai d’attente.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Un utilisateur malveillant peut fournir une entrée RegularExpressions pour provoquer une attaque par déni de service.A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. ASP.NET Core les API d’infrastructure RegularExpressions qui utilisent passent un délai d’expiration.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

Plusieurs itinéraires d’attributsMultiple attribute routes

Le routage par attributs prend en charge la définition de plusieurs routes pour atteindre la même action.Attribute routing supports defining multiple routes that reach the same action. L’utilisation la plus courante de ceci est d’imiter le comportement de la route conventionnelle par défaut, comme le montre l’exemple suivant :The most common usage of this is to mimic the behavior of the default conventional route as shown in the following example:

[Route("[controller]")]
public class Products13Controller : Controller
{
    [Route("")]     // Matches 'Products13'
    [Route("Index")] // Matches 'Products13/Index'
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

Le fait de placer plusieurs attributs de route sur le contrôleur signifie que chacun d’eux est combiné avec chacun des attributs de route sur les méthodes d’action :Putting multiple route attributes on the controller means that each one combines with each of the route attributes on the action methods:

[Route("Store")]
[Route("[controller]")]
public class Products6Controller : Controller
{
    [HttpPost("Buy")]       // Matches 'Products6/Buy' and 'Store/Buy'
    [HttpPost("Checkout")]  // Matches 'Products6/Checkout' and 'Store/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Toutes les contraintes d’itinéraire http Verb implémentent IActionConstraint .All the HTTP verb route constraints implement IActionConstraint.

Quand plusieurs attributs d’itinéraire implémentent IActionConstraint sont placés sur une action :When multiple route attributes that implement IActionConstraint are placed on an action:

  • Chaque contrainte d’action est associée au modèle de routage appliqué au contrôleur.Each action constraint combines with the route template applied to the controller.
[Route("api/[controller]")]
public class Products7Controller : ControllerBase
{
    [HttpPut("Buy")]        // Matches PUT 'api/Products7/Buy'
    [HttpPost("Checkout")]  // Matches POST 'api/Products7/Checkout'
    public IActionResult Buy()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

L’utilisation de plusieurs itinéraires sur des actions peut paraître utile et puissante, mais il est préférable de conserver l’espace d’URL de base et bien défini.Using multiple routes on actions might seem useful and powerful, it's better to keep your app's URL space basic and well defined. Utilisez plusieurs itinéraires sur des actions uniquement lorsque cela est nécessaire, par exemple pour prendre en charge les clients existants.Use multiple routes on actions only where needed, for example, to support existing clients.

Spécification facultative de paramètres, de valeurs par défaut et de contraintes pour les routes d’attributSpecifying attribute route optional parameters, default values, and constraints

Les routes d’attribut prennent en charge la même syntaxe inline que les routes conventionnelles pour spécifier des paramètres, des valeurs par défaut et des contraintes facultatifs.Attribute routes support the same inline syntax as conventional routes to specify optional parameters, default values, and constraints.

public class Products14Controller : Controller
{
    [HttpPost("product14/{id:int}")]
    public IActionResult ShowProduct(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

Dans le code précédent, [HttpPost("product/{id:int}")] applique une contrainte d’itinéraire.In the preceding code, [HttpPost("product/{id:int}")] applies a route constraint. L' ProductsController.ShowProduct action est mise en correspondance uniquement par les chemins d’accès d’URL tels que /product/3 .The ProductsController.ShowProduct action is matched only by URL paths like /product/3. La partie de modèle {id:int} de routage limite ce segment à des entiers uniquement.The route template portion {id:int} constrains that segment to only integers.

Pour une description détaillée de la syntaxe du modèle de route, consultez Informations de référence sur le modèle de route.See Route Template Reference for a detailed description of route template syntax.

Attributs d’itinéraire personnalisés à l’aide de IRouteTemplateProviderCustom route attributes using IRouteTemplateProvider

Tous les attributs d’itinéraire implémentent IRouteTemplateProvider .All of the route attributes implement IRouteTemplateProvider. Le runtime ASP.NET Core :The ASP.NET Core runtime:

  • Recherche des attributs sur les classes de contrôleur et les méthodes d’action au démarrage de l’application.Looks for attributes on controller classes and action methods when the app starts.
  • Utilise les attributs qui implémentent IRouteTemplateProvider pour générer le jeu initial d’itinéraires.Uses the attributes that implement IRouteTemplateProvider to build the initial set of routes.

Implémentez IRouteTemplateProvider pour définir des attributs de routage personnalisés.Implement IRouteTemplateProvider to define custom route attributes. Chaque IRouteTemplateProvider vous permet de définir une route avec un modèle, un nom et un ordre de route personnalisés :Each IRouteTemplateProvider allows you to define a single route with a custom route template, order, and name:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
    public string Template => "api/[controller]";
    public int? Order => 2;
    public string Name { get; set; }
}

[MyApiController]
[ApiController]
public class MyTestApiController : ControllerBase
{
    // GET /api/MyTestApi
    [HttpGet]
    public IActionResult Get()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

La Get méthode précédente retourne Order = 2, Template = api/MyTestApi .The preceding Get method returns Order = 2, Template = api/MyTestApi.

Utiliser le modèle d’application pour personnaliser les itinéraires d’attributsUse application model to customize attribute routes

Le modèle d’application :The application model:

  • Est un modèle objet créé au démarrage.Is an object model created at startup.
  • Contient toutes les métadonnées utilisées par ASP.NET Core pour router et exécuter les actions dans une application.Contains all of the metadata used by ASP.NET Core to route and execute the actions in an app.

Le modèle d’application comprend toutes les données collectées à partir des attributs d’itinéraire.The application model includes all of the data gathered from route attributes. Les données des attributs de route sont fournies par l' IRouteTemplateProvider implémentation de.The data from route attributes is provided by the IRouteTemplateProvider implementation. UtiliséesConventions:

  • Peut être écrit pour modifier le modèle d’application afin de personnaliser le comportement du routage.Can be written to modify the application model to customize how routing behaves.
  • Sont lus au démarrage de l’application.Are read at app startup.

Cette section présente un exemple simple de personnalisation du routage à l’aide du modèle d’application.This section shows a basic example of customizing routing using application model. Le code suivant permet aux itinéraires de s’aligner à peu près avec la structure de dossiers du projet.The following code makes routes roughly line up with the folder structure of the project.

public class NamespaceRoutingConvention : Attribute, IControllerModelConvention
{
    private readonly string _baseNamespace;

    public NamespaceRoutingConvention(string baseNamespace)
    {
        _baseNamespace = baseNamespace;
    }

    public void Apply(ControllerModel controller)
    {
        var hasRouteAttributes = controller.Selectors.Any(selector =>
                                                selector.AttributeRouteModel != null);
        if (hasRouteAttributes)
        {
            return;
        }

        var namespc = controller.ControllerType.Namespace;
        if (namespc == null)
            return;
        var template = new StringBuilder();
        template.Append(namespc, _baseNamespace.Length + 1,
                        namespc.Length - _baseNamespace.Length - 1);
        template.Replace('.', '/');
        template.Append("/[controller]/[action]/{id?}");

        foreach (var selector in controller.Selectors)
        {
            selector.AttributeRouteModel = new AttributeRouteModel()
            {
                Template = template.ToString()
            };
        }
    }
}

Le code suivant empêche l' namespace application de la Convention aux contrôleurs qui sont des attributs routés :The following code prevents the namespace convention from being applied to controllers that are attribute routed:

public void Apply(ControllerModel controller)
{
    var hasRouteAttributes = controller.Selectors.Any(selector =>
                                            selector.AttributeRouteModel != null);
    if (hasRouteAttributes)
    {
        return;
    }

Par exemple, le contrôleur suivant n’utilise pas NamespaceRoutingConvention :For example, the following controller doesn't use NamespaceRoutingConvention:

[Route("[controller]/[action]/{id?}")]
public class ManagersController : Controller
{
    // /managers/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        return Content($"Index- template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

La méthode NamespaceRoutingConvention.Apply :The NamespaceRoutingConvention.Apply method:

  • Ne fait rien si le contrôleur est un attribut routé.Does nothing if the controller is attribute routed.
  • Définit le modèle de contrôleurs en fonction de namespace , avec la base namespace supprimée.Sets the controllers template based on the namespace, with the base namespace removed.

Le NamespaceRoutingConvention peut être appliqué dans Startup.ConfigureServices :The NamespaceRoutingConvention can be applied in Startup.ConfigureServices:

namespace My.Application
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews(options =>
            {
                options.Conventions.Add(
                    new NamespaceRoutingConvention(typeof(Startup).Namespace));
            });
        }
        // Remaining code ommitted for brevity.

Considérons, par exemple, le contrôleur suivant :For example, consider the following controller:

using Microsoft.AspNetCore.Mvc;

namespace My.Application.Admin.Controllers
{
    public class UsersController : Controller
    {
        // GET /admin/controllers/users/index
        public IActionResult Index()
        {
            var fullname = typeof(UsersController).FullName;
            var template = 
                ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
            var path = Request.Path.Value;

            return Content($"Path: {path} fullname: {fullname}  template:{template}");
        }

        public IActionResult List(int? id)
        {
            var path = Request.Path.Value;
            return Content($"Path: {path} ID:{id}");
        }
    }
}

Dans le code précédent :In the preceding code:

  • La base namespace est My.Application .The base namespace is My.Application.
  • Le nom complet du contrôleur précédent est My.Application.Admin.Controllers.UsersController .The full name of the preceding controller is My.Application.Admin.Controllers.UsersController.
  • NamespaceRoutingConventionDéfinit le modèle de contrôleurs sur Admin/Controllers/Users/[action]/{id? .The NamespaceRoutingConvention sets the controllers template to Admin/Controllers/Users/[action]/{id?.

NamespaceRoutingConventionPeut également être appliqué en tant qu’attribut sur un contrôleur :The NamespaceRoutingConvention can also be applied as an attribute on a controller:

[NamespaceRoutingConvention("My.Application")]
public class TestController : Controller
{
    // /admin/controllers/test/index
    public IActionResult Index()
    {
        var template = ControllerContext.ActionDescriptor.AttributeRouteInfo?.Template;
        var actionname = ControllerContext.ActionDescriptor.ActionName;
        return Content($"Action- {actionname} template:{template}");
    }

    public IActionResult List(int? id)
    {
        var path = Request.Path.Value;
        return Content($"List- Path:{path}");
    }
}

Routage mixte : routage conventionnel et routage par attributsMixed routing: Attribute routing vs conventional routing

Les applications ASP.NET Core peuvent combiner l’utilisation du routage conventionnel et du routage des attributs.ASP.NET Core apps can mix the use of conventional routing and attribute routing. Il est courant d’utiliser des routes conventionnelles pour les contrôleurs délivrant des pages HTML pour les navigateurs, et le routage par attributs pour les contrôleurs délivrant des API REST.It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

Les actions sont routées de façon conventionnelle ou routées par attribut.Actions are either conventionally routed or attribute routed. Le fait de placer une route sur le contrôleur ou sur l’action les rend « routés par attribut ».Placing a route on the controller or the action makes it attribute routed. Les actions qui définissent des routes d’attribut ne sont pas accessibles via les routes conventionnelles et vice versa.Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Tout attribut de route sur le contrôleur effectue toutes les actions dans l’attribut de contrôleur routé.Any route attribute on the controller makes all actions in the controller attribute routed.

Le routage des attributs et le routage conventionnel utilisent le même moteur de routage.Attribute routing and conventional routing use the same routing engine.

Génération d’URL et valeurs ambiantesURL Generation and ambient values

Les applications peuvent utiliser les fonctionnalités de génération d’URL de routage pour générer des liens URL vers des actions.Apps can use routing URL generation features to generate URL links to actions. La génération d’URL élimine le codage en dur des URL, ce qui rend le code plus robuste et plus facile à gérer.Generating URLs eliminates hardcoding URLs, making code more robust and maintainable. Cette section se concentre sur les fonctionnalités de génération d’URL fournies par MVC et couvre uniquement les notions de base du fonctionnement de la génération d’URL.This section focuses on the URL generation features provided by MVC and only cover basics of how URL generation works. Pour une description détaillée de la génération d’URL, consultez Routage.See Routing for a detailed description of URL generation.

L' IUrlHelper interface est l’élément sous-jacent de l’infrastructure entre MVC et le routage pour la génération d’URL.The IUrlHelper interface is the underlying element of infrastructure between MVC and routing for URL generation. Une instance de IUrlHelper est disponible via la Url propriété dans les contrôleurs, les vues et les composants de vue.An instance of IUrlHelper is available through the Url property in controllers, views, and view components.

Dans l’exemple suivant, l' IUrlHelper interface est utilisée par le biais de la Controller.Url propriété pour générer une URL vers une autre action.In the following example, the IUrlHelper interface is used through the Controller.Url property to generate a URL to another action.

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

Si l’application utilise l’itinéraire conventionnel par défaut, la valeur de la url variable est la chaîne de chemin d’URL /UrlGeneration/Destination .If the app is using the default conventional route, the value of the url variable is the URL path string /UrlGeneration/Destination. Ce chemin d’URL est créé par le routage en combinant :This URL path is created by routing by combining:

  • Valeurs d’itinéraire de la requête actuelle, qui sont appelées valeurs ambiantes.The route values from the current request, which are called ambient values.
  • Valeurs passées à Url.Action et substituant ces valeurs dans le modèle de routage :The values passed to Url.Action and substituting those values into the route template:
ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

La valeur de chaque paramètre de route du modèle de route est remplacée en établissant une correspondance avec les valeurs et les valeurs ambiantes.Each route parameter in the route template has its value substituted by matching names with the values and ambient values. Un paramètre d’itinéraire qui n’a pas de valeur peut :A route parameter that doesn't have a value can:

  • Utilisez une valeur par défaut s’il en a une.Use a default value if it has one.
  • Être ignoré s’il est facultatif.Be skipped if it's optional. Par exemple, id à partir du modèle de routage {controller}/{action}/{id?} .For example, the id from the route template {controller}/{action}/{id?}.

La génération d’URL échoue si un paramètre d’itinéraire requis n’a pas de valeur correspondante.URL generation fails if any required route parameter doesn't have a corresponding value. Si la génération d’URL échoue pour une route, la route suivante est essayée, ceci jusqu’à ce que toutes les routes aient été essayées ou qu’une correspondance soit trouvée.If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

L’exemple précédent de Url.Action suppose un routage conventionnel.The preceding example of Url.Action assumes conventional routing. La génération d’URL fonctionne de la même manière avec le routage des attributs, bien que les concepts soient différents.URL generation works similarly with attribute routing, though the concepts are different. Avec routage conventionnel :With conventional routing:

  • Les valeurs de route sont utilisées pour développer un modèle.The route values are used to expand a template.
  • Les valeurs de route pour controller et action apparaissent généralement dans ce modèle.The route values for controller and action usually appear in that template. Cela fonctionne parce que les URL mises en correspondance par le routage adhèrent à une convention.This works because the URLs matched by routing adhere to a convention.

L’exemple suivant utilise le routage d’attributs :The following example uses attribute routing:

public class UrlGenerationAttrController : Controller
{
    [HttpGet("custom")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination()
    {
       return ControllerContext.MyDisplayRouteInfo();
    }
}

L' Source action dans le code précédent génère custom/url/to/destination .The Source action in the preceding code generates custom/url/to/destination.

LinkGeneratora été ajouté dans ASP.NET Core 3,0 comme alternative à IUrlHelper .LinkGenerator was added in ASP.NET Core 3.0 as an alternative to IUrlHelper. LinkGeneratoroffre des fonctionnalités similaires mais plus flexibles.LinkGenerator offers similar but more flexible functionality. Chaque méthode sur IUrlHelper a également une famille de méthodes correspondante LinkGenerator .Each method on IUrlHelper has a corresponding family of methods on LinkGenerator as well.

Génération des URL par nom d’actionGenerating URLs by action name

URL. action, LinkGenerator. GetPathByActionet toutes les surcharges associées sont toutes conçues pour générer le point de terminaison cible en spécifiant un nom de contrôleur et un nom d’action.Url.Action, LinkGenerator.GetPathByAction, and all related overloads all are designed to generate the target endpoint by specifying a controller name and action name.

Lors de l’utilisation Url.Action de, les valeurs d’itinéraire actuelles pour controller et action sont fournies par le Runtime :When using Url.Action, the current route values for controller and action are provided by the runtime:

  • La valeur de controller et action font partie des valeurs et valeurs ambiantes .The value of controller and action are part of both ambient values and values. La méthode Url.Action utilise toujours les valeurs actuelles de action et controller et génère un chemin d’accès d’URL qui achemine vers l’action actuelle.The method Url.Action always uses the current values of action and controller and generates a URL path that routes to the current action.

Le routage tente d’utiliser les valeurs des valeurs ambiantes pour renseigner les informations qui n’ont pas été fournies lors de la génération d’une URL.Routing attempts to use the values in ambient values to fill in information that wasn't provided when generating a URL. Prenons l’exemple d’un itinéraire {a}/{b}/{c}/{d} avec des valeurs ambiantes { a = Alice, b = Bob, c = Carol, d = David } :Consider a route like {a}/{b}/{c}/{d} with ambient values { a = Alice, b = Bob, c = Carol, d = David }:

  • Le routage dispose de suffisamment d’informations pour générer une URL sans aucune valeur supplémentaire.Routing has enough information to generate a URL without any additional values.
  • Le routage a suffisamment d’informations, car tous les paramètres d’itinéraire ont une valeur.Routing has enough information because all route parameters have a value.

Si la valeur { d = Donovan } est ajoutée :If the value { d = Donovan } is added:

  • La valeur { d = David } est ignorée.The value { d = David } is ignored.
  • Le chemin d’URL généré est Alice/Bob/Carol/Donovan .The generated URL path is Alice/Bob/Carol/Donovan.

Avertissement: les chemins d’accès d’URL sont hiérarchiques.Warning: URL paths are hierarchical. Dans l’exemple précédent, si la valeur { c = Cheryl } est ajoutée :In the preceding example, if the value { c = Cheryl } is added:

  • Les deux valeurs { c = Carol, d = David } sont ignorées.Both of the values { c = Carol, d = David } are ignored.
  • Il n’y a plus de valeur pour d et la génération d’URL échoue.There is no longer a value for d and URL generation fails.
  • Les valeurs souhaitées de c et d doivent être spécifiées pour générer une URL.The desired values of c and d must be specified to generate a URL.

Vous pouvez vous attendre à rencontrer ce problème avec l’itinéraire par défaut {controller}/{action}/{id?} .You might expect to hit this problem with the default route {controller}/{action}/{id?}. Ce problème est rare dans la pratique, car Url.Action spécifie toujours explicitement une controller action valeur et.This problem is rare in practice because Url.Action always explicitly specifies a controller and action value.

Plusieurs surcharges d' URL. action acceptent un objet de valeurs d’itinéraire pour fournir des valeurs pour les paramètres de routage autres que controller et action .Several overloads of Url.Action take a route values object to provide values for route parameters other than controller and action. L’objet de valeurs d’itinéraire est fréquemment utilisé avec id .The route values object is frequently used with id. Par exemple : Url.Action("Buy", "Products", new { id = 17 }).For example, Url.Action("Buy", "Products", new { id = 17 }). Objet de valeurs d’itinéraire :The route values object:

  • Par Convention, est généralement un objet de type anonyme.By convention is usually an object of anonymous type.
  • Il peut s’agir d’un IDictionary<> ou d’un poco).Can be an IDictionary<> or a POCO).

Toutes les valeurs de route supplémentaires qui ne correspondent pas aux paramètres de route sont placées dans la chaîne de requête.Any additional route values that don't match route parameters are put in the query string.

public IActionResult Index()
{
    var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
    return Content(url);
}

Le code précédent génère /Products/Buy/17?color=red .The preceding code generates /Products/Buy/17?color=red.

Le code suivant génère une URL absolue :The following code generates an absolute URL:

public IActionResult Index2()
{
    var url = Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme);
    // Returns https://localhost:5001/Products/Buy/17
    return Content(url);
}

Pour créer une URL absolue, utilisez l’une des options suivantes :To create an absolute URL, use one of the following:

Générer des URL par itinéraireGenerate URLs by route

Le code précédent a démontré la génération d’une URL en passant le nom du contrôleur et de l’action.The preceding code demonstrated generating a URL by passing in the controller and action name. IUrlHelperfournit également la famille de méthodes URL. RouteUrl .IUrlHelper also provides the Url.RouteUrl family of methods. Ces méthodes sont similaires à URL. action, mais elles ne copient pas les valeurs actuelles de action et controller vers les valeurs de route.These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. L’utilisation la plus courante de Url.RouteUrl :The most common usage of Url.RouteUrl:

  • Spécifie un nom d’itinéraire pour générer l’URL.Specifies a route name to generate the URL.
  • Ne spécifie généralement pas un nom de contrôleur ou d’action.Generally doesn't specify a controller or action name.
public class UrlGeneration2Controller : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route");
        return ControllerContext.MyDisplayRouteInfo("", $" URL = {url}");
    }

    [HttpGet("custom/url/to/destination2", Name = "Destination_Route")]
    public IActionResult Destination()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

Le Razor fichier suivant génère un lien HTML vers Destination_Route :The following Razor file generates an HTML link to the Destination_Route:

<h1>Test Links</h1>

<ul>
    <li><a href="@Url.RouteUrl("Destination_Route")">Test Destination_Route</a></li>
</ul>

Générer des URL en HTML etRazorGenerate URLs in HTML and Razor

IHtmlHelperfournit les HtmlHelper méthodes html. BeginForm et html. ActionLink pour générer <form> des <a> éléments et respectivement.IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. Ces méthodes utilisent la méthode URL. action pour générer une URL et elles acceptent des arguments similaires.These methods use the Url.Action method to generate a URL and they accept similar arguments. Les pendants de Url.RouteUrl pour HtmlHelper sont Html.BeginRouteForm et Html.RouteLink, qui ont des fonctionnalités similaires.The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

Les TagHelpers génèrent des URL via le TagHelper form et le TagHelper <a>.TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. Ils utilisent tous les deux IUrlHelper pour leur implémentation.Both of these use IUrlHelper for their implementation. Pour plus d’informations, consultez tag Helpers in Forms .See Tag Helpers in forms for more information.

Dans les vues, IUrlHelper est disponible via la propriété Url pour toute génération d’URL ad hoc non couverte par ce qui figure ci-dessus.Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

Génération d’URL dans les résultats d’actionURL generation in Action Results

Les exemples précédents ont montré l’utilisation IUrlHelper de dans un contrôleur.The preceding examples showed using IUrlHelper in a controller. L’utilisation la plus courante dans un contrôleur consiste à générer une URL dans le cadre d’un résultat d’action.The most common usage in a controller is to generate a URL as part of an action result.

Les classes de base ControllerBase et Controller fournissent des méthodes pratiques pour les résultats d’action qui référencent une autre action.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. Une utilisation classique consiste à effectuer une redirection après avoir accepté l’entrée d’utilisateur :One typical usage is to redirect after accepting user input:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        ViewData["Message"] = $"Successful edit of customer {id}";
        return RedirectToAction("Index");
    }
    return View(customer);
}

Les méthodes de fabrique des résultats d’action, telles que RedirectToAction et, CreatedAtAction suivent un modèle similaire aux méthodes sur IUrlHelper .The action results factory methods such as RedirectToAction and CreatedAtAction follow a similar pattern to the methods on IUrlHelper.

Cas spécial pour les routes conventionnelles dédiéesSpecial case for dedicated conventional routes

Le routage conventionnel peut utiliser un type spécial de définition d’itinéraire appelé itinéraire conventionnel dédié.Conventional routing can use a special kind of route definition called a dedicated conventional route. Dans l’exemple suivant, l’itinéraire nommé blog est une route conventionnelle dédiée :In the following example, the route named blog is a dedicated conventional route:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "blog",
                pattern: "blog/{*article}",
                defaults: new { controller = "Blog", action = "Article" });
    endpoints.MapControllerRoute(name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
});

À l’aide des définitions d’itinéraire précédentes, Url.Action("Index", "Home") génère le chemin d’accès de l’URL / à l’aide de l' default itinéraire, mais pourquoi ?Using the preceding route definitions, Url.Action("Index", "Home") generates the URL path / using the default route, but why? Vous pouvez deviner que les valeurs de route { controller = Home, action = Index } seraient suffisantes pour générer une URL avec blog, et que le résultat serait /blog?action=Index&controller=Home.You might guess the route values { controller = Home, action = Index } would be enough to generate a URL using blog, and the result would be /blog?action=Index&controller=Home.

Les itinéraires conventionnels dédiés s’appuient sur un comportement spécial des valeurs par défaut qui n’ont pas de paramètre de routage correspondant qui empêche l’itinéraire d’être trop gourmand en génération d’URL.Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being too greedy with URL generation. Dans ce cas, les valeurs par défaut sont { controller = Blog, action = Article }, et ni controller ni action n’apparaissent comme paramètre de route.In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. Quand le routage effectue une génération d’URL, les valeurs fournies doivent correspondre aux valeurs par défaut.When routing performs URL generation, the values provided must match the default values. La génération d’URL avec blog échoue car les valeurs { controller = Home, action = Index } ne correspondent pas { controller = Blog, action = Article } .URL generation using blog fails because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. Le routage essaye alors d’utiliser default, ce qui réussit.Routing then falls back to try default, which succeeds.

Zones (Areas)Areas

Les zones sont une fonctionnalité MVC utilisée pour organiser les fonctionnalités associées dans un groupe sous la forme d’un groupe distinct :Areas are an MVC feature used to organize related functionality into a group as a separate:

  • Espace de noms de routage pour les actions du contrôleur.Routing namespace for controller actions.
  • Structure de dossiers pour les vues.Folder structure for views.

L’utilisation de zones permet à une application d’avoir plusieurs contrôleurs portant le même nom, à condition qu’ils aient des zones différentes.Using areas allows an app to have multiple controllers with the same name, as long as they have different areas. L’utilisation de zones crée une hiérarchie qui permet le routage par ajout d’un autre paramètre de route, area, à controller et à action.Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. Cette section explique comment le routage interagit avec les zones.This section discusses how routing interacts with areas. Pour plus d’informations sur la façon dont les zones sont utilisées avec les vues, consultez zones .See Areas for details about how areas are used with views.

L’exemple suivant configure MVC pour utiliser l’itinéraire conventionnel par défaut et un area itinéraire pour un area nommé Blog :The following example configures MVC to use the default conventional route and an area route for an area named Blog:

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
    endpoints.MapControllerRoute("default_route", "{controller}/{action}/{id?}");
});

Dans le code précédent, MapAreaControllerRoute est appelé pour créer le "blog_route" .In the preceding code, MapAreaControllerRoute is called to create the "blog_route". Le deuxième paramètre, "Blog" , est le nom de la zone.The second parameter, "Blog", is the area name.

En cas de correspondance avec un chemin d’URL comme /Manage/Users/AddUser , l' "blog_route" itinéraire génère les valeurs d’itinéraire { area = Blog, controller = Users, action = AddUser } .When matching a URL path like /Manage/Users/AddUser, the "blog_route" route generates the route values { area = Blog, controller = Users, action = AddUser }. La area valeur de route est produite par une valeur par défaut pour area .The area route value is produced by a default value for area. L’itinéraire créé par MapAreaControllerRoute est équivalent à ce qui suit :The route created by MapAreaControllerRoute is equivalent to the following:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute("blog_route", "Manage/{controller}/{action}/{id?}",
        defaults: new { area = "Blog" }, constraints: new { area = "Blog" });
    endpoints.MapControllerRoute("default_route", "{controller}/{action}/{id?}");
});

MapAreaControllerRoute crée une route avec à la fois une valeur par défaut et une contrainte pour area en utilisant le nom de la zone fournie, dans ce cas Blog.MapAreaControllerRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. La valeur par défaut garantit que la route produit toujours { area = Blog, ... }, et la contrainte nécessite la valeur { area = Blog, ... } pour la génération d’URL.The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

Le routage conventionnel est dépendant de l’ordre.Conventional routing is order-dependent. En général, les itinéraires avec des zones doivent être placés plus tôt, car ils sont plus spécifiques que les itinéraires sans zone.In general, routes with areas should be placed earlier as they're more specific than routes without an area.

À l’aide de l’exemple précédent, les valeurs d’itinéraire { area = Blog, controller = Users, action = AddUser } correspondent à l’action suivante :Using the preceding example, the route values { area = Blog, controller = Users, action = AddUser } match the following action:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}

L’attribut [Area] désigne un contrôleur dans le cadre d’une zone.The [Area] attribute is what denotes a controller as part of an area. Ce contrôleur est dans la Blog zone.This controller is in the Blog area. Les contrôleurs sans [Area] attribut ne sont pas membres d’une zone et ne correspondent pas lorsque la valeur de routage area est fournie par le routage.Controllers without an [Area] attribute are not members of any area, and do not match when the area route value is provided by routing. Dans l’exemple suivant, seul le premier contrôleur répertorié peut correspondre aux valeurs de route { area = Blog, controller = Users, action = AddUser }.In the following example, only the first controller listed can match the route values { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        // GET /zebra/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
    // Matches { area = string.Empty, controller = Users, action = AddUser }
    // Matches { area = null, controller = Users, action = AddUser }
    // Matches { controller = Users, action = AddUser }
    public class UsersController : Controller
    {
        // GET /users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }
    }
}

L’espace de noms de chaque contrôleur est indiqué ici par exhaustivité.The namespace of each controller is shown here for completeness. Si les contrôleurs précédents utilisent le même espace de noms, une erreur de compilateur est générée.If the preceding controllers uses the same namespace, a compiler error would be generated. Les espaces de noms de classe n’ont pas d’effet sur le routage de MVC.Class namespaces have no effect on MVC's routing.

Les deux premiers contrôleurs sont membres de zones, et ils sont trouvés en correspondance seulement quand le nom de leur zone respective est fourni par la valeur de route area.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. Le troisième contrôleur n’est membre d’aucune zone et peut être trouvé en correspondance seulement quand aucune valeur pour area n’est fournie par le routage.The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

En termes de mise en correspondance avec aucune valeur, l’absence de la valeur area est identique à une valeur null ou de chaîne vide pour area.In terms of matching no value, the absence of the area value is the same as if the value for area were null or the empty string.

Lors de l’exécution d’une action à l’intérieur d’une zone, la valeur de route pour area est disponible en tant que valeur ambiante pour le routage à utiliser pour la génération d’URL.When executing an action inside an area, the route value for area is available as an ambient value for routing to use for URL generation. Cela signifie que par défaut, les zones agissent par attraction pour la génération d’URL, comme le montre l’exemple suivant.This means that by default areas act sticky for URL generation as demonstrated by the following sample.

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute(name: "duck_route", 
                                     areaName: "Duck",
                                     pattern: "Manage/{controller}/{action}/{id?}");
    endpoints.MapControllerRoute(name: "default",
                                 pattern: "Manage/{controller=Home}/{action=Index}/{id?}");
});
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
    [Area("Duck")]
    public class UsersController : Controller
    {
        // GET /Manage/users/GenerateURLInArea
        public IActionResult GenerateURLInArea()
        {
            // Uses the 'ambient' value of area.
            var url = Url.Action("Index", "Home");
            // Returns /Manage/Home/Index
            return Content(url);
        }

        // GET /Manage/users/GenerateURLOutsideOfArea
        public IActionResult GenerateURLOutsideOfArea()
        {
            // Uses the empty value for area.
            var url = Url.Action("Index", "Home", new { area = "" });
            // Returns /Manage
            return Content(url);
        }
    }
}

Le code suivant génère une URL vers /Zebra/Users/AddUser :The following code generates a URL to /Zebra/Users/AddUser:

public class HomeController : Controller
{
    public IActionResult About()
    {
        var url = Url.Action("AddUser", "Users", new { Area = "Zebra" });
        return Content($"URL: {url}");
    }

Définition de l’actionAction definition

Les méthodes publiques sur un contrôleur, à l’exception de celles avec l’attribut non- action , sont des actions.Public methods on a controller, except those with the NonAction attribute, are actions.

Exemple de codeSample code

Diagnostics de débogageDebug diagnostics

Pour une sortie de diagnostic de routage détaillée, affectez à la valeur Logging:LogLevel:Microsoft Debug .For detailed routing diagnostic output, set Logging:LogLevel:Microsoft to Debug. Dans l’environnement de développement, définissez le niveau de journalisation dans appsettings.Development.jssur:In the development environment, set the log level in appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

ASP.NET Core MVC utilise l’intergiciel de routage pour mettre en correspondance les URL des requêtes entrantes et les mapper à des actions.ASP.NET Core MVC uses the Routing middleware to match the URLs of incoming requests and map them to actions. Les routes sont définies dans le code de démarrage ou dans des attributs.Routes are defined in startup code or attributes. Les routes décrivent comment les chemins des URL doivent être mis en correspondance avec les actions.Routes describe how URL paths should be matched to actions. Les routes sont également utilisées pour générer des URL (pour les liens) envoyés dans les réponses.Routes are also used to generate URLs (for links) sent out in responses.

Les actions sont routées de façon conventionnelle ou routées par attribut.Actions are either conventionally routed or attribute routed. Le fait de placer une route sur le contrôleur ou sur l’action les rend « routés par attribut ».Placing a route on the controller or the action makes it attribute routed. Pour plus d’informations, consultez Routage mixte.See Mixed routing for more information.

Ce document explique les interactions entre MVC et le routage, et comment les applications MVC classiques utilisent les fonctionnalités du routage.This document will explain the interactions between MVC and routing, and how typical MVC apps make use of routing features. Pour plus d’informations sur le routage avancé, consultez Routage.See Routing for details on advanced routing.

Configuration de l’intergiciel de routageSetting up Routing Middleware

Dans votre méthode Configure, vous pouvez voir un code similaire à celui-ci :In your Configure method you may see code similar to:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

À l’intérieur de l’appel à UseMvc, MapRoute est utilisé pour créer une route, nous allons appeler route default.Inside the call to UseMvc, MapRoute is used to create a single route, which we'll refer to as the default route. La plupart des applications MVC utilisent une route avec un modèle similaire à la route default.Most MVC apps will use a route with a template similar to the default route.

Le modèle de route "{controller=Home}/{action=Index}/{id?}" peut correspondre à un chemin d’URL comme /Products/Details/5 et il extrait les valeurs { controller = Products, action = Details, id = 5 } de la route en décomposant le chemin en jetons.The route template "{controller=Home}/{action=Index}/{id?}" can match a URL path like /Products/Details/5 and will extract the route values { controller = Products, action = Details, id = 5 } by tokenizing the path. MVC tente de trouver un contrôleur nommé ProductsController et d’exécuter l’action Details :MVC will attempt to locate a controller named ProductsController and run the action Details:

public class ProductsController : Controller
{
   public IActionResult Details(int id) { ... }
}

Notez que dans cet exemple, la liaison de modèle utilise la valeur de id = 5 pour définir le paramètre id sur 5 lors de l’appel de cette action.Note that in this example, model binding would use the value of id = 5 to set the id parameter to 5 when invoking this action. Pour plus d’informations, consultez Liaison de modèle.See the Model Binding for more details.

Utilisation de la route default :Using the default route:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

Le modèle de route :The route template:

  • {controller=Home} définit Home comme controller par défaut.{controller=Home} defines Home as the default controller

  • {action=Index} définit Index comme action par défaut.{action=Index} defines Index as the default action

  • {id?} définit id comme étant facultatif.{id?} defines id as optional

Les paramètres de route par défaut et facultatifs n’ont pas besoin d’être présents dans le chemin d’URL pour qu’une correspondance soit établie.Default and optional route parameters don't need to be present in the URL path for a match. Pour une description détaillée de la syntaxe du modèle de route, consultez Informations de référence sur le modèle de route.See Route Template Reference for a detailed description of route template syntax.

"{controller=Home}/{action=Index}/{id?}" peut correspondre au chemin d’URL / et produit les valeurs de route { controller = Home, action = Index }."{controller=Home}/{action=Index}/{id?}" can match the URL path / and will produce the route values { controller = Home, action = Index }. Les valeurs de controller et action utilisent les valeurs par défaut, et id ne produit pas de valeur, car il n’existe pas de segment correspondant dans le chemin d’URL.The values for controller and action make use of the default values, id doesn't produce a value since there's no corresponding segment in the URL path. MVC utilisez ces valeurs de route pour sélectionner HomeController et l’action Index :MVC would use these route values to select the HomeController and Index action:

public class HomeController : Controller
{
  public IActionResult Index() { ... }
}

Avec cette définition de contrôleur et ce modèle de route, l’action HomeController.Index est exécutée pour tous les chemins d’URL suivants :Using this controller definition and route template, the HomeController.Index action would be executed for any of the following URL paths:

  • /Home/Index/17

  • /Home/Index

  • /Home

  • /

La méthode pratique UseMvcWithDefaultRoute :The convenience method UseMvcWithDefaultRoute:

app.UseMvcWithDefaultRoute();

Peut être utilisée pour remplacer :Can be used to replace:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc et UseMvcWithDefaultRoute ajoutent une instance de RouterMiddleware au pipeline de l’intergiciel.UseMvc and UseMvcWithDefaultRoute add an instance of RouterMiddleware to the middleware pipeline. MVC n’interagit pas directement avec l’intergiciel et utilise le routage pour gérer les requêtes.MVC doesn't interact directly with middleware, and uses routing to handle requests. MVC est connecté aux routes via une instance de MvcRouteHandler.MVC is connected to the routes through an instance of MvcRouteHandler. Le code de UseMvc est similaire à ceci :The code inside of UseMvc is similar to the following:

var routes = new RouteBuilder(app);

// Add connection to MVC, will be hooked up by calls to MapRoute.
routes.DefaultHandler = new MvcRouteHandler(...);

// Execute callback to register routes.
// routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

// Create route collection and add the middleware.
app.UseRouter(routes.Build());

UseMvc ne définit directement aucune route, il ajoute un espace réservé à la collection de routes pour la route attribute.UseMvc doesn't directly define any routes, it adds a placeholder to the route collection for the attribute route. La surcharge UseMvc(Action<IRouteBuilder>) vous permet d’ajouter vos propres routes et prend également en charge le routage par attribut.The overload UseMvc(Action<IRouteBuilder>) lets you add your own routes and also supports attribute routing. UseMvcet toutes ses variantes ajoutent un espace réservé pour l’attribut route-attribute Routing est toujours disponible, quelle que soit la façon dont vous configurez UseMvc .UseMvc and all of its variations add a placeholder for the attribute route - attribute routing is always available regardless of how you configure UseMvc. UseMvcWithDefaultRoute définit une route par défaut et prend en charge le routage par attribut.UseMvcWithDefaultRoute defines a default route and supports attribute routing. La section Routage par attribut comprend plus de détails sur le routage par attribut.The Attribute Routing section includes more details on attribute routing.

Routage conventionnelConventional routing

La route default :The default route:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

Le code précédent est un exemple de routage conventionnel.The preceding code is an example of a conventional routing. Ce style est appelé routage conventionnel, car il établit une Convention pour les chemins d’URL :This style is called conventional routing because it establishes a convention for URL paths:

  • Le premier segment de chemin d’accès correspond au nom du contrôleur.The first path segment maps to the controller name.
  • Le deuxième correspond au nom de l’action.The second maps to the action name.
  • Le troisième segment est utilisé pour un facultatif id .The third segment is used for an optional id. idcorrespond à une entité de modèle.id maps to a model entity.

En utilisant cette route default, le chemin d’URL /Products/List mappe à l’action ProductsController.List, et /Blog/Article/17 mappe à BlogController.Article.Using this default route, the URL path /Products/List maps to the ProductsController.List action, and /Blog/Article/17 maps to BlogController.Article. Ce mappage est basé uniquement sur les noms de contrôleur et d’action ; il n’est pas basé sur les espaces de noms, les emplacements des fichiers sources ou les paramètres de méthode.This mapping is based on the controller and action names only and isn't based on namespaces, source file locations, or method parameters.

Conseil

L’utilisation du routage conventionnel avec la route par défaut vous permet de créer rapidement l’application sans avoir à élaborer un nouveau modèle d’URL pour chaque action que vous définissez.Using conventional routing with the default route allows you to build the application quickly without having to come up with a new URL pattern for each action you define. Pour une application avec des actions de style CRUD, le fait de disposer d’une cohérence pour les URL entre vos contrôleurs peut simplifier votre code et rendre votre interface utilisateur plus prévisible.For an application with CRUD style actions, having consistency for the URLs across your controllers can help simplify your code and make your UI more predictable.

Avertissement

id est défini comme étant facultatif par le modèle de route, ce qui signifie que vos actions peuvent s’exécuter sans l’ID fourni dans le cadre de l’URL.The id is defined as optional by the route template, meaning that your actions can execute without the ID provided as part of the URL. En général, si id est omis de l’URL, il est défini sur 0 par la liaison de modèle : aucune entité correspondant à id == 0 n’est donc trouvée dans la base de données.Usually what will happen if id is omitted from the URL is that it will be set to 0 by model binding, and as a result no entity will be found in the database matching id == 0. Le routage par attribut vous donne un contrôle précis pour rendre le code obligatoire pour certaines actions et pas pour d’autres.Attribute routing can give you fine-grained control to make the ID required for some actions and not for others. Par convention, la documentation inclut des paramètres facultatifs comme id quand ils sont susceptibles d’apparaître dans une utilisation correcte.By convention the documentation will include optional parameters like id when they're likely to appear in correct usage.

Routes multiplesMultiple routes

Vous pouvez ajouter plusieurs routes dans UseMvc en ajoutant plusieurs appels à MapRoute.You can add multiple routes inside UseMvc by adding more calls to MapRoute. Ceci vous permet de définir plusieurs conventions ou d’ajouter des routes conventionnelles qui sont dédiées à une action spécifique, comme :Doing so allows you to define multiple conventions, or to add conventional routes that are dedicated to a specific action, such as:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
            defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

La route blog est ici une route conventionnelle dédiée, ce qui signifie qu’elle utilise le système de routage conventionnel, mais qu’elle est dédiée à une action spécifique.The blog route here is a dedicated conventional route, meaning that it uses the conventional routing system, but is dedicated to a specific action. Comme controller et action n’apparaissent pas dans le modèle de route en tant que paramètres, ils peuvent seulement avoir les valeurs par défaut et par conséquent, cette route sera toujours mappée à l’action BlogController.Article.Since controller and action don't appear in the route template as parameters, they can only have the default values, and thus this route will always map to the action BlogController.Article.

Les routes de la collection de routes sont ordonnées et elles sont traitées dans l’ordre où elles sont ajoutées.Routes in the route collection are ordered, and will be processed in the order they're added. Ainsi, dans cet exemple, la route blog est essayée avant la route default.So in this example, the blog route will be tried before the default route.

Notes

Les itinéraires conventionnels dédiés utilisent souvent des paramètres de routage de type « catch-all » comme {*article} pour capturer la partie restante du chemin d’URL.Dedicated conventional routes often use catch-all route parameters like {*article} to capture the remaining portion of the URL path. Ceci peut rendre une route « trop globale », ce qui signifie qu’elle correspond à des URL qui devaient être mises en correspondance par d’autres routes.This can make a route 'too greedy' meaning that it matches URLs that you intended to be matched by other routes. Pour résoudre ce problème, placez les routes « globales » plus loin dans la table de routage.Put the 'greedy' routes later in the route table to solve this.

SecoursFallback

Dans le cadre du traitement des requêtes, MVC vérifie que les valeurs de route peuvent être utilisées pour rechercher un contrôleur et une action dans votre application.As part of request processing, MVC will verify that the route values can be used to find a controller and action in your application. Si les valeurs de route ne correspondent pas à une action, la route n’est pas considérée comme une correspondance, et la route suivante est essayée.If the route values don't match an action then the route isn't considered a match, and the next route will be tried. Ceci est appelé processus de repli et est conçu pour simplifier les cas où des routes conventionnelles se chevauchent.This is called fallback, and it's intended to simplify cases where conventional routes overlap.

Résolution des ambiguïtés pour les actionsDisambiguating actions

Quand deux actions correspondent via le routage, MVC doit résoudre l’ambiguïté pour choisir le « meilleur » candidat ou sinon lever une exception.When two actions match through routing, MVC must disambiguate to choose the 'best' candidate or else throw an exception. Par exemple :For example:

public class ProductsController : Controller
{
   public IActionResult Edit(int id) { ... }

   [HttpPost]
   public IActionResult Edit(int id, Product product) { ... }
}

Ce contrôleur définit deux actions qui correspondraient au chemin d’URL /Products/Edit/17 et les données de routage { controller = Products, action = Edit, id = 17 }.This controller defines two actions that would match the URL path /Products/Edit/17 and route data { controller = Products, action = Edit, id = 17 }. Il s’agit d’un modèle classique pour les contrôleurs MVC, où Edit(int) montre un formulaire pour modifier un produit, et où Edit(int, Product) traite le formulaire envoyé.This is a typical pattern for MVC controllers where Edit(int) shows a form to edit a product, and Edit(int, Product) processes the posted form. Pour rendre cela possible, MVC doit choisir Edit(int, Product) quand la requête est POST HTTP, et Edit(int) quand le verbe HTTP est autre chose.To make this possible MVC would need to choose Edit(int, Product) when the request is an HTTP POST and Edit(int) when the HTTP verb is anything else.

HttpPostAttribute ([HttpPost]) est une implémentation de IActionConstraint qui permet la sélection de l’action seulement quand le verbe HTTP est POST.The HttpPostAttribute ( [HttpPost] ) is an implementation of IActionConstraint that will only allow the action to be selected when the HTTP verb is POST. La présence d’une IActionConstraint fait de Edit(int, Product) une correspondance « meilleure » que Edit(int), de sorte que Edit(int, Product) est essayé en premier.The presence of an IActionConstraint makes the Edit(int, Product) a 'better' match than Edit(int), so Edit(int, Product) will be tried first.

Vous devez écrire des implémentations personnalisées de IActionConstraint seulement dans des scénarios spécifiques, mais il est important de comprendre le rôle d’attributs comme HttpPostAttribute ; des attributs similaires sont définis pour les autres verbes HTTP.You will only need to write custom IActionConstraint implementations in specialized scenarios, but it's important to understand the role of attributes like HttpPostAttribute - similar attributes are defined for other HTTP verbs. Dans le routage conventionnel, il est courant que des actions utilisent un même nom d’action quand elles font partie d’un flux de travail show form -> submit form.In conventional routing it's common for actions to use the same action name when they're part of a show form -> submit form workflow. L’avantage de ce modèle devient plus évident après la lecture de la section Présentation d’IActionConstraint.The convenience of this pattern will become more apparent after reviewing the Understanding IActionConstraint section.

Si plusieurs routes correspondent et que MVC ne peut pas trouver une « meilleure » route, elle lève une AmbiguousActionException.If multiple routes match, and MVC can't find a 'best' route, it will throw an AmbiguousActionException.

Noms des routesRoute names

Les chaînes "blog" et "default" dans les exemples suivants sont des noms de routes :The strings "blog" and "default" in the following examples are route names:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
               defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Les noms de routes donnent aux routes des noms logiques : le nom de route peut ainsi être utilisé pour la génération des URL.The route names give the route a logical name so that the named route can be used for URL generation. Ceci simplifie considérablement la création d’URL quand l’ordonnancement des routes peut rendre compliquée la génération des URL.This greatly simplifies URL creation when the ordering of routes could make URL generation complicated. Les noms de routes doivent être unique à l’échelle de l’application.Route names must be unique application-wide.

Les noms de routes n’ont pas d’impact sur la correspondance des URL ni sur le traitement des requêtes ; ils sont utilisés seulement pour la génération d’URL.Route names have no impact on URL matching or handling of requests; they're used only for URL generation. La section Routage contient des informations plus détaillées sur la génération d’URL, notamment la génération d’URL dans les helpers spécifiques à MVC.Routing has more detailed information on URL generation including URL generation in MVC-specific helpers.

Routage par attributsAttribute routing

Le routage par attributs utilise un ensemble d’attributs pour mapper les actions directement aux modèles de routes.Attribute routing uses a set of attributes to map actions directly to route templates. Dans l’exemple suivant, app.UseMvc(); est utilisé dans la méthode Configure et aucune route n’est passée.In the following example, app.UseMvc(); is used in the Configure method and no route is passed. HomeController va trouver des correspondances avec un ensemble d’URL similaires aux correspondances qui seraient trouvées par la route par défaut {controller=Home}/{action=Index}/{id?}:The HomeController will match a set of URLs similar to what the default route {controller=Home}/{action=Index}/{id?} would match:

public class HomeController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult Index()
   {
      return View();
   }
   [Route("Home/About")]
   public IActionResult About()
   {
      return View();
   }
   [Route("Home/Contact")]
   public IActionResult Contact()
   {
      return View();
   }
}

L’action HomeController.Index() sera exécutée pour tous les chemins d’URL /, /Home ou /Home/Index.The HomeController.Index() action will be executed for any of the URL paths /, /Home, or /Home/Index.

Notes

Cet exemple met en évidence une différence importante en termes de programmation entre le routage par attributs et le routage conventionnel.This example highlights a key programming difference between attribute routing and conventional routing. Le routage par attributs nécessite des entrées en plus grand nombre pour spécifier une route ; la route conventionnelle par défaut gère les routes de façon plus succincte.Attribute routing requires more input to specify a route; the conventional default route handles routes more succinctly. Cependant, le routage par attributs permet (et nécessite) un contrôle précis des modèles de routes qui s’appliquent à chaque action.However, attribute routing allows (and requires) precise control of which route templates apply to each action.

Avec le routage par attributs, le nom du contrôleur et les noms des actions ne jouent aucun rôle dans la sélection de l’action.With attribute routing the controller name and action names play no role in which action is selected. Cet exemple trouve une correspondance avec les mêmes URL que l’exemple précédent.This example will match the same URLs as the previous example.

public class MyDemoController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult MyIndex()
   {
      return View("Index");
   }
   [Route("Home/About")]
   public IActionResult MyAbout()
   {
      return View("About");
   }
   [Route("Home/Contact")]
   public IActionResult MyContact()
   {
      return View("Contact");
   }
}

Notes

Les modèles de routes ci-dessus ne définissent pas de paramètres de route pour action, area et controller.The route templates above don't define route parameters for action, area, and controller. En fait, ces paramètres de route ne sont pas autorisés dans les routes par attributs.In fact, these route parameters are not allowed in attribute routes. Comme le modèle de route est déjà associé à une action, cela n’aurait pas de sens d’analyser le nom de l’action à partir de l’URL.Since the route template is already associated with an action, it wouldn't make sense to parse the action name from the URL.

Routage par attributs avec des attributs Http[Verbe]Attribute routing with Http[Verb] attributes

Le routage par attributs peut aussi utiliser les attributs Http[Verb], comme HttpPostAttribute.Attribute routing can also make use of the Http[Verb] attributes such as HttpPostAttribute. Tous ces attributs peuvent accepter un modèle de route.All of these attributes can accept a route template. Cet exemple montre deux actions qui correspondent au même modèle de route :This example shows two actions that match the same route template:

[HttpGet("/products")]
public IActionResult ListProducts()
{
   // ...
}

[HttpPost("/products")]
public IActionResult CreateProduct(...)
{
   // ...
}

Pour un chemin d’URL comme /products, l’action ProductsApi.ListProducts est exécutée quand le verbe HTTP est GET, et ProductsApi.CreateProduct est exécutée quand le verbe HTTP est POST.For a URL path like /products the ProductsApi.ListProducts action will be executed when the HTTP verb is GET and ProductsApi.CreateProduct will be executed when the HTTP verb is POST. Le routage par attributs recherche d’abord une correspondance de l’URL par rapport à l’ensemble des modèles de routes défini par les attributs de la route.Attribute routing first matches the URL against the set of route templates defined by route attributes. Une fois qu’un modèle de route correspond, les contraintes de IActionConstraint sont appliquées pour déterminer quelles actions peuvent être exécutées.Once a route template matches, IActionConstraint constraints are applied to determine which actions can be executed.

Conseil

Lors de la génération d’une API REST, il est rare que vous souhaitiez utiliser [Route(...)] sur une méthode d’action, car l’action acceptera toutes les méthodes http.When building a REST API, it's rare that you will want to use [Route(...)] on an action method as the action will accept all HTTP methods. Il est préférable d’utiliser les Http*Verb*Attributes plus spécifiques pour plus de précision quant à ce qui est pris en charge par votre API.It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. Les clients des API REST doivent normalement connaître les chemins et les verbes HTTP qui correspondent à des opérations logiques spécifiques.Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

Dans la mesure où une route d’attribut s’applique à une action spécifique, il est facile de placer les paramètres nécessaires dans la définition du modèle de route.Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. Dans cet exemple, id est obligatoire dans le chemin d’URL.In this example, id is required as part of the URL path.

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

L’action ProductsApi.GetProduct(int) est exécutée pour un chemin d’URL comme /products/3, mais pas pour un chemin d’URL comme /products.The ProductsApi.GetProduct(int) action will be executed for a URL path like /products/3 but not for a URL path like /products. Consultez Routage pour obtenir une description complète des modèles de routes et des options associées.See Routing for a full description of route templates and related options.

Nom des routesRoute Name

Le code suivant définit un nom de routeProducts_List :The following code defines a route name of Products_List:

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

Les noms de routes peuvent être utilisés pour générer une URL basée sur une route spécifique.Route names can be used to generate a URL based on a specific route. Les noms de routes n’ont pas d’impact sur le comportement de mise en correspondance des URL du routage et ils sont utilisés seulement pour la génération d’URL.Route names have no impact on the URL matching behavior of routing and are only used for URL generation. Les noms de routes doivent être unique à l’échelle de l’application.Route names must be unique application-wide.

Notes

Comparez ceci avec la route par défaut conventionnelle, qui définit le paramètre id comme étant facultatif ({id?}).Contrast this with the conventional default route, which defines the id parameter as optional ({id?}). Cette possibilité de spécifier les API avec précision présente des avantages, par exemple de permettre de diriger /products et /products/5 vers des actions différentes.This ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

Combinaison de routesCombining routes

Pour rendre le routage par attributs moins répétitif, les attributs de route sont combinés avec des attributs de route sur les actions individuelles.To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. Les modèles de routes définis sur le contrôleur sont ajoutés à des modèles de routes sur les actions.Any route templates defined on the controller are prepended to route templates on the actions. Placer un attribut de route sur le contrôleur a pour effet que toutes les actions du contrôleur utilisent le routage par attributs.Placing a route attribute on the controller makes all actions in the controller use attribute routing.

[Route("products")]
public class ProductsApiController : Controller
{
   [HttpGet]
   public IActionResult ListProducts() { ... }

   [HttpGet("{id}")]
   public ActionResult GetProduct(int id) { ... }
}

Dans cet exemple, le chemin d’URL /products peut être mis en correspondance avec ProductsApi.ListProducts et le chemin d’URL /products/5 peut être mis en correspondance avec ProductsApi.GetProduct(int).In this example the URL path /products can match ProductsApi.ListProducts, and the URL path /products/5 can match ProductsApi.GetProduct(int). Ces deux actions correspondent uniquement à HTTP GET , car elles sont marquées avec le HttpGetAttribute .Both of these actions only match HTTP GET because they're marked with the HttpGetAttribute.

Les modèles de routes appliqués à une action qui commencent par / ou ~/ ne sont pas combinés avec les modèles de routes appliqués au contrôleur.Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. Cet exemple met en correspondance avec un ensemble de chemins d’URL similaires à la route par défaut.This example matches a set of URL paths similar to the default route.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]      // Combines to define the route template "Home"
    [Route("Index")] // Combines to define the route template "Home/Index"
    [Route("/")]     // Doesn't combine, defines the route template ""
    public IActionResult Index()
    {
        ViewData["Message"] = "Home index";
        var url = Url.Action("Index", "Home");
        ViewData["Message"] = "Home index" + "var url = Url.Action; =  " + url;
        return View();
    }

    [Route("About")] // Combines to define the route template "Home/About"
    public IActionResult About()
    {
        return View();
    }   
}

Ordonnancement des routes d’attributsOrdering attribute routes

Contrairement aux itinéraires conventionnels, qui s’exécutent dans un ordre défini, le routage d’attributs génère une arborescence et met en correspondance tous les itinéraires simultanément.In contrast to conventional routes, which execute in a defined order, attribute routing builds a tree and matches all routes simultaneously. Il se comporte comme-si les entrées des routes étaient placées dans un ordre idéal ; les routes les plus spécifiques ont ainsi plus de probabilités de s’exécuter avant les routes plus générales.This behaves as-if the route entries were placed in an ideal ordering; the most specific routes have a chance to execute before the more general routes.

Par exemple, une route comme blog/search/{topic} est plus spécifique qu’une route comme blog/{*article}.For example, a route like blog/search/{topic} is more specific than a route like blog/{*article}. D’un point de vue logique, la route blog/search/{topic} « s’exécute » par défaut en premier, car il s’agit du seul ordre sensé.Logically speaking the blog/search/{topic} route 'runs' first, by default, because that's the only sensible ordering. Avec le routage conventionnel, le développeur est responsable du placement des routes dans l’ordre souhaité.Using conventional routing, the developer is responsible for placing routes in the desired order.

Les routes d’attribut peuvent configurer un ordre en utilisant la propriété Order de tous les attributs de route fournis par le framework.Attribute routes can configure an order, using the Order property of all of the framework provided route attributes. Les routes sont traitées selon un ordre croissant de la propriété Order.Routes are processed according to an ascending sort of the Order property. L’ordre par défaut est 0.The default order is 0. La définition d’une route avec Order = -1 fait que cette route « s’exécute » avant les routes qui ne définissent pas d’ordre.Setting a route using Order = -1 will run before routes that don't set an order. La définition d’une route avec Order = 1 fait que cette route « s’exécute » après l’ordre des routes par défaut.Setting a route using Order = 1 will run after default route ordering.

Conseil

Évitez de dépendre de Order.Avoid depending on Order. Si votre espace d’URL nécessite des valeurs d’ordre explicites pour router correctement, il est probable qu’il prête également à confusion pour les clients.If your URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. D’une façon générale, le routage par attributs sélectionne la route correcte avec la mise en correspondance d’URL.In general attribute routing will select the correct route with URL matching. Si l’ordre par défaut utilisé pour la génération d’URL ne fonctionne pas, l’utilisation à titre de remplacement d’un nom de route est généralement plus simple que d’appliquer la propriété Order.If the default order used for URL generation isn't working, using route name as an override is usually simpler than applying the Order property.

RazorLe routage des pages et le routage du contrôleur MVC partagent une implémentation. Pages routing and MVC controller routing share an implementation. Des informations sur l’ordre des itinéraires dans les Razor rubriques pages sont disponibles à la Razor page conventions de routage et d’application : ordre de routage.Information on route order in the Razor Pages topics is available at Razor Pages route and app conventions: Route order.

Remplacement de jetons dans les modèles de routes ([contrôleur], [action], [zone])Token replacement in route templates ([controller], [action], [area])

Pour plus de commodité, les itinéraires d’attributs prennent en charge le remplacement de jetons en plaçant un jeton entre crochets ( [ , ] ).For convenience, attribute routes support token replacement by enclosing a token in square-brackets ([, ]). Les jetons [action], [area] et [controller] sont remplacés par les valeurs du nom d’action, du nom de la zone et du nom du contrôleur de l’action où la route est définie.The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined. Dans l’exemple suivant, les actions correspondent aux chemins d’URL comme décrit dans les commentaires :In the following example, the actions match URL paths as described in the comments:

[Route("[controller]/[action]")]
public class ProductsController : Controller
{
    [HttpGet] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

Le remplacement des jetons se produit à la dernière étape de la création des routes d’attribut.Token replacement occurs as the last step of building the attribute routes. L’exemple ci-dessus se comporte comme le code suivant :The above example will behave the same as the following code:


public class ProductsController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("[controller]/[action]/{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

Les routes d’attribut peuvent aussi être combinées avec l’héritage.Attribute routes can also be combined with inheritance. Combiné avec le remplacement de jetons, c’est particulièrement puissant.This is particularly powerful combined with token replacement.

[Route("api/[controller]")]
public abstract class MyBaseController : Controller { ... }

public class ProductsController : MyBaseController
{
   [HttpGet] // Matches '/api/Products'
   public IActionResult List() { ... }

   [HttpPut("{id}")] // Matches '/api/Products/{id}'
   public IActionResult Edit(int id) { ... }
}

Le remplacement des jetons s’applique aussi aux noms de routes définis par des routes d’attribut.Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] génère un nom de route unique pour chaque action.[Route("[controller]/[action]", Name="[controller]_[action]")] generates a unique route name for each action.

Pour faire correspondre le délimiteur littéral de remplacement de jetons [ ou ], placez-le en échappement en répétant le caractère ([[ ou ]]).To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

Utiliser un transformateur de paramètre pour personnaliser le remplacement des jetonsUse a parameter transformer to customize token replacement

Le remplacement des jetons peut être personnalisé à l’aide d’un transformateur de paramètre.Token replacement can be customized using a parameter transformer. Un transformateur de paramètre implémente IOutboundParameterTransformer et transforme la valeur des paramètres.A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. Par exemple, un transformateur de paramètre SlugifyParameterTransformer personnalisé transforme la valeur de la route SubscriptionManagement en subscription-management.For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management.

RouteTokenTransformerConvention est une convention de modèle d’application qui :The RouteTokenTransformerConvention is an application model convention that:

  • Applique un transformateur de paramètre à toutes les routes d’attribut dans une application.Applies a parameter transformer to all attribute routes in an application.
  • Personnalise les valeurs de jeton de route d’attribut quand elles sont remplacées.Customizes the attribute route token values as they are replaced.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/subscription-management/list-all'
    public IActionResult ListAll() { ... }
}

RouteTokenTransformerConvention est inscrit en tant qu’option dans ConfigureServices.The RouteTokenTransformerConvention is registered as an option in ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Conventions.Add(new RouteTokenTransformerConvention(
                                     new SlugifyParameterTransformer()));
    });
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        // Slugify value
        return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}

Routes multiplesMultiple Routes

Le routage par attributs prend en charge la définition de plusieurs routes pour atteindre la même action.Attribute routing supports defining multiple routes that reach the same action. L’utilisation la plus courante de ceci est d’imiter le comportement de la route conventionnelle par défaut, comme le montre l’exemple suivant :The most common usage of this is to mimic the behavior of the default conventional route as shown in the following example:

[Route("[controller]")]
public class ProductsController : Controller
{
   [Route("")]     // Matches 'Products'
   [Route("Index")] // Matches 'Products/Index'
   public IActionResult Index()
}

Le fait de placer plusieurs attributs de route sur le contrôleur signifie que chacun d’eux se combine avec chacun des attributs de route sur les méthodes d’action.Putting multiple route attributes on the controller means that each one will combine with each of the route attributes on the action methods.

[Route("Store")]
[Route("[controller]")]
public class ProductsController : Controller
{
   [HttpPost("Buy")]     // Matches 'Products/Buy' and 'Store/Buy'
   [HttpPost("Checkout")] // Matches 'Products/Checkout' and 'Store/Checkout'
   public IActionResult Buy()
}

Quand plusieurs attributs de route (qui implémentent IActionConstraint) sont placés sur une action, chaque contrainte d’action se combine avec le modèle de route de l’attribut qui l’a défini.When multiple route attributes (that implement IActionConstraint) are placed on an action, then each action constraint combines with the route template from the attribute that defined it.

[Route("api/[controller]")]
public class ProductsController : Controller
{
   [HttpPut("Buy")]      // Matches PUT 'api/Products/Buy'
   [HttpPost("Checkout")] // Matches POST 'api/Products/Checkout'
   public IActionResult Buy()
}

Conseil

Si utiliser plusieurs routes sur des actions peut paître puissant, il est préférable de conserver l’espace d’URL de votre application simple et bien définie.While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. Utilisez plusieurs routes sur les actions seulement là où c’est nécessaire, par exemple pour prendre en charge des clients existants.Use multiple routes on actions only where needed, for example to support existing clients.

Spécification facultative de paramètres, de valeurs par défaut et de contraintes pour les routes d’attributSpecifying attribute route optional parameters, default values, and constraints

Les routes d’attribut prennent en charge la même syntaxe inline que les routes conventionnelles pour spécifier des paramètres, des valeurs par défaut et des contraintes facultatifs.Attribute routes support the same inline syntax as conventional routes to specify optional parameters, default values, and constraints.

[HttpPost("product/{id:int}")]
public IActionResult ShowProduct(int id)
{
   // ...
}

Pour une description détaillée de la syntaxe du modèle de route, consultez Informations de référence sur le modèle de route.See Route Template Reference for a detailed description of route template syntax.

Attributs de route personnalisés avec IRouteTemplateProviderCustom route attributes using IRouteTemplateProvider

Tous les attributs de route fournis dans le framework ([Route(...)], [HttpGet(...)], etc.) implémentent l’interface IRouteTemplateProvider.All of the route attributes provided in the framework ( [Route(...)], [HttpGet(...)] , etc.) implement the IRouteTemplateProvider interface. MVC recherche les attributs sur les classes de contrôleur et les méthodes d’action quand l’application démarre et utilise ceux qui implémentent IRouteTemplateProvider pour créer l’ensemble initial des routes.MVC looks for attributes on controller classes and action methods when the app starts and uses the ones that implement IRouteTemplateProvider to build the initial set of routes.

Vous pouvez implémenter IRouteTemplateProvider pour définir vos propres attributs de route.You can implement IRouteTemplateProvider to define your own route attributes. Chaque IRouteTemplateProvider vous permet de définir une route avec un modèle, un nom et un ordre de route personnalisés :Each IRouteTemplateProvider allows you to define a single route with a custom route template, order, and name:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
   public string Template => "api/[controller]";

   public int? Order { get; set; }

   public string Name { get; set; }
}

L’attribut de l’exemple ci-dessus définit automatiquement Template sur "api/[controller]" quand [MyApiController] est appliqué.The attribute from the above example automatically sets the Template to "api/[controller]" when [MyApiController] is applied.

Utilisation d’un modèle d’application pour personnaliser les routes d’attributUsing Application Model to customize attribute routes

Le modèle d’application est un modèle d’objet créé au démarrage avec toutes les métadonnées utilisée par MVC pour router et exécuter vos actions.The application model is an object model created at startup with all of the metadata used by MVC to route and execute your actions. Le modèle d’application inclut toutes les données collectées à partir des attributs de route (via IRouteTemplateProvider).The application model includes all of the data gathered from route attributes (through IRouteTemplateProvider). Vous pouvez écrire des conventions pour modifier le modèle d’application au moment du démarrage pour personnaliser le comporte du routage.You can write conventions to modify the application model at startup time to customize how routing behaves. Cette section montre un exemple simple de personnalisation du routage avec le modèle d’application.This section shows a simple example of customizing routing using application model.

using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
using System.Text;
public class NamespaceRoutingConvention : IControllerModelConvention
{
    private readonly string _baseNamespace;

    public NamespaceRoutingConvention(string baseNamespace)
    {
        _baseNamespace = baseNamespace;
    }

    public void Apply(ControllerModel controller)
    {
        var hasRouteAttributes = controller.Selectors.Any(selector =>
                                                selector.AttributeRouteModel != null);
        if (hasRouteAttributes)
        {
            // This controller manually defined some routes, so treat this 
            // as an override and not apply the convention here.
            return;
        }

        // Use the namespace and controller name to infer a route for the controller.
        //
        // Example:
        //
        //  controller.ControllerTypeInfo ->    "My.Application.Admin.UsersController"
        //  baseNamespace ->                    "My.Application"
        //
        //  template =>                         "Admin/[controller]"
        //
        // This makes your routes roughly line up with the folder structure of your project.
        //
        var namespc = controller.ControllerType.Namespace;
        if (namespc == null)
            return;
        var template = new StringBuilder();
        template.Append(namespc, _baseNamespace.Length + 1,
                        namespc.Length - _baseNamespace.Length - 1);
        template.Replace('.', '/');
        template.Append("/[controller]");

        foreach (var selector in controller.Selectors)
        {
            selector.AttributeRouteModel = new AttributeRouteModel()
            {
                Template = template.ToString()
            };
        }
    }
}

Routage mixte : routage conventionnel et routage par attributsMixed routing: Attribute routing vs conventional routing

Les applications MVC peuvent combiner l’utilisation du routage conventionnel et du routage par attributs.MVC applications can mix the use of conventional routing and attribute routing. Il est courant d’utiliser des routes conventionnelles pour les contrôleurs délivrant des pages HTML pour les navigateurs, et le routage par attributs pour les contrôleurs délivrant des API REST.It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

Les actions sont routées de façon conventionnelle ou routées par attribut.Actions are either conventionally routed or attribute routed. Le fait de placer une route sur le contrôleur ou sur l’action les rend « routés par attribut ».Placing a route on the controller or the action makes it attribute routed. Les actions qui définissent des routes d’attribut ne sont pas accessibles via les routes conventionnelles et vice versa.Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Tout attribut de route sur le contrôleur a pour effet que toutes les actions du contrôleur sont routées par attributs.Any route attribute on the controller makes all actions in the controller attribute routed.

Notes

Ce qui distingue les deux types de systèmes de routage est le processus appliqué une fois qu’une URL correspond à un modèle de route.What distinguishes the two types of routing systems is the process applied after a URL matches a route template. Dans le routage conventionnel, les valeurs de route de la correspondance sont utilisées pour choisir l’action et le contrôleur dans une table de recherche comprenant toutes les actions routées de façon conventionnelle.In conventional routing, the route values from the match are used to choose the action and controller from a lookup table of all conventional routed actions. Dans le routage par attributs, chaque modèle est déjà associé à une action, et aucune recherche supplémentaire n’est nécessaire.In attribute routing, each template is already associated with an action, and no further lookup is needed.

Segments complexesComplex segments

Les segments complexes (par exemple, [Route("/dog{token}cat")]), sont traités par la mise en correspondance des littéraux de droite à gauche de manière non gourmande.Complex segments (for example, [Route("/dog{token}cat")]), are processed by matching up literals from right to left in a non-greedy way. Consultez le code source pour obtenir une description.See the source code for a description. Pour plus d’informations, consultez ce problème.For more information, see this issue.

Génération des URLURL Generation

Les applications MVC peuvent utiliser les fonctionnalités de génération d’URL de routage pour générer des liens URL vers des actions.MVC applications can use routing's URL generation features to generate URL links to actions. La génération d’URL élimine le codage en dur des URL, ce qui rend votre code plus robuste et plus facile à maintenir.Generating URLs eliminates hardcoding URLs, making your code more robust and maintainable. Cette section se concentre sur les fonctionnalités de génération d’URL fournies par MVC et couvre seulement les principes de base du fonctionnement de la génération d’URL.This section focuses on the URL generation features provided by MVC and will only cover basics of how URL generation works. Pour une description détaillée de la génération d’URL, consultez Routage.See Routing for a detailed description of URL generation.

L’interface IUrlHelper est l’élément d’infrastructure sous-jacent entre MVC et le routage pour la génération d’URL.The IUrlHelper interface is the underlying piece of infrastructure between MVC and routing for URL generation. Vous pouvez trouver une instance de IUrlHelper disponible via la propriété Url dans les composants controllers, views et view.You'll find an instance of IUrlHelper available through the Url property in controllers, views, and view components.

Dans cet exemple, l’interface IUrlHelper est utilisée via la propriété Controller.Url pour générer une URL vers une autre action.In this example, the IUrlHelper interface is used through the Controller.Url property to generate a URL to another action.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return Content($"Go check out {url}, it's really great.");
    }

    public IActionResult Destination()
    {
        return View();
    }
}

Si l’application utilise la route conventionnelle par défaut, la valeur de la variable url est la chaîne de chemin d’URL /UrlGeneration/Destination.If the application is using the default conventional route, the value of the url variable will be the URL path string /UrlGeneration/Destination. Ce chemin d’URL est créé par le routage en combinant les valeurs de route de la requête en cours (valeurs ambiantes) avec les valeurs passées à Url.Action, et en remplaçant les valeurs dans le modèle de route :This URL path is created by routing by combining the route values from the current request (ambient values), with the values passed to Url.Action and substituting those values into the route template:

ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

La valeur de chaque paramètre de route du modèle de route est remplacée en établissant une correspondance avec les valeurs et les valeurs ambiantes.Each route parameter in the route template has its value substituted by matching names with the values and ambient values. Un paramètre de route qui n’a pas de valeur peut utiliser une valeur par défaut s’il en a une, ou il peut être ignoré s’il est facultatif (comme dans le cas de id dans cet exemple).A route parameter that doesn't have a value can use a default value if it has one, or be skipped if it's optional (as in the case of id in this example). La génération d’URL échoue si un paramètre de route obligatoire n’a pas de valeur correspondante.URL generation will fail if any required route parameter doesn't have a corresponding value. Si la génération d’URL échoue pour une route, la route suivante est essayée, ceci jusqu’à ce que toutes les routes aient été essayées ou qu’une correspondance soit trouvée.If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

L’exemple de Url.Action ci-dessus suppose un routage conventionnel, mais la génération d’URL fonctionne de façon similaire avec le routage par attributs, même si les concepts sont différents.The example of Url.Action above assumes conventional routing, but URL generation works similarly with attribute routing, though the concepts are different. Avec le routage conventionnel, les valeurs de route sont utilisées pour développer un modèle, et les valeurs de route pour controller et action apparaissent généralement dans ce modèle : ceci fonctionne car les URL mises en correspondance par le routage adhèrent à une convention.With conventional routing, the route values are used to expand a template, and the route values for controller and action usually appear in that template - this works because the URLs matched by routing adhere to a convention. Dans le routage par attributs, les valeurs de route pour controller et action ne sont pas autorisées à apparaître dans le modèle : au lieu de cela, elles sont utilisées pour rechercher le modèle à utiliser.In attribute routing, the route values for controller and action are not allowed to appear in the template - they're instead used to look up which template to use.

Cet exemple utilise le routage par attributs :This example uses attribute routing:

// In Startup class
public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
}
using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination"); // Generates /custom/url/to/destination
        return Content($"Go check out {url}, it's really great.");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination() {
        return View();
    }
}

MVC génère une table de recherche de toutes les actions routées par attributs et recherche une correspondance avec les valeurs de controller et de action pour sélectionner le modèle de route à utiliser pour la génération d’URL.MVC builds a lookup table of all attribute routed actions and will match the controller and action values to select the route template to use for URL generation. Dans l’exemple ci-dessus, custom/url/to/destination est généré.In the sample above, custom/url/to/destination is generated.

Génération des URL par nom d’actionGenerating URLs by action name

Url.Action (IUrlHelper .Url.Action (IUrlHelper . Action) et toutes les surcharges associées sont tous basés sur cette idée que vous voulez spécifier ce à quoi vous liez en spécifiant un nom de contrôleur et un nom d’action.Action) and all related overloads all are based on that idea that you want to specify what you're linking to by specifying a controller name and action name.

Notes

Quand vous utilisez Url.Action, les valeurs de route actuelles pour controller et action sont spécifiées pour vous : la valeur de controller et de action font partie des valeurs ambiantes ** et des ** valeurs.When using Url.Action, the current route values for controller and action are specified for you - the value of controller and action are part of both ambient values and values. La méthode Url.Action utilise toujours les valeurs actuelles de action et de controller, et génère un chemin d’URL qui route vers l’action actuelle.The method Url.Action, always uses the current values of action and controller and will generate a URL path that routes to the current action.

Le routage essaye d’utiliser les valeurs dans les valeurs ambiantes pour renseigner les informations que vous n’avez pas fournies lors de la génération d’une URL.Routing attempts to use the values in ambient values to fill in information that you didn't provide when generating a URL. En utilisant une route comme {a}/{b}/{c}/{d} et les valeurs ambiantes { a = Alice, b = Bob, c = Carol, d = David }, le routage a suffisamment d’informations pour générer une URL sans aucune autre valeur supplémentaire, car tous les paramètres de route ont une valeur.Using a route like {a}/{b}/{c}/{d} and ambient values { a = Alice, b = Bob, c = Carol, d = David }, routing has enough information to generate a URL without any additional values - since all route parameters have a value. Si vous avez ajouté la valeur { d = Donovan }, la valeur { d = David } est ignorée, et le chemin d’URL généré est Alice/Bob/Carol/Donovan.If you added the value { d = Donovan }, the value { d = David } would be ignored, and the generated URL path would be Alice/Bob/Carol/Donovan.

Avertissement

Les chemins d’URL sont hiérarchiques.URL paths are hierarchical. Dans l’exemple ci-dessus, si vous avez ajouté la valeur { c = Cheryl }, les deux valeurs { c = Carol, d = David } sont ignorées.In the example above, if you added the value { c = Cheryl }, both of the values { c = Carol, d = David } would be ignored. Dans ce cas nous n’avons plus de valeur pour d et la génération d’URL échoue.In this case we no longer have a value for d and URL generation will fail. Vous devez spécifier la valeur souhaitée de c et de d.You would need to specify the desired value of c and d. Vous vous attendez peut-être à rencontrer ce problème avec la route par défaut ({controller}/{action}/{id?}), mais vous rencontrerez rarement ce comportement en pratique, car Url.Action spécifie toujours explicitement une valeur pour controller et pour action.You might expect to hit this problem with the default route ({controller}/{action}/{id?}) - but you will rarely encounter this behavior in practice as Url.Action will always explicitly specify a controller and action value.

Les surcharges plus longues de Url.Action prennent également un objet supplémentaire de *valeurs de route * pour fournir des valeurs pour les paramètres de route autres que controller et action.Longer overloads of Url.Action also take an additional route values object to provide values for route parameters other than controller and action. Vous verrez ceci plus couramment utilisé avec un id comme Url.Action("Buy", "Products", new { id = 17 }).You will most commonly see this used with id like Url.Action("Buy", "Products", new { id = 17 }). Par convention, l’objet de valeurs de route objet est généralement un objet de type anonyme, mais il peut également être un IDictionary<> ou un objet .NET traditionnel.By convention the route values object is usually an object of anonymous type, but it can also be an IDictionary<> or a plain old .NET object. Toutes les valeurs de route supplémentaires qui ne correspondent pas aux paramètres de route sont placées dans la chaîne de requête.Any additional route values that don't match route parameters are put in the query string.

using Microsoft.AspNetCore.Mvc;

public class TestController : Controller
{
    public IActionResult Index()
    {
        // Generates /Products/Buy/17?color=red
        var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
        return Content(url);
    }
}

Conseil

Pour créer une URL absolue, utilisez une surcharge qui accepte un protocol :Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)To create an absolute URL, use an overload that accepts a protocol: Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)

Génération des URL par routeGenerating URLs by route

Le code ci-dessus a montré la génération d’une URL en passant le nom du contrôleur et le nom de l’action.The code above demonstrated generating a URL by passing in the controller and action name. IUrlHelper fournit également la famille de méthodes Url.RouteUrl.IUrlHelper also provides the Url.RouteUrl family of methods. Ces méthodes sont similaires à Url.Action, mais elle ne copient pas les valeurs actuelles de action et de controller vers les valeurs de route.These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. L’utilisation la plus courante est de spécifier un nom de route pour utiliser une route spécifique pour générer l’URL, généralement sans spécifier un nom de contrôleur ou d’action.The most common usage is to specify a route name to use a specific route to generate the URL, generally without specifying a controller or action name.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route"); // Generates /custom/url/to/destination
        return Content($"See {url}, it's really great.");
    }

    [HttpGet("custom/url/to/destination", Name = "Destination_Route")]
    public IActionResult Destination() {
        return View();
    }
}

Génération des URL en HTMLGenerating URLs in HTML

IHtmlHelper fournit les méthodes HtmlHelper``Html.BeginForm et Html.ActionLink pour générer respectivement les éléments <form> et <a>.IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. Ces méthodes utilisent la méthode Url.Action pour générer une URL et ils acceptent les arguments similaires.These methods use the Url.Action method to generate a URL and they accept similar arguments. Les pendants de Url.RouteUrl pour HtmlHelper sont Html.BeginRouteForm et Html.RouteLink, qui ont des fonctionnalités similaires.The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

Les TagHelpers génèrent des URL via le TagHelper form et le TagHelper <a>.TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. Ils utilisent tous les deux IUrlHelper pour leur implémentation.Both of these use IUrlHelper for their implementation. Pour plus d’informations, consultez Utilisation des formulaires.See Working with Forms for more information.

Dans les vues, IUrlHelper est disponible via la propriété Url pour toute génération d’URL ad hoc non couverte par ce qui figure ci-dessus.Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

Génération des URL dans les résultats d’actionGenerating URLS in Action Results

Les exemples précédents ont montré l’utilisation de IUrlHelper dans un contrôleur, alors que l’utilisation la plus courante dans un contrôleur est de générer une URL dans le cadre d’un résultat d’action.The examples above have shown using IUrlHelper in a controller, while the most common usage in a controller is to generate a URL as part of an action result.

Les classes de base ControllerBase et Controller fournissent des méthodes pratiques pour les résultats d’action qui référencent une autre action.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. Une utilisation typique est de rediriger après acceptation de l’entrée utilisateur.One typical usage is to redirect after accepting user input.

public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        return RedirectToAction("Index");
    }
    return View(customer);
}

Les méthodes de fabrique de résultats d’action suivent un modèle similaire aux méthodes sur IUrlHelper.The action results factory methods follow a similar pattern to the methods on IUrlHelper.

Cas spécial pour les routes conventionnelles dédiéesSpecial case for dedicated conventional routes

Le routage conventionnel peut utiliser un type spécial de définition de route appelé route conventionnelle dédiée.Conventional routing can use a special kind of route definition called a dedicated conventional route. Dans l’exemple ci-dessous, la route nommée blog est une route conventionnelle dédiée.In the example below, the route named blog is a dedicated conventional route.

app.UseMvc(routes =>
{
    routes.MapRoute("blog", "blog/{*article}",
        defaults: new { controller = "Blog", action = "Article" });
    routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

En utilisant ces définitions de route, Url.Action("Index", "Home") génère le chemin d’URL / avec la route default, mais pourquoi ?Using these route definitions, Url.Action("Index", "Home") will generate the URL path / with the default route, but why? Vous pouvez deviner que les valeurs de route { controller = Home, action = Index } seraient suffisantes pour générer une URL avec blog, et que le résultat serait /blog?action=Index&controller=Home.You might guess the route values { controller = Home, action = Index } would be enough to generate a URL using blog, and the result would be /blog?action=Index&controller=Home.

Les routes conventionnelles dédiées s’appuient sur un comportement spécial des valeurs par défaut qui n’ont pas de paramètre de route correspondant qui empêche la route d’être « trop globale » avec la génération d’URL.Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being "too greedy" with URL generation. Dans ce cas, les valeurs par défaut sont { controller = Blog, action = Article }, et ni controller ni action n’apparaissent comme paramètre de route.In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. Quand le routage effectue une génération d’URL, les valeurs fournies doivent correspondre aux valeurs par défaut.When routing performs URL generation, the values provided must match the default values. La génération d’URL avec blog échoue, car les valeurs { controller = Home, action = Index } ne correspondent pas à { controller = Blog, action = Article }.URL generation using blog will fail because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. Le routage essaye alors d’utiliser default, ce qui réussit.Routing then falls back to try default, which succeeds.

Zones (Areas)Areas

Les zones sont une fonctionnalité de MVC utilisée pour organiser des fonctionnalités connexes dans un groupe sous la forme d’un espace de noms de routage distinct (pour les actions de contrôleur) et d’une structure de dossiers (pour les vues).Areas are an MVC feature used to organize related functionality into a group as a separate routing-namespace (for controller actions) and folder structure (for views). L’utilisation de zones permet à une application d’avoir plusieurs contrôleurs portant le même nom, pour autant qu’ils soient dans des zones différentes.Using areas allows an application to have multiple controllers with the same name - as long as they have different areas. L’utilisation de zones crée une hiérarchie qui permet le routage par ajout d’un autre paramètre de route, area, à controller et à action.Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. Cette section explique comment le routage interagit avec les zones. Pour plus d’informations sur l’utilisation des zones avec des vues, consultez Zones.This section will discuss how routing interacts with areas - see Areas for details about how areas are used with views.

L’exemple suivant configure MVC pour utiliser la route conventionnelle par défaut et une route de zone pour une zone nommée Blog :The following example configures MVC to use the default conventional route and an area route for an area named Blog:

app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
    endpoints.MapControllerRoute("default_route", "{controller}/{action}/{id?}");
});

Lors de la mise en correspondance d’un chemin d’URL comme /Manage/Users/AddUser, la première route produit les valeurs de route { area = Blog, controller = Users, action = AddUser }.When matching a URL path like /Manage/Users/AddUser, the first route will produce the route values { area = Blog, controller = Users, action = AddUser }. La valeur de route area est produite par une valeur par défaut pour area ; en fait, la route créée par MapAreaRoute est équivalente à la suivante :The area route value is produced by a default value for area, in fact the route created by MapAreaRoute is equivalent to the following:

MapAreaRoute crée une route avec à la fois une valeur par défaut et une contrainte pour area en utilisant le nom de la zone fournie, dans ce cas Blog.MapAreaRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. La valeur par défaut garantit que la route produit toujours { area = Blog, ... }, et la contrainte nécessite la valeur { area = Blog, ... } pour la génération d’URL.The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

Conseil

Le routage conventionnel est dépendant de l’ordre.Conventional routing is order-dependent. En général, les routes avec des zones doivent être placées plus haut dans la table de routage, car elles sont plus spécifiques que les routes sans zone.In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

Avec l’exemple ci-dessus, les valeurs de route seraient mises en correspondance avec l’action suivante :Using the above example, the route values would match the following action:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}

AreaAttribute est ce qui indique qu’un contrôleur fait partie d’une zone : nous disons que ce contrôleur est dans la zone Blog.The AreaAttribute is what denotes a controller as part of an area, we say that this controller is in the Blog area. Les contrôleurs sans attribut [Area] ne sont membres d’aucune zone et ne sont pas trouvés en correspondance quand la valeur de route area est fournie par le routage.Controllers without an [Area] attribute are not members of any area, and will not match when the area route value is provided by routing. Dans l’exemple suivant, seul le premier contrôleur répertorié peut correspondre aux valeurs de route { area = Blog, controller = Users, action = AddUser }.In the following example, only the first controller listed can match the route values { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        // GET /manage/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        // GET /zebra/users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
    // Matches { area = string.Empty, controller = Users, action = AddUser }
    // Matches { area = null, controller = Users, action = AddUser }
    // Matches { controller = Users, action = AddUser }
    public class UsersController : Controller
    {
        // GET /users/adduser
        public IActionResult AddUser()
        {
            var area = ControllerContext.ActionDescriptor.RouteValues["area"];
            var actionName = ControllerContext.ActionDescriptor.ActionName;
            var controllerName = ControllerContext.ActionDescriptor.ControllerName;

            return Content($"area name:{area}" +
                $" controller:{controllerName}  action name: {actionName}");
        }
    }
}

Notes

L’espace de noms de chaque contrôleur est montré ici par souci d’exhaustivité, sans quoi les contrôleurs auraient un conflit de noms et généreraient une erreur de compilateur.The namespace of each controller is shown here for completeness - otherwise the controllers would have a naming conflict and generate a compiler error. Les espaces de noms de classe n’ont pas d’effet sur le routage de MVC.Class namespaces have no effect on MVC's routing.

Les deux premiers contrôleurs sont membres de zones, et ils sont trouvés en correspondance seulement quand le nom de leur zone respective est fourni par la valeur de route area.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. Le troisième contrôleur n’est membre d’aucune zone et peut être trouvé en correspondance seulement quand aucune valeur pour area n’est fournie par le routage.The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

Notes

En termes de mise en correspondance avec aucune valeur, l’absence de la valeur area est identique à une valeur null ou de chaîne vide pour area.In terms of matching no value, the absence of the area value is the same as if the value for area were null or the empty string.

Lors de l’exécution d’une action à l’intérieur d’une zone, la valeur de route pour area est disponible en tant que valeur ambiante, que le routage peut utiliser pour la génération d’URL.When executing an action inside an area, the route value for area will be available as an ambient value for routing to use for URL generation. Cela signifie que par défaut, les zones agissent par attraction pour la génération d’URL, comme le montre l’exemple suivant.This means that by default areas act sticky for URL generation as demonstrated by the following sample.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
    [Area("Duck")]
    public class UsersController : Controller
    {
        // GET /Manage/users/GenerateURLInArea
        public IActionResult GenerateURLInArea()
        {
            // Uses the 'ambient' value of area.
            var url = Url.Action("Index", "Home");
            // Returns /Manage/Home/Index
            return Content(url);
        }

        // GET /Manage/users/GenerateURLOutsideOfArea
        public IActionResult GenerateURLOutsideOfArea()
        {
            // Uses the empty value for area.
            var url = Url.Action("Index", "Home", new { area = "" });
            // Returns /Manage
            return Content(url);
        }
    }
}

Présentation d’IActionConstraintUnderstanding IActionConstraint

Notes

Cette section est une présentation détaillée des mécanismes internes du framework et de la façon dont MVC choisit une action à exécuter.This section is a deep-dive on framework internals and how MVC chooses an action to execute. Une application classique n’a pas besoin d’une IActionConstraint personnalisée.A typical application won't need a custom IActionConstraint

Vous avez probablement déjà utilisé IActionConstraint même si vous n’êtes pas familiarisé avec l’interface.You have likely already used IActionConstraint even if you're not familiar with the interface. L’attribut [HttpGet] et les attributs [Http-VERB] similaires implémentent IActionConstraint de façon à limiter l’exécution d’une méthode d’action.The [HttpGet] Attribute and similar [Http-VERB] attributes implement IActionConstraint in order to limit the execution of an action method.

public class ProductsController : Controller
{
    [HttpGet]
    public IActionResult Edit() { }

    public IActionResult Edit(...) { }
}

Dans l’hypothèse d’une route conventionnelle par défaut, le chemin d’URL /Products/Edit produirait les valeurs { controller = Products, action = Edit }, qui seraient en correspondance avec les deux actions montrées ici.Assuming the default conventional route, the URL path /Products/Edit would produce the values { controller = Products, action = Edit }, which would match both of the actions shown here. Dans la terminologie IActionConstraint, nous pouvons dire que ces deux actions sont considérées comme candidates, car elles correspondent toutes deux aux données de la route.In IActionConstraint terminology we would say that both of these actions are considered candidates - as they both match the route data.

Quand HttpGetAttribute s’exécute, il indique que Edit() est une correspondance pour GET et qu’il n’est une correspondance pour aucun des autres verbes HTTP.When the HttpGetAttribute executes, it will say that Edit() is a match for GET and isn't a match for any other HTTP verb. L’action Edit(...) n’a aucune contrainte définie et elle ne correspond donc à aucun verbe HTTP.The Edit(...) action doesn't have any constraints defined, and so will match any HTTP verb. Par conséquent, dans l’hypothèse d’un POST, seul Edit(...) est en correspondance.So assuming a POST - only Edit(...) matches. Cependant, pour un GET, les deux actions peuvent néanmoins être en correspondance, mais une action avec IActionConstraint est toujours considérée comme étant *meilleure * qu’une action sans.But, for a GET both actions can still match - however, an action with an IActionConstraint is always considered better than an action without. Par conséquent, comme Edit() a [HttpGet], elle est considérée comme étant plus spécifique et est sélectionnée si les deux actions peuvent correspondre.So because Edit() has [HttpGet] it's considered more specific, and will be selected if both actions can match.

D’un point de vue conceptuel, IActionConstraint est une forme de surcharge, mais au lieu de surcharger des méthodes portant le même nom, elle surcharge entre des actions qui correspondent à la même URL.Conceptually, IActionConstraint is a form of overloading, but instead of overloading methods with the same name, it's overloading between actions that match the same URL. Le routage par attributs utilise également IActionConstraint et peut aboutir à des actions de différents contrôleurs, toutes considérées comme candidates.Attribute routing also uses IActionConstraint and can result in actions from different controllers both being considered candidates.

Implémentation d’IActionConstraintImplementing IActionConstraint

La façon la plus simple d’implémenter une IActionConstraint est de créer une classe dérivée de System.Attribute et de la placer sur vos actions et vos contrôleurs.The simplest way to implement an IActionConstraint is to create a class derived from System.Attribute and place it on your actions and controllers. MVC découvre automatiquement les IActionConstraint qui sont appliquées en tant qu’attributs.MVC will automatically discover any IActionConstraint that are applied as attributes. Vous pouvez utiliser le modèle d’application pour appliquer des contraintes, et il s’agit probablement de l’approche la plus souple, car elle vous permet de programmer des méta-informations indiquant comment elles sont appliquées.You can use the application model to apply constraints, and this is probably the most flexible approach as it allows you to metaprogram how they're applied.

Dans l’exemple suivant, une contrainte choisit une action en fonction de l' indicatif du pays à partir des données de l’itinéraire.In the following example, a constraint chooses an action based on a country code from the route data. Exemple complet sur GitHub.The full sample on GitHub.

public class CountrySpecificAttribute : Attribute, IActionConstraint
{
    private readonly string _countryCode;

    public CountrySpecificAttribute(string countryCode)
    {
        _countryCode = countryCode;
    }

    public int Order
    {
        get
        {
            return 0;
        }
    }

    public bool Accept(ActionConstraintContext context)
    {
        return string.Equals(
            context.RouteContext.RouteData.Values["country"].ToString(),
            _countryCode,
            StringComparison.OrdinalIgnoreCase);
    }
}

Vous êtes responsable de l’implémentation de la méthode Accept et du choix d’un « ordre » pour l’exécution de la contrainte.You are responsible for implementing the Accept method and choosing an 'Order' for the constraint to execute. Dans ce cas, la méthode Accept retourne true pour indiquer que l’action est une correspondance quand la valeur de la route country correspond à la valeur.In this case, the Accept method returns true to denote the action is a match when the country route value matches. Ceci diffère d’un RouteValueAttribute, car elle permet à défaut d’appliquer une action sans attributs.This is different from a RouteValueAttribute in that it allows fallback to a non-attributed action. L’exemple montre que si vous définissez une action en-US, un code pays comme fr-FR passe à défaut à un contrôleur plus générique auquel [CountrySpecific(...)] n’est pas appliqué.The sample shows that if you define an en-US action then a country code like fr-FR will fall back to a more generic controller that doesn't have [CountrySpecific(...)] applied.

La propriété Order décide de l’étape dont la contrainte fait partie.The Order property decides which stage the constraint is part of. Les contraintes d’action s’exécutent dans des groupes en fonction de Order.Action constraints run in groups based on the Order. Par exemple, tous les attributs de méthode HTTP fournis par le framework utilisent la même valeur pour Order, de façon à ce qu’ils s’exécutent dans la même étape.For example, all of the framework provided HTTP method attributes use the same Order value so that they run in the same stage. Vous pouvez avoir autant d’étapes que nécessaire pour implémenter les stratégies souhaitées.You can have as many stages as you need to implement your desired policies.

Conseil

Pour décider d’une valeur pour Order, déterminez si votre contrainte doit ou non être appliquée avant les méthodes HTTP.To decide on a value for Order think about whether or not your constraint should be applied before HTTP methods. Les nombres les plus petits s’exécutent en premier.Lower numbers run first.