构建视图模型的代码应该放在哪里?

Tra*_*s J 5 c# viewmodel asp.net-mvc-3

在asp.net的MVC3中构建视图模型时,代码应该在哪里实例化该视图模型的对象?我现在主要在控制器中执行它,除了查询数据库的代码.这是代码中的一个例子:

查看型号:

public class WorkListVM
{
    //list for employees
    [Display(Name = "Select A Employee")]
    [Required]
    public int? EmployeeId { get; set; }
    public GenericSelectList EmployeeList { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

控制器代码:

        //build view model
        var vm = new WorkListVM();

        //build employee list
        vm.EmployeeList = new GenericSelectList(0,"-- Select Employee --");
        var employees = new List<Employee>();
        using (var gr = new GenericRepo<Employee>())
        {
            employees = gr.Get().ToList();
        }
        foreach(var employee in employees)
        {
            var gl = new GenericListItem();
            gl.Id = employee.EmployeeId;
            gl.DisplayFields = employee.FirstName + " " + employee.LastName;
            vm.EmployeeList.Values.Add(gl);
        }
Run Code Online (Sandbox Code Playgroud)

通用选择列表是一个简单的类来保存进去辅助数据@html.dropdownforSelectList.我构建了这些选择列表,并为控制器代码中的视图模型构建了类似的数据配置.托管此代码的控制器总共有109行代码,因此它不是很大或无法控制.但是,我一直在努力减少冗余,有时代码//build employee list最终被复制粘贴(呃,我讨厌复制粘贴)到其他控制器.

有没有更好的地方有这个代码?我是否应该使用工厂模式为这些选择列表/其他视图数据对象构建数据?

编辑

感谢你的帮助.这就是我最终做的事情.我最终在泛型选择列表类中创建了一个非常类似于Richard和Jesse建议的.ToSelectList(...)的方法:

    public class GenericSelectList
{
    public List<GenericListItem> Values { get; set; }
    public int StartValue { get; set; }
    public string Message { get; set; }

    public GenericSelectList(int StartValue = 0, string Message = "select")
    {
        Values = new List<GenericListItem>();
        this.StartValue = StartValue;
        this.Message = Message;
    }

    public void BuildValues<T>(List<T> items, Func<T, int> value, Func<T, string> text) where T : class
    {
        this.Values = items.Select(f => new GenericListItem()
        {
            Id = value(f),
            DisplayFields = text(f)
        }).ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

Jes*_*sse 2

如果创建视图模型的业务逻辑非常复杂,我通常将其提取到一个辅助方法中,我可以独立于控制器进行测试。

然而,除此之外,您创建的视图模型在控制器中完全没有问题。正如已经指出的,如何使生成选择列表变得更加简单(更不用说可重用)。

以下是 IEnumerable 的 ToSelectList 扩展以及使用示例:

public static List<SelectListItem> ToSelectList<T>( this IEnumerable<T> enumerable, Func<T, string> value, Func<T, string> text, string defaultOption)
{
    var items = enumerable.Select(f => new SelectListItem()
                                          {
                                              Text = text(f) ,
                                              Value = value(f)
                                          }).ToList();

    if (!string.IsNullOrEmpty(defaultOption))
    {
                    items.Insert(0, new SelectListItem()
                        {
                            Text = defaultOption,
                            Value = string.Empty
                        });
    }

    return items;
}
Run Code Online (Sandbox Code Playgroud)

在您的视图模型中,您可以添加如下属性:

IEnumerable<SelectListItem> Employees { get; set; }
Run Code Online (Sandbox Code Playgroud)

在您的控制器内(我假设您的存储库返回 IEnumberable):

var employees = new IEnumerable<Employee>();
using (var gr = new GenericRepo<Employee>())
{
    employees = gr.Get();
}

vm.Employees = employees.ToSelectList(x=>x.FirstName + " " + x.LastName, x=>x.Id, "-- Select Employee --")
Run Code Online (Sandbox Code Playgroud)

然后在视图中设置下拉列表,它看起来像:

@Html.DropDownListFor(model => model.EmployeeId, Model.employees)
Run Code Online (Sandbox Code Playgroud)