MVC - Контроллер с несколькими списками выбора - PullRequest
2 голосов
/ 04 февраля 2012

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

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);

    // 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);
}

Ответы [ 3 ]

3 голосов
/ 04 февраля 2012

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

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

Определение ViewModel ernicher означает, что в любом месте, где используется 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>();
    }

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

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

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

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

2 голосов
/ 04 февраля 2012

Вы можете настроить вспомогательный класс, поместить каждый список выбора в статический метод. После этого вы можете получить каждый список выбора с помощью 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 ())

1 голос
/ 04 февраля 2012

Конечно, просто рефакторинг его в метод, например так:

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.
}

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

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