Вопрос по asp.net-mvc, c# – MVC - Контроллер с несколькими списками выбора

2

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

public class Model
{
    public IEnumerable<SelectListItem> AllLocations { get; set; }
    public IEnumerable&,lt;SelectListItem> TopLocations { get; set; }
    public IEnumerable<SelectListItem> AllTemplates { get; set; }
    public IEnumerable<SelectListItem> TopTemplates { get; set; }
    // ...
}

[HttpGet]
public ActionResult Index(int id)
{
    var domain = Repository.Get(id);
    var model = Mapper.Map<Domain, ViewModel>(item);

    // any way to abstract this type of code?
    model.AllLocations = new SelectList(repository.GetAllLocations(), "Value", "Text");
    model.TopLocations = new SelectList(repository.GetTopLocations(), "Value", "Text");
    model.AllTemplates = new SelectList(repository.GetAllTemplates(), "Value", "Text");
    model.TopTemplates = new SelectList(repository.GetTopTemplates(), "Value", "Text");
    // etc. etc.

    return View(model);
}

[HttpPost]
public ActionResult Index(ViewModel model)
{
    // any way to abstract this type of code?
    model.AllLocations = new SelectList(repository.GetAllLocations(), "Value", "Text");
    model.TopLocations = new SelectList(repository.GetTopLocations(), "Value", "Text");
    model.AllTemplates = new SelectList(repository.GetAllTemplates(), "Value", "Text");
    model.TopTemplates = new SelectList(repository.GetTopTemplates(), "Value", "Text");
    // etc. etc.

    return View(model);
}
В общем, если вы хотите уменьшить код контроллера, вы можете получить действие get до одной строки, если вы использовали привязку модели для преобразования Id в объект домена, а затем использовали результат настраиваемого действия для сопоставления и обогащения модели. Подумайте, многое из того, что описано в книге MVC 3 в действии GraemeMiller

Ваш Ответ

3   ответа
2

поместить каждый список выбора в статический метод. После этого вы можете получить каждый список выбора с помощью htmlhelper. Контроллер очистит. В то же время, другой вид также может использовать этот список выбора.

например:

public class SelectHelper
{
     public static List<SelectListItem> AllLocations()
     {
         //TODO repository.GetAllLocations()
     }
     public static List<SelectListItem> TopLocations()
     {
         //TODO repository.GetTopLocations()
     }
     ...
}

просмотреть код: @ Html.DropDownList ("selectname", SelectHelper.AllLocations ())

Я бы предпочел, чтобы ViewModel содержал все данные, необходимые для построения представления. Вместо того, чтобы иметь представление, несут ответственность за получение данных. GraemeMiller
ViewModel - хороший способ. Иногда я часто позволяю ViewModel простой, просто DTO.Next, я сделаю это в ViewModel. Если многие ViewModels имеют этот список выбора, я думаю, что инкапсулировать метод необходимо. javan
Я просто не думаю, что представление должно получать данные независимо от контроллера. Контроллер должен действовать между представлением и данными. Однако это, очевидно, зависит от размера и сложности приложения. GraemeMiller
1

public class Model
{
    public IEnumerable<SelectListItem> AllLocations { get; set; }
    public IEnumerable<SelectListItem> TopLocations { get; set; }
    public IEnumerable<SelectListItem> AllTemplates { get; set; }
    public IEnumerable<SelectListItem> TopTemplates { get; set; }
    // ...
}

[HttpGet]
public ActionResult Index(int id)
{
    var domain = Repository.Get(id);
    var model = Mapper.Map<Domain, ViewModel>(item);
    InitializeSelectLists(model);

    return View(model);
}

[HttpPost]
public ActionResult Index(ViewModel model)
{
    InitializeSelectLists(model);
    View(model);
}


private void InitializeSelectLists(Model model)
{
    model.AllLocations = new SelectList(repository.GetAllLocations(), "Value", "Text");
    model.TopLocations = new SelectList(repository.GetTopLocations(), "Value", "Text");
    model.AllTemplates = new SelectList(repository.GetAllTemplates(), "Value", "Text");
    model.TopTemplates = new SelectList(repository.GetTopTemplates(), "Value", "Text");
    // etc. etc.
}

Или вы можете даже сделать это в конструкторе для вашей модели или в фасадном сервисе, если хотите.

3

держать действия контроллера маленькими - это здорово. Как говорит Джимми Богардпосадить своих контролеров на диету!

Я использую IModelEnricher в сочетании с Automapper. Я возвращаю сущность и т. Д., Используя определенный ActionResult, который затем автоматизирует мою сущность в ViewModel и обогащает данными, необходимыми для списков выбора (и любыми дополнительными данными, необходимыми). Этот метод делает ваш код СУХИМЫМ и контроллерами тонкими, как супер-модель :-)! Также сохраняя данные списка выбора как часть вашей ViewModel, вы сохраняете обязанности своего контроллера, модели и представления.

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

В моем случае это выглядит примерно так в контроллере:

public virtual ActionResult Edit(int id)
{
    return AutoMappedEnrichedView<PersonEditModel>(_personRepository.Find(id));
}

[HttpPost]
public virtual ActionResult Edit(PersonEditModel person)
{
     if (ModelState.IsValid){
            //This is simplified (probably don't use Automapper to go VM-->Entity)
            var insertPerson = Mapper.Map<PersonEditModel , Person>(person);
            _personRepository.InsertOrUpdate(insertPerson);
            _requirementRepository.Save();
            return RedirectToAction(Actions.Index());
      }
     return EnrichedView(person);
 }

Этот вид ViewModel:

public class PersonEditModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public int FavouriteTeam { get; set; }
    public IEnumerable<SelectListItem> Teams= new List<SelectListItem>();
}

С этим видом Enricher:

public  class PersonEditModelEnricher :
IModelEnricher<PersonEditModel>
{
    private readonly ISelectListService _selectListService;

    public PersonEditModelEnricher(ISelectListService selectListService)
    {
        _selectListService = selectListService;
    }

    public PersonEditModelEnrich(PersonEditModel model)
    {
        model.Teams = new SelectList(_selectListService.AllTeams(), "Value", "Text")
        return model;
    }
} 

Еще один вариант - украсить ViewModel атрибутами, которые определяют расположение данных для заполнения списка выбора. Подобно:

  public class PersonEditModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public int FavouriteTeam { get; set; }
        [LoadSelectListData("Teams")]
        public IEnumerable<SelectListItem> Teams= new List<SelectListItem>();
    }

Теперь вы можете украсить соответствующий метод в вашем сервисе select с помощью атрибута:

   [ProvideSelectData("Teams")]
   public IEnumerable Teams()
   {
        return _teamRepository.All.ToSelectList(a => a.Name, a => a.TeamId);
   }

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

Посмотри этовопрос, Также этоСообщение блога а такжеэто, Также этовопрос на форуме Automapper

Мне нравится этот подход. Dismissile

Похожие вопросы