Controller与 View之间的值传递
在上一节的实验二中已经创建了静态View。然而在实际使用情况下,View常用于显示动态数据。在实验三中们将在View中动态显示数据。
View将从从Controller获得Model中的数据。
Model是MVC中 表示业务数据的层。
实验3 ——使用View数据
ViewData相当于数据字典,包含Controlle和View之间传递的所有数据。Controller会在该字典中添加新数据项,View从字典中读取数据。
1. 创建Model 类
在Model文件夹下新建Employee类,如下。
??1: ?public class Employee
??2: ?
??3: ?{
??4: ?public string FirstName { get; set; }
??5: ?
??6: ?public string LastName { get; set; }
??7: ?
??8: ?public int Salary { get; set; }
??9: ?
?10: ?}
2. 在Controller 中获取Model
在GetView 方法中创建Employee 对象:
??1: ?Employee emp = new Employee();
??2: ?emp.FirstName = "Sukesh";
??3: ?emp.LastName="Marla";
??4: ?emp.Salary = 20000;
注意:请确保使用Using语句包含此类,或者使用类的全称。
??1: ?using WebApplication1.Models;
3. 创建ViewData 并返回View
在ViewData中存储Employee 对象。
??1: ?ViewData["Employee"] = emp;
??2: ?return View("MyView");
4. 在View中显示Employee 数据
打开MyView.cshtml。
从ViewData中获取Employee 数据并按照如下代码显示:
??1: ?<div>
??2: ?????@{
??3: ?????????WebApplication1.Models.Employee emp=(WebApplication1.Models.Employee)
??4: ?????????????ViewData["Employee"];
??5: ?????}
??6: ?
??7: ?<b>Employee Details </b><br />
??8: ?????Employee Name : @emp.FirstName@emp.LastName <br />
??9: ?????Employee Salary: @emp.Salary.ToString("C")
?10: ?</div>
5. 测试输出
按F5运行
关于实验 3
1. 写Razor代码带花括号和没有花括号有什么区别?
在实验三中@emp.FirstName能够使用以下脚本来代替
??1: ?@{
??2: ?????Response.Write(emp.FirstName);
??3: ?}
@符号后没有花括号只是简单的显示变量或表达式的值
2. 为什么需要强制转换类型
ViewData可操作内部对象,每次添加新值,会封装成对象类型,因此每次都需要解压来提取值。
3. @emp.FirstName @emp.LastName有什么特殊含义?
意味着LastName显示在FirstName之后并自动添加空格。
4. 为什么 Employee中的 硬编码是由Controller创建的 ?
在本文中只是为了实现实验目的,因此采用硬编码,实际使用中,是从数据库或Web服务中获取的。
5. 数据库逻辑,数据访问层,业务层分别指的是什么?
- 数据访问层是ASP.NET MVC中是一直隐式存在的,MVC定义中不包含数据访问层的定义。
- 业务层是解释器的先驱,是Model的一部分。
完整的MVC结构
实验4——ViewBag的使用
ViewBag可以称为ViewData的一块关于语法的辅助的糖果,ViewBag使用C# 4.0的动态特征,使得ViewData也具有动态特性。
ViewData与ViewBag对比:
ViewData | ViewBag |
它是Key/Value字典集合 | 它是dynamic类型对像 |
从Asp.net MVC 1 就有了 | ASP.NET MVC3 才有 |
基于Asp.net 3.5 framework | 基于Asp.net 4.0与.net framework |
ViewData比ViewBag快 | ViewBag比ViewData慢 |
在ViewPage中查询数据时需要转换合适的类型 | 在ViewPage中查询数据时不需要类型转换 |
有一些类型转换代码 | 可读性更好 |
ViewBag内部调用ViewData。
1. 创建View Bag
在实验三的基础之上,使用以下脚本代替第三步中的代码。
??1: ?ViewBag.Employee = emp;
2. 在View中显示EmployeeData
使用以下代码来替代实验三中第四步中的代码:
??1: ?@{
??2: ?????WebApplication1.Models.Employee emp = (WebApplication1.Models.Employee)
??3: ?????????ViewBag.Employee;
??4: ?}
??5: ?Employee Details
??6: ?
??7: ?Employee Name: @emp.FirstName @emp.LastName
??8: ?
??9: ?Employee Salary: @emp.Salary.ToString("C")
3. 测试输出
运行结果:
关于实验4
可以传递ViewData,接收时获取ViewBag吗?
答案是肯定的,反之亦然。如之前所说的,ViewBag只是ViewData的一块糖/
ViewData与ViewBag的问题
ViewData和ViewBag 是Contoller与View之间值传递的内容。但是在实际使用的过程中,它们并不是最佳选择,接下来我们来看看使用它们的缺点:
- 性能问题;ViewData中的值都是对象类型,使用之前必须强制转换为合适的类型。会添加额外的性能负担。
- 没有类型安全就没有编译时错误,如果尝试将其转换为错误的类型,运行时会报错。良好的编程经验告诉我们,错误必须在编译时捕获。
- 数据发送和数据接收之间没有正确的连接;MVC中,Controller和View是松散的连接的。Controller是无法捕获View变化,View也无法捕获到Controller内部发生的变化。从Controller传递一个ViewData或ViewBag的值,当开发人员正在View中写入,就必须记录从Controller中即将获得什么值。如果Controller与View开发人员不是相同的开发人员,开发工作会变得非常困难。会导致许多运行时问题,降低了开发效率。
实验5——理解强类型View
ViewData和ViewBag引起的所有问题根源都在于数据类型。参数值的数据类型是被封装在ViewData中的,称为对象。
如果能够设置Controller和View之间参数传递的数据类型,那么上述问题就会得到解决,因此从得出强类型View。
接下来,我们看一个简单的例子,如果工资大于15000则显示黄色,低于显示绿色。
1. 创建View的强类型
在View的顶部添加以下代码:
@model WebApplication1.Models.Employee
2. 显示数据
在View内部输入@Model.就会查看到Model类的属性
添加以下代码来显示数据:
??1: ?Employee Details
??2: ?
??3: ?Employee Name : @Model.FirstName @Model.LastName
??4: ?
??5: ?@if(Model.Salary>15000)
??6: ?{
??7: ?<span style="
??8: ?????????Employee Salary: @Model.Salary.ToString("C")
??9: ?</span>
?10: ?}
?11: ?else
?12: ?{ ??????????
?13: ?<span style="
?14: ????????
?15: ?????????Employee Salary: @Model.Salary.ToString("C")
?16: ?</span>
?17: ?}
3. 从Controller Action方法中传递Model数据。
修改action代码
??1: ?Employee emp = new Employee();
??2: ?emp.FirstName = "Sukesh";
??3: ?emp.LastName="Marla";
??4: ?emp.Salary = 20000; ??????????
??5: ?return View("MyView",emp);
4. 测试输出
关于实验5
View中使用类时需要声明类的全称吗 (Namespace.ClassName)?
添加以下语句,就不需要添加全称。
??1: ?@using WebApplication1.Models
??2: ?@model Employee
是否必须设置强类型视图或不使用ViewData和ViewBag?
设置强类型视图是最佳解决方案。
是否能将View设置为多个Model使用的强类型?
不可以,实际项目中在一个View中想要显示多个Model时以点结束的。该问题的解决方法将在下一节讨论。
理解ASP.NET MVC 中的View Model
实验5中已经违反了MVC的基本准则。根据MVC,V是View纯UI,不包含任何逻辑层。而我们在实验5中以下三点违反了MVC的体系架构规则。
1. 附加姓和名显示全名——逻辑层
2. 使用货币显示工资——逻辑层
3. 使用不同的颜色表示工资值,使用简单的逻辑改变了HTML元素的外观。——逻辑层
ViewModel 解决方法
ViewModel是ASP.NET MVC应用中隐式声明的层。它是用于维护Model与View之间数据传递的,是View的数据容器。
Model 和 ViewModel 的区别
Model是业务相关数据,是根据业务和数据结构创建的。ViewModel是视图相关的数据。是根据View创建的。
具体的工作原理
- Controller 处理用户交互逻辑或简单的判断。处理用户需求
- Controller 获取一个或多个Model数据
- Controller 决策哪个View最符合用户的请求
- Controller 将根据Model数据和View需求创建并且初始化ViewModel对象。
- Controller 将ViewModel数据以ViewData或ViewBag或强类型View等对象传递到View中。
- Controller 返回View。
View 与 ViewModel 之间是如何关联的?
View将变成ViewModel的强类型View。
Model和 ViewModel 是如何关联的?
Model和ViewModel 是互相独立的,Controller将根据Model对象创建并初始化ViewModel对象。
接下来我们来看实验6:
实验6—— 实现ViewModel
1. 新建文件夹
在项目中创建新文件夹并命名为ViewModels。
2. 新建EmployeeViewModel
为了达到实验目的,首先列出我们的实验需求:
1. 名和姓应该合并显示。
2. 使用货币显示数量
3. 薪资以不同的颜色来显示
4. 当前登录用户也需要在View中显示。
在ViewModels类中,创建新类并命名为EmployeeViewModel,如下所示:
??1: ?public class EmployeeViewModel
??2: ?{
??3: ?????public string EmployeeName { get; set; }
??4: ?????public string Salary { get; set; }
??5: ?????public string SalaryColor { get; set; }
??6: ?????public string UserName{get;set;}
??7: ?}
注意,姓和名应该使用EmployeeName这一个属性。而Salary属性的数据类型是字符串,且有两个新的属性添加称为SalaryColor和UserName。
3. View中使用ViewModel
实验五中已经创建了View的强类型Employee。将它改为 EmployeeViewModel
??1: ?@using WebApplication1.ViewModels
??2: ?@model EmployeeViewModel
4. 在View中显示数据
使用以下脚本代替View部分的内容
??1: ?Hello @Model.UserName
??2: ?<hr />
??3: ?<div>
??4: ?<b>Employee Details</b><br />
??5: ?????Employee Name : @Model.EmployeeName <br />
??6: ?<span style="
??7: ?????????Employee Salary: @Model.Salary
??8: ?</span>
??9: ?</div>
5. 新建并传递ViewModel
在GetView方法中,获取Model数据并且将强制转换为ViewModel对象。
??1: ?public ActionResult GetView()
??2: ?{
??3: ?????Employee emp = new Employee();
??4: ?????emp.FirstName = "Sukesh";
??5: ?????emp.LastName="Marla";
??6: ?????emp.Salary = 20000;
??7: ?
??8: ?????EmployeeViewModel vmEmp = new EmployeeViewModel();
??9: ?????vmEmp.EmployeeName = emp.FirstName + " " + emp.LastName;
?10: ?????vmEmp.Salary = emp.Salary.ToString("C");
?11: ?????if(emp.Salary>15000)
?12: ?????{
?13: ?????????vmEmp.SalaryColor="yellow";
?14: ?????}
?15: ?????else
?16: ?????{
?17: ?????????vmEmp.SalaryColor = "green";
?18: ?????}
?19: ?
?20: ?vmEmp.UserName = "Admin"
?21: ?
?22: ?????return View("MyView", vmEmp);
?23: ?}
6. 测试输出
尽管运行结果类似,但是View中不包含任何业务逻辑。
关于实验6
是否意味着,每个Model都有一个ViewModel?
每个View有其对应的ViewModel。
Model与ViewModel之间存在关联是否是好的实现方法?
最好的是Model与ViewModel之间相互独立。
需要每次都创建ViewModel吗?假如View不包含任何呈现逻辑只显示Model数据的情况下还需要创建ViewModel吗?
建议是每次都创建ViewModel,每个View都应该有对应的ViewModel,尽管ViewModel包含与Model中相同的属性。
假定一个View不包含任何呈现逻辑,只显示Model数据,我们不创建ViewModel会发生什么?
无法满足未来的需求,如果未来需要添加新数据,我们需要从头开始创建全新的UI,所以如果我们保持规定,从开始创建ViewModel,就不会发生这种情况。在本实例中,初始阶段的ViewModel将与Model几乎完全相同。
实验7——带有集合的View
在本实验中,在View中显示Employee列表。
1. 修改EmployeeViewModel 类
删除UserName属性
??1: ?public class EmployeeViewModel
??2: ?{
??3: ?????public string EmployeeName { get; set; }
??4: ?????public string Salary { get; set; }
??5: ?????public string SalaryColor { get; set; }
??6: ?}
2. 创建结合ViewModel
在ViewModels 文件下,创建新类并命名为EmployeeListViewModel
??1: ?public class EmployeeListViewModel
??2: ?{
??3: ?????public List<employeeviewmodel> Employees { get; set; }
??4: ?public string UserName { get; set; }
??5: ?}
3. 修改强类型View的类型
??1: ?@using WebApplication1.ViewModels
??2: ?@model EmployeeListViewModel
4. 显示View中所有的Employee
??1: ?<body>
??2: ?????Hello @Model.UserName
??3: ?<hr />
??4: ?<div>
??5: ?<table>
??6: ?<tr>
??7: ?<th>Employee Name</th>
??8: ?<th>Salary</th>
??9: ?</tr>
?10: ????????????@foreach (EmployeeViewModel item in Model.Employees)
?11: ????????????{
?12: ?<tr>
?13: ?<td>@item.EmployeeName</td>
?14: ?<td style="@item.Salary</td>
?15: ?</tr>
?16: ????????????}
?17: ?</table>
?18: ?</div>
?19: ?</body>
5. 创建Employee的业务逻辑
新建类并命名为EmployeeBusinessLayer ,并带有GetEmployees()方法。
??1: ?public class EmployeeBusinessLayer
??2: ?{
??3: ?????public List<employee> GetEmployees()
??4: ?????{
??5: ?????????List<employee> employees = new List<employee>();
??6: ?????????Employee emp = new Employee();
??7: ?????????emp.FirstName = "johnson";
??8: ?????????emp.LastName = " fernandes";
??9: ?????????emp.Salary = 14000;
?10: ?????????employees.Add(emp);
?11: ?
?12: ?????????emp = new Employee();
?13: ?????????emp.FirstName = "michael";
?14: ?????????emp.LastName = "jackson";
?15: ?????????emp.Salary = 16000;
?16: ?????????employees.Add(emp);
?17: ?
?18: ?????????emp = new Employee();
?19: ?????????emp.FirstName = "robert";
?20: ?????????emp.LastName = " pattinson";
?21: ?????????emp.Salary = 20000;
?22: ?????????employees.Add(emp);
?23: ?
?24: ?????????return employees;
?25: ?????}
?26: ?}
?27: ?</employee>
6.从控制器中传参
??1: ?public ActionResult GetView()
??2: ?{
??3: ?????EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
??4: ?
??5: ?????EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
??6: ?????List<employee> employees = empBal.GetEmployees();
??7: ?
??8: ?????List<employeeviewmodel> empViewModels = new List<employeeviewmodel>();
??9: ?
?10: ?????foreach (Employee emp in employees)
?11: ?????{
?12: ?????????EmployeeViewModel empViewModel = new EmployeeViewModel();
?13: ?????????empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName;
?14: ?????????empViewModel.Salary = emp.Salary.ToString("C");
?15: ?????????if (emp.Salary > 15000)
?16: ?????????{
?17: ?????????????empViewModel.SalaryColor = "yellow";
?18: ?????????}
?19: ?????????else
?20: ?????????{
?21: ?????????????empViewModel.SalaryColor = "green";
?22: ?????????}
?23: ?????????empViewModels.Add(empViewModel);
?24: ?????}
?25: ?????employeeListViewModel.Employees = empViewModels;
?26: ?????employeeListViewModel.UserName = "Admin";
?27: ?????return View("MyView", employeeListViewModel);
?28: ?}
?29: ?</employeeviewmodel></employeeviewmodel></employee>
7. 执行
关于实验7
是否可以制定强类型View列表?
是的 为什么要新建EmployeeListViewModel单独的类而不直接使用强类型View的列表?1. 策划未来会出现的呈现逻辑2. UserName属性。UserName是与employees无关的属性,与完整View相关的属性。为什么删除EmployeeViewModel 的UserName属性,而不是将它作为EmployeeListViewModel的一部分?UserName 是相同的,不需要EmployeeViewModel中添加UserName。
结论
以上就是我们第二天所讲的内容,在第三天我们会学习新内容!
数据传递是MVC知识的重要组成部分,深入理解了这部分知识,能够帮助我们更好的进行MVC的开发。同时,请记得借助开发工具来助力开发过程,使用 ComponentOne Studio ASP.NET MVC 这款轻量级控件,工作效率大大提高的同时,工作量也会大大减少。
七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递
原文地址:http://www.cnblogs.com/ahxujian/p/8051855.html