Partager via


Routage ASP.NET

Mise à jour : novembre 2007

Le routage ASP.NET vous permet d'utiliser des URL qui n'ont pas à mapper aux fichiers spécifiques dans un site Web. L'URL n'ayant pas à mapper à un fichier, vous pouvez donc utiliser dans une application Web des URL descriptives de l'action de l'utilisateur qui sont de ce fait plus facilement compréhensibles.

Dans une application ASP.NET qui n'utilise pas de routage, une demande entrante pour une URL mappe généralement à un fichier physique sur le disque tel qu'un fichier .aspx. Par exemple, une demande pour https://server/application/Products.aspx?id=4 mappe à un fichier nommé Products.aspx qui contient le code et le balisage permettant de restituer une réponse au navigateur. La page Web utilise la valeur de chaîne de requête de id=4 pour déterminer le type de contenu à afficher, mais il est probable que la valeur soit peu évocatrice pour l'utilisateur.

Dans le routage ASP.NET, vous définissez des modèles d'URL qui contiennent des espaces réservés pour les valeurs utilisées lorsque vous gérez des demandes d'URL. Au moment de l'exécution, les éléments de l'URL qui suivent le nom de l'application sont analysés sous la forme de valeurs discrètes, selon le modèle d'URL que vous avez défini. Par exemple, dans la demande pour https://server/application/Products/show/beverages, l'analyseur de routage peut passer les valeurs Products, show et beverages à un gestionnaire pour la demande. Par opposition, dans une demande qui n'est pas gérée par routage d'URL, le fragment /Products/show/beverages serait interprété comme le chemin d'accès à un fichier dans l'application.

Vous pouvez également utiliser des modèles d'URL pour créer par programme des URL qui correspondent aux itinéraires. Cela vous permet de centraliser la logique permettant de créer des liens hypertexte dans votre application ASP.NET.

Routage ASP.NET et réécriture d'URL

Le routage ASP.NET diffère des autres méthodes de réécriture d'URL. La réécriture d'URL traite les demandes entrantes en modifiant réellement l'URL avant qu'elle envoie la demande à la page Web. Par exemple, une application qui utilise la réécriture d'URL peut changer une URL de /Products/Widgets/ en /Products.aspx?id=4. Par ailleurs, la réécriture d'URL n'implique généralement pas d'API pour la création d'URL basées sur vos modèles. Si, lors de la réécriture, vous modifiez un modèle d'URL, vous devez mettre à jour manuellement tous les liens hypertexte qui contiennent l'URL d'origine.

Avec le routage ASP.NET, l'URL n'est pas modifiée lorsqu'une demande entrante est gérée, car le routage peut extraire des valeurs de l'URL. Lorsque vous devez créer une URL, vous passez des valeurs de paramètre dans une méthode qui génère l'URL pour vous. Pour modifier le modèle d'URL, modifiez-le dans un emplacement, et tous les liens que vous créez dans l'application qui sont basés sur ce modèle utiliseront automatiquement le nouveau.

Définition d'itinéraires d'URL

Les modèles d'URL que vous définissez sont connus sous le nom d'itinéraires. Dans un itinéraire, vous spécifiez des espaces réservés mappés à des valeurs qui sont analysées à partir de la demande d'URL. Vous pouvez également spécifier des valeurs de constante qui sont utilisées pour la mise en correspondance des demandes d'URL.

Dans un itinéraire, vous définissez des espaces réservés (connus sous le nom de paramètres d'URL) en les plaçant entre accolades ( { and } ). Le caractère / est interprété comme un délimiteur lorsque l'URL est analysée. Les informations dans la définition d'itinéraire autres que les délimiteurs et non placées entre accolades sont traitées comme une valeur de constante. Les valeurs extraites entre les délimiteurs sont assignées aux espaces réservés.

Vous pouvez définir plusieurs espaces réservés entre les délimiteurs, mais ils doivent être séparés par une valeur de constante. Par exemple, {language}-{country}/{action} est un modèle d'itinéraire valide. Toutefois, {language}{country}/{action} n'est pas un modèle valide, car il n'y a pas de constante ou de délimiteur entre les espaces réservés. Par conséquent, le routage ne peut pas déterminer où séparer la valeur pour l'espace réservé language de la valeur pour l'espace réservé country.

Le tableau suivant présente des modèles d'itinéraire valides, ainsi que des exemples de demandes d'URL correspondantes.

Définition d'itinéraire

Exemple d'URL correspondante

{controller}/{action}/{id}

/Products/show/beverages

{table}/Details.aspx

/Products/Details.aspx

blog/{action}/{entry}

/blog/show/123

{reporttype}/{year}/{month}/{day}

/sales/2008/1/5

{locale}/{action}

/en-US/show

{language}-{country}/{action}

/en-US/show

En général, vous ajoutez des itinéraires dans une méthode qui est appelée à partir du gestionnaire pour l'événement Application_Start dans le fichier Global.asax. Cette approche garantit la disponibilité des itinéraires lors du démarrage de l'application. Elle vous permet également d'appeler la méthode directement lorsque vous exécutez un test unitaire de l'application. Si vous souhaitez appeler une méthode directement lorsque vous exécutez le test unitaire de l'application, la méthode qui enregistre les itinéraires doit être statique (Shared dans Visual Basic) et doit avoir un paramètre RouteCollection.

Pour ajouter des itinéraires, ajoutez-les à la propriété Routes statique de la classe RouteTable. La propriété Routes est un objet RouteCollection objet qui stocke tous les itinéraires pour l'application ASP.NET. L'exemple suivant présente le code d'un fichier Global.asax qui ajoute un objet Route qui définit deux paramètres d'URL nommés action et categoryName.

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    RegisterRoutes(RouteTable.Routes)
End Sub

Shared Sub RegisterRoutes(routes As RouteCollection)
    Dim urlPattern As String
    Dim categoryRoute As Route

    urlPattern = "Category/{action}/{categoryName}"
    categoryRoute = New Route(urlPattern, New CategoryRouteHandler)

    routes.Add(categoryRoute)
End Sub
protected void Application_Start(object sender, EventArgs e)
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add(new Route
    (
         "Category/{action}/{categoryName}"
         , new CategoryRouteHandler()
    ));
}

Définition de valeurs par défaut pour les paramètres d'itinéraire

Lorsque vous définissez un itinéraire, vous pouvez assigner une valeur par défaut à un paramètre. La valeur par défaut est utilisée si une valeur pour ce paramètre n'est pas incluse dans l'URL. Pour définir des valeurs par défaut pour un itinéraire, assignez un dictionnaire à la propriété Defaults de la classe Route. L'exemple suivant présente un itinéraire avec des valeurs par défaut.

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
    RegisterRoutes(RouteTable.Routes)
End Sub

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    Dim urlPattern As String
    Dim categoryRoute As Route

    urlPattern = "Category/{action}/{categoryName}"
    categoryRoute = New Route(urlPattern, New CategoryRouteHandler)
    categoryRoute.Defaults = New RouteValueDictionary(New With _
        {.categoryName = "food", _
         .action = "show"} )

    routes.Add(categoryRoute)
End Sub
void Application_Start(object sender, EventArgs e) 
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
  routes.Add(new Route
  (
     "Category/{action}/{categoryName}"
          new CategoryRouteHandler()
  )
    {
       Defaults = new RouteValueDictionary 
           {{"categoryName", "food"}, {"action", "show"}}
     }
  );
}

Lorsque le routage ASP.NET gère une demande d'URL, la définition d'itinéraire présentée dans l'exemple (avec les valeurs par défaut food pour categoryName et show pour action) donne les résultats figurant dans le tableau suivant.

URL

Des valeurs de paramètre

/Category

action = "show" (valeur par défaut)

categoryName = "food" (valeur par défaut)

/Category/add

action = "add"

categoryName = "food" (valeur par défaut)

/Category/add/beverages

action = "add"

categoryName= "beverages"

Gestion d'un nombre variable de segments

Vous pouvez parfois être amené à gérer des demandes d'URL qui contiennent un nombre variable de segments d'URL. Lorsque vous définissez un itinéraire, vous pouvez spécifier que le dernier paramètre corresponde au reste de l'URL en le marquant avec un astérisque (*). Ce type de paramètre est connu sous le nom de paramètre passe-partout. Un itinéraire avec un paramètre passe-partout correspondra également aux URL qui ne contiennent pas de valeurs pour le dernier paramètre. L'exemple suivant présente un modèle d'itinéraire qui correspond à un nombre inconnu de segments.

query/{queryname}/{*queryvalues}

Lorsque le routage ASP.NET gère une demande d'URL, la définition d'itinéraire affichée dans l'exemple donne les résultats figurant dans le tableau suivant.

URL

Des valeurs de paramètre

/query/select/bikes/onsale

NomRequête = "select"

ValeursRequête = "bikes/onsale"

/query/select/bikes

NomRequête = "select"

ValeursRequête = "bikes"

/query/select

NomRequête = "select"

ValeursRequête = Chaîne vide

Ajout de contraintes aux itinéraires

Outre la mise en correspondance d'une demande d'URL avec une définition d'itinéraire en fonction du nombre de paramètres dans l'URL, vous pouvez spécifier que les valeurs des paramètres se conforment à certaines contraintes. Si une URL contient des valeurs non conformes aux contraintes d'un itinéraire, celui-ci n'est pas utilisé pour gérer la demande. Vous ajoutez des contraintes pour vous assurer que les paramètres d'URL contiennent des valeurs qui fonctionneront dans votre application.

Les contraintes sont définies en utilisant des expressions régulières ou des objets qui implémentent l'interface IRouteConstraint. Lorsque vous ajoutez la définition d'itinéraire à la collection Routes, vous ajoutez des contraintes en créant un objet RouteValueDictionary qui contient le test de vérification. Vous assignez ensuite cet objet à la propriété Constraints. La clé dans le dictionnaire identifie le paramètre auquel la contrainte s'applique. La valeur dans le dictionnaire peut être soit une chaîne qui représente une expression régulière, soit un objet qui implémente l'interface IRouteConstraint.

Si vous fournissez une chaîne, le routage traite la chaîne comme une expression régulière et vérifie si la valeur du paramètre est valide en appelant la méthode IsMatch de la classe Regex. L'expression régulière ne nécessite jamais de respecter la casse. Pour plus d'informations, consultez Expressions régulières du .NET Framework.

Si vous fournissez un objet IRouteConstraint, le routage ASP.NET vérifie si la valeur du paramètre est valide en appelant la méthode Match de l'objet IRouteConstraint. La méthode Match retourne une valeur booléenne qui indique si la valeur du paramètre est valide.

L'exemple suivant présente des contraintes qui limitent les valeurs pouvant être incluses dans les paramètres locale et year.

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    Dim urlPattern As String
    Dim reportRoute As Route

    urlPattern = "{locale}/{year}"
    reportRoute = New Route(urlPattern, New ReportRouteHandler)
    reportRoute.Constraints = New RouteValueDictionary(New With _
        {.locale = "[a-z]{2}-[a-z]{2}", .year = "\d{4}"})

    routes.Add(reportRoute) 
End Sub
void Application_Start(object sender, EventArgs e) 
{
    RegisterRoutes(RouteTable.Routes);
}

public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add(new Route
    (
      "{locale}/{year}"
         , new ReportRouteHandler()
    )
       {
          Constraints = new RouteValueDictionary 
          {{"locale", "[a-z]{2}-[a-z]{2}"},{year, @"\d{4}"}}
       });
}

Lorsque le routage gère une demande d'URL, la définition d'itinéraire affichée dans l'exemple précédent donne les résultats figurant dans le tableau suivant.

URL

Résultat

/en-US

Pas de correspondance. locale et year sont tous deux requis.

/en-US/08

Pas de correspondance. La contrainte sur year requiert 4 chiffres.

/en-US/2008

locale = "en-US"

year = "2008"

Scénarios lorsque le routage ne s'applique pas

Par défaut, le routage ne gère pas les demandes qui mappent à un fichier physique existant sur le serveur Web. Par exemple, une demande pour https://server/application/Products/Beverages/Coffee.aspx n'est pas gérée par le routage si un fichier physique existe sur Products/Beverages/Coffee.aspx. Le routage ne gère pas la demande même si elle correspond à un modèle défini, tel que {controller}/{action}/{id}.

Si vous souhaitez que le routage gère toutes les demandes, même celles qui pointent sur des fichiers, vous pouvez substituer le comportement par défaut en affectant true à la propriété RouteExistingFiles de l'objet RouteCollection. Lorsque vous définissez cette valeur à true, toutes les demandes qui correspondent à un modèle défini sont gérées par le routage.

Vous pouvez également spécifier que le routage ne gère pas certaines demandes d'URL. Pour ce faire, définissez un itinéraire et spécifiez l'utilisation de la classe StopRoutingHandler pour gérer ce modèle. Lorsqu'une demande est gérée par un objet StopRoutingHandler, l'objet StopRoutingHandler bloque tout autre traitement de la demande en tant qu'itinéraire. À la place, la demande est traitée en tant que page ASP.NET, service Web ou autre point de terminaison ASP.NET. Par exemple, vous pouvez ajouter la définition d'itinéraire suivante pour que le routage ne gère pas les demandes pour le fichier WebResource.axd.

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    routes.Add(New Route("{resource}.axd/{*pathInfo}", New StopRouteHandler()))
End Sub
public static void RegisterRoutes(RouteCollection routes)
{
  routes.Add(new Route("{resource}.axd/{*pathInfo}", new StopRouteHandler()));
}

Mise en correspondance des URL avec les itinéraires

Lorsque le routage gère des demandes d'URL, il essaie de mettre l'URL de la demande en correspondance avec un itinéraire. La mise en correspondance d'une demande d'URL avec un itinéraire dépend de l'ensemble des conditions suivantes :

  • Modèles d'itinéraire que vous avez définis ou modèles d'itinéraire par défaut, le cas échéant, qui sont inclus dans votre type de projet.

  • Ordre dans lequel vous les avez ajoutés à la collection Routes.

  • Valeurs par défaut que vous avez fournies pour un itinéraire.

  • Contraintes que vous avez fournies pour un itinéraire.

  • Si vous avez défini que le routage doit gérer les demandes qui correspondent à un fichier physique.

Pour éviter la gestion d'une demande par le gestionnaire incorrect, vous devez prendre toutes ces conditions en compte lors de la définition des itinéraires. L'ordre dans lequel les objets Route apparaissent dans la collection Routes est important. La tentative de mise correspondance d'itinéraire s'effectue du premier itinéraire au dernier dans la collection. En cas de correspondance avérée, les itinéraires restants ne sont pas évalués. En règle générale, ajoutez des itinéraires à la propriété Routes en partant des définitions d'itinéraire les plus spécifiques aux moins spécifiques.

Par exemple, supposons que vous ajoutez des itinéraires avec les modèles suivants :

  • Itinéraire 1 : {controller}/{action}/{id}

  • Itinéraire 2 : products/show/{id}

Itinéraire 2 ne gèrera jamais une demande car Itinéraire 1 est évalué en premier, et il correspondra toujours aux demandes qui pourraient également fonctionner pour Itinéraire 2. Une demande pour https://server/application/products/show/bikes semble davantage correspondre à Itinéraire 2, mais elle est gérée par Itinéraire 1 avec les valeurs suivantes :

  • controller = products

  • action = show

  • id = bikes

Les valeurs par défaut sont utilisées si un paramètre ne figure pas dans la demande. Par conséquent, un itinéraire peut correspondre à une demande à laquelle vous ne vous attendiez pas. Par exemple, supposons que vous ajoutez des itinéraires avec les modèles suivants :

  • Itinéraire 1 : {report}/{year}/{month}, avec les valeurs par défaut pour year et month.

  • Itinéraire 2 : {report}/{year}, avec la valeur par défaut pour year.

Itinéraire 2 ne gèrera jamais une demande. Itinéraire 1 peut être prévu pour un rapport mensuel, et Itinéraire 2 peut être prévu pour un rapport annuel. Toutefois, les valeurs par défaut dans Itinéraire 1 signifient qu'il correspondra aux demandes qui peuvent également fonctionner pour Itinéraire 2.

Vous pouvez éviter toute ambiguïté dans les modèles en incluant des constantes, telles que annual/{report}/{year} et monthly/{report}/{year}/{month}.

Si une URL ne correspond pas à un objet Route défini dans la collection RouteTable, le routage ASP.NET ne traite pas la demande. À la place, le traitement est passé à une page ASP.NET, à un service Web ou à un autre point de terminaison ASP.NET.

Création d'URL à partir des itinéraires

Vous pouvez utiliser des itinéraires pour générer des URL lorsque vous souhaitez centraliser la logique permettant de construire des URL. Pour créer une URL, passez les valeurs de paramètre en tant que dictionnaire à la méthode GetVirtualPath de l'objet RouteCollection. La méthode GetVirtualPath recherche le premier itinéraire dans l'objet RouteCollection qui correspond aux paramètres dans le dictionnaire. L'itinéraire correspondant est utilisé pour générer l'URL. L'exemple suivant présente une définition d'itinéraire.

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    routes.Add(New Route( _
      "Category/{action}/{categoryName}", _
      New RouteValueDictionary(New With _
          {.categoryName = "food", _
           .action = "show"}), _
           New CategoryRouteHandler()) )
End Sub
public static void RegisterRoutes(RouteCollection routes)
{
  routes.Add(new Route
  (
     "Category/{action}/{categoryName}"
          new CategoryRouteHandler()
  )
    {
       Defaults = new RouteValueDictionary {{"categoryName", "food"}, 
           {"action", "show"}}
     }
  );
}

L'exemple suivant présente un contrôle qui crée une URL en fonction de l'itinéraire.

Dim urlParameters As RouteValueDictionary

urlParameters = New RouteValueDictionary(New With {.categoryName = "beverages", _
        .action = "summarize"})
HyperLink1.href = RouteTable.Routes.GetVirtualPath _
    (context, urlParameters).VirtualPath
HyperLink1.href = RouteTable.Routes.GetVirtualPath
  (context,
  new RouteValueDictionary { 
    { "categoryName", "beverages" }, 
    {"action", "summarize" }}
  ).VirtualPath;

Lorsque ce code s'exécutera, le contrôle HyperLink1 contiendra la valeur "Category/summarize/beverages" dans la propriété href.

Lorsque vous créez une URL à partir d'un itinéraire, vous pouvez spécifier l'itinéraire à utiliser en incluant un nom pour celui-ci. Pour plus d'informations, consultez Comment : construire une URL à partir d'un itinéraire.

Voir aussi

Concepts

Présentation de l'infrastructure ASP.NET