Почему Html.ActionLink отображает «? Length = 4»


305

Я ОЧЕНЬ не понимаю, почему этот код

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

результаты в этой ссылке:

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

Это hidefocusто, чего я стремился достичь, но откуда это ?Length=4взялось?


4
Это поведение также появляется с методами Html.BeginForm ().
Джонатон Уотни

Ответы:


326

Длина = 4 происходит от попытки сериализации строкового объекта. Ваш код выполняет этот ActionLinkметод:

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

Это берет stringобъект "Home" для routeValues, который MVC ищет в открытых свойствах, превращая их в значения маршрута. В случае stringобъекта единственным общедоступным свойством является Length, и поскольку не будет определено ни одного маршрута с параметром Length, он добавляет имя и значение свойства в качестве параметра строки запроса. Вы, вероятно, обнаружите, что если вы запустите это со страницы, которой нет, вы HomeControllerувидите ошибку о пропущенном Aboutметоде действия. Попробуйте использовать следующее:

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

@Blah_Blah в эти дни я вообще не использую это, предпочитаю писать свои собственные теги <a> и просто использовать Url.Action ("Action", "Controller")
roryf

@roryf не беспокойтесь ... это использовалось в обзоре кода как лучшая практика, они не проверяли дату. Там действительно должен быть способ фильтровать
переполнение стека

Отличный ответ. Просто добавить это также происходит на Html.BeginRouteForm по той же причине. Html.BeginRouteForm ("Маршрут", "Действие", FormMethod.Post)) Должен быть Html.BeginRouteForm ("Маршрут", новый {action = "AgentSignUp"}, FormMethod.Post), который избавляется от вещи странной длины
radm4

Также бывает с Url.Action(). Изменение с Url.Action("Action", "Controller", new { area = "" })на не Url.Action("Action", new { controller = "Controller", area = "" })позволяет показывать свойство Length.
Джон Уошам

Чтобы избежать подобных ситуаций, вы всегда можете указать, какие параметры вы передаете, например:Html.ActionLink("About", "About", "Home", routeValues: null, htmlAttributes: new { hidefocus = "hidefocus" })
Epiplon

195

Я решил это путем добавления нулевого значения к четвертому параметру перед анонимным объявлением ( new {}), чтобы он использовал следующую перегрузку метода: (linkText, actionName, controllerName, routeValues, htmlAttributes):

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

Это лучший ответ, если вы не связываете между областями. Если вам нужно указать область для ссылки, вам нужно будет указать routeValues ​​с помощью controllerи, areaчтобы свойство Length не отображалось в URL.
Джон Уошам

@JohnWasham На самом деле вам не нужно указывать контроллер, routeValuesа только область. Например:Html.ActionLink("About", "About", "Home", new {@area = "Admin"}, new { hidefocus = "hidefocus" })
Epiplon

1
@epiplon, причина, по которой я указываю такой контроллер, заключается в том, что если вы не включите htmlAttributes в качестве последнего аргумента ActionLink, MVC будет включать странный Length=xпараметр в конце URL-адреса. Например, поместите это на страницу, затем просмотрите источник своей страницы, и вы поймете, что я имею в виду: @Html.ActionLink("About", "About", "Home", new { area = "Admin" }, new { hidefocus = "hidefocus" }) @Html.ActionLink("About", "About", "Home", new { area = "Admin" }) Но если вы поместите controllerзапись в routeValues, она никогда не будет вставлена Length=xв URL.
Джон Уошам

@epiplon, вы также не должны использовать @в @area = "Admin", только так вы знаете.
Джон Уошам

88

Вы забыли добавить параметр HTMLAttributes.

Это будет работать без каких-либо изменений:

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

Я не знаю, почему это не работает для меня. Я пытался с "new {hidefocus =" "}", и это работает для меня.
Наредла Нитеш Редди

28

Параметры ActionLink неверны, он пытается использовать значение «Home» в качестве значения маршрута вместо анонимного типа.

Я считаю, что вам просто нужно добавить new { }или nullв качестве последнего параметра.

РЕДАКТИРОВАТЬ: Просто перечитайте пост и понял, что вы, вероятно, захотите указать ноль в качестве второго последнего параметра, а не последний.


1
Кстати, они должны удалить один метод, так как его невозможно использовать!
Марк Климент

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

Это займет перегрузку: string linkText, string actionName, string controllerName, Object routeValues, Object htmlAttributes


3

Пожалуйста, используйте правильный перегруженный метод с пятью (5) параметрами. Пример:

@using (@Ajax.BeginForm("Register", "Account", null,
    new AjaxOptions
    {
        HttpMethod = "POST",
        OnSuccess = "OnSuccess",
        OnFailure = "OnFailure",
        OnBegin = "OnBegin",
        OnComplete = "OnComplete"
    }, new { @class = "form-login" }))

добавление нуля после имени контроллера было полезно в моем случае.
Мунам Юсуф

По сути, это тот же ответ, что и ответ @ Jesse, с дополнительным бонусом в том, что он охватывает версию Ajax, которая не является тем, о чем просил OP, но связана с той же проблемой.
gcoulby

2

Просто удалите «Home» (имя контроллера), чтобы код был:

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

1

С именами атрибутов:

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

0

Как отметил в комментарии Джонатон Уотни, это также относится и к

Html.BeginForm ()

методы. В моем случае я находился в Create.cshtml, предназначенном для запроса на публикацию соответствующего контроллера + действие Create, и имел

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

который добавлял строку запроса "? Length = 6" к действию формы при визуализации. Намекнув на одобренный ответ Рорифа и понимая, что длина строки «Создать» равна 6, я наконец решил эту проблему, удалив явную спецификацию действий:

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

0

Возможно, у других была такая же проблема, и они должны указывать значение класса через HTMLAttributes parm . Вот мое решение:

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


0

Поиск ответа на мой вопрос привел меня сюда, в основном это выбор правильной перегрузки, @Html.ActionLink введите описание изображения здесь которая имеет значение.
Я отбирал перегрузку , которая не существует, ( без последней null ), и MVCне было такой перегрузки, в результате ложного URL что - то вроде ОП упоминается.

Личное примечание: вы можете использовать useанонимные типы, это не значит, что вы можете использовать какие-либо из перегрузок, которых не существует? - убедитесь , что: он должен быть определен!
- Пришел сюда во времена MVC 5.2

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.