Por que o Html.ActionLink renderiza "? Length = 4"

305

Estou muito confuso sobre o porquê deste código

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

resultados neste link:

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

A hidefocusparte é o que eu pretendia alcançar, mas de onde ?Length=4vem?

My Alter Ego
fonte
4
Esse comportamento também aparece com os métodos Html.BeginForm ().
Jonathon Watney 8/12

Respostas:

326

O comprimento = 4 é proveniente de uma tentativa de serializar um objeto de seqüência de caracteres. Seu código está executando este ActionLinkmétodo:

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

Isso leva um stringobjeto "Home" para routeValues, que o encanamento do MVC procura por propriedades públicas, transformando-os em valores de rota. No caso de um stringobjeto, a única propriedade pública é Lengthe, como não haverá rotas definidas com um parâmetro Length, ele anexa o nome e o valor da propriedade como um parâmetro da string de consulta. Você provavelmente descobrirá que, se executar isso em uma página que não está HomeControllernela, gera um erro sobre um Aboutmétodo de ação ausente . Tente usar o seguinte:

Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
roryf
fonte
@Blah_Blah esses dias eu não use isso em tudo, prefere escrever as minhas próprias tags <a> e utilizando apenas Url.Action ( "Action", "Controller")
roryf
@roryf não se preocupe ... isso foi usado em uma revisão de código como uma prática recomendada, eles não verificaram a data. Há realmente deve ser uma maneira de filtrar o stackoverflow por data ...
THBBFT
Ótima resposta. Só para adicionar isso também acontece em Html.BeginRouteForm pelo mesmo motivo. Html.BeginRouteForm ("Route", "Action", FormMethod.Post)) deve ser Html.BeginRouteForm ("Route", novo {action = "AgentSignUp"}, FormMethod.Post) que se livra da coisa de tamanho estranho
radm4
Também acontece com Url.Action(). Alterar de Url.Action("Action", "Controller", new { area = "" })para Url.Action("Action", new { controller = "Controller", area = "" })impede que a propriedade Length seja exibida.
John Washam
Para evitar esse tipo de situação, você sempre pode especificar quais parâmetros você está passando, como:Html.ActionLink("About", "About", "Home", routeValues: null, htmlAttributes: new { hidefocus = "hidefocus" })
Epiplon 13/03/2015
195

A maneira que resolvi isso foi adicionar um nulo ao quarto parâmetro antes da declaração anônima ( new {}) para que ele use o seguinte método de sobrecarga: (linkText, actionName, controllerName, routeValues, htmlAttributes):

Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
Manuel Castro
fonte
Essa é a melhor resposta se você não estiver vinculando as áreas. Se você precisar especificar a área para o link, precisará especificar os routeValues ​​com controllere areapara impedir que a propriedade Length apareça na URL.
John Washam
@ JohnWasham Na verdade, você não precisa especificar o controlador na, routeValuesmas apenas na área. Por exemplo:Html.ActionLink("About", "About", "Home", new {@area = "Admin"}, new { hidefocus = "hidefocus" })
Epiplon 13/03/2015
1
@epiplon, a razão pela qual eu especifico o controlador dessa maneira é porque, se você nunca incluir htmlAttributes como o último argumento ActionLink, o MVC incluirá um Length=xparâmetro estranho no final da URL. Por exemplo, coloque isso em uma página, depois veja a fonte da sua página e você verá o que quero dizer: @Html.ActionLink("About", "About", "Home", new { area = "Admin" }, new { hidefocus = "hidefocus" }) @Html.ActionLink("About", "About", "Home", new { area = "Admin" }) Mas se você inserir a controllerentrada na routeValues, ela nunca será inserida Length=xna URL.
21815 John Washam
@epiplon, você também não precisa usar @em @area = "Admin", só para você saber.
31415 John Washam
88

Você esqueceu de adicionar o parm HTMLAttributes.

Isso funcionará sem nenhuma alteração:

Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
Jesse Rose
fonte
Não sei por que isso não funcionou para mim. Tentei com "new {hidefocus =" "}", e isso funciona para mim.
Naredla Nithesh Reddy
28

Os parâmetros para o ActionLink não estão corretos, ele está tentando usar o valor "Inicial" como um valor de rota, em vez do tipo anônimo.

Eu acredito que você só precisa adicionar new { }ou nullcomo o último parâmetro.

EDIT: basta reler a postagem e percebi que você provavelmente desejará especificar null como o segundo último parâmetro, não o último.


fonte
1
Entre eles devem remover um método, pois não é possível usá-lo!
Marc Climent
5
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })

Isso exigirá a sobrecarga: string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes

user2254436
fonte
3

Por favor, use o método sobrecarregado à direita com cinco (5) parâmetros. Exemplo:

@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
fonte
adicionar nulo após o nome do controlador foi útil no meu caso.
Munam Yousuf
Essa é efetivamente a mesma resposta que a resposta de @ Jesse, com o bônus adicional de cobrir a versão do Ajax, que não é o que o OP solicitou, mas está relacionada ao mesmo problema.
precisa saber é o seguinte
2

Apenas remova "Home" (nome do controlador) para que o código seja:

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

Com nomes de atributo:

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

Como Jonathon Watney apontou em um comentário, isso também vale para

Html.BeginForm ()

métodos. No meu caso, eu estava em um Create.cshtml visando a solicitação de postagem do controlador correspondente + ação Create e tinha

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

que estava adicionando a querystring "? Length = 6" à ação do formulário quando renderizada. Sugerido pela resposta aprovada por roryf e percebendo que o comprimento da string de "Create" é 6, finalmente resolvi isso removendo a especificação de ação explícita:

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

Talvez outros tenham o mesmo problema e precisem fornecer um valor de classe via HTMLAttributes parm. Aqui está a minha solução:

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

Taersious
fonte
0

Procurar uma resposta para minha pergunta me levou até aqui, basicamente é a seleção da sobrecarga correta @Html.ActionLink insira a descrição da imagem aqui que interessa.
Eu estava selecionando uma sobrecarga que não existia ( sem a última null ) e MVCnão tinha essa sobrecarga, resultando em uma URL falsa, algo como o OP mencionado.

Uma observação pessoal : você pode usetipos anônimos não significa que você pode usar qualquer uma das sobrecargas - que não existem? - tornar certa: ele tem de ser definido!
- Vim aqui em tempos de MVC 5.2

Irf
fonte