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. }
或者,如果您愿意,您甚至可以在模型的构造函数或外观服务中执行此操作。
- 服务器发送的事件如何与ASP.NET MVC一起使用?
- 如何使用DI在Class Constructor中获取Microsoft.AspNet.Http.HttpContext实例
- 每种类型自定义Json.NET序列化程序设置
- DDD域模型复杂validation
- Asp.Net MVC vs Castle MonoRail
- 在Entity Framework支持的Web API 2 POST调用中返回一个对象以及409 Conflict错误?
- 将LINQ扩展为SQL生成的类
- 将多个数据库与单个DbContext和Entites一起使用,并在运行时生成Conn String
- ASP.NET MVC 3中的部分页面缓存和VaryByParam