Избежание использования SelectList на бизнес-уровне (MVC 3) - PullRequest
6 голосов
/ 19 февраля 2011

Я работаю над довольно большим приложением MVC 3 и сталкиваюсь с проблемой, которая не совсем мне подходит.Этот вопрос требует некоторой настройки, чтобы понять, поэтому вот условия, над которыми я сейчас работаю:

  • Представления должны быть строго типизированы (следует избегать ViewBag / ViewData)
  • Поскольку представления строго типизированы, должны быть созданы объекты модели представления, которые инкапсулируют все данные, которые необходимо отобразить для представления
  • Когда нам нужно выпадающее меню, у нас должно быть два свойства:
    1. Свойство в модели, в котором хранится выбранное значение раскрывающегося
    2. Свойство SelectList в модели представления, представляющее элементы раскрывающегося списка
  • Само представление всегда использует вспомогательный метод @Html.DropDownListFor()
  • . Мы используем Entity Framework 4 и позволяем ему генерировать классы сущностей из нашей уже спроектированной базы данных
  • . Чтобы избежать дублирования и использовать преимущества LINQ,мы не создаем наши собственные отдельные классы бизнес / модели, а добавляем к частичным классам, генерируемым структурой сущностей
  • Частичные классы, которые мы пишем, расположены на бизнес-уровне, чтобы все правильно компилировалось
  • Большинство классов моделей имеют общий шаблон редактора, который можно использовать в нескольких представлениях

Вот гдепроблема приходит. Тип модели шаблона общего редактора устанавливается на класс модели.Это означает, что частичное представление, составляющее шаблон редактора, не имеет доступа к содержащему объект модели представления, где хранится список раскрывающихся элементов.

Мне удалось «решить» это, добавив SelectList свойство непосредственно к классу модели на бизнес-уровне вместо сохранения его в модели представления.Но класс SelectList специфичен для MVC, что, в свою очередь, означает, что мой бизнес-уровень зависит от MVC.Это не кажется мне правильным, потому что BL должен быть агностиком по отношению к пользовательскому интерфейсу.

Кто-нибудь еще сталкивался с этой проблемой?Как мне решить это?Также возможно, что одно из моих предположений неверно.

Ответы [ 3 ]

4 голосов
/ 19 февраля 2011

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

Большинство классов моделей имеют общий редакторшаблон, который можно использовать в нескольких представлениях

Это модели представления, которые должны иметь шаблоны редактора, а не модели EF.А поскольку модели представлений специфичны для требований представления, вы можете свободно помещать в них любую необходимую информацию, например, в данном случае SelectList.Поэтому не просто определяйте модель представления root , в которой ваши EF-модели являются свойствами (это не модель представления).Определите модель представления, разработанную с учетом требований конкретного представления.Не помещайте ни одного класса EF в иерархию моделей представлений, и вы увидите, насколько проще будет ваша жизнь: -)

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

1 голос
/ 19 февраля 2011

У вас есть 2 основных решения ИМХО:

1. Генерация DTO / моделей для ваших бизнес-логических объектов

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

2. Используйте методы расширения

Вместо объявления свойства SelectList в частичном классе сущности EF и загрязнения вашей бизнес-логики кодом, связанным с представлением, создайте методы расширения для ваших объектов EF в веб-проекте. Затем вы можете переместить свой связанный с просмотром код в веб-проект из BL и сохранить безопасность типов.

Пример:

Сборка бизнес-логики

// This is EF entity
public partial class FooTable
{
    public long Id { get; set; }
    public string Name { get; set; }
}

Веб-сборка

public static class FooTableExtensions
{
    public static SelectList GetSelectList(this IEnumerable<FooTable> fooTables)
    {
        return new SelectList(); // Create your select list from FooTables here.
    }
}
0 голосов
/ 21 мая 2011

Ну, мы закончили тем, что выбрали простой выход.На бизнес-уровне мы просто изменили тип на обычный старый Object.Я подумал, что, независимо от уровня представления, ему понадобится какой-то список, чтобы содержать доступные опции.

Я знаю, что это не очень чисто, как в @Darin и @Jakub, но я немы видим, что наш конечный результат в этом отношении несколько иной, за исключением того, что мы избежали необходимости писать и / или настраивать целую связку между объектами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...