ViewData、ViewBag、TempData、Session的区别与联系

本文探讨了ASP.NET MVC中ViewData、ViewBag、TempData和Session四种数据传递方式的特性与应用场景,深入分析了它们的生命周期、数据类型及安全性考量。

简介

这篇文章是我在学习ASP.NET MVC程序传值方式梳理总结的笔记。在ASP.NET MVC中,页面间和Controller与View之间主要有以下几种小量数据传值方式, ViewDataViewBagTempDataSession变量。 我们是幸运的,微软提供给了我们这么多传值方法,但选择越多越让人抓狂,这些技术每一种都有自己的优点和缺点,我应该何时使用哪一种传值方式呢?

正文

上面的这四种方法中,ViewData和ViewBag其实是一回事, ViewBag其实是对ViewData的封装, 其内部其实是使用ViewData实现数据存储的。唯一的不同点是,ViewBag可以存储动态类型(dynamic)的变量值, 而ViewData只能存储String Key/Object Value字典数组。 所以我们可以将这四种方法归为三大类, ViewData和ViewBag, TempData, Session。

ViewData["Message"] = "Hello ASP.NET MVC";
// Or
ViewBag.Message = "Hello ASP.NET MVC";

TempData也是一个String Key/Object Value字典数组。 和ViewData与ViewBag不同的是其所存储的数据对象的生命周期。 如果页面发生了跳转(Redirection),ViewBag和ViewData中的值将不复存在, 但是TempData中的值依然还在。 换句话讲, ViewBag和ViewData存储的值的生命周期只有在从Controller到View中, 而TempData中的数据不仅在从Controller到View中有效,在不同的Action之间或者从一个页面跳转到另一页面(Controller to Controller)后依然有效。

TempData["Message"] = "Hello ASP.NET MVC";

Session其实和ViewData类似,也是一个String Key/Object Value字典数组。但是,Session是存储在客户端的Cookies中,所以它的生命周期是最长的。 但是,正因为其存储的客户端, 所以必须确保没有敏感机密的信息存储其中

Session["Message"] = "Hello ASP.NET MVC";

下面我们对每一个传值方法的特点进行以下总结。

ViewData

  • ViewData是一个继承自ViewDataDictionary类的Dictionary对象。
  • ViewData用来从Controller向对应的View传递值。
  • ViewData的只在当前当前的请求中有效,生命周期和View相同,其值不能在多个请求中共享。
  • 在重定向(redirection)后,ViewData中存储的变量值将变为null。
  • 在取出ViewData中的变量值是,必须进行合适的类型转换(隐式或显式)和空值检查。

下面我们来看一个简单的例子,演示一下如何使用ViewData来从Controller向View传值。

public ActionResult Index()
{
    ViewData["Message"] = "This is a message from ViewData";

    return View();
}

然后,我们从视图中取出这个变量,

执行后,你将会在浏览器中看到如下的结果,

可能你注意到了,我在从ViewData中取出变量Message时并没有对其进行类型转换,那时因为我们存储的是一个简单类型的变量值。假如存储的是复杂对象,在取出是必须进行类型转换。

综上, ViewData更适合从Controller向View传递简单对象数据时使用。

ViewBag

  • ViewBag是一个动态类型变量(dynamic),这是C# 4.0引入的新特性,变量类型会在运行时进行解析。
  • ViewBag基本上是ViewData的包装,也是用来从Controller向View来传递值的。
  • ViewBag也只在当前的请求中有效。
  • 在重定向(redirection)后,ViewBag中存储的变量值将变为null
  • 因为ViewBag是动态类型,所以我们在取得其值时,不需要进行类型转换。

同样,我们通过一个简单的例子来演示一下如何利用ViewBag从Controller向View传递数据。

public ActionResult Index()
{
    ViewBag.Message = "This is a message from ViewBag";

    return View();
}

然后,在视图中取出数据并显示,

最后,执行程序,你将会在浏览器中看到如下结果,

综上, ViewBag更适合从Controller向View传递复杂对象数据时使用, 因为取出存储在其中的数据变量时无需进行类型转换。

TempData

  • TempData是一个继承自TempDataDictionary类的字典对象,它默认情况下是基于Session存储机制之上的。(备注: 你也可以让你的TempData基于其他存储机制之上, 我们可以提供我们自定义的ITempDataProvider来完成,具体可以参见: Session-less Controllers and TempData in ASP.NET MVC)
  • TempData是用来在多个Actions或从当前请求向子请求, 页面发生了重定向(Redirection)时传递共享数据。
  • 只有在目标视图(View)完全加载后才有效。
  • 在取出TempData存储的变量值时,必须进行合适的类型转换(隐式或显式)和空值检查。

下面,我们透过一个例子来演示一下如何在两个Action方法中传递数据。

首先,创建一个客户Model类,如下:

public class Customer
{
    public int Id { get; set; }
    public string Code { get; set; }
    public double Amount { get; set; }
}

然后,在Controller中加入如下代码:

public ActionResult DisplayCustomer1()
{
    Customer customer = new Customer
    {
        Id = 1001,
        Code = "100101",
        Amount = 100
    };

    TempData["OneCustomer"] = customer;

    return RedirectToAction("DisplayCustomer2");
}

public ActionResult DisplayCustomer2()
{
    Customer customer = TempData["OneCustomer"] as Customer;

    return View(customer);
}

最后,创建一个强类型视图(Strong Typed View)来显示客户信息。

执行程序,浏览器中会显示如下结果:

综上, TempData主要用在需要在多个Actions或者页面重定向时共享传递数据时使用。

Session

  • Session也是ASP.NET MVC程序传递值的一种方式,但与TempData不同,用户的整个会话中Session都不会过期。
  • Session在同一用户会话过程中的所有请求中有效,比如,刷新页面。
  • Session中的值也需要进行类型转换(隐式或显式)和非空检查。

我们仍然使用上面的这个例子,假如我们不用TempData而是使用Session, 也可以得到同样的结果。

public ActionResult DisplayCustomer1()
{
    Customer customer = new Customer
    {
        Id = 1001,
        Code = "100101",
        Amount = 100
    };

    Session["OneCustomer"] = customer;

    return RedirectToAction("DisplayCustomer2");
}

public ActionResult DisplayCustomer2()
{
    Customer customer = Session["OneCustomer"] as Customer;

    return View(customer);
}

Session的生命周期是最长的,但是它默认使用的是Cookies来存储数据,所以使用的时候必须注意数据保密的问题。

综上, Session主要用在需要在多个Controllers, Actions and Views共享数据(非敏感数据)时使用。

图说传递方式的生命周期

Maintains data betweenViewData/ViewBagTempData ( For single request)Session
Controller to ControllerNoYesYes
Controller to ViewYesYesYes
View to ControllerNoNoYes

后记

本文试图通过介绍ASP.NET MVC程序中传递小量数据的几种机制的优缺点和适用场景。 本文只是一篇学习笔记,笔者初学ASP.NET MVC, 理解难免有偏差, 如有错误, 还望指正。

参考资料:

ASP.NET MVC学习笔记系列

转载于:https://www.cnblogs.com/EasonWu/p/beginner-aspnet-mvc-various-ways-of-passing-data-in-mvcapps.html

本 PPT 介绍了制药厂房中供配电系统的总体概念设计要点,内容包括: 洁净厂房的特点及其对供配电系统的特殊要求; 供配电设计的一般原则依据的国家/行业标准; 从上级电网到工厂变电所、终端配电的总体结构模块化设计思路; 供配电范围:动力配电、照明、通讯、接地、防雷消防等; 动力配电中电压等级、接地系统形式(如 TN-S)、负荷等级可靠性、UPS 配置等; 照明的电源方式、光源选择、安装方式、应急备用照明要求; 通讯系统、监控系统在生产管理消防中的作用; 接地等电位连接、防雷等级防雷措施; 消防设施及其专用供电(消防泵、排烟风机、消防控制室、应急照明等); 常见高压柜、动力柜、照明箱等配电设备案例及部分设计图纸示意; 公司已完成的典型项目案例。 1. 工程背景总体框架 所属领域:制药厂房工程的公用工程系统,其中本 PPT 聚焦于供配电系统。 放在整个公用工程中的位置:给排水、纯化水/注射用水、气体热力、暖通空调、自动化控制等系统并列。 2. Part 01 供配电概述 2.1 洁净厂房的特点 空间密闭,结构复杂、走向曲折; 单相设备、仪器种类多,工艺设备昂贵、精密; 装修材料工艺材料种类多,对尘埃、静电等更敏感。 这些特点决定了:供配电系统要安全可靠、减少积尘、便于清洁和维护。 2.2 供配电总则 供配电设计应满足: 可靠、经济、适用; 保障人身财产安全; 便于安装维护; 采用技术先进的设备方案。 2.3 设计依据规范 引用了大量俄语标准(ГОСТ、СНиП、SanPiN 等)以及国家、行业和地方规范,作为设计的法规基础文件,包括: 电气设备、接线、接地、电气安全; 建筑物电气装置、照明标准; 卫生安全相关规范等。 3. Part 02 供配电总览 从电源系统整体结构进行总览: 上级:地方电网; 工厂变电所(10kV 配电装置、变压
<think>我们正在处理一个关于ASP.NET MVC中ViewBag的使用问题。用户想了解如何使用@ViewBag在视图中回填数据。根据引用内容,我们可以总结出以下几点: 1. ViewBag是动态属性,允许从控制器向视图传递数据。 2. 在控制器中,我们可以给ViewBag动态添加属性(如ViewBag.Title, ViewBag.ProjectName等)。 3. 在视图中,我们使用`@ViewBag.PropertyName`来获取值。 4. 注意:在JavaScript中使用时,如果值是字符串,需要加上引号,否则会被当作变量(如引用[2]中的问题)。 具体步骤: ### 控制器中设置ViewBag 在控制器的Action方法中,可以给ViewBag动态赋值。例如: ```csharp public ActionResult MyAction() { ViewBag.UserName = "John Doe"; ViewBag.Age = 30; ViewBag.IsAdmin = true; return View(); } ``` ### 视图中使用ViewBag 在Razor视图中,可以直接使用`@ViewBag.PropertyName`来输出值。 #### 示例1:在HTML中回填数据 ```html <div> <label>用户名:</label> <input type="text" value="@ViewBag.UserName" /> </div> ``` #### 示例2:在JavaScript中使用 如果需要在JavaScript中使用ViewBag传递的值,要注意字符串类型需要加引号。有两种方法: 方法一:将ViewBag的值放在引号内(使用`Json.Encode`可以确保字符串被正确转义) ```javascript <script> var userName = '@Html.Raw(Json.Encode(ViewBag.UserName))'; // 或者对于简单的字符串(注意:如果字符串包含单引号,可能会出错) // var userName = '@ViewBag.UserName'; </script> ``` 方法二:使用JSON序列化(对于复杂对象) ```javascript <script> var userInfo = @Html.Raw(Json.Encode(new { Name = ViewBag.UserName, Age = ViewBag.Age })); // 然后可以通过userInfo.Name, userInfo.Age访问 </script> ``` ### 注意事项 1. 在JavaScript中使用非字符串类型(如数字、布尔值)时,不需要加引号,例如: ```javascript var age = @ViewBag.Age; // 正确,因为age是数字 var isAdmin = @Json.Encode(ViewBag.IsAdmin); // 对于布尔值,使用Json.Encode确保正确转换 ``` 2. 如果ViewBag属性值为字符串,并且需要在JavaScript中作为字符串使用,必须用引号括起来,否则会被当作变量名(如引用[2]中的错误)。 3. 在Razor中,如果ViewBag属性值为空(null),则不会输出任何内容,不会报错。 ### 引用中的例子 - 引用[1]展示了在控制器中设置多个ViewBag属性,包括字符串、日期、数字、字典和列表。 - 引用[2]指出了在JavaScript中直接使用`@ViewBag.Flag`而不加引号会导致错误,因为生成的代码是`var itemId = auth;`,而`auth`被当作变量。正确做法是加上引号:`var itemId = '@ViewBag.Flag';`。 - 引用[3]展示了在视图中使用`@ViewBag.startTM`模型属性进行比较。 ### 总结步骤 1. 在控制器Action中设置ViewBag属性。 2. 在视图中,通过`@ViewBag.PropertyName`获取值。 3. 在HTML中,可以直接将值赋给表单元素的value属性。 4. 在JavaScript中,字符串值需要加引号,可以使用`Json.Encode`确保安全。 §§相关问题§§ 1. ViewBagViewData有什么区别? 2. 在JavaScript中使用ViewBag传递复杂对象有哪些方法? 3. 如何避免在JavaScript中使用ViewBag时出现未定义变量的错误? 4. ViewBag在跨控制器传递数据时是否有效?</think>在ASP.NET MVC中,使用`@ViewBag`回填数据是一种常见的数据传递技术,以下是具体使用方法和注意事项: ### 一、基础使用步骤 1. **控制器赋值** 在Controller中通过动态属性存储数据: ```csharp public ActionResult Details(string id) { ViewBag.UserName = "张三"; // 字符串 ViewBag.Age = 28; // 数值 ViewBag.IsAdmin = true; // 布尔值 return View(); } ``` 2. **视图回填** 在Razor视图中直接调用,支持HTML控件: ```html <!-- 文本输入框回填 --> <input type="text" value="@ViewBag.UserName" /> <!-- 下拉列表回填 --> <select> <option value="1" selected="@(ViewBag.Age == 28)">28岁</option> </select> <!-- 条件渲染 --> @if (ViewBag.IsAdmin) { <p>管理员权限</p> } ``` ### 二、JavaScript中使用 1. **字符串需加引号**(避免未定义错误)[^2]: ```javascript // 正确方式:添加单引号包裹 var userName = '@ViewBag.UserName'; // 错误方式:直接使用会解析为变量名 var userName = @ViewBag.UserName; // 可能报错"auth未定义" ``` 2. **复杂对象处理** 使用`Json.Encode`转换对象: ```javascript var userData = @Html.Raw(Json.Encode(ViewBag.User)); console.log(userData.Name); // 输出对象属性 ``` ### 三、特殊场景处理 1. **日期类型转换** 需显式转换日期格式[^3]: ```csharp // Controller中 ViewBag.StartDate = DateTime.Now; ``` ```html <!-- 视图中 --> @if (Model.CreatedDate < Convert.ToDateTime(ViewBag.StartDate)) { <span>过期数据</span> } ``` 2. **集合类型回填** 支持列表/字典类型[^1]: ```csharp // Controller ViewBag.Modules = new List<string> { "Admin", "ShoppingCart" }; ``` ```html <!-- 视图循环 --> <ul> @foreach (var module in ViewBag.Modules) { <li>@module</li> } </ul> ``` ### 四、注意事项 1. **动态类型风险** - 属性名拼写错误不会编译报错 - 建议使用强类型`ViewModel`替代复杂场景 2. **作用域限制** - ViewBag仅在同一请求内有效(Controller→View) - 跨请求需使用`TempData`或Session 3. **性能优化** - 避免在循环中频繁访问ViewBag - 大型数据建议用`ViewData`或模型绑定 > **关键点总结**:回填数据时需注意类型转换(尤其是JS中的字符串和日期),集合类型可直接遍历,复杂逻辑推荐结合强类型模型使用。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值