您的位置:首页 > 编程语言 > ASP

七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递

2015-06-23 12:31 513 查看
通过第一天的学习之后,我们相信您已经对MVC有一些基本了解。

本节所讲的内容是在上节的基础之上,因此需要确保您是否掌握了上一节的内容。本章的目标是在今天学习结束时利用最佳实践解决方案创建一个小型的MVC项目,本节的主要目标是了解MVC之间的数据传递问题。我们会逐步深入讲解,并添加新功能,使项目越来越完善。





系列文章

七天学会ASP.NETMVC(一)——深入理解ASP.NETMVC

七天学会ASP.NETMVC(二)——ASP.NETMVC数据传递

七天学会ASP.NETMVC(三)——ASP.NetMVC数据处理

七天学会ASP.NETMVC(四)——用户授权认证问题

七天学会ASP.NETMVC(五)——Layout页面使用和用户角色管理

七天学会ASP.NETMVC(六)——线程问题、异常处理、自定义URL

七天学会ASP.NETMVC(七)——创建单页应用

Controller与View之间的值传递

在上一节的实验二中已经创建了静态View。然而在实际使用情况下,View常用于显示动态数据。在实验三中们将在View中动态显示数据。

View将从从Controller获得Model中的数据。

Model是MVC中表示业务数据的层。

实验3——使用View数据

ViewData相当于数据字典,包含Controlle和View之间传递的所有数据。Controller会在该字典中添加新数据项,View从字典中读取数据。

1.创建Model

在Model文件夹下新建Employee类,如下。

publicclassEmployee

[code]
{

publicstringFirstName{get;set;}


publicstringLastName{get;set;}


publicintSalary{get;set;}


}

[/code]

2.在Controller中获取Model

在GetView方法中创建Employee对象:


Employeeemp=newEmployee();

[code]emp.FirstName="Sukesh";
emp.LastName="Marla";

emp.Salary=20000;

[/code]

注意:请确保使用Using语句包含此类,或者使用类的全称。


usingWebApplication1.Models;



3.创建ViewData并返回View

在ViewData中存储Employee对象。


ViewData["Employee"]=emp;

[code]returnView("MyView");
[/code]

4.在View中显示Employee数据

打开MyView.cshtml。

从ViewData中获取Employee数据并按照如下代码显示:

<div>

[code]@{
WebApplication1.Models.Employeeemp=(WebApplication1.Models.Employee)

ViewData["Employee"];

}


<b>EmployeeDetails</b><br/>

EmployeeName:@emp.FirstName@emp.LastName<br/>

EmployeeSalary:@emp.Salary.ToString("C")

</div>

[/code]

5.测试输出

按F5运行





关于实验3

1.写Razor代码带花括号和没有花括号有什么区别?

在实验三中@emp.FirstName能够使用以下脚本来代替

@{

[code]Response.Write(emp.FirstName);
}

[/code]


@符号后没有花括号只是简单的显示变量或表达式的值

2.为什么需要强制转换类型

ViewData可操作内部对象,每次添加新值,会封装成对象类型,因此每次都需要解压来提取值。

3.@emp.FirstName@emp.LastName有什么特殊含义?

意味着LastName显示在FirstName之后并自动添加空格。

4.为什么Employee中的硬编码是由Controller创建的?

在本文中只是为了实现实验目的,因此采用硬编码,实际使用中,是从数据库或Web服务中获取的。

5.数据库逻辑,数据访问层,业务层分别指的是什么?

数据访问层是ASP.NETMVC中是一直隐式存在的,MVC定义中不包含数据访问层的定义。

业务层是解释器的先驱,是Model的一部分。

完整的MVC结构





实验4——ViewBag的使用

ViewBag可以称为ViewData的一块关于语法的辅助的糖果,ViewBag使用C#4.0的动态特征,使得ViewData也具有动态特性。

ViewData与ViewBag对比:

ViewData

ViewBag

它是Key/Value字典集合

它是dynamic类型对像

从Asp.netMVC1就有了

ASP.NETMVC3才有

基于Asp.net3.5framework

基于Asp.net4.0与.netframework

ViewData比ViewBag快

ViewBag比ViewData慢

在ViewPage中查询数据时需要转换合适的类型

在ViewPage中查询数据时不需要类型转换

有一些类型转换代码

可读性更好

ViewBag内部调用ViewData。

1.创建ViewBag

在实验三的基础之上,使用以下脚本代替第三步中的代码。


ViewBag.Employee=emp;



2.在View中显示EmployeeData

使用以下代码来替代实验三中第四步中的代码:

@{

[code]WebApplication1.Models.Employeeemp=(WebApplication1.Models.Employee)
ViewBag.Employee;

}

EmployeeDetails


EmployeeName:@emp.FirstName@emp.LastName


EmployeeSalary:@emp.Salary.ToString("C")

[/code]

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的顶部添加以下代码:

@modelWebApplication1.Models.Employee

2.显示数据

在View内部输入@Model.就会查看到Model类的属性





添加以下代码来显示数据:


EmployeeDetails

[code]
EmployeeName:@Model.FirstName@Model.LastName


@if(Model.Salary>15000)

{

<spanstyle="background-color:yellow">

EmployeeSalary:@Model.Salary.ToString("C")

</span>

}

else

{

<spanstyle="background-color:green">


EmployeeSalary:@Model.Salary.ToString("C")

</span>

}

[/code]

3.从ControllerAction方法中传递Model数据。

修改action代码


Employeeemp=newEmployee();

[code]emp.FirstName="Sukesh";
emp.LastName="Marla";

emp.Salary=20000;

returnView("MyView",emp);

[/code]


4.测试输出





关于实验5

View中使用类时需要声明类的全称吗(Namespace.ClassName)?

添加以下语句,就不需要添加全称。


@usingWebApplication1.Models

[code]@modelEmployee
[/code]


是否必须设置强类型视图或不使用ViewData和ViewBag?

设置强类型视图是最佳解决方案。

是否能将View设置为多个Model使用的强类型?

不可以,实际项目中在一个View中想要显示多个Model时以点结束的。该问题的解决方法将在下一节讨论。

理解ASP.NETMVC中的ViewModel

实验5中已经违反了MVC的基本准则。根据MVC,V是View纯UI,不包含任何逻辑层。而我们在实验5中以下三点违反了MVC的体系架构规则。

1.附加姓和名显示全名——逻辑层

2.使用货币显示工资——逻辑层

3.使用不同的颜色表示工资值,使用简单的逻辑改变了HTML元素的外观。——逻辑层

ViewModel解决方法

ViewModel是ASP.NETMVC应用中隐式声明的层。它是用于维护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,如下所示:

publicclassEmployeeViewModel

[code]{
publicstringEmployeeName{get;set;}

publicstringSalary{get;set;}

publicstringSalaryColor{get;set;}

publicstringUserName{get;set;}

}

[/code]

注意,姓和名应该使用EmployeeName这一个属性。而Salary属性的数据类型是字符串,且有两个新的属性添加称为SalaryColor和UserName。

3.View中使用ViewModel

实验五中已经创建了View的强类型Employee。将它改为EmployeeViewModel


@usingWebApplication1.ViewModels

[code]@modelEmployeeViewModel
[/code]


4.在View中显示数据

使用以下脚本代替View部分的内容


Hello@Model.UserName

[code]<hr/>
<div>

<b>EmployeeDetails</b><br/>

EmployeeName:@Model.EmployeeName<br/>

<spanstyle="background-color:@Model.SalaryColor">

EmployeeSalary:@Model.Salary

</span>

</div>

[/code]

5.新建并传递ViewModel

在GetView方法中,获取Model数据并且将强制转换为ViewModel对象。


publicActionResultGetView()

[code]{
Employeeemp=newEmployee();

emp.FirstName="Sukesh";

emp.LastName="Marla";

emp.Salary=20000;


EmployeeViewModelvmEmp=newEmployeeViewModel();

vmEmp.EmployeeName=emp.FirstName+""+emp.LastName;

vmEmp.Salary=emp.Salary.ToString("C");

if(emp.Salary>15000)

{

vmEmp.SalaryColor="yellow";

}

else

{

vmEmp.SalaryColor="green";

}


vmEmp.UserName="Admin"


returnView("MyView",vmEmp);

}

[/code]

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属性

publicclassEmployeeViewModel

[code]{
publicstringEmployeeName{get;set;}

publicstringSalary{get;set;}

publicstringSalaryColor{get;set;}

}

[/code]

2.创建结合ViewModel

在ViewModels文件下,创建新类并命名为EmployeeListViewModel

publicclassEmployeeListViewModel

[code]{
publicList<employeeviewmodel>Employees{get;set;}

publicstringUserName{get;set;}

}


[/code]

3.修改强类型View的类型


@usingWebApplication1.ViewModels

[code]@modelEmployeeListViewModel
[/code]

4.显示View中所有的Employee

<body>

[code]Hello@Model.UserName
<hr/>
<div>

<table>

<tr>

<th>EmployeeName</th>

<th>Salary</th>

</tr>

@foreach(EmployeeViewModeliteminModel.Employees)

{

<tr>

<td>@item.EmployeeName</td>

<tdstyle="background-color:@item.SalaryColor">@item.Salary</td>

</tr>

}

</table>

</div>

</body>

[/code]


5.创建Employee的业务逻辑

新建类并命名为EmployeeBusinessLayer,并带有GetEmployees()方法。

publicclassEmployeeBusinessLayer

[code]{
publicList<employee>GetEmployees()

{

List<employee>employees=newList<employee>();

Employeeemp=newEmployee();

emp.FirstName="johnson";

emp.LastName="fernandes";

emp.Salary=14000;

employees.Add(emp);


emp=newEmployee();

emp.FirstName="michael";

emp.LastName="jackson";

emp.Salary=16000;

employees.Add(emp);


emp=newEmployee();

emp.FirstName="robert";

emp.LastName="pattinson";

emp.Salary=20000;

employees.Add(emp);


returnemployees;

}

}

</employee>

[/code]

6.从控制器中传参


publicActionResultGetView()

[code]{
EmployeeListViewModelemployeeListViewModel=newEmployeeListViewModel();


EmployeeBusinessLayerempBal=newEmployeeBusinessLayer();

List<employee>employees=empBal.GetEmployees();


List<employeeviewmodel>empViewModels=newList<employeeviewmodel>();


foreach(Employeeempinemployees)

{

EmployeeViewModelempViewModel=newEmployeeViewModel();

empViewModel.EmployeeName=emp.FirstName+""+emp.LastName;

empViewModel.Salary=emp.Salary.ToString("C");

if(emp.Salary>15000)

{

empViewModel.SalaryColor="yellow";

}

else

{

empViewModel.SalaryColor="green";

}

empViewModels.Add(empViewModel);

}

employeeListViewModel.Employees=empViewModels;

employeeListViewModel.UserName="Admin";

returnView("MyView",employeeListViewModel);

}

</employeeviewmodel></employeeviewmodel></employee>

[/code]

7.执行




关于实验7

是否可以制定强类型View列表?

是的为什么要新建EmployeeListViewModel单独的类而不直接使用强类型View的列表?1.策划未来会出现的呈现逻辑2.UserName属性。UserName是与employees无关的属性,与完整View相关的属性。为什么删除EmployeeViewModel的UserName属性,而不是将它作为EmployeeListViewModel的一部分?UserName是相同的,不需要EmployeeViewModel中添加UserName。

结论

以上就是我们第二天所讲的内容,在第三天我们会学习新内容!

一起ComponentOneStudio!

原文链接:http://www.codeproject.com/Articles/897559/Learn-MVC-in-days-Day



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: