Почему 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.