MVC - 控制器与多个选择列表 [英] MVC - Controller with multiple select lists

查看:108
本文介绍了MVC - 控制器与多个选择列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有什么好的方法可以让我的控制器简单,当他们有依赖于很多选择列表中的模式?我尽量保持我的大部分控制器操作尽可能的简单(希望不超过10行左右),但需要大量的下拉列表中的我的行为一般不超过本网页:

 公共类模型
{
    公共IEnumerable的< SelectListItem> AllLocations {搞定;组; }
    公共IEnumerable的< SelectListItem> TopLocations {搞定;组; }
    公共IEnumerable的< SelectListItem> AllTemplates {搞定;组; }
    公共IEnumerable的< SelectListItem> TopTemplates {搞定;组; }
    // ...
}[HTTPGET]
公众的ActionResult指数(INT ID)
{
    VAR域= Repository.Get(ID);
    VAR模型= Mapper.Map<域名,视图模型>(项目);    //任何方式抽象这类code的?
    model.AllLocations =新的SelectList(repository.GetAllLocations(),值,文本);
    model.TopLocations =新的SelectList(repository.GetTopLocations(),值,文本);
    model.AllTemplates =新的SelectList(repository.GetAllTemplates(),值,文本);
    model.TopTemplates =新的SelectList(repository.GetTopTemplates(),值,文本);
    //等等,等等    返回查看(模型);
}[HttpPost]
公众的ActionResult指数(视图模型模型)
{
    //任何方式抽象这类code的?
    model.AllLocations =新的SelectList(repository.GetAllLocations(),值,文本);
    model.TopLocations =新的SelectList(repository.GetTopLocations(),值,文本);
    model.AllTemplates =新的SelectList(repository.GetAllTemplates(),值,文本);
    model.TopTemplates =新的SelectList(repository.GetTopTemplates(),值,文本);
    //等等,等等    返回查看(模型);
}


解决方案

至于你说的保持控制器动作小是很大的。吉米·博加德说<一href=\"http://www.google.co.uk/search?aq=f&sourceid=chrome&ie=UTF-8&q=Jimmy+Boggard#hl=en&sa=X&ei=PlctT_K2HoPY8QO-_OSHDw&ved=0CBoQvwUoAQ&q=Jimmy+Bogard+controllers+diet&spell=1&bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&fp=cee598fc631c5c56&biw=1920&bih=933\"相对=nofollow>把你的控制器节食!

我使用IModelEnricher与A​​utomapper相结合。我回使用特定的ActionResult是那么automaps我的实体到一个视图模型,并与选择列表(以及所需的任何额外的数据)所需要的数据,丰富的实体等。这种方法使你的code DRY和控制器薄得像一个超级模特:-)!还保持选择列表中的数据,因为视图模型的一部分​​,让你的控制器,模型和视图职责明确。

定义视图模型ernicher意味着任何地方视图模型使用它可以使用相同的富集器以获得其属性。所以,你可以在多个地方返回视图模型,它只会得到填入正确的数据。

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

 公共虚拟的ActionResult编辑(INT ID)
{
    返回AutoMappedEnrichedView&所述; PersonEditModel&GT;(_ personRepository.Find(ID));
}[HttpPost]
公共虚拟的ActionResult编辑(PersonEditModel人)
{
     如果(ModelState.IsValid){
            //这是简化的(可能不使用Automapper去VM - &GT;实体)
            VAR insertPerson = Mapper.Map&LT; PersonEditModel,人&GT;(人);
            _personRepository.InsertOrUpdate(insertPerson);
            _requirementRepository.Save();
            返回RedirectToAction(Actions.Index());
      }
     返回EnrichedView(人);
 }

这有点视图模型的:

 公共类PersonEditModel
{
    公共字符串名字{获得;组; }
    公共字符串名字{获得;组; }
    公众诠释年龄{搞定;组; }
    公众诠释FavouriteTeam {搞定;组; }
    公共IEnumerable的&LT; SelectListItem&GT;团队=新的List&LT; SelectListItem&GT;();
}

通过这种富集器的:

 公共类PersonEditModelEnricher:
IModelEnricher&LT; PersonEditModel&GT;
{
    私人只读ISelectListService _selectListService;    公共PersonEditModelEnricher(ISelectListService selectListService)
    {
        _selectListService = selectListService;
    }    公共PersonEditModelEnrich(PersonEditModel模型)
    {
        model.Teams =新的SelectList(_selectListService.AllTeams(),值,文本)
        回归模型;
    }
}

另外一种方式是通过定义数据是如何定位以填充选择列表属性来装点视图模型。这样的:

 公共类PersonEditModel
    {
        公共字符串名字{获得;组; }
        公共字符串名字{获得;组; }
        公众诠释年龄{搞定;组; }
        公众诠释FavouriteTeam {搞定;组; }
        [LoadSelectListData(小组)]
        公共IEnumerable的&LT; SelectListItem&GT;团队=新的List&LT; SelectListItem&GT;();
    }

现在你可以在你选择的服务装饰一个合适的方法与属性,如:

  [ProvideSelectData(小组)]
   公共IEnumerable的团队()
   {
        返回_teamRepository.All.ToSelectList(一个= GT; a.Name,一个= GT; a.TeamId);
   }

那么对于简单的模型,没有复杂的富集只是普通的富集过程可以处理它。如果你想做的任何事情更复杂,你可以定义一个富集器,它会被使用,如果它存在。

请参阅此<一个href=\"http://stackoverflow.com/questions/3507466/how-to-get-data-for-a-dropdownlist-into-viewmodel-when-using-automapper-automapv\">question.另外这款<一个href=\"http://blog.opo.li/post/ASPNET-MVC-Loading-data-for-select-lists-into-edit-model-using-attributes.aspx\"相对=nofollow>博客文章和这个。另外这款质疑上Automapper论坛

Are there any good ways to keep my controllers simpler when they have models that depend on a lot of select lists? I try to keep most of my controller actions as simple as possible (hopefully no more than 10 or so lines) but on pages that require a lot of dropdowns my actions usually exceed this:

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

解决方案

As you say keeping controller actions small is great. As Jimmy Bogard says put your controllers on a diet!

I use an IModelEnricher combined with Automapper. I return an entity etc using a specific ActionResult that then automaps my entity to a ViewModel and enriches with data required for select lists (and any additional data required). This method keeps your code DRY and controllers thin like a super model :-)! Also keeping the select list data as part of your ViewModel keeps your controller, model, and view responsibilities clear.

Defining a ViewModel ernicher means that anywhere that ViewModel is used it can use the same enricher to get its properties. So you can return the ViewModel in multiple places and it will just get populated with the correct data.

In my case this looks something like this in the 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);
 }

This sort of 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>();
}

With this sort of 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;
    }
} 

One other option is to decorate the ViewModel with attributes that define how the data is located to populate the select list. Like:

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

Now you can decorate an appropriate method in your select service with an attribute like:

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

Then for simple models with no complex enrichment just the generic enrichment process can handle it. If you want to do anything more complex you can define an enricher and it will be used if it exists.

See this question. Also this blog post and this. Also this question on Automapper forum

这篇关于MVC - 控制器与多个选择列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆