在阅读
ASP.NET MVC 2 in Action和观看
Jimmy Bogard’s presentation from MvcConf(都强烈推荐!)后,我开始实施他们的一些想法.
他们做的很酷的事情之一不仅是使用AutoMapper将实体映射到某些viewmodel,而且可以使用AutoMapViewResult自动化:
public class EventsController : BaseController { public ActionResult Show(Event id) // EntityModelBinder gets Event from repository { return AutoMapView<EventsShowModel>(id); // AutoMapView<T>(model) is a helper method on the BaseController,that calls AutoMapViewResult<T>(...) } } // not exactly what you'll find in the book,but it also works :-) public class AutoMapViewResult<TDestination> : ViewResult { public AutoMapViewResult(string viewName,string masterName,object model) { ViewName = viewName; MasterName = masterName; ViewData.Model = Mapper.Map(model,model.GetType(),typeof(TDestination)); } }
这一切都很好,但现在有一个编辑动作与其EventsEditModel:
public class EventsEditModel { // ... some properties ... public int LocationId { get; set; } public IList<SelectListItem> Locations { get; set; } } public class EventsController : BaseController { public ActionResult Edit(Event id) { return AutoMapView<EventsEditModel>(id); } }
现在(最后)的问题:
你认为什么是将位置从某种数据源(如存储库)到EventsEditModel的Locations属性的最佳方式?
请记住,我想使用AutoMapViewResult和很多不同的实体视图模型组合.
更新:
我去了Necros的想法,并创建了一个自定义属性.您可以在我的博客ASP.NET MVC: Loading data for select lists into edit model using attributes上查看代码并将其下载.
解决方法
当我需要这个时,我没有看到这一点(因为我看到这个话题),但是我想到了一个可能的解决方案.我认为创建一个属性是有效的,指定需要加载该属性.我将从一个抽象类开始:
public abstract class LoadDataAttribute : Attribute { public Type Type { get; set; } protected LoadDataAttribute(Type type) { Type = type; } public abstract object LoadData(); }
然后为要加载的每种类型创建特定版本(您的案例中的位置)
public class LoadLocationsAttribute : LoadDataAttribute { public LoadLocationsAttribute() : base(typeof(IList<SelectListItem>)) public override object LoadData() { // get locations and return IList<SelectListItem> } }
在AutoMappViewResult的ExecuteResult中,您可以使用LoadDataAttribute查找所有属性,调用LoadData(),将其转换为属性中指定的类型并将其分配给该属性.
我想你只是想以这种方式加载选择列表,你可以返回IList< SelectListItem>而不是物体,并且为自己节省一些投射的麻烦.
您的视图模型显然会使用该属性.
public class EventsEditModel { // ... some properties ... public int LocationId { get; set; } [LoadLocations] public IList<SelectListItem> Locations { get; set; } }