使用 AutoMapper/AutoMapViewResult 时如何将下拉列表的数据获取到视图模型中 [英] How to get data for a dropdownlist into viewmodel when using AutoMapper/AutoMapViewResult

查看:17
本文介绍了使用 AutoMapper/AutoMapViewResult 时如何将下拉列表的数据获取到视图模型中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读ASP.NET MVC 2 in Action 并观看Jimmy Bogard 在 MvcConf 的演讲(强烈推荐!),我开始实施他们的一些想法.

他们所做的一件很酷的事情,不仅是使用 AutoMapper 将您的实体映射到某个视图模型,而且还使用 AutoMapViewResult 自动执行此操作:

public class EventsController : BaseController{public ActionResult Show(Event id)//EntityModelBinder 从存储库中获取事件{返回 AutoMapView(id);//AutoMapView(model) 是 BaseController 上的一个辅助方法,它调用 AutoMapViewResult(...)}}//不完全是你会在书中找到的,但它也有效:-)公共类 AutoMapViewResult: 查看结果{public AutoMapViewResult(string viewName, string masterName, object model){视图名称 = 视图名称;大师名 = 大师名;ViewData.Model = Mapper.Map(model, model.GetType(), typeof(TDestination));}}

这一切都很好,但现在有一个带有 EventsEditModelEdit 操作:

公共类 EventsEditModel{//... 一些属性 ...公共 int LocationId { 获取;放;}公共 IList地点{得到;放;}}公共类 EventsController : BaseController{公共 ActionResult 编辑(事件 ID){返回 AutoMapView(id);}}

现在(最后)问题:

您认为将位置从某种数据源(例如存储库)获取到 EventsEditModelLocations 属性的最佳方法是什么?

请记住,我想使用 AutoMapViewResult 和许多不同的实体-视图模型组合.

更新:

我接受了 Necros 的想法并创建了一个自定义属性.你可以查看代码并在我的博客上下载 ASP.NET MVC:使用属性将选择列表的数据加载到编辑模型中.

解决方案

当我需要这个时,我还没有进入正题(因为我看到了这个演讲),但我想到了一个可能的解决方案.我认为创建一个属性会起作用,指定需要加载这个属性.我将从一个抽象类开始:

公共抽象类 LoadDataAttribute : 属性{公共类型类型{获取;放;}受保护的 LoadDataAttribute(类型类型){类型 = 类型;}公共抽象对象 LoadData();}

然后为您要加载的每种类型创建特定版本(在您的情况下为位置)

公共类 LoadLocationsAttribute : LoadDataAttribute{public LoadLocationsAttribute() : base(typeof(IList))公共覆盖对象 LoadData(){//获取位置并返回 IList}}

AutoMappViewResultExecuteResult 中,您会找到所有带有 LoadDataAttribute 的属性,调用 LoadData(),转换将其键入属性中指定的类型并将其分配给属性.

如果您只想以这种方式加载选择列表,您可以只返回 IList 而不是 object,这样可以省去一些转换的麻烦.

您的视图模型显然会使用该属性.

公共类 EventsEditModel{//... 一些属性 ...公共 int LocationId { 获取;放;}[加载位置]公共 IList地点{得到;放;}}

After reading ASP.NET MVC 2 in Action and watching Jimmy Bogard's presentation from MvcConf (both highly recommended!), I began to implement some of their ideas.

One of the cool things they do, is not only to use AutoMapper to map your entities to some viewmodel, but automate this with an 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));
    }
}

This all works great, but now there's a Edit action with its 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); 
    }
}

And now (finally) the question:

What do you think, is the best way to get the locations from some sort of data source such as a repository to the EventsEditModel's Locations property?

Keep in mind, that I want to use the AutoMapViewResult and a lot of different entity-viewmodel combinations.

Update:

I went with Necros' idea and created a custom attribute. You can look at the code and download it on my blog ASP.NET MVC: Loading data for select lists into edit model using attributes.

解决方案

I haven't gotten to the point (since I saw the talk) when I needed this, but I have a possible solution for this in mind. I think it would work to create an attribute, specifying that this property needs to be loaded. I would start with an abstract class:

public abstract class LoadDataAttribute : Attribute
{
    public Type Type { get; set; }

    protected LoadDataAttribute(Type type)
    {
        Type = type;
    }

    public abstract object LoadData();
}

Then create specific version for each type you want to load (Locations in your case)

public class LoadLocationsAttribute : LoadDataAttribute
{
    public LoadLocationsAttribute() : base(typeof(IList<SelectListItem>))

    public override object LoadData()
    {
        // get locations and return IList<SelectListItem>
    }
}

In your ExecuteResult of AutoMappViewResult you would find all properties with LoadDataAttribute, call LoadData(), cast it to type specified in the attribute and assign it to the property.

I case you just want to load select lists this way, you can just return IList<SelectListItem> instead of object, and save yourself some trouble with casting.

Your view model would the obviously use the attribute.

public class EventsEditModel
{
    // ... some properties ...
    public int LocationId { get; set; }

    [LoadLocations]
    public IList<SelectListItem> Locations { get; set; }
}

这篇关于使用 AutoMapper/AutoMapViewResult 时如何将下拉列表的数据获取到视图模型中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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