Подтвердить что ты не робот

Правильное использование Model vs Controller в MVC/ASP.NET MVC

У меня есть класс Service с методом GetProducts(). Это инкапсулирует бизнес-логику и вызывает репозиторий для получения списка продуктов.

My MVC view хочет показать этот список продуктов как MVC SelectList. Где правильное место для этой логики. Кажется, у меня есть 3 варианта:

  • Model

    Модель должна выставить свойство под названием ProductSelectList. Когда получатель этого свойства вызывается View, модель должна вызывать Service.GetProducts() и преобразовывать результат в SelectList перед его передачей.

    Допустимый аргумент: модель должна делать вызовы бизнес-логике и репозиторию. Представление должно просто отображать предопределенные данные. Контроллер не должен быть задействован, за исключением передачи в контекстную информацию.

  • Просмотр

    В представлении должен содержаться код, который вызывает Service.GetProducts() напрямую и преобразует результат в строку SelectList.

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

  • контроллер

    Контроллер должен сделать вызов Service.GetProducts(), преобразовать результаты в SelectList и передать его в Модель, которая должна содержать простое свойство ProductSelectList. Вид получит доступ к этому свойству для рендеринга.

    Допустимый аргумент: Контроллер знает, какие параметры необходимо предоставить методу службы, поэтому он должен сделать вызов. Модель должна быть простой заполнитель для данных, заполненных Контроллером. Задача "Просмотр" - просто визуализировать данные из модели.

У меня такое чувство, что правильный ответ Model, но два других делают некоторые разумные моменты. Возможно, я загрязнил воды, уже имея класс обслуживания, который отделен от Модели?

Кто-нибудь хотел бы поделиться своим мнением? Это только вопрос вкуса?

4b9b3361

Ответ 1

Я лично подписываюсь на логику Номер 3, позволяя контроллеру заполнять модель (или просмотреть модель, которая иногда дифференцируется).

  • У меня есть мои представления немые и только отображение данных.
  • У меня есть мои модели просмотра, которые хранят информацию, которая нужна View, иногда выставляя свойства "получить только", которые форматируют другие свойства в более удобный формат. Если моей модели нужен доступ к моим услугам, то я чувствую, что делаю что-то неправильно.
  • Контроллеры организуют и собирают всю информацию вместе (но не выполняют фактическую работу, которая остается для служб.

В вашем примере у меня было бы действие моего контроллера похоже на:

public ActionResult Index()
{
    IndexViewModel viewModel = new IndexViewModel();
    viewModel.ProductSelectList = new SelectList(Service.GetProducts(), "Value", "Name");
    return View(viewModel);
}

и моя модель просмотра похожа на:

public class IndexViewModel()
{
   public SelectList ProductSelectList { get; set; }
   public int ProductID { get; set; }
}

Соответствующая часть вида выглядит так:

@Html.DropDownListFor(x => x.ProductID, Model.ProductSelectList);

Таким образом, я доволен тем, что знаю, где искать, если есть проблема с чем угодно, и все имеет очень специфическое место.

Тем не менее, нет правильного пути, как кажется всегда, с этими вещами. Стивен Вальтер хорошая серия блога по советам MVC. В одном он говорит об акценте View Model, и хотя он не является списком SelectList, который он заполняет, SelectList по-прежнему является данными так же, как и его список продуктов.

Ответ 2

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

Затем ваш контроллер отвечает за заполнение вашего ViewModel из модели сущностей, возвращаемой вашим уровнем обслуживания.

Из-за удобства некоторые разработчики будут использовать свои объекты уровня сервиса непосредственно в своих ViewModels, но в долгосрочной перспективе это может привести к головным болям. Один из способов - использовать инструмент AutoMapper для автоматизации перетасовки данных в модели ViewModel и сущностей и из них.

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

public class Customer : IEntity
{
  public string CustomerID { get; set; }
  public string SSN { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }    
  public Address Address { get; set; }
}

public class CustomerEditViewModel
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string Address1 { get; set; }
  public string Address2 { get; set; }
  public string Country { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public string Zip { get; set; }
  public string PhoneNumber { get; set; }
}

public class CustomerController
{
  [AcceptVerbs (HttpVerbs.Get)]
  public ActionResult Edit ()
  {
    Customer customer = _customerService.GetCustomer (User.Identity.Name);

    var model = new CustomerEditViewModel ()
    {
      FirstName = customer.FirstName,
      LastName = customer.LastName,
      Address1 = customer.Address.Address1,
      Address2 = customer.Address.Address2,
      Country = customer.Address.Country,
      City = customer.Address.City,
      State = customer.Address.State,
      Zip = customer.Address.Zip,
      PhoneNumber = customer.Address.PhoneNumber,
    };

    return View (model);
  }
}

Ответ 3

Вы правы, что есть несколько способов справиться с этим, и что даже до рассмотрения таких вариаций, как MVP, MVVM и т.д. Поскольку вы спрашиваете о ASP.Net MVC, в частности, я отложусь до Microsoft:

Модель MVC содержит всю вашу логику приложения, которая не является содержащихся в представлении или контроллере. Модель должна содержать все бизнес-логика приложения, логика проверки и доступ к базе данных логика. Например, если вы используете Microsoft Entity Framework для доступ к вашей базе данных, то вы создадите свою инфраструктуру Entity Framework классов (ваш .edmx файл) в папке "Модели".

В представлении должна содержаться только логика, связанная с генерированием пользователя интерфейс. Контроллер должен содержать только минимум логики требуется для возврата правильного представления или перенаправления пользователя на другой действие (управление потоком). Все остальное должно содержаться в модель.

В общем, вы должны стремиться к жирным моделям и тощим контроллерам. Ваши методы контроллера должны содержать только несколько строк кода. Если действие регулятора становится слишком толстым, тогда вам следует рассмотреть возможность перемещения логика в новый класс в папке "Модели".

Источник

Я бы сказал, что ваш вызов принадлежит модели.

Ответ 4

Следует иметь в виду, что класс SelectList специфичен только для MVC. Поэтому, на мой взгляд, он не должен быть включен в какую-либо бизнес-логику, а классы моделей попадают в эту категорию. Поэтому ваш список выбора должен быть частью класса модели представления.

Так оно работает в моих проектах:

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

Ответ 5

Я бы выбрал вариант 3. В общем, я создам свои приложения MVC таким образом, чтобы контроллер вызывал вызов службе, чтобы вернуть модель (или коллекцию моделей), которые затем передаются в представление.

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

Вы определенно не хотите, чтобы представление вызывало вызовы ваших услуг.

Обновление...
Я предполагаю, что это SelectList - ваша модель. Если вместо этого это часть вашей модели, тогда вы правы, вы должны поместить ее в свою модель. Я вообще не люблю делать это вызов метода. У меня будет свойство на моей модели:

public SelectList Products { get; set; }

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

Ответ 6

Я собираюсь с вариантом 1.

Модели - это место, где можно совершать вызовы бизнес-логике и т.д.

View - должен отображать только то, что уже было замечено в ViewModel.

Контроллер - задача Контроллера - направлять входящий трафик (от веб-запросов) к логике, которая отвечает за обработку запроса. Следовательно, термин " контроллер".

Есть всегда исключения из них, но лучшим местом (структурно) является Модель.

Ответ 7

У меня была эта проблема, когда я начал работать в MVC и придумал это решение.

Контроллер говорит об уровне обслуживания. Сервисный уровень содержит мои модели домена и выполняет всю обработку запроса с контроллеров. Уровень обслуживания также возвращает ViewModels для удовлетворения запросов от контроллера.

Уровень сервиса вызывает репозиторий и получает объекты, которые ему необходимы для создания ViweModels. Я часто использую Automapper для заполнения ViewModel или коллекций в модели представления.

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

Я не вижу проблемы с просмотром определенных элементов, таких как SelectLists, в модели просмотра.

Ответ 8

Ничего из перечисленного.

В моем веб-слое у меня просто есть html и javascript-представления. Модель не должна течь в точку зрения, и ни одна из них не должна обслуживаться.

У меня также есть уровень инфраструктуры, который связывает сервисы и модель с представлениями. В этом слое есть ViewModels, которые представляют собой классы, которые отображают то, что будет отображаться на экране, Mappers, которые выполняют работу по получению данных из сервисов/модели и сопоставлению ее с моделью просмотра, а также Задачи, которые выполняют такие задачи, как Saving, Обновление и удаление данных.

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

public class CustomerController
{
  [AcceptVerbs (HttpVerbs.Get)]
  public ActionResult Edit (int id)
  {
    return View (CustomerEditMapper.Map(id));
  }

  [AcceptVerbs (HttpVerbs.Post)]
  public ActionResult Save(CustomerEditViewModel model)
  {
    var errors = CustomerEditUpdatorCommand.Execute(model);
    ModelState.AddErrors(errors);
    return View ();
  }

}

Ответ 9

Я разрывается между опцией 1 и опцией 3. Я полностью выбрал вариант 2, поскольку я загрязняю представление с помощью процедур, которые вызывают не только работу с презентационным слоем.

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

Другой вариант здесь заключается в том, чтобы избежать плотной связи представления и модели, помещая Dictionary продуктов в представление через Сервисный вызов, а затем используя представление для преобразования Dictionary в SelectList, но это также дает вам возможность просто выводить информацию.

Я думаю, это сводится к тому, чтобы вы были довольны своей логикой.