Помощник тега формы MVC Core, который наследует текущий URL-адрес представления для своего атрибута действия

С MVC5 (и более старыми фреймворками MVC) я смог написать свою форму без указания метода контроллера / действия:

@using (Html.BeginForm())
{
}

Таким образом, я смог повторно использовать форму с другим URL. Если бы форма была вызвана из маршрута «/ books / 2 / edit», сгенерированный HTML-код был бы таким:

<form action="/books/2/edit"></form>

И если я вызову форму, используя URL-адрес "/ books / add", сгенерированный HTML-код будет:

<form action="/books/add"></form>

Как я могу сделать то же самое с синтаксисом вспомогательного тега? Я пробовал все виды синтаксиса, но он всегда генерирует пустой атрибут действия:

<form></form>
<form asp-route=""></form>
<form asp-controller="" asp-action=""></form>

Результат:

<form></form>
<form action></form>
<form action></form>

person Alexandre Jobin    schedule 16.03.2018    source источник


Ответы (1)


При использовании помощников HTML значения, которые не указаны явно, по умолчанию соответствуют значениям маршрута, содержащимся в текущем запросе. Вот почему вы можете указать BeginForm без параметров.

При использовании помощников тегов эта логика по умолчанию больше не применяется - значения должны быть указаны явно. По умолчанию нет.

Вариант 1 - тег form

Самый простой способ имитировать действия помощника HTML с помощью тега form:

<form action="@Url.RouteUrl(this.ViewContext.RouteData.Values)" method="post">
</form>

Вариант 2 - Html.BeginForm

Обратите внимание, что ваш текущий синтаксис также по-прежнему действителен в ASP.NET Core MVC:

@using (Html.BeginForm())
{
}

Но поскольку вам пришлось задать этот вопрос, я бы сказал, что совершенно не ясно, как создается URL при использовании этого синтаксиса, а это значит, что вам, вероятно, следует перейти на использование Url.RouteUrl, чтобы сделать его более читабельным. несмотря на то, что написать немного больше.

Вариант 3 - Помощник по тегам

Вот пример того, как вы могли бы использовать помощника тега для достижения этой цели, хотя это немного некрасиво.

Существует вспомогательный атрибут тега формы asp-all-route-values, который позволяет передавать все значения маршрута в одном параметре. Однако согласно asp-all-route-data должно быть IDictionary<string,object> или RouteValueDictionary, невозможно передать RouteValueDictionary в этот атрибут, вам нужно будет преобразовать его в IDictionary<string, string>. Один из способов сделать это - создать метод расширения для преобразования.

public static class RouteValueDictionaryExtensions
{
    public static IDictionary<string, string> ToTagHelperValues(this RouteValueDictionary routeValueDictionary)
    {
        var result = new Dictionary<string, string>();
        foreach (var kvp in routeValueDictionary)
        {
            result.Add(kvp.Key, kvp.Value as string);
        }
        return result;
    }
}

Затем вы можете использовать вспомогательную функцию тега для генерации текущего URL-адреса следующим образом:

<form asp-all-route-data="@this.ViewContext.RouteData.Values.ToTagHelperValues()">
</form>

Вариант 4 - Нет атрибута действия

Также можно использовать тег формы без атрибута action. Если вы опустите атрибут action, по умолчанию в большинстве (если не во всех) браузерах будет использоваться текущий URL.

<form method="post">
</form>

ПРЕДУПРЕЖДЕНИЕ. Использование этой опции не соответствует стандартам, и технически поведение браузеров не обязательно должно по умолчанию - ожидаемое поведение при использовании текущего URL-адреса, если он не указан.

В конце концов, какой метод вы используете, - это вопрос ваших предпочтений.

person NightOwl888    schedule 16.03.2018
comment
Вариант 1 действительно хорош. Я воспользуюсь этим. Спасибо! - person Alexandre Jobin; 16.03.2018