ASP.NET MVC: значение скрытого поля не отображается при использовании HtmlHelper.Hidden - PullRequest
70 голосов
/ 07 января 2010

Что-то довольно странное происходит с моим приложением:

В моем ViewModel есть следующее свойство:

public int? StakeholderId { get; set; }

Отображается в частичном виде следующим образом:

<%= Html.Hidden("StakeholderId", Model.StakeholderId) %>

Форма отправлена, и соответствующее действие контроллера генерирует идентификатор и обновляет модель, прежде чем возвращать то же представление с обновленной моделью

Проблема, с которой я сталкиваюсь, заключается в том, что скрытое поле не имеет ничего в своем атрибуте «значение», отображаемом во второй раз, хотя StakeholderId теперь имеет значение.

Если я просто выведу значение само по себе, оно появится на странице, поэтому я получу его для рендеринга значения следующим образом:

<input type="hidden" id="StakeholderId" name="stakeholderId" value="<%: Model.StakeholderId %>" />

Но довольно странно, что помощник не получает обновленное значение?

(Я использую jQuery для отправки форм и рендеринга результатов действий в div, но я проверил, и HTML-код, который я получаю, уже неверен, прежде чем jQuery что-то с ним сделает, поэтому я не думаю, что делать с чем угодно)

UPDATE

С тех пор я обнаружил, что могу также очистить соответствующий ключ ModelState до того, как действие моего контроллера вернет частичное представление.

Ответы [ 2 ]

60 голосов
/ 07 января 2010

Помощник сначала ищет значения POST и использует их. Когда вы публикуете форму, она забирает старое значение идентификатора. Ваш обходной путь правильный.

34 голосов
/ 01 февраля 2011

ADDENDUM: несколько HTML-форм, например, в сетке

В качестве дополнения к этой проблеме, ОЧЕНЬ нужно быть ОЧЕНЬ осторожным с несколькими формами на одной странице, например, в сетке, например, сгенерированной с использованием Ajax.BeginForm.

У вас может возникнуть желание написать что-то вроде:

@foreach (var username in Model.TutorUserNames)
        {
            <tr>
                <td>
                    @Html.ActionLink(username, MVC.Admin.TutorEditor.Details(username))
                </td>
                <td>
                    @using (Ajax.BeginForm("DeleteTutor", "Members",
                        new AjaxOptions
                        {
                            UpdateTargetId = "AdminBlock",
                            OnBegin = "isValidPleaseWait",
                            LoadingElementId = "PleaseWait"
                        },
                        new { name = "DeleteTutorForm", id = "DeleteTutorForm" }))
                    {    
                        <input type="submit" value="Delete" />
                        @Html.Hidden("TutorName", username)
                    }
                </td>
            </tr>
        }

Смертельная линия здесь:

@Html.Hidden("TutorName", username)

... и намеревается использовать TutorName в качестве параметра вашего действия. EG:

public virtual ActionResult DeleteTutor(string TutorName){...}

Если вы сделаете это, неприятным сюрпризом для вас будет то, что Html.Hidden ("TutorName", имя пользователя), как объясняет Дарин Димитров, будет отображать последнее значение POSTed. То есть, независимо от вашего цикла, ВСЕ элементы будут отображаться с именем TutorName последнего удаленного Tutor!

Смысл в синтаксисе Razor - заменить вызов @ Html.Hidden явным тегом ввода:

<input type="hidden" id="TutorName" name="TutorName" value='@username' />

Это работает как ожидалось.

Т.е.:

НИКОГДА, НИКОГДА НЕ ИСПОЛЬЗУЙТЕ Html. Спрятан, чтобы передать ПАРАМЕТР ВЕРНУТЬСЯ В ВАШИ ДЕЙСТВИЯ, КОГДА ВЫ ИСПОЛЬЗУЕТЕ НЕСКОЛЬКО ФОРМ В СЕТЕ !!!

Заключительная оговорка:

При создании скрытого входного тега вам необходимо включить и имя, и идентификатор, установить одно и то же значение, иначе во время написания (февраль 2011 г.) он не будет работать должным образом. Конечно, не в Google Chrome. Все, что вы получаете, это нулевой параметр, возвращаемый, если у вас есть только идентификатор и атрибут name.

...