ASP.NET MVC ActionLink: URL étrange généré
-
18-09-2019 - |
Question
Pourquoi l'appel Html.ActionLink
suivant:
Html.ActionLink("Approve", "Advance", new { id = Model.ID, step = StepType.Approve })
générer une URL avec des paramètres de requête plutôt que d'une URL « reposant », i.e..
http://localhost/Website/Case/Advance/1?step=Refer
Je n'ai que la route par défaut enregistré, ai-je besoin des itinéraires supplémentaires qui peuvent comprendre ce que le paramètre « StepType » est?
Je l'ai essayé d'ajouter cette voie dans après la route par défaut:
routes.MapRoute(
"CaseAdvance",
"{controller}/{action}/{id}/{step}",
new {controller = "Case", action = "Advance", id = "", step = StepType.Refer});
mais il n'a eu aucun effet. Ajout du nouvel enregistrement d'itinéraire avant la valeur par défaut m'a donné une erreur:
Le dictionnaire de paramètres contient une entrée nulle pour le paramètre « id » de type non annulable « System.Int64 » pour System.Web.Mvc.ActionResult » méthode Advance (Int64, Website.Core.StepType) » dans 'Website.Controllers.CaseController'. Pour un paramètre optionnel son type devrait être soit un type de référence ou d'un type Nullable.
La solution
route personnalisée attraper trop au moment
Votre exception ne vous indique que votre itinéraire personnalisé est attraper quelque chose que vous ne l'avez pas l'intention d'attraper. Donc, s'il y aurait une demande à votre application URL racine:
votre itinéraire personnalisé serait l'attraper. Et il est défini par défaut. Et appelez votre action CaseController.Advance()
. Et bien sûr, jeter une exception, car id
n'est pas défini.
Gardez votre itinéraire personnalisé devant un défaut
Mais vous devrez changer vos contraintes d'itinéraire itinéraire ou ajouter personnalisée pour elle il attrapera fait que les demandes qu'il est censé attraper.
Mais quel changement devriez-vous faire? S'il y a seulement va être un seul contrôleur qui a besoin de changer pour:
routes.MapRoute(
"CaseAdvance",
"Case/{action}/{id}/{step}",
new { controller = "Case", action = "Advance", id = "", step = StepType.Refer});
S'il y a d'autres contrôleurs un puits, vous pouvez le garder comme il a été, il suffit d'ajouter des contraintes:
routes.MapRoute(
"CaseAdvance",
"{controller}/{action}/{id}/{step}",
new { controller = "Case", action = "Advance", id = "", step = StepType.Refer},
new { controller = "Case|Other" });
S'il peut y avoir un contrôleur, vous pouvez faire une exigence pour votre identifiant soit numérique:
routes.MapRoute(
"CaseAdvance",
"{controller}/{action}/{id}/{step}",
new { controller = "Case", action = "Advance", id = "", step = StepType.Refer},
new { id = @"\d+" })
Dans ce cas, cette voie ne fonctionnera que pour les demandes qui ont en fait un identifiant défini. Comme un certain nombre de cours.
Vous saurez qui vous convient le mieux.
Autres conseils
Oui, s'il n'y a pas d'itinéraire tel que "{contrôleur} / {action} / {id} / {étape}" alors la méthode ActionLink simplement passer "étape" en tant que paramètre querystring.
Dans votre itinéraire que vous avez spécifié un paramètre de StepType mais votre passage un paramètre appelé étape.
Vos noms des paramètres de ActionLink doivent correspondre aux noms des paramètres d'itinéraire ou vous obtiendrez exactement ce que votre vision.
EDIT: Ok, vous avez changé votre code pendant que je tapais cette réponse !!
Essayez d'utiliser RouteLink et voir si cela fonctionne pour vous.
Html.RouteLink("Approve", "CaseAdvance", new { controller = "Case", action = "Advance", id = Model.ID, step = StepType.Approve })
Si vous appelez RouteLink produit un lien valide, il sera au moins signifie votre itinéraire est correctement configuré.