MVC – 具有多个选择列表的控制器

当他们的模型依赖于大量选择列表时,有没有什么好方法可以让我的控制器更简单? 我尽量保持我的大多数控制器操作尽可能简单(希望不超过10行),但在需要大量下拉菜单的页面上,我的操作通常会超出此范围:

public class Model { public IEnumerable AllLocations { get; set; } public IEnumerable TopLocations { get; set; } public IEnumerable AllTemplates { get; set; } public IEnumerable TopTemplates { get; set; } // ... } [HttpGet] public ActionResult Index(int id) { var domain = Repository.Get(id); var model = Mapper.Map(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); } 

正如你所说保持控制器动作小很多。 正如Jimmy Bogard所说, 让你的控制器节食 !

我使用IModelEnricher结合Automapper。 我使用特定的ActionResult返回实体等,然后将我的实体自动化为ViewModel,并丰富选择列表所需的数据(以及所需的任何其他数据)。 这种方法让您的代码DRY和控制器像超级模型一样瘦:-)! 同时将选择列表数据保留为ViewModel的一部分可以使您的控制器,模型和查看职责保持清晰。

定义ViewModel ernicher意味着在使用ViewModel的任何地方,它都可以使用相同的richr来获取其属性。 因此,您可以在多个位置返回ViewModel,它只会填充正确的数据。

在我的情况下,这在控制器中看起来像这样:

 public virtual ActionResult Edit(int id) { return AutoMappedEnrichedView(_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(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 Teams= new List(); } 

有了这种Enricher:

 public class PersonEditModelEnricher : IModelEnricher { 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 Teams= new List(); } 

现在,您可以使用以下属性在选择服务中修饰适当的方法:

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

然后对于没有复杂浓缩的简单模型,只需通用浓缩过程就可以处理它。 如果你想做更复杂的事情,你可以定义一个更丰富的,如果它存在,它将被使用。

看到这个问题 。 这篇博文也是这个 。 还有关于Automapper论坛的这个问题

您可以设置一个辅助类,将每个选择列表放在一个静态方法中。然后,在视图中,您可以通过htmlhelper获取每个选择列表。 控制器将清除。 同时,其他视图也可以使用这些选择列表。

例如:

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

查看代码:@ Html.DropDownList(“selectname”,SelectHelper.AllLocations())

当然,只需将它重构为一个方法,如下所示:

 public class Model { public IEnumerable AllLocations { get; set; } public IEnumerable TopLocations { get; set; } public IEnumerable AllTemplates { get; set; } public IEnumerable TopTemplates { get; set; } // ... } [HttpGet] public ActionResult Index(int id) { var domain = Repository.Get(id); var model = Mapper.Map(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. } 

或者,如果您愿意,您甚至可以在模型的构造函数或外观服务中执行此操作。