zoukankan      html  css  js  c++  java
  • 浅谈 MVC3 中关于 ViewData 和 ViewBag 的区别和联系

    原文转至:http://archive.cnblogs.com/a/2236962/

    我们在用 MVC3 开发网站的时候,Controller 和 View 中经常会用到这两个变量 ViewBag、ViewData,ViewBag 是动态类型(dynamic),ViewData 是一个字典型的(Dictionary)。

    一般情况下,我们都知道这两个变量怎么用,但新手们一般都不知道有什么区别和联系(包括我自己也是),前两天跟几位同事一起讨论研究了一下 MCV3 中 ViewData 和 ViewBag 的区别和联系,在此跟各位博友分享一下。

    当然鄙人对这两种变量的研究也不是很深入,发布这篇随笔呢,只想抛砖引玉,希望广大的博友都能谈谈对这两种变量的理解。

    在用 ViewBag 和 ViewData 的时候,我们可以这样写:

    Controller 端:

    public ActionResult Index()
    {
    ViewBag.Hi = "Hi Girl!";
    ViewData["Hello"] = "Hello Boy!";

    return View();
    }

    View 端:

    @ViewBag.Hi
    <br />
    @ViewData["Hello"]

    输出:

    当然,我们也可以这么写:

    Controller 端:

    public ActionResult Index()
    {
    ViewBag.Hi = "Hi Girl!";
    ViewData["Hello"] = "Hello Boy!";

    return View();
    }

    View 端:

    @ViewData["Hi"]<br />
    @ViewBag.Hello

    输出:

    从上面的两个例子我们可以看出,ViewBag 和 ViewData 是互通的,那么他们到底有什么区别呢?

    我们可以看到他们的定义:

    //
    // Summary:
    // Gets the dynamic view data dictionary.
    //
    // Returns:
    // The dynamic view data dictionary.
    [Dynamic]
    public dynamic ViewBag { get; }
    //
    // Summary:
    // Gets or sets the dictionary for view data.
    //
    // Returns:
    // The dictionary for the view data.
    public ViewDataDictionary ViewData { get; set; }

    从注释来看,ViewBag 是“获取动态视图数据字典。”并没有设置视图数据这一说,而且 ViewBag 也没有 set 方法,而我们在使用的过程中,恰恰是能够进行 set 操作的,这是为什么呢?

    ViewData 相对于 ViewBag 更全面,而且支持更多的方法和属性,从下图我们便可看出:

    那到底为什么 ViewBag 和 ViewData 的数据能够互通呢, MVC 做了什么操作呢?

    我们来分析分析他的源码:

    public dynamic ViewBag
    {
    get
    {
    if (_dynamicViewDataDictionary == null)
    {
    _dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
    }
    return _dynamicViewDataDictionary;
    }
    }

    上面这段是 ViewBag 的源码,我们看到 ViewBag 的值是从一个 DynamicViewDataDictionary 的实例中获取的,而这个 DynamicViewDataDictionary 内部是什么样子的呢:

    internal sealed class DynamicViewDataDictionary : DynamicObject
    {
    private readonly Func<ViewDataDictionary> _viewDataThunk;

    public DynamicViewDataDictionary(Func<ViewDataDictionary> viewDataThunk)
    {
    _viewDataThunk = viewDataThunk;
    }

    private ViewDataDictionary ViewData
    {
    get
    {
    ViewDataDictionary viewData = _viewDataThunk();
    Debug.Assert(viewData != null);
    return viewData;
    }
    }

    // Implementing this function improves the debugging experience as it provides the debugger with the list of all
    // the properties currently defined on the object
    public override IEnumerable<string> GetDynamicMemberNames()
    {
    return ViewData.Keys;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
    result = ViewData[binder.Name];
    // since ViewDataDictionary always returns a result even if the key does not exist, always return true
    return true;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
    ViewData[binder.Name] = value;
    // you can always set a key in the dictionary so return true
    return true;
    }
    }

    上面这段就是 DynamicViewDataDictionary 的类的源码了,相信大家看了自然了解了 ViewBag 和 ViewData 的异同了,而且 TrySetMember 方法也解释了,为什么 ViewBag 只有 set 方法却可以赋值的原因。

    上面这些都是鄙人对这两种变量的理解和认识,若有任何不足或者不对之处欢迎大侠们指出!

  • 相关阅读:
    Eclipse安装代码反编译插件Enhanced Class Decompiler
    使用idea创建web项目
    shell编程学习笔记(十二):Shell中的break/continue跳出循环
    shell编程学习笔记(十一):Shell中的while/until循环
    windows环境下安装zookeeper(仅本地使用)
    解决base64-encoded secret key cannot be null or empty问题
    不就一个上传图片功能吗,为什么要搞得那么复杂?
    解决WARN警告:Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended
    Jmeter发送jdbc请求(操作mysql)
    Jmeter-ForEach控制器
  • 原文地址:https://www.cnblogs.com/fannyatg/p/2352213.html
Copyright © 2011-2022 走看看