ASP.NET MVC 使用动态类型传递数据

2017-04-09
2分钟阅读时长

问题起因

在 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(); 
}

这是一篇过去很久的文章,其中的信息可能已经有所发展或是发生改变。

本文作者:她和她的猫
本文地址https://her-cat.com/posts/2017/04/09/asp-net-mvc-use-dynamic-types/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!