当 Controller 的模型依赖于大量选择列表时,有什么好的方法可以让 Controller 变得更简单吗?我尝试让大部分 Controller 操作尽可能简单(希望不超过 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);
}
最佳答案
正如你所说,保持 Controller Action 较小是很好的。正如吉米·博加德所说 put your controllers on a diet !
我将 IModelEnricher 与 Automapper 结合使用。我使用特定的 ActionResult 返回一个实体等,然后将我的实体自动映射到 ViewModel 并丰富选择列表所需的数据(以及所需的任何其他数据)。这种方法使您的代码保持干燥,并且 Controller 像 super 模型一样瘦:-)!此外,将选择列表数据保留为 ViewModel 的一部分可以使 Controller 、模型和 View 职责保持清晰。
定义 ViewModel ernicer 意味着在使用 ViewModel 的任何地方都可以使用相同的丰富器来获取其属性。因此,您可以在多个位置返回 ViewModel,它只会填充正确的数据。
就我而言, Controller 中看起来像这样:
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>();
}
使用这种丰富器:
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);
}
对于没有复杂丰富的简单模型,只需通用的丰富过程就可以处理它。如果您想做任何更复杂的事情,您可以定义一个丰富器,如果存在,就会使用它。
查看此question 。还有这个blog post和 this 。还有这个question在 Automapper 论坛上
关于c# - MVC - 具有多个选择列表的 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9136091/