Каково правильное поведение UpdateModel в ASP.NET MVC?

Мне интересно знать, что, по вашему мнению, следует считать «правильным поведением» с точки зрения метода UpdateModel в ASP.NET MVC.

Причина, по которой я спрашиваю здесь, заключается в том, что, возможно, если эта функциональность создана «по дизайну», кто-то может прояснить, почему она такая, и, возможно, способ назвать ее по-другому для достижения желаемой функциональности, что, как я полагаю, было бы способом 90 % людей хотели бы, чтобы это сработало?

По сути, меня беспокоит поведение процесса привязки в UpdateModel.

Предположим, вы хотите обновить форму с помощью простого Save метода действия, для которого поля данных в форме отражают модель в вашей базе данных, сначала для сохранения запроса мы можем получить существующую модель из БД, а затем обновить соответствующие поля, которые были изменены, отправлены через FormCollection, а затем обновлены UpdateModel для нашей существующей модели. Эта функция, однако кажется, что любое из существующих свойств этого объекта, заполненного БД, "сбрасывается"; и под этим я имею в виду, что для них устанавливаются значения по умолчанию null или инициализации, как если бы это был совершенно новый объект, за исключением, очевидно, тех, которые соответствуют тем, что в FormCollection.

Это проблема, потому что любые существующие свойства, которые существуют в объекте, но не обязательно существуют в форме, такие как любые дочерние коллекции или объекты, даты или любые поля, не связанные с пользовательским интерфейсом, пусты, оставляя вас с наполовину заполненным, более или менее непригодный для использования объект, который не может быть сохранен в БД из-за отсутствия всех данных, включая, вероятно, стек идентификаторов, теперь установленный на 0.

Я считаю, что это нежелательное поведение, и UpdateModel должен обновлять только те свойства, которые находят совпадение свойств в FormCollection. Это означало бы, что все ваши существующие свойства останутся нетронутыми, но ваши обновления будут установлены. Однако из того, что было сделано до сих пор, очевидно, что это не так - похоже, что он создает новую копию объекта, обновляет свойства из формы, а затем возвращает новый объект.

Наконец, чтобы представить себе, насколько это обременительно, единственный способ сохранить полусложную форму и сохранить все существующие данные объекта - это вручную объединить каждое свойство. с соответствующим свойством формы, чтобы абсолютно гарантировать, что обновляются только те свойства, которые существуют в форме.

Наверное,

  1. Те, кто согласен с тем, что это сделано намеренно, лучший ли мой подход к формальному браку?
  2. Или как вы с этим справились?

Пожалуйста, не стесняйтесь высказать свои мысли об этих ребятах, спасибо.

Вот еще один случай, когда кто-то страдает от этой проблемы:
Вызов UpdateModel с набором сложных типов данных для сброса всех несвязанных значений?


person GONeale    schedule 07.08.2009    source источник
comment
Мне интересно узнать, что здесь думают другие, поскольку я согласен с вами. Должен быть правильный, более элегантный способ справиться с этим.   -  person Tim S. Van Haren    schedule 07.08.2009
comment
Спасибо за вашу поддержку, svanharen, эту проблему сложно описать, и когда вы на самом деле ничего не слышите, это заставляет задуматься, единственный ли вы в мире с этой проблемой;)   -  person GONeale    schedule 07.08.2009


Ответы (4)


Поведение, которое вы испытываете с UpdateModel (), похоже на привязку к списку, и в этом случае UpdateModel () удалит содержимое списка и повторно заполнит его. Обсуждение этого вопроса см. В блоге Хансельмана. Если вы обновляете отдельный объект, UpdateModel () обновит этот отдельный объект, оставив свойства, не имеющие соответствующего значения формы, как есть.

Многие из этих проблем сводятся к тому, что UpdateModel () действительно предназначен для повторного заполнения моделей представления, а не моделей предметной области, на основе ввода формы. (Я немного упрощаю ситуацию, говоря, что модель представления - это просто контракт между контроллером и представлением, в то время как ваша модель предметной области может быть объектом модели LINQ2SQL или EF.) Все учебные пособия и демонстрации MVC показывают, что UpdateModel () является используется против объектов базы данных, что я считаю неудачным, поскольку это несколько вводит в заблуждение относительно предполагаемой цели привязки модели. Сообщение Роберта больше указывает на истинное предназначение UpdateModel ().

person Levi    schedule 07.08.2009
comment
Ах, отлично, именно такой ответ я хотел. Спасибо, что немного прояснили это, и я согласен, что большинство руководств и демонстраций заставят вас поверить, что UpdateModel - это инструмент, который можно использовать для обновления вашей модели БД, я думаю, не так много - так есть ли что-то для нас? Или мне интересно, будет ли оно в будущем. Я полагаю, что видел что-то в EF, чтобы взять модель для обновления, возможно, EF мог бы быть более подходящим ORM по сравнению с L2S для MVC .. Я также проверю эту статью, спасибо. - person GONeale; 07.08.2009
comment
Я прочитал статью «Еще раз спасибо, Леви (старший разработчик MVC?)», Хотя она не проясняет мои конкретные требования, но объясняет, как привязка модели работает довольно четко. - person GONeale; 07.08.2009
comment
Я только что получил как самый большой опыт ага. - person Martin; 03.02.2010

Я считаю, что вы правы насчет поведения UpdateModel.

Однако ASP.NET MVC следует модели «туда и обратно», что означает, что ваша форма уже должна содержать все поля, необходимые для создания полной записи, либо потому, что вы поместили значения для всех полей в представление, либо вы запрашивают у пользователя все поля.

Эта концепция «туда и обратно» очень важна. Помните, что в настоящей модели MVC нет понятия состояния. Вы извлекаете данные из таблицы базы данных, отправляете эти данные в представление, данные отображаются пользователю, и программа останавливается. Пользователь редактирует данные, нажимает кнопку публикации, представление отправляет данные в метод контроллера, данные сохраняются в базе данных, и программа останавливается. Нет никакой зависимости от одной операции к другой.

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

person Robert Harvey    schedule 07.08.2009
comment
Но я чувствую, что, если бы я следовал этой концепции, у меня был бы гораздо более весомый обзор и я включил бы много избыточных данных, которые не нужны, и особенно не нужно публиковать, поскольку они не должны быть изменены. Плюс не знаю, как это будет обрабатываться для коллекций и других отношений, отображаемых через LINQ to SQL. - person GONeale; 07.08.2009
comment
Представления ASP.NET MVC намного легче обычного ASP.NET. Разметка намного чище, и вам не нужно бороться с ViewState. В любом случае, сколько данных у вас действительно есть? Это онлайн-заявление о приеме на работу или что-то подобное с множеством полей формы? - person Robert Harvey; 07.08.2009
comment
Нет, это простой инструмент администрирования. Я бы не ожидал, что эта проблема возникнет только со сложными системами; Как объясняет Леви, как только вы говорите о списках детей 1+ в своей модели, вы уже входите в мир проблем, поэтому любой программист столкнется с этой проблемой, и, вероятно, уже столкнулся с ней. - person GONeale; 07.08.2009
comment
С уважением, я думаю, вы называете проблему, которой нет. У меня есть страницы, запущенные в приложении, в которых содержится 100 КБ данных, и они загружаются почти мгновенно. - person Robert Harvey; 07.08.2009
comment
ОК, все в порядке. размер. Но я все еще борюсь с идеей представления всей моей объектной модели в форме, особенно если, скажем, у меня было 2 дочерних объекта и несколько списков, я не уверен, как это легко можно отобразить; Стек скрытых полей, отображающий всю карту объекта? Это кажется странным. - person GONeale; 08.08.2009
comment
Также в re. к сожалению, я бы также оспорил это, я не думаю, что нужно полностью гарантировать, что любые данные, которые вы хотите обновить в своей модели БД, должны полностью существовать в форме. Я не думаю, что у меня есть одна таблица db, которая могла бы облегчить это, например, рассмотреть дату создания или дату обновления, я не думаю, что было бы идеально хранить это в скрытом поле в форме. - person GONeale; 08.08.2009
comment
PS. Я уважаю ваше мнение и рад, что вы нашли время, чтобы написать ответ :) Я просто обсуждаю это, чтобы понять, где мы находимся с MVC. - person GONeale; 08.08.2009
comment
GONeale, см. Мой новый ответ ниже. - person Robert Harvey; 08.08.2009
comment
Если у меня есть Employee форма с подробными сведениями, которую я хочу разместить в Интернете, чтобы сотрудники могли обновлять себя, например, для изменения их контактной информации в чрезвычайных ситуациях, номера телефона и т. Д., Я определенно не хотят, чтобы они могли обновлять свою зарплату. Должна быть возможность обновлять только часть такой записи и не требовать, чтобы все это передавалось в сообщениях HTTP. - person Funka; 23.09.2009

Я довольно успешно использую UpdateModel для типов, не являющихся списками. Я всегда осторожно указываю массив includeProperties (не из-за возможности возникновения этой проблемы, а из соображений безопасности - хотите ли вы, чтобы пользователь мог взломать форму (очень просто), отправить даты и т. Д.?).

Это не значит, что его нельзя улучшить.

Кроме того, практический момент, о котором следует помнить при установке требований: для веб-сервера, получающего POST, пустое поле аналогично несуществующему полю. Это означает, что если UpdateModel был спроектирован таким образом, что он не «сбрасывал» несуществующие поля формы (например, дату), такое же поведение означало бы, что если пользователь удалит текст в вашем поле даты и публикации, он не будет обновляться. с пустым (или нулевым).

Джеймс

person James S    schedule 07.08.2009
comment
Верно, но они могут определить, существует ли элемент формы в массиве, и если он пуст, это может помочь в различии. - person GONeale; 08.08.2009

Но я все еще борюсь с идеей представления всей моей объектной модели в форме, особенно если, скажем, у меня было 2 дочерних объекта и несколько списков, я не уверен, как это легко можно отобразить; Стек скрытых полей, отображающий всю карту объекта? Это кажется странным.

Для этого вам нужно изучить такие вещи, как SubControllers и RenderAction. Вы можете их погуглить. Я много использую RenderAction. Это позволяет мне вставлять виджет на страницу из его собственного метода контроллера без необходимости вставлять отдельные данные в ViewData.

Я не думаю, что нужно полностью гарантировать, что любые данные, которые вы хотите обновить для своей модели БД, должны полностью существовать в форме. Я не думаю, что у меня есть одна таблица db, которая могла бы облегчить это, например, рассмотрим «дату создания» или «дату обновления», я не думаю, что было бы идеально хранить это в скрытом поле в форме.

Вы правы насчет этого. Такие вещи, как CreationDate, UpdatedBy, должны обрабатываться в Контроллере (на самом деле репозиторий, если вы используете репозитории). К тому времени у вас уже должны быть все поля, которые вам нужны из модели представления для обновления вашей базы данных.

Возможно, вам потребуется использовать объекты «строго типизированной модели представления». Если вы не знаете или не уверены, просмотрите эту страницу: http://nerddinnerbook.s3.amazonaws.com/Part6.htm

person Robert Harvey    schedule 07.08.2009
comment
Спасибо, Роб. Я уже использую строго типизированные объекты модели представления для настройки и включения нескольких наборов объектов. Нет проблем и спасибо за вашу помощь, я предполагаю, что NerdDinner будет иметь ту же проблему, что и они используют FormCollection и UpdateModel, возможно, модель недостаточно сложна. Мне нужно провести расследование. - person GONeale; 09.08.2009
comment
Придется уважительно не согласиться. Просто создайте модель представления DTO и сопоставьте свои данные с объектами домена в контроллере (если они большие, в отдельном классе сопоставления). - person Beep beep; 13.12.2009
comment
@LuckyLindy - это один из способов сделать это, но он бесконечно повторяется, если у вас есть хоть одна функция, которую вы хотите повторить во многих представлениях. - person Robert Harvey; 13.12.2009