ASP.NET MVC控制器向视图传递多个集合(非ViewBag)的方法
传递多个集合到视图的解决方案(无需ViewBag)
你现在遇到的问题其实是因为视图没办法直接绑定匿名类型——匿名类型的访问级别是internal,视图所在的项目(一般是Web项目)没法访问控制器项目里的匿名类型,所以得换用强类型的载体来传递多个集合,最常用的有两种方案,我给你详细说说:
方案一:创建专用ViewModel(推荐,可维护性更高)
这是ASP.NET MVC里传递多组数据的标准做法,专门创建一个类来封装你需要传递到视图的所有数据。
1. 定义ViewModel类
在你的项目里新建一个ViewModel类(比如放在Models文件夹下):
public class MyIndexViewModel { public Dictionary<int, string> DictOne { get; set; } public Dictionary<int, string> DictTwo { get; set; } }
2. 修改控制器代码
实例化这个ViewModel,把两个字典赋值进去,再传递给View:
public ActionResult Index() { Dictionary<int, string> DictOne = MyObjOne.DictOne; Dictionary<int, string> DictTwo = MyObjTwo.DictTwo; var viewModel = new MyIndexViewModel { DictOne = DictOne, DictTwo = DictTwo }; return View(viewModel); }
3. 修改视图代码
指定视图的模型类型为你创建的ViewModel,然后分别访问两个字典:
@model MyIndexViewModel <!-- 注意替换成你的ViewModel的完整命名空间 --> <div class="row"> <!-- 第一个字典的展示 --> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list"></span> DictOne </div> <div class="panel-body"> <table class="table"> <thead> <tr> <th> DictOne Items </th> </tr> </thead> <tbody> @foreach (KeyValuePair<int, string> kvp in Model.DictOne) { <tr> <td> @kvp.Value </td> </tr> } </tbody> </table> </div> </div> </div> <!-- 第二个字典的展示 --> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list"></span> DictTwo </div> <div class="panel-body"> <table class="table"> <thead> <tr> <th> DictTwo Items </th> </tr> </thead> <tbody> @foreach (KeyValuePair<int, string> kvp in Model.DictTwo) { <tr> <td> @kvp.Value </td> </tr> } </tbody> </table> </div> </div> </div> </div>
方案二:使用Tuple(适合简单场景)
如果只是临时传递少量数据,也可以用Tuple来打包多个集合,不用额外创建类:
1. 修改控制器代码
用Tuple.Create把两个字典打包:
public ActionResult Index() { Dictionary<int, string> DictOne = MyObjOne.DictOne; Dictionary<int, string> DictTwo = MyObjTwo.DictTwo; return View(Tuple.Create(DictOne, DictTwo)); }
2. 修改视图代码
指定模型类型为对应的Tuple,通过Item1和Item2访问两个字典:
@model Tuple<Dictionary<int, string>, Dictionary<int, string>> <div class="row"> <!-- 第一个字典(Item1)的展示 --> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list"></span> DictOne </div> <div class="panel-body"> <table class="table"> <thead> <tr> <th> DictOne Items </th> </tr> </thead> <tbody> @foreach (KeyValuePair<int, string> kvp in Model.Item1) { <tr> <td> @kvp.Value </td> </tr> } </tbody> </table> </div> </div> </div> <!-- 第二个字典(Item2)的展示 --> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> <span class="glyphicon glyphicon-th-list"></span> DictTwo </div> <div class="panel-body"> <table class="table"> <thead> <tr> <th> DictTwo Items </th> </tr> </thead> <tbody> @foreach (KeyValuePair<int, string> kvp in Model.Item2) { <tr> <td> @kvp.Value </td> </tr> } </tbody> </table> </div> </div> </div> </div>
为什么原来的匿名对象不行?
你之前尝试的return View(new { DictOne, DictTwo })没法正常工作,是因为C#的匿名类型默认是internal访问级别,而视图通常在单独的Web项目里,没法访问控制器项目里的internal类型,所以视图无法强类型绑定这个匿名对象。上面两种方案都是用public类型(ViewModel类或Tuple)来解决这个问题。
内容的提问来源于stack exchange,提问作者Barrosy
相关产品推荐
相关产品推荐

