4

Я работаю над приложением 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 и связал их свойство значения с моей обновленной моделью. Это просто УДИВИТЕЛЬНО! Но я хочу доказать это предположение. Я не могу найти документацию об этом в любом месте в Интернете. Может ли кто-либо подтвердить мою гипотезу о том, ПОЧЕМУ/КАК, ЧТО это УДИВИТЕЛЬНОЕ поведение, связанное с автоматическим связыванием, происходит и/или обучает меня тому, почему и как это происходит, надеюсь, подкреплено некоторыми ссылками онлайн-документации, чтобы я более подробно понял, что происходит под обложками?

ответ

0
public ActionResult EditDetail(EditDetailItemModel model) 

Эта линия будет выполнять привязку модели. Подумайте о параметрах ActionMethod, которые всегда заполняются вызовом UpdateModel.

Вы не видите значения refreshedModel в представлении, вы видите записи и значения ModelState из EditDetailItemModel.

+0

Вправо - значения, которые я вижу в представлении после того, как я вернусь назад, являются элементами ModelState. НО с разницей - «другие» свойства не-формы НЕ НУЛЬНЫЕ! Если я не обновил модель до отправки обратно в представление, эти другие свойства все равно будут иметь значение null. Но поскольку я обновил модель, когда я установил точку останова в представлении, я вижу, что свойства исправления не только правильно восстановлены, но свойства формы возвращены обратно к значениям, введенным пользователем в форме - ТОЧНО что я хотел. Я ищу некоторые документы, которые подтверждают эту функциональность. – tbehunin

+1

Ничего онлайн (что я могу найти) говорит о необходимости «обновить» модель перед возвратом, чтобы отобразить ошибки проверки, что, я думаю, странно. Похоже, это довольно стандартная вещь, но нет примеров, которые я нашел для этого. Если посмотреть на код в моем вопросе выше, если бы я не сделал вызов TryUpdateModel <>(), оказалось бы, что «refreshModel» (значения которого прямо из db) будут отображаться пользователем - а не значения, которые они вводили до POST. Это замечательно. Только бы облегчить мою совесть, если бы я мог прочитать эту ожидаемую функциональность в Интернете. – tbehunin

+0

@tbehunin, я не понимаю, что вы ищете. Когда вы вызываете 'return View (refreshedModel);' вы передаете эту viewmodel в представление. Вот как все работает.TryUpdateModel создаст записи ModelState для этого refreshedModel, и любые htmlhelpers будут использовать их сначала, прежде чем смотреть в модель. – jfar