Есть ли лучший способ использовать несколько моделей, чем через ViewModels в ASP.NET MVC?

Я новичок в работе с ASP.NET MVC 2, и один из примеров, которым я следую, - это официальный музыкальный магазин ASP.NET MVC. на codeplex.

В примере проекта у них есть такой сценарий: Есть три модели: Albums, Artists, Genres.

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

public class StoreManagerViewModel{
  public Album Album{get;set;}
  public List<Artists> Artists{get;set;}
  public List<Genre> Genres{get;set;}
}

Эта ViewModel передается в представление и позволяет intellisense и видеть несколько моделей в представлении.

Похоже, что этот метод заставит меня иметь дополнительный класс почти для каждого отношения в моей модели: если у меня есть класс Discography, и я хочу связать Artists с Discography, мне придется создать еще одну ViewModel, как указано выше.

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

public List<Artists> Artists{get;set;}
public List<Genre> Genres{get;set;}

Есть ли лучший способ сделать это, кроме ViewModels? Есть способ чище?


person Msam85    schedule 27.01.2011    source источник
comment
Я не понимаю, почему вам нужно было создать другую модель представления, чтобы добавить информацию о дискографии: не могли бы вы просто добавить свойство Discography в Artist или добавить словарь дискографий к существующей модели представления?   -  person Jeff Sternal    schedule 27.01.2011
comment
Это просто потому, что при редактировании альбома вам нужно передать список ВСЕХ альбомов в представление (конечно, в классе Album у вас есть свойство с текущей дискографией и артитстом этого альбома)   -  person Msam85    schedule 27.01.2011


Ответы (5)


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

Скажем, например, вы хотите загрузить на свой сайт 100 самых популярных пользователей переполнения стека, имена которых начинаются с myNamePrefix. Затем для каждого пользователя вы хотите отобразить список тегов, по которым они получили более 10 голосов. Вы можете просто передать список Users в ваше представление, а затем вызвать свойство .Tags, которое затем совершит круговой обход базы данных для каждого из ваших 100 пользователей. Это может быть нормально, если база данных находится на том же компьютере, что и веб-сервер, и вы получаете лишь несколько обращений в день. Но допустим, вы пытаетесь обрабатывать эти данные для различных значений myNamePrefix каждую секунду. Вероятно, вы могли бы найти несколько творческих способов кэширования результатов, но по большей части лучше заполнить вашу модель представления всеми необходимыми данными (в данном случае с помощью одного запроса) и просто дать представлению результаты. Помните, задача представления - отображать данные, а не получать их.

person Nick Larsen    schedule 27.01.2011
comment
Я согласен с вами, и именно поэтому я стараюсь сохранять представления как можно более жесткими и избегаю вставки в классы моделей параметров или свойств, которые на самом деле предназначены для определенного представления, а не являются частью модели или бизнес-логики. Я предполагаю, что уловка состоит в том, чтобы отделить эти ViewModels от реальных моделей (например, создать папку), чтобы избежать смешивания обеих концепций. - person Msam85; 27.01.2011
comment
Я почти всегда реализую свои реальные модели или любую другую систему ORM, которую я использую, в отдельном проекте, даже если это просто перетаскивание таблиц из проводника сервера в dbml. В этом нет необходимости, но он рисует конечную линию того, где заканчиваются данные и начинается веб-приложение. Само веб-приложение - это просто представление реальной модели. После этого папка моделей приложения MVC заполняется только моделями представления. - person Nick Larsen; 27.01.2011

Причина, по которой они решили создать отдельный ViewModel вместо использования уже созданной модели, такой как Albums, Artist или Genre, заключается в том, что все 3 были необходимы. Если бы требовался только один, например Albums, можно было бы передать только Album или IList<Album> в зависимости от использования.

В ASP.NET MVC Модель может быть любым объектом в системе, который вы хотите отправить в представление. Даже string, int и любой другой базовый тип.

В ASP.NET MVC 3 вы также можете использовать ключевое слово dynamic в качестве модели представления, так что вам даже не нужно указывать тип. Однако вам, вероятно, следует избегать этого, пока это не станет последним средством, потому что всегда лучше иметь статически типизированную ViewModel.

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

person Nick Berardi    schedule 27.01.2011
comment
Я думаю, что в целом это хорошая практика, чтобы держать вещи в строгом смысле слова, это создает меньше спагетти-кода (кроме Intellisense, который на самом деле очень помогает). Итак, единственное предложение этой ViewModels - передать связанные данные в представление, не так ли? - person Msam85; 27.01.2011

ViewModel существует по двум причинам:

  1. Поддержка Intellisense.
  2. Случаев, когда передача простой модели просто недостаточна для вашего представления.

ViewModel позволяет вам отправлять несколько моделей в ваше представление в тех случаях, когда это имеет смысл - есть много случаев, когда одна простая модель просто не работает.

Бывают также случаи, когда вам нужно отправить в модель только один вид. Используйте его там, где это имеет смысл, и когда вам нужно отправить только одну модель в представление (и вас не волнует intellisense), тогда отправьте только одну модель в это представление.

person George Stocker    schedule 27.01.2011

когда вы используете Linq to SQL, каждая модель будет иметь своих дочерних и родительских элементов, загруженных в объект (когда ваша БД в порядке). Таким образом, в этом случае исходная модель очень часто является всем, что вам нужно в режиме редактирования или в режиме создания. потому что ваша модель будет сделана для вас.

ViewModels ЕСТЬ чистый путь.

грязный способ - использовать ViewData. ну "грязный". если вам нужен SelectList вместе с вашей моделью, использование ViewData не является грязным, это лучший способ в таких случаях.

person Stefanvds    schedule 27.01.2011

Есть другой способ. Вы можете использовать ChildActions.

Дочерние действия можно кэшировать, и каждое дочернее действие можно вызывать из нескольких представлений.

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

Это просто другой способ. Какой из них лучше, зависит от проблемы, которую вы пытаетесь решить.

person frennky    schedule 27.01.2011