ASP.NET MVC 使用动态类型传递数据
问题起因
在 Controller 中定义动态类型的对象传递给视图,报错无法找到成员。
Controller:
public ActionResult Index()
{
ViewBag.User = new { name = "何湘辉", age = 20 };
return View();
}
视图:
姓名:@ViewBag.User.name
年龄:@ViewBag.User.age
按道理来说,这样写是没问题的,但是运行后却说Model中不存在‘name’。
然后经过一番百度才找到了答案,因为 dynamic 是“匿名类型”,它的访问级是 internal,所以只有在同一程序集的文件中才是可以访问的。ASP.NET MVC 在编译的时候,会将 cshtml 视图和 Controller 分别编译成两个 DLL 文件,因此视图是无法访问到 Controller 所在程序集的 internal 成员的。
解决办法
第一种解决办法是使用 Moon.Cecil 修改程序集,将所有匿名类型的访问级别修改成 public。可以说是从问题根源解决了问题,但是这个方法我并没有成功,我也不知道哪里出错了,所以就不讲详细过程了。想了解的话可以看看使用Mono.Cecil辅助ASP.NET MVC使用dynamic类型Model
第二种解决办法是使用ExpandoObject类型。ExpandoObject 是一种可以在运行时动态添加、删除成员的类型,并且可以跨程序集访问。
使用方法:
public ActionResult Index()
{
dynamic expandoObj = new ExpandoObject();
expandoObj.name= "何湘辉";
expandoObj.age = 20;
ViewBag.User = expandoObj;
return View();
}
这种方法虽然解决了跨程序集访问的问题,但是每次都要 new 一个 ExpandoObject 对象,然后再为它手动添加成员,就显得有点麻烦了,所以就有了第三种方法。
第三种方法是先将匿名对象转换成 JSON 格式的字符串,然后再将 JSON 字符串转换成 JSON 对象。
这里我用的是 Newtonsoft.Json 来对 JSON 进行操作。
public ActionResult Index()
{
var varObj = new { name = "何湘辉", age = 20};
// 将匿名对象转换成JSON字符串 {"name": "何湘辉", "age": 20}
string jsonStr = JsonConvert.SerializeObject(varObj);
// 再将JSON字符串转换成object
object obj = JsonConvert.DeserializeObject(jsonStr);
ViewBag.User = obj;
return View();
}
这是一篇过去很久的文章,其中的信息可能已经有所发展或是发生改变。