Я работаю над приложением ASP.NET MVC2. Я осознал удивительную, но удивительную вещь, которую MVC делает за кулисами, связанную с привязкой ModelState и модели. У меня есть ViewModel, у которого есть целая куча данных - некоторые поля являются частью формы, а другие - просто частью пользовательского интерфейса. В HttpPost мой метод Action использует DefaultModelBinder, который пытается связать всю модель, но только поля, которые были частью формы, успешно десериализованы - все остальные остаются пустыми. Это прекрасно и понятно. Если ModelState недействителен, мне нужно вернуть модель из db и свяжите эти конкретные поля формы, прежде чем возвращаться к тому же самому виду редактирования, чтобы отобразить связанные с ним ошибки проверки ModelState.ASP.NET MVC автоматически связывает обновленную модель, когда ModelState недействителен в HttpPost
Вот где мое удивление и любопытство. Это было мое предположение, что для меня свяжите поля формы с обновленной моделью, мне нужно позвонить либо UpdateModel()
, либо TryUpdateModel<>()
, переходя в обновленную модель. Например:
[HttpPost]
public ActionResult EditDetail(EditDetailItemModel model)
{
if (model.IsValid)
{
// Save the results to the db
return RedirectToAction(...)
}
// Can't simply "return View(model)". Not all fields in EditDetailItemModel
// were part of the form - thus they returned null. Have to refresh
// model from the db.
var refreshedModel = RefreshModelFromDB();
// Is this line necessary?????
TryUpdateModel<EditDetailItemModel>(refreshedModel);
return View(refreshedModel);
}
Но то, что я обнаружил, что если я просто вернулся refreshedModel
к представлению, не делая вызов TryUpdateModel<>()
, обновилась модель была автоматически связана со значениями поля формы размещены !! Следовательно, TryUpdateModel<>()
здесь не нужен!
Единственный способ, которым я могу это понять, состоит в том, что, поскольку ModelState находится в недопустимом состоянии, как только я вернул представление с обновленной моделью, «механизм рендеринга MVC» зациклился на ошибках ModelState и связал их свойство значения с моей обновленной моделью. Это просто УДИВИТЕЛЬНО! Но я хочу доказать это предположение. Я не могу найти документацию об этом в любом месте в Интернете. Может ли кто-либо подтвердить мою гипотезу о том, ПОЧЕМУ/КАК, ЧТО это УДИВИТЕЛЬНОЕ поведение, связанное с автоматическим связыванием, происходит и/или обучает меня тому, почему и как это происходит, надеюсь, подкреплено некоторыми ссылками онлайн-документации, чтобы я более подробно понял, что происходит под обложками?
Вправо - значения, которые я вижу в представлении после того, как я вернусь назад, являются элементами ModelState. НО с разницей - «другие» свойства не-формы НЕ НУЛЬНЫЕ! Если я не обновил модель до отправки обратно в представление, эти другие свойства все равно будут иметь значение null. Но поскольку я обновил модель, когда я установил точку останова в представлении, я вижу, что свойства исправления не только правильно восстановлены, но свойства формы возвращены обратно к значениям, введенным пользователем в форме - ТОЧНО что я хотел. Я ищу некоторые документы, которые подтверждают эту функциональность. – tbehunin
Ничего онлайн (что я могу найти) говорит о необходимости «обновить» модель перед возвратом, чтобы отобразить ошибки проверки, что, я думаю, странно. Похоже, это довольно стандартная вещь, но нет примеров, которые я нашел для этого. Если посмотреть на код в моем вопросе выше, если бы я не сделал вызов TryUpdateModel <>(), оказалось бы, что «refreshModel» (значения которого прямо из db) будут отображаться пользователем - а не значения, которые они вводили до POST. Это замечательно. Только бы облегчить мою совесть, если бы я мог прочитать эту ожидаемую функциональность в Интернете. – tbehunin
@tbehunin, я не понимаю, что вы ищете. Когда вы вызываете 'return View (refreshedModel);' вы передаете эту viewmodel в представление. Вот как все работает.TryUpdateModel создаст записи ModelState для этого refreshedModel, и любые htmlhelpers будут использовать их сначала, прежде чем смотреть в модель. – jfar