ASP.NET MVC автоматически привязывает обновленную модель, когда ModelState недопустима в HttpPost

Я работаю над приложением ASP.NET MVC2. Я осознал очень удивительную, но удивительную вещь, которую MVC делает за кулисами, связанную с ModelState и привязкой модели. У меня есть ViewModel, в котором есть целый набор данных - некоторые поля являются частью формы, а другие - просто частью пользовательского интерфейса. В HttpPost мой метод Action использует DefaultModelBinder, который пытается связать всю модель, но только поля, которые были частью формы, успешно десериализованы - все остальные остаются нулевыми. Это нормально и понятно. Если ModelState недействителен, мне нужно обновить модель из базы данных и привязать эти конкретные поля формы, прежде чем вернуться в то же представление редактирования, чтобы отобразить связанные с этим ошибки проверки ModelState.

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


person tbehunin    schedule 02.11.2010    source источник


Ответы (1)


public ActionResult EditDetail(EditDetailItemModel model)

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

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

person John Farrell    schedule 02.11.2010
comment
Справа - значения, которые я вижу в представлении после отправки, являются записями ModelState. НО с разницей - другие свойства, не являющиеся формами, НЕ НУЛЕНЫ! Если бы я не обновлял модель перед отправкой обратно в представление, эти другие свойства все равно были бы нулевыми. Но поскольку я обновил модель, когда я установил точку останова в представлении, я вижу, что не только правильно восстановлены свойства, не относящиеся к форме, но и свойства формы были возвращены к значениям, введенным пользователем в форму - ТОЧНО то, что я хотел случиться. Я ищу документы, подтверждающие эту функциональность. - person tbehunin; 02.11.2010
comment
Ничего в сети (что я могу найти) не говорит о необходимости обновлять модель перед возвращением для отображения ошибок проверки, что я считаю странным. Это кажется довольно стандартным, но я не нашел примеров попытки сделать это. Глядя на код в моем вопросе выше, если бы я не вызвал TryUpdateModel ‹› (), могло бы показаться, что refreshModel (значения которого прямо из базы данных) были бы значениями, отображаемыми для пользователя, а не значения, которые они ввели перед POSTing. Это замечательно. Просто облегчило бы мою совесть, если бы я мог прочитать эту ожидаемую функциональность в Интернете. - person tbehunin; 02.11.2010
comment
@tbehunin, я не понимаю, что вы ищете. Когда вы вызываете return View(refreshedModel);, вы передаете эту модель представления представлению. Вот как все работает. TryUpdateModel создаст записи ModelState для этого refreshedModel, и любые htmlhelpers будут использовать их в первую очередь, прежде чем изучать модель. - person John Farrell; 02.11.2010