Pourquoi Html.ActionLink affiche «? Longueur = 4»

305

Je suis TRÈS confus quant à la raison pour laquelle ce code

Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" })

donne ce lien:

<a hidefocus="hidefocus" href="/Home/About?Length=4">About</a>

La hidefocuspartie est ce que je visais à réaliser, mais d'où ?Length=4vient-elle?

My Alter Ego
la source
4
Ce comportement apparaît également avec les méthodes Html.BeginForm ().
Jonathon Watney

Réponses:

326

La longueur = 4 provient d'une tentative de sérialisation d'un objet chaîne. Votre code exécute cette ActionLinkméthode:

public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes)

Cela prend un stringobjet "Home" pour routeValues, que la plomberie MVC recherche pour les propriétés publiques en les transformant en valeurs de route. Dans le cas d'un stringobjet, la seule propriété publique est Length, et comme aucun itinéraire n'est défini avec un paramètre Longueur, il ajoute le nom et la valeur de la propriété en tant que paramètre de chaîne de requête. Vous constaterez probablement que si vous l'exécutez à partir d'une page qui ne HomeControllers'y trouve pas, une erreur sur une Aboutméthode d'action manquante sera générée. Essayez d'utiliser les éléments suivants:

Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
roryf
la source
@Blah_Blah ces jours-ci, je ne l'utilise pas du tout, je préfère écrire mes propres balises <a> et simplement utiliser Url.Action ("Action", "Controller")
roryf
@roryf pas de soucis ... cela a été utilisé dans une revue de code comme meilleures pratiques, ils n'ont pas vérifié la date. Il devrait vraiment y avoir un moyen de filtrer le stackoverflow par date ...
THBBFT
Très bonne réponse. Juste pour ajouter cela se produit également sur Html.BeginRouteForm pour la même raison. Html.BeginRouteForm ("Route", "Action", FormMethod.Post)) Doit être Html.BeginRouteForm ("Route", new {action = "AgentSignUp"}, FormMethod.Post) qui se débarrasse de la chose bizarre
radm4
Se produit également avec Url.Action(). Le passage de Url.Action("Action", "Controller", new { area = "" })à Url.Action("Action", new { controller = "Controller", area = "" })empêche la propriété Length de s'afficher.
John Washam
Pour éviter ce genre de situation, vous pouvez toujours spécifier les paramètres que vous passez, comme:Html.ActionLink("About", "About", "Home", routeValues: null, htmlAttributes: new { hidefocus = "hidefocus" })
Epiplon
195

La façon dont j'ai résolu cela était d'ajouter un null au quatrième paramètre avant la déclaration anonyme ( new {}) afin qu'il utilise la surcharge de méthode suivante: (linkText, actionName, controllerName, routeValues, htmlAttributes):

Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
Manuel Castro
la source
C'est la meilleure réponse si vous ne reliez pas les zones. Si vous devez spécifier la zone du lien, vous devez spécifier les valeurs routeValues ​​avec controlleret areapour empêcher la propriété Length de s'afficher dans l'URL.
John Washam
@JohnWasham En fait, vous n'avez pas besoin de spécifier le contrôleur dans routeValuesmais uniquement la zone. Par exemple:Html.ActionLink("About", "About", "Home", new {@area = "Admin"}, new { hidefocus = "hidefocus" })
Epiplon
1
@epiplon, la raison pour laquelle je spécifie le contrôleur comme ça est parce que si vous n'incluez jamais htmlAttributes comme dernier argument de ActionLink, MVC inclura un Length=xparamètre étrange à la fin de l'URL. Par exemple, mettez cela sur une page, puis affichez la source de votre page, et vous verrez ce que je veux dire: @Html.ActionLink("About", "About", "Home", new { area = "Admin" }, new { hidefocus = "hidefocus" }) @Html.ActionLink("About", "About", "Home", new { area = "Admin" }) mais si vous mettez l' controllerentrée dans le routeValues, elle ne mettra jamais Length=xl'URL.
John Washam
@epiplon, vous n'avez pas non plus besoin d'utiliser @dans @area = "Admin", juste pour que vous le sachiez.
John Washam
88

Vous avez oublié d'ajouter le paramètre HTMLAttributes.

Cela fonctionnera sans aucun changement:

Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
Jesse Rose
la source
Je ne sais pas pourquoi cela ne fonctionne pas pour moi. J'ai essayé avec "new {hidefocus =" "}", et cela fonctionne pour moi.
Naredla Nithesh Reddy
28

Les paramètres d'ActionLink ne sont pas corrects, il essaie d'utiliser la valeur "Home" comme valeur d'itinéraire, au lieu du type anonyme.

Je crois que vous avez juste besoin d'ajouter new { }ou nullcomme dernier paramètre.

EDIT: relisez simplement le message et réalisez que vous voudrez probablement spécifier null comme avant-dernier paramètre, pas le dernier.


la source
1
BTW Ils devraient supprimer une méthode car il n'est pas possible de l'utiliser!
Marc Climent
5
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })

Cela prendra la surcharge: string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes

user2254436
la source
3

Veuillez utiliser la bonne méthode surchargée avec cinq (5) paramètres. Exemple:

@using (@Ajax.BeginForm("Register", "Account", null,
    new AjaxOptions
    {
        HttpMethod = "POST",
        OnSuccess = "OnSuccess",
        OnFailure = "OnFailure",
        OnBegin = "OnBegin",
        OnComplete = "OnComplete"
    }, new { @class = "form-login" }))
Omveer singh maurya
la source
l'ajout de null après le nom du contrôleur a été utile dans mon cas.
Munam Yousuf
C'est effectivement la même réponse que la réponse de @ Jesse avec le bonus supplémentaire qu'elle couvre la version Ajax, ce qui n'est pas ce que l'OP a demandé, mais elle est liée au même problème.
gcoulby
2

Supprimez simplement "Home" (nom du contrôleur) pour que le code soit:

Html.ActionLink("About", "About", new { hidefocus = "hidefocus" })
Fil
la source
1

Avec des noms d'attribut:

 @Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
utileBee
la source
0

Comme Jonathon Watney l'a souligné dans un commentaire, cela vaut également pour

Html.BeginForm ()

méthodes. Dans mon cas, j'étais dans un Create.cshtml ciblant la demande de publication du contrôleur correspondant + l'action Créer et j'avais

using (Html.BeginForm("Create")) {
  @Html.AntiForgeryToken()
  ...
}

qui ajoutait la chaîne de requête "? Longueur = 6" à l'action de formulaire lors du rendu. Insinué par la réponse approuvée de roryf et réalisant que la longueur de chaîne de "Create" est 6, j'ai finalement résolu cela en supprimant la spécification d'action explicite:

using (Html.BeginForm()) {
      @Html.AntiForgeryToken()
      ...
    }
Frederik Struck-Schøning
la source
0

Peut-être que d'autres ont eu le même problème et doivent fournir une valeur de classe via HTMLAttributes parm. Voici ma solution:

@Html.ActionLink("About", "About", new { controller = "Home", area = "" }, new { hidefocus = "hidefocus", @class = "nav-item nav-link" })

Taersious
la source
0

La recherche d'une réponse à ma question m'a atterri ici, c'est essentiellement la sélection de la surcharge correcte @Html.ActionLink entrez la description de l'image ici qui compte.
Je sélectionnais une surcharge qui n'existait pas ( sans la dernière null ), etMVC n'avait pas une telle surcharge, résultant en une fausse URL quelque chose comme l'OP mentionné.

Une note personnelle : vous pouvez useutiliser des types anonymes ne signifie pas que vous pouvez utiliser l'une des surcharges qui n'existent pas? - assurez - vous: il doit être défini!
- Entré ici à l'époque de MVC 5.2

Irf
la source