如何将匿名对象的集合从控制器传递到视图

时间:2012-07-11 23:33:41

标签: asp.net-mvc asp.net-mvc-3

我是MVC的新手,所以如果我的问题听起来很愚蠢或太简单,请原谅。我正在使用实体数据模型进行数据库访问。所以在我的Models文件夹中,我添加了一个EDMX文件,我可以从我的控制器和强类型视图访问模型类。当我在控制器中访问多个表时会出现问题,例如

如果我的数据库中有以下表格:

 Departments(DepartmentID, DepartmentName, DepartmentPhone)
 Insurances(InsuranceID, InsuranceName, InsuranceAddress)
 Employees(EmployeeID, EmpFName, EmpLName, DepartmentID, InsuranceID)

我想显示员工名单及其部门和保险信息。

在我的Controller的操作方法中,我使用EDM访问数据库,并以匿名类型获取信息:

 using (var context = new MyEntities())
        {
            var model = (from d in context.Departments
                         join e in context.Employees on d.DepartmentID equals e.DepartmentID
                         join I in context.Insurances on I.InsuranceID equals e.InsuranceID

                         select new
                         {
                             DepartmentID = d.DepartmentID,
                             EmployeeID= e.EmployeeID,
                             EmpFName= e.EmpFName,
                             EmpLName= e.EmpLName,
                             DepartmentName= d.DepartmentName,
                             InsuranceName= I.InsuranceName

                         }).ToList();

            return View(model);
        }

我的Model文件夹中没有这个匿名类的类,所以我无法创建强类型视图。那么将此列表传递给View的最佳方法是什么?如果集合太大,使用viewbag将是一种过度杀伤。为这个匿名类创建一个新模型听起来不对,因为如果我在控制器操作方法中更改我的选择,它需要一直更新。

欢迎所有建议。我尝试在SO上查看其他问题,但找不到任何相关内容。

感谢。

3 个答案:

答案 0 :(得分:2)

  

我的Model文件夹中没有这个匿名类的类,所以我   无法创建强类型视图

右键单击您的项目,添加新类...现在您在Model文件夹中有一个类型。这是ASP.NET MVC =>的方法。查看模型。

然后显然你将这种类型传递给你的观点:

select new MyViewModel
{
    DepartmentID = d.DepartmentID,
    EmployeeID = e.EmployeeID,
    EmpFName = e.EmpFName,
    EmpLName = e.EmpLName,
    DepartmentName = d.DepartmentName,
    InsuranceName = I.InsuranceName
}).ToList();

当然,现在您的视图会强烈输入此视图模型:

@model IEnumerable<MyViewModel>
...

答案 1 :(得分:0)

我担心预定义的强类型ViewModel是可行的方法。在多个地方更新看似重复的代码是一件痛苦的事情,但根据我的经验,这对于较小的项目来说只是一个问题。随着项目的增长,您开始看到数据库模型对象(实体)与传递给视图的视图模型之间的差异,例如验证和处理属性以及特定于视图的数据,当您到达那一点时,您开始更喜欢使用单独的实体和ViewModel定义。

但是,回到主题:您的问题的替代解决方案是使用反射将匿名类型转换为Dictionary<String,Object>对象。请注意,ASP.NET MVC执行此操作以将new { foo = "bar" } - 语法表达式转换为路径值和HTML属性的字典。性能是可以接受的,但是不要为单个HTTP请求尝试为10,000个对象执行此操作,否则您可能会陷入困境。

这里的代码是什么样的:

Object anonymousType = new { whatever = "foo" };
Dictionary<String,Object> dict = new Dictionary<String,Object>();

foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(anonymousType )) {
    Object value = descriptor.GetValue(anonymousType );
    dict.Add( descriptor.Name, value );
}

当然这意味着您的视图不会受益于编译时类型检查,并且您必须维护一个记录的字典键列表(假设您不是在重复键入你的观点)。

我注意到我很惊讶微软并没有让匿名类型自动实现IDictionary,因为它似乎很自然。

答案 2 :(得分:0)

dynamic类型是你的朋友。

您可以将视图声明为松散类型,具有动态模型

@model dynamic

您将像在强类型视图中一样访问模型属性

<h1>Model.DepartmentId</h1> - <h2>Model.DepartmentName</h2>
<span>Model.EmployeeId</span>

问题是,动态包含内部属性,如果你使用MVC2,你需要一点trick来使它工作。但似乎MVC3及更高版本,不再需要它。