¿Por qué Html.ActionLink representa "? Longitud = 4"

305

Estoy MUY confundido en cuanto a por qué este código

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

resultados en este enlace:

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

La hidefocusparte es lo que pretendía lograr, pero ¿de dónde ?Length=4viene?

Mi alter ego
fuente
44
Este comportamiento también aparece con los métodos Html.BeginForm ().
Jonathon Watney

Respuestas:

326

La longitud = 4 proviene de un intento de serializar un objeto de cadena. Su código está ejecutando este ActionLinkmétodo:

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

Esto toma un stringobjeto "Inicio" para routeValues, que la plomería MVC busca propiedades públicas convirtiéndolas en valores de ruta. En el caso de un stringobjeto, la única propiedad pública es Length, y dado que no habrá rutas definidas con un parámetro Longitud, agrega el nombre y el valor de la propiedad como un parámetro de cadena de consulta. Probablemente encontrará que si ejecuta esto desde una página que no está en HomeControllerél, arrojará un error sobre un Aboutmétodo de acción faltante . Intenta usar lo siguiente:

Html.ActionLink("About", "About", new { controller = "Home" }, new { hidefocus = "hidefocus" })
roryf
fuente
@Blah_Blah en estos días no uso esto en absoluto, prefiero escribir mis propias etiquetas <a> y solo usar Url.Action ("Acción", "Controlador")
roryf
@roryf no te preocupes ... esto se usó en una revisión de código como una mejor práctica, no verificaron la fecha. Realmente debería haber una manera de filtrar el stackoverflow por fecha ...
THBBFT
Gran respuesta. Solo para agregar esto también sucede en Html.BeginRouteForm por la misma razón. Html.BeginRouteForm ("Ruta", "Acción", FormMethod.Post)) Debe ser Html.BeginRouteForm ("Ruta", nueva {action = "AgentSignUp"}, FormMethod.Post) que elimina la cosa de longitud extraña
radm4
También pasa con Url.Action(). Cambiar de Url.Action("Action", "Controller", new { area = "" })a Url.Action("Action", new { controller = "Controller", area = "" })evita que se muestre la propiedad Longitud.
John Washam
Para evitar este tipo de situaciones, siempre puede especificar qué parámetros está pasando, como:Html.ActionLink("About", "About", "Home", routeValues: null, htmlAttributes: new { hidefocus = "hidefocus" })
Epiplon
195

La forma en que resolví esto fue agregando un valor nulo al cuarto parámetro antes de la declaración anónima ( new {}) para que use la siguiente sobrecarga de método: (linkText, actionName, controllerName, routeValues, htmlAttributes):

Html.ActionLink("About", "About", "Home", null, new { hidefocus = "hidefocus" })
Manuel Castro
fuente
Esta es la mejor respuesta si no está vinculando áreas. Si necesita especificar el área para el enlace, deberá especificar los valores de ruta con controllery areapara evitar que la propiedad Longitud se muestre en la URL.
John Washam
@JohnWasham En realidad, no necesita especificar el controlador en el área, routeValuessino solo en ella. Por ejemplo:Html.ActionLink("About", "About", "Home", new {@area = "Admin"}, new { hidefocus = "hidefocus" })
Epiplon
1
@epiplon, la razón por la que especifico el controlador de esa manera es porque si alguna vez no incluye htmlAttributes como último argumento de ActionLink, MVC incluirá un Length=xparámetro extraño al final de la URL. Por ejemplo, coloque esto en una página, luego vea la fuente de su página y verá lo que quiero decir: @Html.ActionLink("About", "About", "Home", new { area = "Admin" }, new { hidefocus = "hidefocus" }) @Html.ActionLink("About", "About", "Home", new { area = "Admin" }) pero si coloca la controllerentrada en routeValues, nunca se colocará Length=xen la URL.
John Washam
@epiplon, tampoco es necesario utilizar @en @area = "Admin", para que lo sepas.
John Washam
88

Olvidó agregar el parámetro HTMLAttributes.

Esto funcionará sin ningún cambio:

Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" },null)
Jesse Rose
fuente
No sé por qué esto no me funcionó. Intenté con "new {hidefocus =" "}", y esto funciona para mí.
Naredla Nithesh Reddy
28

Los parámetros para ActionLink no son correctos, está intentando utilizar el valor "Inicio" como valor de ruta, en lugar del tipo anónimo.

Creo que solo necesita agregar new { }o nullcomo último parámetro.

EDITAR: solo vuelva a leer la publicación y se dio cuenta de que probablemente querrá especificar nulo como el segundo último parámetro, no el último.


fuente
1
Por cierto, ¡deberían eliminar un método ya que no es posible usarlo!
Marc Climent
5
Html.ActionLink("About", "About", "Home", new { hidefocus = "hidefocus" }, new { })

Esto tomará la sobrecarga: string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes

usuario2254436
fuente
3

Utilice amablemente el método sobrecargado correcto con cinco (5) parámetros. Ejemplo:

@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
fuente
agregar nulo después del nombre del controlador fue útil en mi caso.
Munam Yousuf
Esta es efectivamente la misma respuesta que la respuesta de @ Jesse con la ventaja adicional de que cubre la versión Ajax, que no es lo que solicitó el OP, pero está relacionado con el mismo problema.
gcoulby
2

Simplemente elimine "Inicio" (nombre del controlador) para que el código sea:

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

Con nombres de atributos:

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

Como Jonathon Watney señaló en un comentario, esto también se aplica a

Html.BeginForm ()

métodos. En mi caso, estaba en un Create.cshtml dirigido a la solicitud posterior del controlador correspondiente + Crear acción y tenía

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

que agregaba la cadena de consulta "? Longitud = 6" a la acción del formulario cuando se procesaba. Insinuado por la respuesta aprobada de roryf y al darme cuenta de que la longitud de la cadena de "Crear" es 6, finalmente resolví esto eliminando la especificación de acción explícita:

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

Quizás otros tuvieron el mismo problema y necesitan proporcionar un valor de clase a través de HTMLAttributes parm. Aquí está mi solución:

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

Taersious
fuente
0

Buscar una respuesta a mi pregunta me trajo aquí, básicamente lo @Html.ActionLink ingrese la descripción de la imagen aquí que importa es la selección de la sobrecarga correcta .
Estaba seleccionando una sobrecarga que no existía ( sin la última null ), y MVCno tenía tal sobrecarga, lo que resultó en una URL falsa similar a la OP mencionada.

Una nota personal : ¿puede usetipos anónimos no significa que puede usar cualquiera de las sobrecargas, que no existen? - asegurarse de que: se tiene que definirse!
- Vine aquí en tiempos de MVC 5.2

Irf
fuente