ViewData 和 ViewBag 有啥区别?

Posted

技术标签:

【中文标题】ViewData 和 ViewBag 有啥区别?【英文标题】:What's the difference between ViewData and ViewBag?ViewData 和 ViewBag 有什么区别? 【发布时间】:2011-06-09 23:28:00 【问题描述】:

我在 MVC 3 中看到了 ViewBag。它与 MVC 2 中的 ViewData 有什么不同?

【问题讨论】:

【参考方案1】:

它使用 C# 4.0 动态特性。它实现了与 viewdata 相同的目标,应避免使用强类型视图模型(应避免使用与 viewdata 相同的方式)。

所以基本上它取代了魔术字符串

ViewData["Foo"]

具有魔法属性

ViewBag.Foo

您没有编译时安全性。

我继续指责微软在 MVC 中引入了这个概念。

属性名称区分大小写。

【讨论】:

你指责微软的目的是什么?如果没有视图数据,我们如何从模型中绑定下拉列表。 (我认为在模型中使用 selectlist 不是一个好主意) @SubinJacob 如果你想要这个问题的答案,你真的应该提出一个新问题。创建一个 SelectList 绝对是制作下拉列表的方法。 我认为这有点主观。强类型模型很好,yada yada,但对于快速启动并运行视图的场景,ViewBag 等比 Controller、View、Model、AutoMapper 到 ViewModel 等更快。 @Darin,你为什么要“责备”微软引入这个?它只是提供给开发人员的工具。如果你知道你在做什么,你就可以充分利用它。如果您不喜欢它或觉得它更容易出错,请不要使用它。 :) 你建议如何在部分和布局之间传递数据?人们在看不到全貌时会责备。我想你到处都有基本控制器和基本视图模型或静态/单例对象。你猜怎么着,最好学会使用视图数据并责备自己使用错误的工具来完成这项工作。【参考方案2】:

ViewBag 属性在内部以名称/值对的形式存储在 ViewData 字典 中。

注意:在 MVC 3 的大多数预发布版本中,ViewBag 属性被命名为 ViewModel,如 MVC 3 发行说明中的​​ sn-p 中所述:

(10-8-12 编辑) 有人建议我发布我发布的此信息的来源,这里是来源: http://www.asp.net/whitepapers/mvc3-release-notes#_Toc2_4

MVC 2 控制器支持 ViewData 使您能够传递数据的属性 使用后期绑定到视图模板 字典 API。在 MVC 3 中,您还可以 使用更简单的语法 ViewBag 属性来完成 相同的目的。例如,而不是 写 ViewData["Message"]="text", 你可以写 ViewBag.Message="text"。 您不需要定义任何 强类型类使用 ViewBag 属性。因为它是一个 动态属性,您可以改为 获取或设置属性,它将 在运行时动态解决它们。 在内部, ViewBag 属性是 存储为名称/值对 查看数据字典。 (注:在大多数 MVC 3 的预发布版本, ViewBag 属性被命名为 ViewModel 属性。)

【讨论】:

这个问题问的是ViewDataViewBag之间的区别,而不是ViewModel 感谢 Matthew Flaschen 的提醒,我在回复中有错字并修复了它,现在读取“ViewData”而不是 ViewModel,这是一个错误。 :) 现在不正确了。两者都没有重命名为另一个。它们都仍然存在。一种是dynamic,支持ViewBag.Message。一个使用旧的ViewData["Message"] 语法。 +1 但是,您引用的来源是什么...?真的应该提供一个链接。 感谢山姆的建议。我添加了指向原始来源的链接。【参考方案3】:

MVC 中的 ViewBag 与 ViewData

http://royalarun.blogspot.in/2013/08/viewbag-viewdata-tempdata-and-view.html

ViewBag 和 ViewData 的相似之处:

当您从控制器移动到视图时,有助于维护数据。曾经 将数据从控制器传递到相应的视图。短暂的生命意味着 发生重定向时 value 变为 null。这是因为他们的目标 是提供一种在控制器和视图之间进行通信的方式。它的 服务器调用中的一种通信机制。

ViewBag 和 ViewData 的区别:

ViewData 是一个对象字典,它派生自 ViewDataDictionary 类,可使用字符串作为键进行访问。查看包 是一个动态属性,它利用了新的动态特性 在 C# 4.0 中。 ViewData 需要对复杂数据类型进行类型转换,并且 检查空值以避免错误。 ViewBag 不需要 复杂数据类型的类型转换。

ViewBag 和 ViewData 示例:

public ActionResult Index()
   
    ViewBag.Name = "Arun Prakash";   
    return View();


public ActionResult Index()
  
    ViewData["Name"] = "Arun Prakash";  
    return View();
   

在视图中调用

@ViewBag.Name    
@ViewData["Name"]

【讨论】:

您的回答表明typecasting,但您没有说明如何执行类型转换【参考方案4】:

ViewData:它需要对复杂数据类型进行类型转换并检查空值以避免错误。

ViewBag:它不需要对复杂数据类型进行类型转换。

考虑以下示例:

public class HomeController : Controller

    public ActionResult Index()
    
        var emp = new Employee
        
            EmpID=101,
            Name = "Deepak",
            Salary = 35000,
            Address = "Delhi"
        ;

        ViewData["emp"] = emp;
        ViewBag.Employee = emp;

        return View(); 
    

View的代码如下:

@model MyProject.Models.EmpModel;
@ 
 Layout = "~/Views/Shared/_Layout.cshtml"; 
 ViewBag.Title = "Welcome to Home Page";
 var viewDataEmployee = ViewData["emp"] as Employee; //need type casting


<h2>Welcome to Home Page</h2>
This Year Best Employee is!
<h4>@ViewBag.Employee.Name</h4>
<h3>@viewDataEmployee.Name</h3>

【讨论】:

帮我理解,但我认为有一个错误。这个&lt;h4&gt;@ViewBag.emp.Name&lt;/h4&gt; 应该更改为&lt;h4&gt;@ViewBag.Employee.Name&lt;/h4&gt;【参考方案5】:

所有答案都表明ViewBag 和/或ViewData 是将数据从Controller 传递到Views,这是错误信息。两者对于将数据从 Views 传递到 Layout 或 Partial 到 Views(或 ViewComponents 等)都非常有用。它不是控制器独有的。

作为默认的 asp.net 示例,在布局页面中有这个:

<title>@ViewData["Title"] - MyApp</title>

在任何视图中

ViewData["Title"] = "Details";

那么,问这个问题:“ViewBagViewData 有什么区别?”

最显着的区别是ViewData 是强类型字典,而 ViewBag 是动态类型。

注意里面的数据IS THE SAME

ViewData["Title"] = "MyTitle";
ViewBag.Title; // returns "MyTitle";

什么时候使用一个或另一个?

ViewBag 不支持无效的 C# 名称。 您无法使用ViewBag 访问ViewData["Key With Space"] ViewBag.Something 是动态的,在调用需要在编译时知道确切参数的方法(如扩展方法)时可能会遇到问题。 ViewBag 可以检查空值语法清理器:ViewBag.Person?.Name ViewData 具有 Dictionary 的所有属性,例如 ContainsKeyAdd 等,因此您可以使用 ViewData.Add("somekey", "somevalue"),记住它可能会引发异常。 在视图上使用 ViewData 需要进行类型转换,而 ViewBag 不需要。

了解细微差别,使用其中一种或另一种更多的是一种口味偏好。

通常您可以将ViewBag.AnyKey 视为ViewData["AnyKey"] 的别名

【讨论】:

这实际上是最完整的答案。【参考方案6】:

我可以建议你不要使用吗?

如果您想向屏幕“发送”数据,请发送强类型对象(A.K.A. ViewModel),因为它更容易测试。

如果您绑定到某种“模型”并具有随机的“viewbag”或“viewdata”项,那么自动化测试会非常困难。

如果您正在使用这些,请考虑如何重组并仅使用 ViewModel。

【讨论】:

忽略“编译器是第一个单元测试”原则,静态类型的视图模型如何使您的代码比动态类型更易于测试?虽然在动态类型的解决方案中测试的要求更为重要,但如果两种解决方案都实现了相同数量和类型的测试,那么您不会失去任何东西。 我同意,这有点模糊。也许涉及智能感知。 一个例子是模拟。如果您想对控制器操作进行单元测试,创建一个“模拟”对象来传递和断言比尝试断言某些字符串已添加到某个字典或某些动态字段设置为某个值更容易 - 它是与具有一个“请求”和一个“响应”对象的服务合同类似的概念,而不是采用多个参数。 如果不使用任何一种,您将如何将数据从视图传递到布局? -1 答案如何?【参考方案7】:

存在一些细微的差异,这意味着您可以以与视图略有不同的方式使用 ViewData 和 ViewBag。这篇文章 http://weblogs.asp.net/hajan/archive/2010/12/11/viewbag-dynamic-in-asp-net-mvc-3-rc-2.aspx 概述了一个优点,并表明在示例中可以通过使用 ViewBag 而不是 ViewData 来避免强制转换。

【讨论】:

【参考方案8】:

viewdata: 是一个字典,用于在视图和控制器之间存储数据,你需要将视图数据对象转换为视图中对应的模型,以便能够从中检索数据...

ViewBag: 是一个动态属性,其工作方式与视图数据类似,但更好的是,在视图中使用它之前不需要将其转换为相应的模型.. .

【讨论】:

【参考方案9】:

以下是关于 ViewData、ViewBag、TempData 和 Session 的点对点差异。 Credit/copied askforprogram.in,点击链接查看我这里没有提到的代码示例。

    MVC 中的视图数据

    ViewData 是 ControllerBase 类的属性。 ViewData 是一种字典对象。 ViewData 是键值字典集合。 ViewData 是在 MVC 1.0 版本中引入的。 ViewData 适用于 .Net 框架 3.5 及更高版本。 枚举时需要对代码进行类型转换。 ViewData 对象仅保留当前请求的数据。

    MVC 中的 ViewBag

    ViewBag 是 ControllerBase 类的属性。 ViewBag 是一种动态对象。 ViewBag 是一种对象。 ViewBag 是在 MVC 3.0 版本中引入的。 ViewBag 适用于 .Net 框架 4.0 及更高版本。 ViewBag 使用属性并对其进行处理,因此无需进行类型转换,同时 枚举。 ViewBag 对象仅保留当前请求的数据。

    MVC 中的临时数据

    TempData 是 ControllerBase 类的属性。 TempData 是一种字典对象。 TempData 是键值字典集合。 TempData 是在 MVC 1.0 版本中引入的。 TempData 适用于 .Net 框架 3.5 及更高版本。 枚举时需要对代码进行类型转换。 TempData 对象用于当前请求和后续请求之间的数据。

    MVC 中的会话

    Session 是 Controller(抽象类)的属性。 Session 是一种 HttpSessionStateBase。 Session 是键值字典集合。 会话是在 MVC 1.0 版本中引入的。 TempData 适用于 .Net 框架 1.0 及更高版本。 枚举时需要对代码进行类型转换。 会话对象保存所有请求的数据。适用于所有请求,永不过期。

【讨论】:

【参考方案10】:

尽管选择一种格式可能没有技术优势 另一个,你应该知道两者之间的一些重要区别 语法。 一个明显的区别是 ViewBag 仅在您访问密钥时才有效 是一个有效的 C# 标识符。例如,如果您在 ViewData["Key 使用 Spaces"],您无法使用 ViewBag 访问该值,因为代码 不会编译。 另一个需要考虑的关键问题是您不能将动态值作为参数传递 到扩展方法。 C# 编译器必须知道每一个的真实类型 编译时的参数,以便选择正确的扩展方法。 如果任何参数是动态的,编译将失败。例如,此代码将 总是失败:@Html.TextBox("name", ViewBag.Name)。要解决此问题,要么 使用 ViewData["Name"] 或强制转换 va

【讨论】:

【参考方案11】:
public ActionResult Index()

    ViewBag.Name = "Monjurul Habib";
    return View();


public ActionResult Index()

    ViewData["Name"] = "Monjurul Habib";
    return View();
 

In View:

@ViewBag.Name 
@ViewData["Name"] 

【讨论】:

【参考方案12】:

通过这种方式,我们可以让它使用这些值将控制器之间的信息传递到带有 TEMP DATA 的其他页面

【讨论】:

【参考方案13】:

我注意到 ViewData 和 ViewBag 之间的一个主要区别是:

ViewData :它会返回对象,无论你分配了什么,都需要再次类型转换回原始类型。

ViewBag :返回您分配给它的确切类型是足够聪明的,无论您分配简单类型(即 int、string 等)还是复杂类型。

例如:控制器代码。

 namespace WebApplication1.Controllers

    public class HomeController : Controller
    
        public ActionResult Index()
        
            Products p1 = new Products();
            p1.productId = 101;
            p1.productName = "Phone";
            Products p2 = new Products();
            p2.productId = 102;
            p2.productName = "laptop";

            List<Products> products = new List<Products>();
            products.Add(p1);
            products.Add(p2);
            ViewBag.Countries = products;
            return View();
        
    
    public class Products
    
        public int productId  get; set; 
        public string productName  get; set; 
    

查看代码。

<ul>
            @foreach (WebApplication1.Controllers.Products item in ViewBag.Countries)
            
            <li>@item.productId &nbsp;&nbsp;&nbsp;@item.productName</li>
            
        </ul>

输出屏幕。

【讨论】:

【参考方案14】: 查看数据
    ViewData 用于将数据从控制器传递到视图 它派生自 ViewDataDictionary 类 仅适用于当前请求 需要对复杂数据类型进行类型转换并检查空值以避免错误 如果发生重定向,则其值为 null
查看包
    ViewBag 还用于将数据从控制器传递到相应的视图 ViewBag 是一个动态属性,它利用了 C# 4.0 中的新动态特性 它也仅适用于当前请求 如果发生重定向,则其值为 null 复杂数据类型不需要类型转换

【讨论】:

【参考方案15】:

这里 ViewDataViewBag 都用于将数据从 Controller 传递到 View

1.查看数据

-- ViewData 是从 ViewDataDictonary 类派生的字典对象。

-- 数据只允许一个请求,当页面重定向发生时,ViewData 值被清除。

-- ViewData 值必须在使用前输入 cate。

示例:在控制器中

public ActionResult PassingDatatoViewWithViewData()

      ViewData["Message"] = "This message shown in view with the ViewData";
      return View();

在视图中

@ViewData["Message"];

-- 如果 ViewData 是 KeyValue 之类的对,Message 是 Key,而引号中的 value 是 Value。

-- 数据很简单,所以如果数据复杂,我们不能在这里使用类型转换,然后使用类型转换。

public ActionResult PassingDatatoViewWithViewData()

      var type= new List<string>
    
        "MVC",
        "MVP",
        "MVVC"
    ;
    ViewData["types"] = type;
    return View();

-- In View 数据可以提取为

<ul>
        @foreach (var items in (List<string>)ViewData["types"])
        
         <li>@items</li>
        
  </ul>

2。查看包

--ViewBag 使用动态 feature.ViewBag 包装 ViewData。

-- 在 ViewBag 中需要类型转换。

--与ViewData相同,如果发生重定向,则值为null。

示例:

public ActionResult PassingDatatoViewWithViewBag()

          ViewData.Message = "This message shown in view with the ViewBag";
          return View();

在视图中

@ViewBag.vbMessage

--对于复杂类型使用ViewBag

public ActionResult PassingDatatoViewWithViewBag()

          var type= new List<string>
        
            "MVC",
            "MVP",
            "MVVC"
        ;
        ViewBag.types = type;
        return View();
 

-- In View 数据可以提取为

<ul>
       @foreach (var items in ViewBag.types)
       
         <li>@items</li>
       
</ul>

-- 主要区别在于 ViewBag 不需要类型转换,但 ViewData 需要类型转换。

【讨论】:

【参考方案16】:

ViewBag 和 ViewData 是 ASP.Net MVC 中用于将信息从控制器传递到视图的两种方式。使用这两种机制的目的是提供控制器和视图之间的通信。两者的生命周期都很短,一旦发生重定向,即一旦页面从源页面(我们设置 ViewBag 或 ViewData 的值)重定向到目标页面,ViewBag 和 ViewData 的值都将变为 null变为空。

尽管两者(ViewBag 和 ViewData)有这些相似之处,但如果我们谈论两者的实现,它们是两个不同的东西。区别如下:

1.) 如果我们对这两个实现进行分析,那么我们会发现 ViewData 是一个字典数据结构 - 对象字典从 ViewDataDictionary 派生并且可以使用字符串作为这些值的键来访问,而 ViewBag 则利用了 C 中引入的动态特性#4.0 并且是动态属性。

2.) 在从 ViewData 访问值时,我们需要对值(数据类型)进行类型转换,因为它们作为对象存储在 ViewData 字典中,但如果我们在 ViewBag 的情况下访问值,则不需要。

3.) 在 ViewBag 中我们可以这样设置值:

      ViewBag.Name = "Value"; 

并且可以访问如下:

          @ViewBag.Name

在 ViewData 的情况下,可以按如下方式设置和访问值: 设置 ViewData 如下:

ViewData["Name"] = "Value";

并像这样访问值

 @ViewData["Name"] 

更多详情click here:

【讨论】:

对不起,我投了反对票,但这个答案需要几个段落才能说没有任何用处。接受的答案中缺少的有用的东西是我从rachelappel.com/… 学到的句子“viewbag 是 viewdata 的动态包装器”【参考方案17】:

ViewBag

    它返回类型对象。 它是ControllerBase 类的dynamic 属性。 ViewBag 仅适用于 .NET Framework 4.0 及更高版本。 它不需要在使用前进行类型转换,因为ViewBag 属性本质上是dynamicViewBag 返回动态类型对象,其属性也是dynamic。 比ViewData快一点。

查看数据

    它返回键值字典对集合。 ViewData 是一个字典对象,它是 ControllerBase 类的属性。 ViewDataViewBag 快。 枚举时需要类型转换代码,因为它是字典对集合。 ViewData返回对象(键值对的类型,值是类型对象,使用前需要强制转换)

public ActionResult Index()
   
    ViewBag.Name = "";   
    return View();


public ActionResult Index()
  
    ViewData["Name"] = "Arun Prakash";  
    return View();

在视图中调用

@ViewBag.Name    
@ViewData["Name"]

【讨论】:

以上是关于ViewData 和 ViewBag 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

NET MVC中ViewData,ViewBag和TempData的区别浅析

ViewData 和 ViewBag 到底有什么区别?

ASP.NET-viewBag Viewdata Tempdata

MVC源码解读ViewDataViewBagTempData的区别

控制器到视图的传值方式

ViewData,ViewBag和TempData