当他们拥有依赖于大量选择列表的模型时,有没有什么好方法可以让我的控制器更简单?我尽量保持我的大多数控制器操作尽可能简单(希望不超过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);
}
答案 0 :(得分:3)
正如你所说保持控制器动作小很多。正如吉米·博加德所说put your controllers on a diet!
我使用IModelEnricher与Automapper结合使用。我使用特定的ActionResult返回一个实体等,然后将我的实体自动化为ViewModel,并丰富选择列表所需的数据(以及所需的任何其他数据)。这种方法让您的代码DRY和控制器像超级模型一样瘦:-)!同时将选择列表数据保留为ViewModel的一部分可以使您的控制器,模型和查看职责保持清晰。
定义ViewModel ernicher意味着在使用ViewModel的任何地方,它都可以使用相同的richher来获取其属性。因此,您可以在多个位置返回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);
}
然后对于没有复杂浓缩的简单模型,只需通用浓缩过程就可以处理它。如果你想做更复杂的事情,你可以定义一个更丰富的,如果它存在就会被使用。
答案 1 :(得分: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())
答案 2 :(得分: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.
}
或者,如果您愿意,您甚至可以在模型的构造函数或外观服务中执行此操作。