Paramètre d'itinéraire 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 l'entrée de date par exemple:
[Route("orders/{*orderdate}")]
Le problème avec le caractère générique n'est applicable qu'au dernier paramètre de L'URI. Comment puis-je résoudre le problème si vous voulez avoir L'URI suivant:
[Route("orders/{orderdate}/customers")]
Mise à Jour:
Je sais qu'il y a peu d'options pour résoudre le problème en refactorisant le code, alors n'offrez pas de solution quelque chose comme:
- changer le modèle de route en
[Route("orders/customers/{orderdate}")]
- modifier la date dans un format différent (par exemple,
"dd-mm-yyyy"
)
3 réponses
@pari.. Je pense que 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 requête url. Dans la plupart des cas, le %2F sera automatiquement traduit en une barre oblique'/', donc si vous devez l'échapper, vous devrez décoder le caractère '%' en premier lieu.. donc, votre URL: ressemblera à quelque chose comme: www.domain.com/api/orders/23%252F06%252F2015/customers
Notez que les caractères '% 252F ' seront traduit en '%2F '
Modifier
Ok voici la solution complète (essayé et travailler pour moi):
-
En supposant que vous avez un point de terminaison D'API comme ceci:
[Route("orders/{date}/customers")] public HttpResponseMessage Get(string date) { }
-
Dans le web.config vous devrez définir requestPathInvalidCharacters sur empty ce qui indique asp.net pour autoriser toutes les requêtes
<system.web> <httpRuntime targetFramework="4.5" requestPathInvalidCharacters=""/> </system.web> <system.webServer> <security> <requestFiltering allowDoubleEscaping="true" /> </security> </system.webServer>
-
Lorsque le client envoie la requête à L'API, vous devez vous assurer d'échapper au ' % ' Comme donc:
Www.domain.com/api/orders/23%252F06%252F2015/customers
-
Vous devez ensuite décoder la requête
[Route("orders/{date}/customers")] public HttpResponseMessage Get(string date) { DateTime actualDate = DateTime.Parse(System.Net.WebUtility.UrlDecode(date)); // date is 23/06/2015 }
, 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 de L'URL termine dans le premier
?
ou#
trouvé dans l'URL. Ainsi, les barres obliques ne créent que des fragments dans la section du chemin D'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 point d'interrogation ("?") caractère et terminé par un signe numérique ("#") caractère ou à la fin de L'URI.
Ainsi, la chaîne de requête peut inclure des barres obliques, /
, si désiré, et elles ne définiront pas de segments de chemin à tout.
Voici quelques solutions à la question:
- incluez des fragments pour le jour, le mois et l'année, comme ceci: {[3] } puis créez la date côté serveur
- exiger de l'utilisateur d'utiliser un séparateur différent, comme un tiret ou un point, ce qui ne créera pas de problèmes, le recevoir à la chaîne une analyse vous-même (ou utiliser votre propre classeur personnalisé pour prendre en charge ce format)
- utilisez l'extension URL Rewrite pour modifier l'URL avant qu'elle n'atteigne le système de routage, et analysez-le comme expliqué dans la solution précédente (cela nécessite un hébergement dans IIS)
- le recevoir 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 originale disait "chaîne de requête" , et mon commentaire sur l'encodage 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", ce qui n'était pas le bon nom pour ce dont vous avez besoin
Vous pouvez utiliser L'URI suivant [Route("orders/{DD:int}/{MM:int}/{YY:int}}/customers")]
et puis utilisez 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 comment vous voulez gérer les contraintes (aller plus strict avec les expressions rationnelles) ou utiliser la validation et renvoyer 400 si elle ne correspond pas.
L'approche La plus simple est de prendre le Day/Month/Year
et le mettre dans le code.
Voici un lien pour traitant modelbinding.