Как asp.net MVC запоминает мои неверные значения при обратной передаче? - PullRequest
6 голосов
/ 06 апреля 2010

Это работает, но как ???

У меня есть действие контроллера для сообщения:

[AcceptVerbs(HttpVerbs.Post )]
public ActionResult Edit(Person person)
{
   bool isvalid = ModelState.IsValid;
   etc.

Объект Person имеет свойство BirthDate, типа DateTime. Когда я ввожу в форму некоторые недопустимые данные, скажем «blabla», что, очевидно, не является допустимым Datetime, оно заполняет все (другие) свойства Person правильными данными, а свойство BirthDate - новым пустым DateTime. Значение bool isvalid имеет значение «false». Пока все хорошо.

Тогда я делаю это:

return View(p);

и в представлении у меня есть это:

<%= Html.TextBox("BirthDate", String.Format("{0:g}", Model.BirthDate)) %>
<%= Html.ValidationMessage("BirthDate", "*") %>

Муравей приходит: я ожидал, что модель будет содержать новый пустой DateTime, потому что я не помещал никаких новых данных. Во-вторых, когда View отображает что-то, это должен быть DateTime, потому что Model.BirthDate can ' не держать ничего, кроме DateTime. Но, к моему удивлению, он показывает текстовое поле со значением «blabla»! (и красный * за ним)

Какой из вариантов хорош, потому что пользователь может видеть, что он напечатал неправильно, но как эту строку (blabla) можно перенести в представление в поле DateTime?

EDIT: Информация ModelState мне очень помогла здесь. Я также заметил, что в MVC 2, когда вы создаете свой собственный шаблон для Html.EditorFor () Вы должны реализовать это поведение самостоятельно. Я создал

DateTime.ascx 

в папке / views / shared / EditorTemplates, и там я должен был проверить, была ли ошибка состояния модели для этого значения свойства, и если да, показать недействительные данные вместо данных модели.

Так что в представлении я использую это:

 <%= Html.LabelFor(model => model.DateOfBirth) %>

и в DateTime.ascx я использую это:

<%
bool invalidData = false;
string propertyName = ViewData.ModelMetadata.PropertyName;

ModelState ms = ViewData.ModelState[propertyName];
if (ms != null)
{
   invalidData = ms.Errors.Count > 0;
}
string valueToshow = invalidData ? ViewData.ModelState[propertyName].Value.AttemptedValue : String.Format("{0:g}", Model);
%>
<input class="text-box single-line" id="<%= propertyName %>" name="<%= propertyName %>" type="text" value="<%= valueToshow %>" />

Ответы [ 3 ]

10 голосов
/ 06 апреля 2010

ModelState содержит KeyValuePairs для каждого элемента формы, ключ - имя поля, а значение - то, что вы указали в поле. Затем Html-помощники просматривают ModelState, и если вы не укажете значение явно, они будут извлекать значение из ModelState.

4 голосов
/ 06 апреля 2010

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

1 голос
/ 06 апреля 2010

У меня в коде постбека был какой-то код, который удалял бы недействительные промо-коды и прописывал ответ. Даже если вы обновите модель новым значением, оно не будет отображаться, поскольку значение ModelState имеет приоритет (как уже ответили другие).

  <%= Html.TextBox("PromoCode", Model.PromoCodes) %>

Но если у вас есть случай, когда это происходит, и вы не хотите, чтобы старое значение сохранялось, вам нужно сделать это:

ModelState.Remove("PromoCode"); 

или явно установите новое значение в состояние модели (возможно, лучший подход):

ModelState.SetModelValue("PromoCode", 
      new ValueProviderResult(newValue, newValue, CultureInfo.CurrentCulture));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...