如何通过ViewBag传递查询列表?遇RuntimeBinderException异常
解决ViewBag传递匿名类列表时
displayName无法访问的错误 兄弟,你踩了ASP.NET MVC里匿名类的一个常见坑——匿名类是internal访问修饰符,而MVC的视图会被编译成独立的程序集,根本没法跨程序集访问internal类型的成员,所以视图里的dynamic类型找不到displayName属性才报这个错。
下面给你几个实用的解决方案,按推荐程度排序:
1. 创建强类型ViewModel(最推荐,规范且易维护)
这是企业项目里的标准做法,类型安全还方便后续扩展:
首先在项目里加个ViewModel类:
public class EmployeeNameViewModel { public string DisplayName { get; set; } }
然后把查询里的匿名类换成这个ViewModel:
var query = (from employee in db.LKEmployeeDatas join transaction in db.AssetTransactions on employee.SamAccountName equals transaction.SamAccountName select new EmployeeNameViewModel { DisplayName = employee.SamAccountName }).ToList(); // 要么丢ViewBag,要么直接用强类型视图更规范 ViewBag.query = query;
视图里这样访问(最好做个类型转换确保安全):
@{ var employeeList = ViewBag.query as List<EmployeeNameViewModel>; if (employeeList != null) { foreach (var emp in employeeList) { @emp.DisplayName } } }
更优的做法是用强类型视图,直接把列表作为视图模型传递:
// 控制器里直接传模型 return View(query);
视图顶部指定模型:
@model List<EmployeeNameViewModel> @foreach (var emp in Model) { @emp.DisplayName }
2. 用Tuple快速解决(临时场景首选)
如果只是临时需求,不想新建类,Tuple是个快速选项:
控制器里修改查询:
var query = (from employee in db.LKEmployeeDatas join transaction in db.AssetTransactions on employee.SamAccountName equals transaction.SamAccountName select Tuple.Create(employee.SamAccountName)).ToList(); ViewBag.query = query;
视图里访问Item1就行:
@{ foreach (var k in ViewBag.query) { @k.Item1 } }
3. 转成ExpandoObject(不推荐,类型不安全)
这种方式适合极简单的临时场景,缺点是完全没有类型检查:
控制器里把匿名类转成ExpandoObject:
var query = (from employee in db.LKEmployeeDatas join transaction in db.AssetTransactions on employee.SamAccountName equals transaction.SamAccountName select new { displayName = employee.SamAccountName }) .Select(x => { dynamic expando = new ExpandoObject(); var dict = (IDictionary<string, object>)expando; dict["displayName"] = x.displayName; return expando; }).ToList(); ViewBag.query = query;
视图里就能正常用@k.displayName了,但这种方式后期维护容易出问题,不建议在正式项目里用。
总的来说,优先用方案1的强类型ViewModel,代码更健壮也更符合MVC的设计思想。
内容的提问来源于stack exchange,提问作者Rasindu De Alwis
相关产品推荐
相关产品推荐

