0. 前言

我相信在開始第 2 天的学习时,你已经顺利地完毕了第 1 天的课程。

我们回想一下第 1 天的主要关注点:

  • 为什么选择 ASP.NET MVC ?

  • ASP.NET Webforms 和 ASP.NET MVC 的对照

  • 理解 ASP.NET MVC 的 Controller 以及 Views

提醒:假设你还没有完毕第 1 天的学习,最好先确保完毕它。我们的目标是在最后一天用最佳实践和最新技术方法来创建一个小的 MVC 项目。

每一天的 Lab 训练中,我们都会比之前一天添加一些有用性的功能,这样看起来会比之前的程序更趋于完美。

1. Controller 向 View 数据传输

在 Lab 2 中,View 的创建都是偏于静态的。

然而在真实的场景中,View 展示的一般是一些动态数据。在下一个 Lab 中。我们将展示 View 中怎样动态展示数据。

View 将从 Controller 中获取以 Model 格式展示的数据。

Model

在 ASP.NET MVC 中,Model 展示的是业务数据。

Lab 3 - 使用 ViewData

ViewData 是一个字典,它存储了 Controller 传输给 View 的数据。Controller 将向 ViewData 字典加入条目,然后 View 从这个字典里读取。如今我们開始做一个 Demo 吧。

第一步:创建一个 Model 类

在 Model 目录下创建一个新的类,命名为 Employee。

public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Salary { get; set; }
}

第二步:从 Controller 中获取 Model

在 GetView 方法中创建一个 Employee 对象。

Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000;

注意:确保在类中使用 Using 语句将 Model 引入,否则就要在编敲代码时使用 Employee 类的全名。

using WebApplication1.Models;

第三步:创建 ViewData 并返回 View

在 ViewData 中存储 Employee 对象。

ViewData["Employee"] = emp;
return View("MyView");

第四步:在 View 中展示 Employee 数据

打开文件 MyView.cshtml。从 ViewData 中检索 Employee 数据并展示。

<div>
@{
WebApplication1.Models.Employee emp =
(WebApplication1.Models.Employee)ViewData["Employee"];
} <b>Employee Details </b><br/>
Employee Name : @emp.FirstName@emp.LastName <br/>
Employee Salary: @emp.Salary.ToString("C")
</div>

第五步:測试输出

按下 F5,測试应用。

Lab 3 的 Q&A

写 Razor 代码的过程中。使用花括号「『{』和『}』」和不使用花括号,有什么差别?

在 lab 3 中,@emp.FirstName 能够使用下面代码替换。

@{
Response.Write(emp.FirstName);
}

假设在 @ 后没有使用花括号,那么它不过为了展示变量或者表达式的值。

为什么须要强制转换?

ViewData 内部承载了一些对象。每一次添加一个新值,就会把它转换为 Object 类型。

所以每一次都须要强制转换来获取对象的值。

「@emp.FirstName @emp.LastName」的含义是什么?

这个意味着 LastName 展示在 FirstName 之后,并通过空格隔开。

假设只想使用一个 @ keyword,能做到刚才的效果吗?

答案是肯定的。通过语法 @(emp.FirstName+””+emp.LastName)。

为什么在 Controller 类中要硬编码 Employee 类?

这不过为了展示 demo。实际上,我们将会在数据库,WCF ,Web Service 或者其他地方获取数据。

什么是数据库逻辑,数据訪问层以及业务层?

  • 数据訪问层在 ASP.NET MVC 中是一个未显示的层。

    实际上,它一直存在,可是在 MVC 的定义中从来没包括过它。

  • 业务层像之前所解释的。它是 Model 的一部分。

完整的 MVC 结构。

Lab 4 - 使用 ViewBag

ViewBag 就像是 ViewData 的语法蜜糖。ViewBag 运用 C# 4.0 的动态特征。使得 ViewData 动态化。

ViewBag 内部运用 ViewData。

第一步:创建 View Bag

继续 Lab 3,然后用例如以下代码片段替换 Lab 3 中的第三步:

ViewBag.Employee = emp;

第二步:在 View 中展示 EmployeeData

用例如以下的代码片段替换 Lab3 中的第四步:

@{
WebApplication1.Models.Employee emp =
(WebApplication1.Models.Employee)ViewBag.Employee;
}
Employee Details
Employee Name: @emp.FirstName @emp.LastName
Employee Salary: @emp.Salary.ToString("C")

第三步:測试并输出

按下 F5 并測试应用程序。

Lab 4 的 Q&A

我们能否够传输 ViewData。然后以 ViewBag 的形式获取到?

答案是肯定的。反过来也是能够的。

就像我之前所提到过的,ViewBag 不过 ViewData 的语法蜜糖。

ViewData 和 ViewBag 的问题

ViewData 和 ViewBag 是 Controller 与 View 之间数据传输的非常好选择方式。可是在实际的项目应用中,它们之中的不论什么一个都不是最佳的实践方式。如今我们来讨论一下运用 ViewData 和 ViewBag 的缺点吧。

性能问题

ViewData 中的数据类型是 Object。

所以我们在使用之前须要进行正确的类型转换。这个操作为性能带来了额外的负担。

没有类型安全,也没有编译时的错误。

假设我们尝试将类型转换为错误的类型。或者我们在检索对象值的时候使用错误的 Key 值。我们将会在执行时出错。可是对于一个好的编程实践而言。错误应该在编译的时候就被捕获到。

在数据传输和数据接收之间没有正确的连接

作为一个开发人员,我个人觉得这是一个非常基本的问题。

在 MVC 中, Controller 和 View 彼此之间的连接是弱连接。松散的。

Controller 全然不会关心 View 之中发生了什么,同理。View 也全然不会关心 Controller 之中发生了什么。

从 Controller 中我们能够传输一个或者多个 ViewData 或者 ViewBag 值。

如今,当一个开发人员要写一个 View 时,他须要记住 Controller 将要传输什么。

假设一个 Controller 开发人员与 View 开发人员不是同一个人。那么情况将会变得更困难。由于是全然的不关心,所以这将导致开发过程的低效率,也有可能引起执行错误。

Lab 5 - 理解强类型 Views

刚才上述关于 ViewData 和 ViewBag 的三点问题能够归结于是由数据类型所引起的。

ViewData 中存储的数据类型是 「Object」。

假设以某种方式,我们能够为传输在 Controller 和 View 中的数据设置数据类型,那么问题将会迎刃而解,而这样的方式便是强类型 Views。

如今让我们做一个 Demo。这次我们将会提升 View 的需求到下一个级别层次。假设薪水大于 15000。那么那么就展示为黄颜色。否则为绿颜色。

第一步:创建强类型的 View

在 View 的顶部加上例如以下代码:

@model WebApplication1.Models.Employee

基于这条语句,使得我们的 View 成为一个类型为 Employee 的强类型视图。

第二步:展示数据

如今,在 View 中。只使用 @Model 和 Dot(.) 操作就能够智能获取 Model,即 Empolyee 的全部数据值。

写下例如以下代码来展示数据:

Employee Details
Employee Name : @Model.FirstName @Model.LastName
@if(Model.Salary>15000)
{
<span style="background-color:yellow">
Employee Salary: @Model.Salary.ToString("C")
</span>
}
else
{
<span style="background-color:green">
Employee Salary: @Model.Salary.ToString("C")
</span>
}

第三步:从 Controller 的 Action 方法传输 Model 数据

更改 Action 方法为例如以下代码片段:

Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000;
return View("MyView",emp);

第四步:測试并输出

Lab 5 的 Q&A

每次在 View 中的类型声明都须要使用类的全称吗,即 Namespace.ClassName ?

答案是否定的。我们能够运用 「using」声明。

@using WebApplication1.Models
@model Employee

我们必须总是使用强类型视图吗,还是我们能够偶尔使用一下 ViewData 或者 ViewBag ?

假设想实践最佳方式,最好使用强类型视图。

我们能够为强类型视图的 View 使用多个 Model 类型吗 ?

答案是否定的。在实际项目中,当我们想要在一个视图中展示多个 Model 时,我们常常会结束在这点上。这一需求的解决方式将在下一节中讨论。

2. 理解 ASP.NET MVC 中的 View Model

在 Lab 5 中我们已经违反了 MVC 的准则。依据 MVC, V 代表的是纯粹的 UI。

它应该不包括不论什么的逻辑。

我们已经通过例如以下的三点违反了 MVC 的结构规则:

  • 附加了 First Name 和 Last Name。而且用它们展示了全名。这属于逻辑操作。

  • 以货币形式展示了 Salary。

    这属于逻辑操作。

  • 展示了不同工资的不同颜色。这些基于不同值的简单的操作改变了 HTML 元素的外观。这属于逻辑操作。

除了以上三点,这里另一个更值得讨论的问题点。

这一种情形是。我们想要在 View 中展示不同类型的数据。比方:显示当前登录的username称和雇员数据。

我们能够使用例如以下两种方式实现这个问题:

  1. 向 Employee 类添加一个 UserName 属性。每一次我们想要在视图中展示一个新数据,我们就像 Employee 类中添加一个属性。这似乎是不合理的,这个属性或许和 Employee 没有关联。这也违反了 SOLID 的 SRP 准则。

  2. 运用 ViewBag 或者 ViewData。这种方法我们已经在刚才讨论了其弊端。

ViewModel 解决方式

ViewModel 是 ASP.NET MVC 应用中没有声明出的层。

它适合于 Model 和 View 之间而且为 View 作为一个数据容器。

Model 和 ViewModel 的差别是什么?

Model 特指业务数据。它基于业务和数据结构创建。ViewModel 特指 View 数据。它基于视图 View 创建。

ViewModel是怎样工作的?

工作原理非常easy。

  • Controller 处理用户的交互逻辑。或者简单来说,处理用户请求。

  • Controller 获得一个或多个 Model 数据。

  • Controller 将决定哪个 View 为请求作出正确回应。

  • Controller 将会依据视图的需求从接收的 Model 数据中创建并初始化 ViewModel 对象。

  • Controller 将会以 ViewData/ViewBag/强类型 View 的方式传输 ViewModel 数据给 View。

  • Controller 将会返回 View。

View 和 ViewModel 将怎样关联?

View 将会是一个以 ViewModel 为强类型的视图。

Model 和 ViewModel 将怎样关联?

Model 和 ViewModel 彼此之间应该是独立的。Controller 将会基于一个或多个 Model 对象来创建并初始化 ViewModel 对象。

让我们做一个小的 Lab 来更好地理解它吧。

3. Lab 6 - 实现 View Model

第一步:创建一个目录

在项目中命名一个目录,命名为 ViewModels。

第二步:创建 EmployeeViewModel

为了做这一步,我们先来理清一下 View 的全部需求。

  1. First Name 和 LastName 须要合并展示。所以在展示前它们应该是合并的。

  2. 使用货币形式来显示 Amount。

  3. 不同的 Salary 展示出不同的颜色。

  4. 当前的 User Name 也要展示在视图中。

在 ViewModels 目录下创建一个 EmployeeViewModel 类。例如以下所看到的:

public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string SalaryColor { get; set; }
public string UserName{get;set;}
}

须要注意的是,在这个 ViewModel 类中, FirstName 和 LastName 被一个属性所替代,即 EmployeeName。

而且 Salary 的数据类型是 String,除此之外,又添加了两个属性。即 SalaryColor 和 UserName。

第三步:在 View 中运用 ViewModel

在 Lab 5 中。我们将 View 强类型为 Employee。

如今将其强类型为 EmployeeViewModel。

@using WebApplication1.ViewModels
@model EmployeeViewModel

第四步:在 View 中展示数据。

使用例如以下的代码片段替换 View 中的内容:

Hello @Model.UserName
<hr />
<div>
<b> Employee Details</b><br />
Employee Name : @Model.EmployeeName <br />
<span style="background-color:@Model.SalaryColor">
Employee Salary: @Model.Salary
</span>
</div>

第五步:创建而且传输 ViewModel

在 GetView 动作方法中,获得 Model 数据,然后将其转换为 ViewModel 对象,例如以下所看到的:

public ActionResult GetView()
{
Employee emp = new Employee();
emp.FirstName = "Sukesh";
emp.LastName="Marla";
emp.Salary = 20000; EmployeeViewModel vmEmp = new EmployeeViewModel();
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"
return View("MyView", vmEmp);
}

第六步:測试并输出

按下 F5 并測试输出。

输出的结果和 Lab 5 的一样,可是这次 View 中不再包括不论什么逻辑。

Lab 6 的 Q&A

这是否意味着,每个 Model 都会有一个 ViewModel?

答案是否定的。

其实,是每个 View 都会有一个 ViewModel。

Model 和 ViewModel 之间存在一些关联是一个好的实践方式吗?

答案是否定的。作为一个最佳实践,Model 和 ViewModel 彼此之间应该是独立的。而不是关联的。

我们须要总是创建 ViewModel 吗? 假设 View 不包括不论什么展示逻辑而且 View 只展示 Model 的数据会怎样?

我们应该总是创建 ViewModel。每个 View 都应该拥有它们自己的 ViewModel。即使 ViewModel 的属性和 Model 的属性全然一样。

假设一种情形。View 不包括展示逻辑。而且使用 Model 数据。而不是 ViewModel。

问题是,假设未来有了向 UI 添加新数据的需求,或者是展示逻辑的需求。那么我们就须要又一次规划一个 UI 了。

所以最好是我们在一開始就创建 ViewModel 以防止需求添加。在这样的情形中,ViewModel 的初始阶段差点儿和 Model 是一致的。

4. Lab 7 - View 中运用 Collection

在这一节 Lab 中。我们将在 View 中展示 Employees 的列表。

第一步:改变 EmployeeViewModel 类

从 EmployeeViewModel 类中移除 UserName 属性。

public class EmployeeViewModel
{
public string EmployeeName { get; set; }
public string Salary { get; set; }
public string SalaryColor { get; set; }
}

第二步:创建集合

在 ViewModel 目录下创建一个类,命名为EmployeeListViewModel。

public class EmployeeListViewModel
{
public List<EmployeeViewModel> Employees { get; set; }
public string UserName { get; set; }
}

第三步:更改 View 的强类型

将 MyView.cshtml 的强类型更换为 EmployeeListViewModel。

@using WebApplication1.ViewModels
@model EmployeeListViewModel

第四步:在 View 中展示全部的雇员信息。

<body>
Hello @Model.UserName
<hr />
<div>
<table>
<tr>
<th>Employee Name</th>
<th>Salary</th>
</tr>
@foreach (EmployeeViewModel item in Model.Employees)
{
<tr>
<td>@item.EmployeeName</td>
<td style="background-color:@item.SalaryColor">@item.Salary</td>
</tr>
}
</table>
</div>
</body>

第五步:为 Employee 创建 Business Layer

在这个 Lab 中。我们将会提升我们的项目到一个新级别。我们将会向项目中添加 Business Layer。在项目中创建一个新的目录,命名为 BusinessLayer,然后创建一个新的类。命名为 EmployeeBusinessLayer。该类里面包括一个方法。命名为 GetEmployees。

public class EmployeeBusinessLayer
{
public List<Employee> GetEmployees()
{
List<Employee> employees = new List<Employee>();
Employee emp = new Employee();
emp.FirstName = "johnson";
emp.LastName = " fernandes";
emp.Salary = 14000;
employees.Add(emp); emp = new Employee();
emp.FirstName = "michael";
emp.LastName = "jackson";
emp.Salary = 16000;
employees.Add(emp); emp = new Employee();
emp.FirstName = "robert";
emp.LastName = " pattinson";
emp.Salary = 20000;
employees.Add(emp); return employees;
}
}

第六步:从 Controller 中传数据

public ActionResult GetView()
{
EmployeeListViewModel employeeListViewModel =
new EmployeeListViewModel(); EmployeeBusinessLayer empBal =
new EmployeeBusinessLayer();
List<employee> employees = empBal.GetEmployees(); List<EmployeeViewModel> empViewModels =
new List<EmployeeViewModel>(); foreach (Employee emp in employees)
{
EmployeeViewModel empViewModel =
new EmployeeViewModel(); 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";
return View("MyView", employeeListViewModel);
}

第七步:执行并測试输出

按下 F5。执行应用。

Lab 7 的 Q&A

我们能将视图的强制类型为 List 吗?

答案是肯定的。我们能够。

为什么我们要创建一个单独的类,即 EmployeeListViewModel,为什么我们不使用强类型为 List< EmployeeListViewModel > 的View 呢?

假设我们直接运用 List,而不是使用 EmployeeListViewModel 类。会引起两个问题。

  1. 未来或许会出现展示逻辑的需求。

  2. UserName 属性。由于 UserName 和 Employees 是没有关联的。它是与一个完整的 View 相关联。

为什么我们要从 EmployeeViewModel 中移除 UserName 属性。然后把它作为EmployeeListViewModel 中的一部分呢?

UserName 对全部雇员都是一样的。假设将 UserName 的属性保留在 EmployeeViewModel 中就会添加了冗余代码,也会为添加数据的传输额外内存空间。

5. 结语

我们已经完毕了第 2 天的 MVC 学习。在第 3 天中我们将使得项目进入下一个阶段。

让我一起在学习中尽情徜徉吧!

原文地址:Learn MVC Project in 7 days

7 天玩转 ASP.NET MVC — 第 1 天

本文系

utm_source=Common&utm_medium=Articles&utm_campaign=TechnicalArticles&from=matefiseco">OneAPM 工程师编译整理。OneAPM 是中国基础软件领域的新兴领军企业,能帮助企业用户和开发人员轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读很多其他技术文章,请訪问 OneAPM

utm_source=TechCommunity&utm_medium=TechArticle&utm_campaign=JulSoftArti">官方博客

7 天玩转 ASP.NET MVC — 第 2 天的更多相关文章

  1. 7 天玩转 ASP.NET MVC — 第 1 天

    0. 前言正如标题「7 天玩儿转 ASP.NET MVC」所言,这是个系列文章,所以将会向大家陆续推出 7 篇.设想一下,一天一篇,你将从一个愉快的周一开始阅读,然后在周末成为一个 ASP.NET M ...

  2. 7 天玩转 ASP.NET MVC — 第 7 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 今天是开心的一天.因为我们终于来到了系列学习的最后一节.我相信你喜欢之前的课程,并从中学到了许多. ...

  3. 全7 天玩转 ASP.NET MVC — 第 2 天

    0. 前言 我相信在开始第 2 天的学习时,你已经顺利地完成了第 1 天的课程. 我们回顾一下第 1 天的主要关注点: 为什么选择 ASP.NET MVC ? ASP.NET Webforms 和 A ...

  4. 玩转Asp.net MVC 的八个扩展点

    MVC模型以低耦合.可重用.可维护性高等众多优点已逐渐代替了WebForm模型.能够灵活使用MVC提供的扩展点可以达到事半功倍的效果,另一方面Asp.net MVC优秀的设计和高质量的代码也值得我们去 ...

  5. 7 天玩转 ASP.NET MVC — 第 3 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 我们假定你在开始学习时已经阅读了前两天的学习内容.在第 2 天我们完成了关于显示 Employee ...

  6. 7 天玩转 ASP.NET MVC — 第 6 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第六天的 MVC 系列学习中.希望你在阅读此篇文章的时候,已经学习了前五天的内容,这也是第 ...

  7. 7 天玩转 ASP.NET MVC — 第 5 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第五天的学习.希望第一天到第四天的学习,你都是开心的. 1. Lab 22 - 增加 Fo ...

  8. 7 天玩转 ASP.NET MVC — 第 4 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第四天的 MVC 系列学习中.如果你直接开始学习今天的课程,我强烈建议你先完成之前的学习内 ...

  9. 7 天玩转 ASP.NET MVC - 第 1 天

    0. 前言 正如标题「7 天玩儿转 ASP.NET MVC」所言,这是个系列文章,所以将会向大家陆续推出 7 篇.设想一下,一天一篇,你将从一个愉快的周一开始阅读,然后在周末成为一个 ASP.NET ...

随机推荐

  1. python标准库介绍——5 re模块详解

    == re 模块== "Some people, when confronted with a problem, think 'I know, I'll use regular expres ...

  2. mysql-5.7 收缩系统表空间详解

    innodb 系统表空间是一个逻辑上的概念,它的物理表现就是innodb系统表空间文件:在讲扩展系统表空间时我们说到 可以用增加文件,增加autoextend标记 这两种方式来解决:但是问题到了收缩表 ...

  3. 编辑控件的警告提示是:This text field does not specify an inputType or a hint

    没有设置editText的inputtype属性,比如<android:inputtype="textpassword"> http://binuu.blog.51ct ...

  4. Windows XP忘记密码的几种解决方法

    1. 问题 朋友一Windows XP系统的密码忘记了,让给解决一下.网上搜索了几种解决方案,列在下面,记一下. 2. 解决 2.1 使用“Administrator”帐户 前提:当前用户名不是“Ad ...

  5. Java中instanceof关键字的理解

    java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. 用法: res ...

  6. 解决Java连接MySQL存储过程返回参数值为乱码问题

    先说MySQL的字符集问题.Windows下可通过修改my.ini内的 [mysql] default-character-set=utf8    //客户端的默认字符集 在MySQL客户端工具中输入 ...

  7. nyoj576 集齐卡片赢大奖(一)

    集齐卡片赢大奖(一) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 小时候你一定曾经为收集一套三国人物的卡片而买过不少零食吧?这些小吃的袋子里一般都会有一张卡片,如 ...

  8. SimpleDateFormat转换时间,12,24时间格式

    Date d = new Date(); SimpleDateFormat ss = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//1 ...

  9. stock article

    stock 征服星辰大海 http://www.tianya.cn/95789158 论坛_悟道股市_天涯社区 http://www.tianya.cn/108318593/bbs?t=post 当下 ...

  10. SVN开启端口监听,并设置开机启动

    svnserve -d -r /home/svn/repo --listen-port=3690,svn仓库地址,及监听端口 vi svn_startup.sh,位置在/root下面编辑一个启动脚本, ...