web-dev-qa-db-fra.com

Paramètre de route avec barre oblique "/" dans l'URL

Je sais que vous pouvez appliquer un caractère générique dans l'attribut route pour autoriser /, Comme la date, par exemple:

[Route("orders/{*orderdate}")]

Le problème avec le caractère générique ne s'applique qu'au dernier paramètre de l'URI. Comment résoudre le problème si vous souhaitez avoir l'URI suivant:

[Route("orders/{orderdate}/customers")]

Mise à jour:

Je sais qu'il existe peu d'options pour résoudre le problème en refactorisant le code, veuillez donc ne pas proposer de solution comme:

  1. changer le modèle de route en [Route("orders/customers/{orderdate}")]
  2. changer la date dans un format différent (par exemple "dd-mm-yyyy")
30
bet

@ bet .. Je pense que le genericUriParserOptions n'est plus applicable à .net 4.5 ou version ultérieure ..

Comme suggéré par @ JotaBe , vous devrez peut-être décoder correctement la demande d'URL. Dans la plupart des cas, le %2F sera automatiquement traduit en barre oblique '/'. Donc, si vous devez y échapper, vous devrez décoder le '%' char en premier lieu .. donc votre URL: ressemblera à: www.domain.com/api/orders/23%252F06%252F2015/customers

Remarquez les caractères '%252F' sera traduit en _ '%2F'

MODIFIER

Ok voici la solution complète (essayé et travaillant pour moi):

  1. En supposant que vous ayez un point de terminaison API comme ceci:

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
    }
    
  2. Dans le web.config vous devrez définir le requestPathInvalidCharacters à vide ce qui indique à asp.net d'autoriser toutes les requêtes

    <system.web>
        <httpRuntime targetFramework="4.5" requestPathInvalidCharacters=""/>                
    </system.web>
    <system.webServer>
        <security>
          <requestFiltering allowDoubleEscaping="true" />
        </security>
    </system.webServer>
    
  3. Lorsque le client envoie la demande à l'API, vous devez vous assurer d'échapper au '%' ainsi:

    www.domain.com/api/orders/23%252F06%252F2015/customers

  4. Vous devez ensuite décoder la demande

    [Route("orders/{date}/customers")]
    public HttpResponseMessage Get(string date)
    {
            DateTime actualDate = DateTime.Parse(System.Net.WebUtility.UrlDecode(date)); // date is 23/06/2015
    }
    
26
ronnie

Comme indiqué dans le commentaire de @AlexeiLevenkov, c'est faux:

Vous ne pouvez pas avoir un paramètre dans l'URL qui accepte les barres obliques, car il s'agit d'un symbole spécial qui sépare chaque fragment d'URL. Ainsi, chaque fois que vous incluez ce symbole dans votre URL, il y aura de nouveaux fragments et un seul paramètre ne peut pas inclure plusieurs fragments.

Si vous voulez plus de détails, lisez ceci , mais ce sont les extraits les plus pertinents:

  • le chemin URL se termine dans le premier ? ou # trouvé dans l'URL. Ainsi, les barres obliques créent uniquement des fragments dans la section du chemin URL avant l'occurrence ou l'un de ces symboles.
  • De la section 3.4: Le composant de requête est indiqué par le premier caractère de point d'interrogation ("?") Et terminé par un caractère de signe numérique ("#") ou par la fin de l'URI.

Ainsi, la chaîne de requête peut inclure des barres obliques, /, Si vous le souhaitez, et elles ne définiront pas du tout de segments de chemin.

Voici quelques solutions à la question:

  • inclure des fragments pour le jour, le mois et l'année, comme ceci: [Route("orders/{month}/{day}/{year}/customers")] puis créer la date côté serveur
  • demander à l'utilisateur d'utiliser un séparateur différent, comme un tiret ou un point, qui ne créera pas de problèmes, le recevoir à la chaîne et l'analyser vous-même (ou utiliser votre propre classeur personnalisé pour prendre en charge ce format)
  • utilisez extension de réécriture d'URL pour modifier l'URL avant qu'elle n'atteigne le système de routage, et analysez-la comme expliqué dans la solution précédente (cela nécessite un hébergement dans IIS)
  • recevez-le comme une chaîne de requête, c'est-à-dire quelque chose comme ceci: ´? date = 02/03/2015´ (vous feriez mieux de l'encoder)

REMARQUE: votre question d'origine disait "chaîne de requête", et mon commentaire sur le codage faisait référence à la chaîne de requête, qui est le dernier segment d'une URL après le point d'interrogation, si présent, like &id=27. J'ai corrigé votre question afin qu'elle ne mentionne pas "chaîne de requête", qui n'était pas le bon nom pour ce dont vous avez besoin

8
JotaBe

Vous pouvez utiliser l'URI [Route("orders/{DD:int}/{MM:int}/{YY:int}}/customers")] suivante, puis utiliser un classeur de modèle personnalisé pour prendre DD/MM/YY et les transformer en une date que vous pouvez lier dans votre méthode d'action.

Vous pouvez choisir la façon dont vous voulez gérer les contraintes (aller plus loin avec les regex) ou utiliser la validation et renvoyer 400 si elle ne correspond pas.

L'approche la plus simple consiste à prendre le Day/Month/Year et le mettre dans le code.

Voici un lien pour traitant de la liaison de modèles .

1
Yishai Galatzer

C # a sa propre méthode qui ignore les règles des séquences d'échappement, le nom de la méthode est ri.UnescapeDataString ( votre paramètre de chaîne de requête ) vous pouvez l'utiliser tout en obtenant la valeur des paramètres

0
asif juneja