经过第一天的学习以后,咱们相信您已经对MVC有一些基本了解。html
本节所讲的内容是在上节的基础之上,所以须要确保您是否掌握了上一节的内容。本章的目标是在今天学习结束时利用最佳实践解决方案建立一个小型的MVC项目,本节的主要目标是了解MVC之间的数据传递问题。咱们会逐步深刻讲解,并添加新功能,使项目愈来愈完善。数据库
系列文章编程
在上一节的实验二中已经建立了静态View。然而在实际使用状况下,View经常使用于显示动态数据。在实验三中们将在View中动态显示数据。安全
View将从从Controller得到Model中的数据。数据结构
Model是MVC中 表示业务数据的层。架构
ViewData至关于数据字典,包含Controlle和View之间传递的全部数据。Controller会在该字典中添加新数据项,View从字典中读取数据。mvc
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运行
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. 数据库逻辑,数据访问层,业务层分别指的是什么?
完整的MVC结构
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. 测试输出
运行结果:
能够传递ViewData,接收时获取ViewBag吗?
答案是确定的,反之亦然。如以前所说的,ViewBag只是ViewData的一块糖/
ViewData与ViewBag的问题
ViewData和ViewBag 是Contoller与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="background-color:yellow">
8: Employee Salary: @Model.Salary.ToString("C")
9: </span>
10: }
11: else
12: {
13: <span style="background-color:green">
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. 测试输出
View中使用类时须要声明类的全称吗 (Namespace.ClassName)?
添加如下语句,就不须要添加全称。
1: @using WebApplication1.Models
2: @model Employee
是否必须设置View的强类型View5或是不使用ViewData和ViewBag?
设置强类型的View是最佳解决方案。
是否能将View设置为多个Model使用的强类型?
不能够,实际项目中在一个View中想要显示多个Model时以点结束的。该问题的解决方法将在下一节讨论。
实验5中已经违反了MVC的基本准则。根据MVC,V是View纯UI,不包含任何逻辑层。而咱们在实验5中如下三点违反了MVC的体系架构规则。
1. 附加姓和名显示全名——逻辑层
2. 使用货币显示工资——逻辑层
3. 使用不一样的颜色表示工资值,使用简单的逻辑改变了HTML元素的外观。——逻辑层
ViewModel是ASP.NET MVC应用中隐式声明的层。它是用于维护Model与View之间数据传递的,是View的数据容器。
Model 和 ViewModel 的区别
Model是业务相关数据,是根据业务和数据结构建立的。ViewModel是视图相关的数据。是根据View建立的。
具体的工做原理
View 与 ViewModel 之间是如何关联的?
View将变成ViewModel的强类型View。
Model和 ViewModel 是如何关联的?
Model和ViewModel 是互相独立的,Controller将根据Model对象建立并初始化ViewModel对象。
接下来咱们来看实验6:
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="background-color:@Model.SalaryColor">
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中不包含任何业务逻辑。
是否意味着,每一个Model都有一个ViewModel?
每一个View有其对应的ViewModel。
Model与ViewModel之间存在关联是不是好的实现方法?
最好的是Model与ViewModel之间相互独立。
须要每次都建立ViewModel吗?假如View不包含任何呈现逻辑只显示Model数据的状况下还须要建立ViewModel吗?
建议是每次都建立ViewModel,每一个View都应该有对应的ViewModel,尽管ViewModel包含与Model中相同的属性。
假定一个View不包含任何呈现逻辑,只显示Model数据,咱们不建立ViewModel会发生什么?
没法知足将来的需求,若是将来须要添加新数据,咱们须要从头开始建立全新的UI,因此若是咱们保持规定,从开始建立ViewModel,就不会发生这种状况。在本实例中,初始阶段的ViewModel将与Model几乎彻底相同。
在本实验中,在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="background-color:@item.SalaryColor">@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></employee></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. 执行
是否能够制定强类型View列表?
是的 为何要新建EmployeeListViewModel单独的类而不直接使用强类型View的列表?1. 策划将来会出现的呈现逻辑2. UserName属性。UserName是与employees无关的属性,与完整View相关的属性。为何删除EmployeeViewModel 的UserName属性,而不是将它做为EmployeeListViewModel的一部分?UserName 是相同的,不须要EmployeeViewModel中添加UserName。
以上就是咱们次日所讲的内容,在第三天咱们会学习新内容
数据传递是MVC知识的重要组成部分,深刻理解了这部分知识,可以帮助咱们更好的进行MVC的开发。同时,请记得借助开发工具来助力开发过程,使用 ComponentOne Studio ASP.NET MVC 这款轻量级控件,工做效率大大提升的同时,工做量也会大大减小。
原文连接:http://www.codeproject.com/Articles/897559/Learn-MVC-in-days-Day