Почему 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" })
roryf
источник
@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

user2254436
источник
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" })
Fil
источник
1

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

 @Html.ActionLink(linkText: "SomeText", actionName: "SomeAction", controllerName: "SomeControllerName", routeValues: new { parameterName = parameterValue}, htmlAttributes: null)
usefulBee
источник
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" })

Taersious
источник
0

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

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

IRF
источник