今天是開心的一天。由於咱們終於來到了系列學習的最後一節。我相信你喜歡以前的課程,並從中學到了許多。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 官方博客。