今天是开心的一天。由于咱们终于来到了系列学习的最后一节。我相信你喜欢以前的课程,并从中学到了许多。css
这个实验确切地讲无关任何新的功能。它只是使项目更有结构性和系统化。html
第一步:建立解决方案文件夹jquery
右击解决方案,而后选择 Add -> New Solution Folder。ajax
将文件夹的名称改成「View And Controller」。如今重复这个步骤,建立多个类似的文件夹,分别命名为「Model」,「ViewModel」,「Data Access Layer」。数据库
第二步:建立数据访问层项目服务器
右击 Data Access Layer 文件夹,而后建立一个新的类库项目,命名为「DataAccessLayer」。架构
第三步:建立业务层和业务实体层项目mvc
在 Model 文件夹下建立两个类库项目,分别命名为「BusinessLayer」 和 「BusinessEntities」。app
第四步:建立 ViewModel 项目async
在 ViewModel 文件夹下建立一个新的类库项目,命名为「ViewModel」。
第五步:添加引用
首先右击每个项目,而后选择 Add -> Reference,选择以下引用。
对于 DataAccessLayer,选择 BusinessEntities。
对于 BusinessLayer,选择 DataAccessLayer 和 BusinessEntities。
对于 MVC Web Application,选择 BusinessLayer,BusinessEntities 和 ViewModel。
对于 BusinessEntities,选择 System.ComponentModel.DataAnnotations。
第六步:设置项目
从 MVC 项目中移除 DataAccessLayer 文件夹。
从 MVC 项目的 Model 文件夹下复制 Employee.cs,UserDetails.cs 和 UserStatus.cs 文件到新建立的 BusinessEntities 类库项目中。
从 MVC 项目的 Model 文件下复制 EmployeeBusinessLayer.cs 文件到新建立的 BusinessLayer 类库项目中。
从 MVC 项目中移除 Model 文件夹。
从 MVC 项目的 ViewModels 文件夹下复制全部类到新建立的 View Model 类库项目中。
从 MVC 项目中移除 ViewModels 文件夹。
将 MVC 项目,即 WebApplication1 移到「View And Controller」解决方案文件夹。
第七步:Build 项目
选择菜单栏的 Build -> Build Solution。你将会获得以下的错误信息。
第八步:解决错误
向 ViewModel 项目中添加 System.Web 引用。
在 DataAccessLayer 和 BusinessLayer 项目中运用 Nuget Manager,安装 Entity Framework。(若是你对 Nuget Manager 感到困惑,建议你看一下第 3 天的课程)
注:业务层须要引用 Entity Framework 是由于 BusinessLayer 直接与 DataAccessLayer 相关联。在一个正确的架构中,业务层不该该与数据访问层直接关联。咱们能够经过 Repository 来完成这个目的。
步骤以下。
右击 MVC 项目,选择「Manage Nuge Packages」选项。
在左侧区域的「Manage Nuget Packages」对话框下选择「Installed Packages」。
右击区域将会显示以前下载过的全部包。选择 EntityFramework,而后点击 Uninstall。
第九步: Build 解决方案
你将会看到以下错误。
第十步:解决错误
如今,咱们在 MVC 项目中既没有 SalesERPDAL 引用,也没有 Entity Framework 引用。添加这些引用不是一个最佳实践。做为最佳实践,控制器不该该与数据访问层直接相关联。
using System.Data.Entity; using WebApplication1.DataAccessLayer; namespace DataAccessLayer { public class DatabaseSettings { public static void SetDatabase() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());<saleserpdal> } } }
using DataAccessLayer; namespace BusinessLayer { public class BusinessSettings { public static void SetBusiness() { DatabaseSettings.SetDatabase(); } } }
using BusinessLayer; ... ... BundleConfig.RegisterBundles(BundleTable.Bundles); BusinessSettings.SetBusiness();
再次 Bulid 应用,这一次将会成功。
什么是解决方案文件夹?
Solution 文件夹只是逻辑文件夹。实际上,它不会在物理硬盘上被建立。它的目的只是为了让解决方案更加系统化。
如今,咱们将不会对已存在的控制器和视图作出改变。咱们将会为此实验建立一个全新的控制器和视图。作这些步骤的理由是:
使已存在的项目不受影响,所以你能够将以前的版本和单一页版本进行对比,更好地学习。
实现并理解 ASP.NET MVC 中的另外一个概念,即 Areas。
正如我所说的,咱们将会建立新的控制器,视图和视图模型。
只有如下组件会被重复利用。
已存在的 Business Layer。
已存在的 Data Access Layer。
已存在的 Business Entities。
Authentication 和异常过滤器。
FooterViewModel。
Footer.cshtml。
第一步:建立一个新的 Area
右击项目,而后选择 Add -> Area。一个对话框将会弹出,输入名称为 SPA,而后点击 Add。
它将在项目中建立一个新的文件夹架构,以下所示。
很明显,咱们并不须要 Area 下的 Model 文件夹,删除便可。
Areas 是实现 ASP.NET MVC 项目模块化的一种简单方式。
每个项目都由多个模块组成。例如:帐户模块,顾客关系模块,付款模块,等等。
在传统的应用开发风格中,咱们常用「Folders」来达到这个目的。咱们在一个单独项目中建立多个文件夹。每个文件夹表明一个模块。咱们会把各自模块的文件放在各自的文件夹中。
当使用 ASP.NET MVC 时,这种自定义文件夹将会遇到大问题。
让咱们来讨论下在 ASP.NET MVC 中,运用简单的文件夹来实现模块。
DataAccessLayer,BusinessLayer,BusinessEntities 和 ViewModels 不会产生任何问题。他们仅仅是简单的类,因此能够被放置到任意地方。
咱们不能将控制器随意放置。它必须放置在 Controller 文件夹下。可是这不会成为一个大问题,由于从 MVC 4 开始,控制器的位置限制就已经被舍弃了。如今咱们能够将其放置到任意想要放置的地方。
不幸的是,对于视图是不可行的。全部的视图都必须放置在「~/Views/ControllerName」或者「~/Views/Shared」文件夹下。
第二步:建立所需的 ViewModels
在 ViewModel 类库项目中建立一个新的文件夹,命名为 SPA,而后建立一个 ViewModel,命名为 MainViewModel。
using WebApplication1.ViewModels; namespace WebApplication1.ViewModels.SPA { public class MainViewModel { public string UserName { get; set; } public FooterViewModel FooterData { get; set; }//New Property } }
第三步:建立 Index 行为方法
在 MainController 中引用以下语句。
using WebApplication1.ViewModels.SPA; using OldViewModel=WebApplication1.ViewModels;
在 MainController 中建立一个新的行为方法,命名为 Index。
public ActionResult Index() { MainViewModel v = new MainViewModel(); v.UserName = User.Identity.Name; v.FooterData = new OldViewModel.FooterViewModel(); v.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value v.FooterData.Year = DateTime.Now.Year.ToString(); return View("Index", v); }
正如你所见,为 WebApplication1.ViewModels 命名空间增长了一个 OldViewModels 别名。如今,咱们可使用 OldViewModel.ClassName,而不是 WebApplication1.ViewModels.ClassName。
不指定别名会致使歧义错误。在命名空间 WebApplication1.ViewModels.SPA 和 WebApplication1.ViewModels 中,存在类似的类。
第四步:建立 Index 视图
建立一个与上述 Index 方法相联系的视图。
@using WebApplication1.ViewModels.SPA @model MainViewModel <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Employee Single Page Application</title>
第五步:执行并测试应用
按下 F5,而后执行应用。完成登陆操做,而后导航到 MainController 中的 Index 行为。
为何在控制器名称以前须要 SPA 关键字?
当咱们向 ASP.NET MVC 中添加 Area 时,Visual Studio 就会建立一个文件,命名为 [AreaName]AreaRegistration.cs,它包含一个类,这个类定义了 AreaName 属性和 RegisterArea 方法,该方法用于为 Area 注册路由信息。
在咱们的例子中,你能够发现名称为 SpaAreaRegistration.cs 文件,它被放置在「~/Areas/Spa」文件夹下。SpaAreaRegistration 类的 RegisterArea 方法包含以下代码。
context.MapRoute( "SPA_default", "SPA/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } );
这就解释了为何咱们须要在控制器名称前添加 SPA 关键字。
SpaAreaRegistration 类中的 RegisterArea 方法如何被触发?
打开 Global.asax 文件,Application_Start 的第一行以下。
AreaRegistration.RegisterAllAreas();
RegisterAllAreas 方法查找到应用中全部来自于 AreaRegistration 的类型,并调用它们的每个 RegisterArea 方法。
咱们能够不使用 SPA 来触发 MainController 动做吗?
让咱们简化一下问题:URL 为「localhost:8870/Main/Index」还会起做用吗?
答案是确定的。AreaRegistration 类建立一个新的路由,可是不会删除其它路由。路由在 RouteConfig 类中定义,仍然起做用。正如我以前所说的那样,控制器的位置没有限制。所以它仍能起做用,可是输出不会被正确地呈现,由于它将不能查找到视图。我建议你执行一下应用,试一试。
第一步:为展现已存在的 Employees 建立 ViewModel
在 ViewModel 类库的 SPA 文件夹下建立两个新的 ViewModel 类,命名为 EmployeeViewModel 和 EmployeeListViewModel。
namespace WebApplication1.ViewModels.SPA { public class EmployeeViewModel { public string EmployeeName { get; set; } public string Salary { get; set; } public string SalaryColor { get; set; } } }
namespace WebApplication1.ViewModels.SPA { public class EmployeeListViewModel { public List<employeeviewmodel> Employees { get; set; } } }
注:两个 ViewModel 实际上都是 Non-Spa 应用的 ViewModel 复制品。惟一的区别是不须要 BaseViewModel 了。
第二步:建立 EmployeeList Index
在 MainController 下建立一个新的行为方法,命名为 EmployeeList。
public ActionResult EmployeeList() { 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.Value.ToString("C"); if (emp.Salary > 15000) { empViewModel.SalaryColor = "yellow"; } else { empViewModel.SalaryColor = "green"; } empViewModels.Add(empViewModel); } employeeListViewModel.Employees = empViewModels; return View("EmployeeList", employeeListViewModel); }
注:HeaderFooterFilter 再也不须要。
第三步:建立 AddNewLink 分部视图
此次咱们不能运用以前的 AddNewLink 分部视图,由于以前的标签设定会致使所有的刷新。咱们的目标是建立一个「Single Page Application」,所以咱们不该该有所有的刷新。
在「~/Areas/Spa/Views/Main」文件夹下建立一个新的分部视图,命名为 AddNewLink.cshtml。
<a href="#" onclick="OpenAddNew();">Add New</a>
第四步:建立 AddNewLink 行为方法
在 MainController 下建立一个新的行为方法,命名为 GetAddNewLink。
public ActionResult GetAddNewLink() { if (Convert.ToBoolean(Session["IsAdmin"])) { return PartialView("AddNewLink"); } else { return new EmptyResult(); } }
第五步:建立 EmployeeList 视图
在「~/Areas/Spa/Views/Main」文件夹下建立一个新的分部视图,命名为 EmployeeList。
@using WebApplication1.ViewModels.SPA @model EmployeeListViewModel <div> @{ Html.RenderAction("GetAddNewLink"); } <table border="1" id="EmployeeTable"> <tr> <th>Employee Name</th>
第六步:设置 EmployeeList 为初始页
在「~/Areas/Spa/Views/Main」文件夹下打开 Index.cshtml 文件,在 DivOptions div 中包含 EmployeeList 行为结果。
第七步:执行并测试
按下 F5,并执行应用。
第一步:建立 AddNew 视图模型
在 ViewModel 类库项目的 SPA 文件夹下建立一个新的视图模型,命名为 CreateEmployeeViewModel。
namespace WebApplication1.ViewModels.SPA { public class CreateEmployeeViewModel { public string FirstName { get; set; } public string LastName { get; set; } public string Salary { get; set; } } }
第二步:建立 AddNew 行为方法
在 MainController 中引用以下声明。
using WebApplication1.Filters;
在 MainController 下建立 AddNew 行为方法以下。
[AdminFilter] public ActionResult AddNew() { CreateEmployeeViewModel v = new CreateEmployeeViewModel(); return PartialView("CreateEmployee", v); }
第三步:建立 CreateEmployee 分部视图
在「~/Areas/Spa/Views/Main」文件夹下建立一个新的分部视图,命名为 CreateEmployee。
@using WebApplication1.ViewModels.SPA @model CreateEmployeeViewModel <div> <table> <tr> <td> First Name: </td>
第四步:引入 JQuery UI
右击项目,而后选择「Manage Nuget Manager」。搜索「JQuery UI」。
安装 JQuery UI。它将会向项目中增长几个 JavaScript.js 和 Stylesheet.css 文件。
第五步:包含 JQuery UI
打开「~/Areas/Spa/Views/Main/Index.cshtml」文件,而后包含 JQuery.js,JQueryUI.js 和 All.css 文件。这些文件做为 JQuery UI 的一部分被 Nuget Manager 所添加。
<head> <meta name="viewport" content="width=device-width" /> <script src="~/Scripts/jquery-1.8.0.js"></script> <script src="~/Scripts/jquery-ui-1.11.4.js"></script> <title>Employee Single Page Application</title> <link href="~/Content/themes/base/all.css" rel="stylesheet" /> ...
第六步:实现 OpenAddNew 函数
在「~/Areas/Spa/Views/Main/Index.cshtml」下建立一个新的 JavaScript 函数,命名为 OpenAddNew。
<script> function OpenAddNew() { $.get("/SPA/Main/AddNew").then ( function (r) { $("<div id='DivCreateEmployee'></div>").html(r). dialog({ width: 'auto', height: 'auto', modal: true, title: "Create New Employee", close: function () { $('#DivCreateEmployee').remove(); } }); } ); } </script>
第七步:执行并测试
按下 F5,执行应用。
完成登陆操做,而后导航到 MainController 的 Index 动做。而后点击 Add New 超连接。
第八步:建立 ResetForm 函数
打开 CreateEmployee.cshtml 视图。在顶部建立 ResetForm 函数。
@model CreateEmployeeViewModel <script> function ResetForm() { document.getElementById('TxtFName').value = ""; document.getElementById('TxtLName').value = ""; document.getElementById('TxtSalary').value = ""; } </script>
第九步:建立 CancelSave 函数
打开 CreateEmployee.cshtml 视图。在顶部建立 CancelSave 函数。
document.getElementById('TxtSalary').value = ""; } function CancelSave() { $('#DivCreateEmployee').dialog('close'); }
在咱们继续第十步以前,咱们先要了解接下来应该作什么。
终端用户点击 Save Employee 按钮。
在客户端对控件的值进行合法性验证。
若是全部的值都是合法的,就被传输到服务器端。
在数据库中存储一个新的 Employee 记录。
CreateEmployee 对话框关闭。
Grid 更新 Employee 记录。
对于认证,咱们能够运用在 Non-Spa 项目中使用过的认证 JavaScript 代码。
咱们将会建立一个 MVC 行为方法,用于保存 Employee,而后经过 JQuery Ajax 来触发它。
以前经过 Form 标签和 Submit 按钮能轻松并自动的处理这件事。如今咱们不能使用该方法,由于它将会带来所有的刷新。取而代之的是,咱们利用 JQuery Ajax 的方式,这种方式容许咱们触发服务器端的 MVC 行为方法,而且不会所有刷新页面。
如今一个重要的问题是,若是调用是手动的,那么数据是如何经过 JavaScript 传输到 MVC 行为方法中的。
理解问题
当你听到数据这个词时,首先映入你脑海的是 JavaScript,.NET,仍是其它技术呢?
答案是变量。咱们能够利用变量来承载临时数据,而后将其转储在持久性的仓库中,例如数据库。
在咱们的例子中,咱们用到了两个技术,即 JavaScript 和 ASP.NET MVC。JavaScript 是一个技术,ASP.NET MVC 是另外一项技术。
它们不能交换彼此的数据,换句话说,它们不能直接与彼此交换变量。你也许会想知道,为何它们不能?
它们都有变量。它们都支持数据格式,例如 Float,Int,Char,那么它们为何不能将变量彼此传输呢?
答案是,它们拥有变量,可是它们不一样。.NET 中的整型数据类型没有要求和其它技术的整型数据类型相同。它们也许在大小上不一样,或者多是其它属性。
举一个现实中的有趣例子。每个人都拥有腿,手,眼睛等。一样,小狗也共同的东西。它们相同吗?显而易见的是,它们不一样。人类的眼睛不能被小狗的眼睛所替代,反之亦然。
在全部的技术中,变量的概念是类似的,可是它们却不相同。再一次重复这句话,「.NET 中的整型和 Java 中的整型是有所区别的」。
解决方案 — 一个统一的数据类型
行业已经意识到了这个问题,所以考虑使用在全部技术中相同的数据类型。
String 数据类型正是如此,而且能够承载任何数据。
咱们能够将整型数据转换为字符串类型,而后将其存储在字符串变量中。
咱们能够将浮点型数据转换为字符串类型,而后将其存储在字符串变量中。
…
任何数据类型均可以存储在字符串变量中。
终极的解决方案是「每一次从技术1传输数据到技术2,技术1须要将数据转换为字符串类型,而后传输给技术2,由于这样能够100%确保技术2可以理解该字符串」。
目前在行业中已经造成标准。
问题 — 如何处理复杂的数据?
若是这种字符串传输方式成为标准,那么复杂的数据如何传输呢?若是咱们想将 Employee 的信息从一个技术传输给另外一个呢?
在 .NET 中,「类和对象」被用于呈现复杂数据。看一下以下例子。
Employee e=new Employee(); e.EmpName= "Sukesh"; e.Address= "Mumbai";
在 JavaScript 中,「JavaScript 对象」用于呈现复杂数据。看一下以下例子。
var e={ EmpName= "Sukesh", Address= "Mumbai" };
将复杂的数据从 .NET 传输给其它技术,意味着类对象从 .NET 传输给其它技术,将复杂数据从 JavaScript 传输给其它技术,意味着 JavaScript 对象从 JavaScript 传输给其它技术。
直接传输是不可能的。按照以前的标准,咱们先要将 .NET 对象或者 JavaScript 对象转换为字符串类型,而后再发送。
解决方案:一个统一的数据格式标准
就像以前同样,行业也指出一个统一的数据格式标准。说它是统一的,意味着全部人要发送数据以前都须要呈现出他们的数据。所以 XML 应运而生。
全部技术都将数据转换为 XML 格式,而后将其发送给其它技术。就像字符串同样,XML 也被当作一种标准格式,所以每个技术都知道它。
C# 代码建立的 Employee 对象也能经过 XML 格式这样呈现。
<employee></employee> <Employee> <EmpName>Sukesh</EmpName> <Address>Mumbai</Address> </Employee>
所以解决方案是,「技术1把复杂的数据转换为 XML 格式的字符串数据,而后将其传送给技术2」。
问题 — XML 格式的问题
XML 格式有以下的问题。
XML 格式增长了须要发送的字符串大小。大小越大,意味着转化须要更多的时间,即意味着更差的性能。
第二个缘由,也是最主要的缘由:XML 很难建立和解析。
让咱们来探讨一下。
正如咱们以前所说,每个技术都须要基于数据建立 XML 字符串,而后传输这个 XML 字符串。如今利用 XML Serializers,用 C# 基于 .NET 对象来建立 XML 字符串是容易的。可是对于 JavaScript 而言呢?实际上, JavaScript 既没有序列化的概念,也没有 XML 操做库用于使用。所以当 JavaScript 传输数据给其它技术时,咱们须要在 JavaScript 对象中手动建立 XML 字符串。这是一个很艰难的任务。
当一个技术从另外一个技术那里接收到数据时,一般都是 XML 格式的字符串。如今经过 XML Deserializers,用 C# 将 XML 字符串解析并建立 .NET 对象是容易的。可是对于 JavaScript 而言呢?实际上, JavaScript 既没有反序列化的概念,也没有 XML 操做库用于使用。所以当 JavaScript 解析 XML 字符串时,这是一个很艰难的任务。
解决方案 — JSON
为了解决 XML 格式带来的问题,行业想出一个新的格式,称为 JSON。它是 「JavaScript Object Notation」的缩写。
利用 C# 来建立 Employee 对象,能够经过以下代码来呈现 JSON 格式。
{ EmpName: "Sukesh", Address: "Mumbai" }
JSON 格式展示的数据和 JavaScript 对象相像,所以这种格式被命名为 JSON(JavaScript Object Notation)。
正如你所看见的,这比以前更轻量级。
有一些完备的函数可用于 JavaScript,即能将 JavaScript 对象转换为 JSON 格式字符串,也能将 JSON 格式字符串解析为 JavaScript 对象。
以下代码展现了如何建立和解析 JSON 字符串。
var e={ EmpName= “Sukesh”, Address= “Mumbai” }; var EmployeeJsonString = JSON.stringify(e);//This EmployeeJsonString will be send to other technologies. var EmployeeJsonString=GetFromOtherTechnology(); var e=JSON.parse(EmployeeJsonString); alert(e.EmpName); alert(e.Address);
关闭对话框
咱们能够运用 JQuery API 来关闭 CreateEmployee 对话框。
更新 Grid
能够经过以下方式来更新 Grid。
a. 像 CreateEmployee 设计函数同样,建立一个 Grid 的分部视图。
b. 在 EmployeeListView 中建立一个含有 Id 的 Div,而后在里面展现 Grid 的分部视图。
c. 当 Save Employee 按钮被点击时,以分部视图结果的格式更新 Grid,而后用新的 PartialViewResult 来替换内部的 Grid HTML。
我相信迄今为止咱们完成的任何一个实验都能给你一个很好的思路来实现这样的目的,所以咱们将把其做为一个任务。须要你来亲自完成它。
在这个方法中,MVC 行为方法将会返回 EmployeeViewModel,而不是 EmloyeeListViewModel,这将会被 JavaScript 接收并运用 JavaScript 来建立一个新的行,而后手动插入到 Grid 中。EmployeeViewModel 将会以 JSON 字符串形式来从 MVC 行为方法中传输到 JavaScript。
第十步:建立 SaveEmployee Action
在 MainController 中建立一个新的行为方法,命名为 SaveEmployee。
[AdminFilter] public ActionResult SaveEmployee(Employee emp) { EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); empBal.SaveEmployee(emp); EmployeeViewModel empViewModel = new EmployeeViewModel(); empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName; empViewModel.Salary = emp.Salary.Value.ToString("C"); if (emp.Salary > 15000) { empViewModel.SalaryColor = "yellow"; } else { empViewModel.SalaryColor = "green"; } return Json(empViewModel); }
如今使用 JSON 的方式来说字符串从 MVC 行为方法传输到 JavaScript。
第十一步:包含 Validation.js
在上述实验中包含 Validation.js 文件。
@using WebApplication1.ViewModels.SPA @model CreateEmployeeViewModel <script src="~/Scripts/Validations.js"></script>
第十二步:建立 SaveEmployee 函数
打开 CreateEmployee.cshtml 视图,在顶部建立 SaveEmployee 函数。
... ... function SaveEmployee() { if (IsValid()) { var e = { FirstName: $('#TxtFName').val(), LastName: $('#TxtLName').val(), Salary: $('#TxtSalary').val() }; $.post("/SPA/Main/SaveEmployee",e).then( function (r) { var newTr = $('<tr></tr>'); var nameTD = $('<td></td>'); var salaryTD = $('<td></td>'); nameTD.text(r.EmployeeName); salaryTD.text(r.Salary); salaryTD.css("background-color", r.SalaryColor); newTr.append(nameTD); newTr.append(salaryTD); $('#EmployeeTable').append(newTr); $('#DivCreateEmployee').dialog('close'); } ); } } </script>
第十三步:执行并测试
按下 F5,执行应用。
JSON 方法是用于作什么的?
JSONResult 是 ActionResult 的一个子类。在第六天的学习中,咱们谈到了 MVC 请求周期。如今咱们再来回顾一下。
在 ActionResult 类中, ExecuteResult 被声明为抽象的。ActionResult 类的全部子类都以本身的方式来定义它。在第一天的学习中,咱们谈论过 ViewResult。在 ViewResult 类中,ExecuteResult 方法将会作以下事情。
它将会建立 ViewPageActivator 类的对象。
它将会选择正确的 ViewEngine,将 ViewPageActivator 对象做为参数传输给 ViewEngine 的构造器。ViewEngine 将会建立 View 类的对象。
它将会触发视图的 RenderView 方法,用于渲染最终 HTML 输出的响应。
当它来自于 JsonResult,ExecuteResult 方法将会:
设置响应内容的类型为「Application/Json」。
运用 JavaScript Serializer,它将会把传输的数据转换为 JSON 格式的字符串。
为响应流书写最终的 JSON 格式字符串。
第一步:建立 SpaBulkUploadController
建立一个新的 AsyncController,称做 SpaBulkUploadController。
namespace WebApplication1.Areas.SPA.Controllers { public class SpaBulkUploadController : AsyncController { } }
第二步:建立 Index 方法
在上述的控制器中建立一个新的行为方法,称为 Index。
[AdminFilter] public ActionResult Index() { return PartialView("Index"); }
第三步:建立 Index 分部视图
在「~/Areas/Spa/Views/SpaBulkUpload」中建立一个新的分部视图,称为 Index。
<div> Select File : <input type="file" name="fileUpload" id="MyFileUploader" value="" /> <input type="submit" name="name" value="Upload" onclick="Upload();" /> </div>
第四步:建立 OpenBulkUpload 方法
在「~/Areas/Spa/Views/Main」文件夹中打开 Index.cshtml,而后建立一个 JavaScript 方法,称为 Index.cshtml。
function OpenBulkUpload() { $.get("/SPA/SpaBulkUpload/Index").then ( function (r) { $("<div id='DivBulkUpload'></div>").html(r).dialog({ width: 'auto', height: 'auto', modal: true, title: "Create New Employee", close: function () { $('#DivBulkUpload').remove(); } }); } ); } </script> </head> <body> <div style="text-align:right">
第五步:执行并测试
按下 F5,并执行应用。完成登陆操做。导航到 Main 控制器下的 Index 行为,而后点击 BulkUpload 连接。
第六步:建立 FileUploadViewModel
在 ViewModel 类库项目的 SPA 文件夹下建立一个新的视图模型类,称为 FileUploadViewModel。
namespace WebApplication1.ViewModels.SPA { public class FileUploadViewModel { public HttpPostedFileBase fileUpload { get; set; } } }
第七步:建立 Upload 行为
在 SpaBulkUploadController 下建立一个新的行为方法,称为 Upload。
[AdminFilter] public async Task<actionresult> Upload(FileUploadViewModel model) { int t1 = Thread.CurrentThread.ManagedThreadId; List<employee> employees = await Task.Factory.StartNew<list<employee>> (() => GetEmployees(model)); int t2 = Thread.CurrentThread.ManagedThreadId; EmployeeBusinessLayer bal = new EmployeeBusinessLayer(); bal.UploadEmployees(employees); EmployeeListViewModel vm = new EmployeeListViewModel(); vm.Employees = new List<employeeviewmodel>(); foreach (Employee item in employees) { EmployeeViewModel evm = new EmployeeViewModel(); evm.EmployeeName = item.FirstName + " " + item.LastName; evm.Salary = item.Salary.Value.ToString("C"); if (item.Salary > 15000) { evm.SalaryColor = "yellow"; } else { evm.SalaryColor = "green"; } vm.Employees.Add(evm); } return Json(vm); } private List<employee> GetEmployees(FileUploadViewModel model) { List<employee> employees = new List<employee>(); StreamReader csvreader = new StreamReader(model.fileUpload.InputStream); csvreader.ReadLine();// Assuming first line is header while (!csvreader.EndOfStream) { var line = csvreader.ReadLine(); var values = line.Split(',');//Values are comma separated Employee e = new Employee(); e.FirstName = values[0]; e.LastName = values[1]; e.Salary = int.Parse(values[2]); employees.Add(e); } return employees; }
正如你所看见的,此次咱们返回的是 JsonResult,而不是重定向。
第八步:建立 Upload 函数
在「~/Areas/Spa/Views/SpaBulkUpload」文件夹下打开 Index 视图。而后建立一个 JavaScript 函数,称为 Upload。
<script> function Upload() { debugger; var fd = new FormData(); var file = $('#MyFileUploader')[0]; fd.append("fileUpload", file.files[0]); $.ajax({ url: "/Spa/SpaBulkUpload/Upload", type: 'POST', contentType: false, processData: false, data: fd }).then(function (e) { debugger; for (i = 0; i < e.Employees.length; i++) { var newTr = $('<tr></tr>'); var nameTD = $('<td></td>'); var salaryTD = $('<td></td>'); nameTD.text(e.Employees[i].EmployeeName); salaryTD.text(e.Employees[i].Salary); salaryTD.css("background-color", e.Employees[i].SalaryColor); newTr.append(nameTD); newTr.append(salaryTD); $('#EmployeeTable').append(newTr); } $('#DivBulkUpload').dialog('close'); }); } </script>
第九步:执行并测试
建立一个文本文件,以下所示。
按下 F5,并执行应用。
这里,咱们完成了 7 天玩转 ASP.NET MVC 的系列学习。咱们已经运用 ASP.NET MVC 的功能完成了一个简单的项目。咱们也在其中穿插讨论了许多详细的理论概念。
学无止境,虽然 ASP.NET MVC 的系列学习已经了结,可是后续的深刻学习,还须要靠脚踏实地,不断地实践和反思。
但愿每个人都享受其中,乐于学习,不断成长。
原文地址:Learn MVC Project in 7 days
OneAPM for .NET 可以深刻到全部 .NET 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。想阅读更多技术文章,请访问 OneAPM 官方博客。