實驗32與其餘實驗不一樣,本實驗並非在以前實驗基礎之上爲程序添加新的功能,實驗32主要目的是整理項目結構,使項目條理清晰,可以結構化系統化,便於其餘人員理解。css
1. 建立解決方案文件夾html
右鍵單擊,選擇「新解決方案文件夾—>添加—>新解決方案」,命名爲「View And Controller」jquery
重複上述步驟 ,建立文件夾「Model」,「ViewModel」,」Data Access Layer」ajax
2. 建立數據訪問層工程數據庫
右擊「Data Access Layer」文件夾,新建類庫「DataAccessLayer」。服務器
3. 建立業務層和業務實體項架構
在Model文件夾下建立新類庫「BusinessLayer」和「BusinessEntities」mvc
4. 建立ViewModel 項app
在ViewModel 文件夾下新建類庫項「ViewModel「async
5. 添加引用
爲以上建立的項目添加引用,以下:
1. DataAccessLayer 添加 BusinessEntities項
2. BusinessLayer 添加DataAccessLayer和 BusinessEntities項
3. MVC WebApplication 選擇 BusinessLayer,BusinessEntities, ViewModel
4. BusinessEntities 添加 System.ComponentModel.DataAnnotations
6. 設置
1.將DataAccessLayer文件夾下的 SalesERPDAL.cs文件,複製粘貼到新建立的 DataAccessLayer 類庫中。
2. 刪除MVC項目(WebApplication1)的DataAccessLayer文件夾
3. 同上,將Model文件夾中的 Employee.cs, UserDetails.cs 及 UserStatus.cs文件複製到新建的 BusinessEntities文件夾中。
4. 將MVC項目中的Model文件夾的 EmployeeBusinessLayer.cs文件粘貼到新建的 BusinessLayer的文件夾中。
5. 刪除MVC中的Model文件夾
6. 將MVC項目的ViewModels文件夾下全部的文件複製到新建的ViewModel 類庫項中。
7. 刪除ViewModels文件夾
8. 將整個MVC項目剪切到」View And Controller」解決方案文件夾中。
7. Build
選擇Build->Build Solution from menu bar,會報錯。
8. 改錯
1. 給ViewModel項添加System.Web 引用
2. 在DataAccessLayer 和 BusinessLayer中使用Nuget 管理,並安裝EF(Entity Framework)(若是對於Nuget的使用有不理解的地方能夠查看第三篇博客文章)
注意:在Business Layer中引用EF 是很是必要的,由於Business Layer與DataAccessLayer 直接關聯的,而完善的體系架構它自身的業務層是不該該與DataAccessLayer直接關聯,所以咱們必須使用pattern庫,協助完成。
3. 刪除MVC 項目中的EF
9. 編譯會發現仍是會報錯
10. 修改錯誤
報錯是因爲在項目中既沒有引用 SalesERPDAL,也沒有引用EF,在項目中直接引用也並非優質的解決方案。
1. 在DataAccessLayer項中 新建帶有靜態方法」SetDatabase「的類」DatabaseSettings「
1: using System.Data.Entity; 2: using WebApplication1.DataAccessLayer; 3: namespace DataAccessLayer 4: { 5: public class DatabaseSettings 6: { 7: public static void SetDatabase() 8: { 9: Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());<saleserpdal> 10: } 11: } 12: }
2. 在 BusinessLayer項中新建帶有」SetBusiness「 靜態方法的」BusinessSettings「類。
1: using DataAccessLayer; 2: 3: namespace BusinessLayer 4: { 5: public class BusinessSettings 6: { 7: public static void SetBusiness() 8: { 9: DatabaseSettings.SetDatabase(); 10: } 11: } 12: }
3. 刪除global.asax 中的報錯的Using語句 和 Database.SetInitializer 語句。 調用 BusinessSettings.SetBusiness 函數:
1: using BusinessLayer; 2: . 3: . 4: . 5: BundleConfig.RegisterBundles(BundleTable.Bundles); 6: BusinessSettings.SetBusiness();
再次編譯程序,會發現成功。
什麼是解決方案文件夾?
解決方案文件夾是邏輯性的文件夾,並非在物理磁盤上實際建立,這裏使用解決方案文件夾就是爲了使項目更系統化更有結構。
實驗33中,再也不使用已建立好的控制器和視圖,會建立新的控制器及視圖,建立新控制器和視圖緣由以下:
1. 保證現有的選項完整,也會用於舊版本與新版本對比
2. 學習理解ASP.NET MVC 新概念:Areas
接下來,咱們須要從頭開始新建controllers, views,ViewModels。
下面的文件能夠被重用:
1. 建立新Area
右擊項目,選擇添加->Area,在彈出對話框中輸入SPA,點擊確認,生成新的文件夾,由於在該文件夾中不須要Model中Area的文件夾,刪掉。
接下來咱們先了解一下Areas的概念
Areas
Areas是實現Asp.net MVC 項目模塊化管理的一種簡單方法。
每一個項目由多個模塊組成,如支付模塊,客戶關係模塊等。在傳統的項目中,採用「文件夾」來實現模塊化管理的,你會發如今單個項目中會有多個同級文件夾,每一個文件夾表明一個模塊,並保存各模塊相關的文件。
然而,在Asp.net MVC 項目中使用自定義文件夾實現功能模塊化會致使不少問題。
下面是在Asp.Net MVC中使用文件夾來實現模塊化功能須要注意的幾點:
2. 建立必要的ViewModels
在ViewModel類庫下新建文件夾並命名爲SPA,建立ViewModel,命名爲」MainViewModel「,以下:
1: using WebApplication1.ViewModels; 2: namespace WebApplication1.ViewModels.SPA 3: { 4: public class MainViewModel 5: { 6: public string UserName { get; set; } 7: public FooterViewModel FooterData { get; set; }//New Property 8: } 9: }
3. 建立Index action 方法
在 MainController 中輸入:
1: using WebApplication1.ViewModels.SPA; 2: using OldViewModel=WebApplication1.ViewModels;
在MainController 中新建Action 方法,以下:
1: public ActionResult Index() 2: { 3: MainViewModel v = new MainViewModel(); 4: v.UserName = User.Identity.Name; 5: v.FooterData = new OldViewModel.FooterViewModel(); 6: v.FooterData.CompanyName = "StepByStepSchools";//Can be set to dynamic value 7: v.FooterData.Year = DateTime.Now.Year.ToString(); 8: return View("Index", v); 9: }
using OldViewModel=WebApplication1.ViewModels 這行代碼中,給WebApplication1.ViewModels 添加了別名OldViewModel,使用時可直接寫成OldViewModel.ClassName這種形式。
若是不定義別名的話,會產生歧義,由於WebApplication1.ViewModels.SPA 和 WebApplication1.ViewModels下有名稱相同的類。
4.建立Index View
建立與上述Index方法匹配的View
1: @using WebApplication1.ViewModels.SPA 2: @model MainViewModel 3: <!DOCTYPE html> 4: 5: <html> 6: <head> 7: <meta name="viewport" content="width=device-width" /> 8: <title>Employee Single Page Application</title>
5. 運行測試
爲何在控制器名前須要使用SPA關鍵字?
在ASP.NET MVC應用中添加area時,Visual Studio會自動建立並命名爲「[AreaName]AreaRegistration.cs」的文件,其中包含了AreaRegistration的派生類。該類定義了 AreaName屬性和用來定義register路勁信息的 RegisterArea 方法。
在本次實驗中你會發現nameSpaArealRegistration.cs文件被存放在「~/Areas/Spa」文件夾下,SpaArealRegistration類的RegisterArea方法的代碼以下:
1: context.MapRoute( 2: "SPA_default", 3: "SPA/{controller}/{action}/{id}", 4: new { action = "Index", id = UrlParameter.Optional } 5: );
這就是爲何一提到Controllers,咱們會在Controllers前面加SPA關鍵字。
SPAAreaRegistration的RegisterArea方法是怎樣被調用的?
打開global.asax文件,首行代碼以下:
1: AreaRegistration.RegisterAllAreas();
RegisterAllAreas方法會找到應用程序域中全部AreaRegistration的派生類,並主動調用RegisterArea方法
是否能夠不使用SPA關鍵字來調用MainController?
AreaRegistration類在不刪除其餘路徑的同時會建立新路徑。RouteConfig類中定義了新路徑仍然會起做用。如以前所說的,Controller存放的路徑是不受限制的,所以它能夠工做但可能不會正常的顯示,由於沒法找到合適的View。
1.建立ViewModel,實現「顯示Empoyee」功能
在SPA中新建兩個ViewModel 類,命名爲」EmployeeViewModel「及」EmployeeListViewModel「:
1: namespace WebApplication1.ViewModels.SPA 2: { 3: public class EmployeeViewModel 4: { 5: public string EmployeeName { get; set; } 6: public string Salary { get; set; } 7: public string SalaryColor { get; set; } 8: } 9: } 1: namespace WebApplication1.ViewModels.SPA 2: { 3: public class EmployeeListViewModel 4: { 5: public List<employeeviewmodel> Employees { get; set; } 6: } 7: }
注意:這兩個ViewModel 都是由非SPA 應用建立的,惟一的區別就在於此次不須要使用BaseViewModel。
2. 建立EmployeeList Index
在MainController 中建立新的Action 方法」EmployeeList「action 方法
1: public ActionResult EmployeeList() 2: { 3: EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel(); 4: EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); 5: List<employee> employees = empBal.GetEmployees(); 6: 7: List<employeeviewmodel> empViewModels = new List<employeeviewmodel>(); 8: 9: foreach (Employee emp in employees) 10: { 11: EmployeeViewModel empViewModel = new EmployeeViewModel(); 12: empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName; 13: empViewModel.Salary = emp.Salary.Value.ToString("C"); 14: if (emp.Salary > 15000) 15: { 16: empViewModel.SalaryColor = "yellow"; 17: } 18: else 19: { 20: empViewModel.SalaryColor = "green"; 21: } 22: empViewModels.Add(empViewModel); 23: } 24: employeeListViewModel.Employees = empViewModels; 25: return View("EmployeeList", employeeListViewModel); 26: }
注意: 不須要使用 HeaderFooterFilter
3. 建立AddNewLink 分部View
以前添加AddNewLink 分部View已經沒法使用,由於Anchor標籤會形成全局刷新,咱們的目標是建立」單頁應用「,所以不須要全局刷新。
在」~/Areas/Spa/Views/Main「 文件夾新建分部View」AddNewLink.cshtml「。
<a href="#" onclick="OpenAddNew();">Add New</a> <a href="#" onclick="OpenBulkUpload();">Bulk Upload</a>
在MainController中建立 」GetAddNewLink「 action 方法。
1: public ActionResult GetAddNewLink() 2: { 3: if (Convert.ToBoolean(Session["IsAdmin"])) 4: { 5: return PartialView("AddNewLink"); 6: } 7: else 8: { 9: return new EmptyResult(); 10: } 11: }
在「~/Areas/Spa/Views/Main」中建立新分部View 命名爲「EmployeeList」。
1: @using WebApplication1.ViewModels.SPA 2: @model EmployeeListViewModel 3: <div> 4: @{ 5: Html.RenderAction("GetAddNewLink"); 6: } 7: 8: <table border="1" id="EmployeeTable"> 9: <tr> 10: <th>Employee Name</th>
打開「~/Areas/Spa/Views/Main/Index.cshtml」文件,在Div標籤內包含EmployeeList action結果。
<div> @Html.Action("EmployeeList", "Main"); </div>
7. 運行
1. 建立AddNew ViewModels
在SPA中新建 ViewModel類庫項的ViewModel,命名爲「CreateEmployeeViewModel」。
1: namespace WebApplication1.ViewModels.SPA 2: { 3: public class CreateEmployeeViewModel 4: { 5: public string FirstName { get; set; } 6: public string LastName { get; set; } 7: public string Salary { get; set; } 8: } 9: }
2. 建立AddNew action 方法
在MainController中輸入using 語句:
1: using WebApplication1.Filters;
在MainController 中建立AddNew action 方法:
1: [AdminFilter] 2: public ActionResult AddNew() 3: { 4: CreateEmployeeViewModel v = new CreateEmployeeViewModel(); 5: return PartialView("CreateEmployee", v); 6: }
在「~/Areas/Spa/Views/Main」中建立新的分部View「CreateEmployee」
1: @using WebApplication1.ViewModels.SPA 2: @model CreateEmployeeViewModel 3: <div> 4: <table> 5: <tr> 6: <td> 7: First Name: 8: </td>
右擊項目選擇「Manage Nuget Manager」。找到「jQuery UI」並安裝。
項目中會自動添加.js和.css文件
打開「~/Areas/Spa/Views/Main/Index.cshtml」,添加jQuery.js,jQueryUI.js 及全部的.css文件的引用。這些文件會經過Nuget Manager添加到jQuery UI 包中。
1: <head> 2: <meta name="viewport" content="width=device-width" /> 3: <script src="~/Scripts/jquery-1.8.0.js"></script> 4: <script src="~/Scripts/jquery-ui-1.11.4.js"></script> 5: <title>Employee Single Page Application</title> 6: <link href="~/Content/themes/base/all.css" rel="stylesheet" /> 7: ...
在「~/Areas/Spa/Views/Main/Index.cshtml」中新建JavaScript方法「OpenAddNew」。
1: <script> 2: function OpenAddNew() { 3: $.get("/SPA/Main/AddNew").then 4: ( 5: function (r) { 6: $("<div id='DivCreateEmployee'></div>").html(r). 7: dialog({ 8: width: 'auto', height: 'auto', modal: true, title: "Create New Employee", 9: close: function () { 10: $('#DivCreateEmployee').remove(); 11: } 12: }); 13: } 14: ); 15: } 16: </script>
7. 運行
完成登陸步驟後導航到Index中,點擊Add New 連接。
在CreateEmployee.cshtml頂部,輸入如下代碼,建立ResetForm函數:
1: @model CreateEmployeeViewModel 2: <script> 3: function ResetForm() { 4: document.getElementById('TxtFName').value = ""; 5: document.getElementById('TxtLName').value = ""; 6: document.getElementById('TxtSalary').value = ""; 7: } 8: </script>
在CreateEmployee.cshtml頂部,輸入如下代碼,建立CancelSave 函數:
1: document.getElementById('TxtSalary').value = ""; 2: } 3: function CancelSave() { 4: $('#DivCreateEmployee').dialog('close'); 5: }
在開始下一步驟以前,咱們先來了解咱們將實現的功能:
爲了實現三大功能,先肯定一些實現計劃:
1.驗證
驗證功能可使用以前項目的驗證代碼。
2.保存功能
咱們會建立新的MVC action 方法實現保存Employee,並使用jQuery Ajax調用
3. 服務器端與客戶端進行數據通訊
在以前的實驗中,使用Form標籤和提交按鈕來輔助完成的,如今因爲使用這兩種功能會致使全局刷新,所以咱們將使用jQuery Ajax方法來替代Form標籤和提交按鈕。
1. 理解問題
你們會疑惑JavaScript和Asp.NET 是兩種技術,如何進行數據交互?
解決方案: 通用數據類型
因爲這兩種技術都支持如int,float等等數據類型,儘管他們的存儲方式,大小不一樣,可是在行業總有一種數據類型可以處理任何數據,稱之爲最兼容數據類型即字符串類型。
通用的解決方案就是將全部數據轉換爲字符串類型,由於不管哪一種技術都支持且能理解字符串類型的數據。
問題:複雜數據該怎麼傳遞?
.net中的複雜數據一般指的是類和對象,這一類數據,.net與其餘技術傳遞複雜數據就意味着傳類對象的數據,從JavaScript給其餘技術傳的複雜類型數據就是JavaScript對象。所以是不可能直接傳遞的,所以咱們須要將對象類型的數據轉換爲標準的字符串類型,而後再發送。
解決方案—標準的通用數據格式
可使用XML定義一種通用的數據格式,由於每種技術都須要將數據轉換爲XML格式的字符串,來與其餘技術通訊,跟字符串類型同樣,XML是每種技術都會考慮的一種標準格式。
以下,用C#建立的Employee對象,能夠用XML 表示爲:
1: <employee></employee><Employee>
2: <EmpName>Sukesh</EmpName>
3: <Address>Mumbai</Address>
4: </Employee>
所以可選的解決方案就是,將技術1中的複雜數據轉換爲XML格式的字符串,然再發送給技術2.
然而使用XML格式可能會致使數據佔用的字節數太多,不易發送。數據SiZE越大意味着性能越低效。還有就是XML的建立和解析比較困難。
爲了處理XML建立和解析的問題,使用JSON格式,全稱「JavaScript Object Notation」。
C#建立的Employee對象用JSON表示:
1: {
2: EmpName: "Sukesh",
3: Address: "Mumbai"
4: }
JSON數據是相對輕量級的數據類型,且JAVASCRIPT提供轉換和解析JSON格式的功能函數。
1: var e={
2: EmpName= 「Sukesh」,
3: Address= 「Mumbai」
4: };
5: var EmployeeJsonString = JSON.stringify(e);//This EmployeeJsonString will be send to other technologies.
1: var EmployeeJsonString=GetFromOtherTechnology();
2: var e=JSON.parse(EmployeeJsonString);
3: alert(e.EmpName);
4: alert(e.Address);
數據傳輸的問題解決了,讓咱們繼續進行實驗。
在MainController中建立action,以下:
1: [AdminFilter] 2: public ActionResult SaveEmployee(Employee emp) 3: { 4: EmployeeBusinessLayer empBal = new EmployeeBusinessLayer(); 5: empBal.SaveEmployee(emp); 6: 7: EmployeeViewModel empViewModel = new EmployeeViewModel(); 8: empViewModel.EmployeeName = emp.FirstName + " " + emp.LastName; 9: empViewModel.Salary = emp.Salary.Value.ToString("C"); 10: if (emp.Salary > 15000) 11: { 12: empViewModel.SalaryColor = "yellow"; 13: } 14: else 15: { 16: empViewModel.SalaryColor = "green"; 17: } 18: return Json(empViewModel); 19: }
上述代碼中,使用Json方法在MVC action方法到JavaScript之間傳Json字符串。
1: @using WebApplication1.ViewModels.SPA
2: @model CreateEmployeeViewModel
3: <script src="~/Scripts/Validations.js"></script>
在CreateEmployee.cshtml View中,建立 SaveEmployee方法:
1: ... 2: ... 3: 4: function SaveEmployee() { 5: if (IsValid()) { 6: var e = 7: { 8: FirstName: $('#TxtFName').val(), 9: LastName: $('#TxtLName').val(), 10: Salary: $('#TxtSalary').val() 11: }; 12: $.post("/SPA/Main/SaveEmployee",e).then( 13: function (r) { 14: var newTr = $('<tr></tr>'); 15: var nameTD = $('<td></td>'); 16: var salaryTD = $('<td></td>'); 17: 18: nameTD.text(r.EmployeeName); 19: salaryTD.text(r.Salary); 20: 21: salaryTD.css("background-color", r.SalaryColor); 22: 23: newTr.append(nameTD); 24: newTr.append(salaryTD); 25: 26: $('#EmployeeTable').append(newTr); 27: $('#DivCreateEmployee').dialog('close'); 28: } 29: ); 30: } 31: } 32: </script>
13. 運行
JSON 方法的做用是什麼?
返回JSONResult,JSONResult 是ActionResult 的子類。在第六篇博客中講過MVC的請求週期。
ExecuteResult是ActionResult中聲明的抽象方法,ActionResult全部的子類都定義了該方法。在第一篇博客中咱們已經講過ViewResult 的ExecuteResult方法實現的功能,有什麼不理解的能夠翻看第一篇博客。
1. 建立SpaBulkUploadController
建立新的AsyncController「 SpaBulkUploadController」
1: namespace WebApplication1.Areas.SPA.Controllers 2: { 3: public class SpaBulkUploadController : AsyncController 4: { 5: } 6: }
2. 建立Index Action
在步驟1中的Controller中建立新的Index Action 方法,以下:
1: [AdminFilter] 2: public ActionResult Index() 3: { 4: return PartialView("Index"); 5: }
3. 建立Index 分部View
在「~/Areas/Spa/Views/SpaBulkUpload」中建立 Index分部View
1: <div> 2: Select File : <input type="file" name="fileUpload" id="MyFileUploader" value="" /> 3: <input type="submit" name="name" value="Upload" onclick="Upload();" /> 4: </div>
4. 建立 OpenBulkUpload 方法
打開「~/Areas/Spa/Views/Main/Index.cshtml」文件,新建JavaScript 方法OpenBulkUpload
1: function OpenBulkUpload() { 2: $.get("/SPA/SpaBulkUpload/Index").then 3: ( 4: function (r) { 5: $("<div id='DivBulkUpload'></div>").html(r).dialog({ width: 'auto', height: 'auto', modal: true, title: "Create New Employee", 6: close: function () { 7: $('#DivBulkUpload').remove(); 8: } }); 9: } 10: ); 11: } 12: </script> 13: </head> 14: <body> 15: <div style="text-align:right">
5. 運行
6. 新建FileUploadViewModel
在ViewModel SPA文件夾中新建View Model」FileUploadViewModel」。
1: namespace WebApplication1.ViewModels.SPA 2: { 3: public class FileUploadViewModel 4: { 5: public HttpPostedFileBase fileUpload { get; set; } 6: } 7: }
7. 建立Upload Action
1: [AdminFilter] 2: public async Task<actionresult> Upload(FileUploadViewModel model) 3: { 4: int t1 = Thread.CurrentThread.ManagedThreadId; 5: List<employee> employees = await Task.Factory.StartNew<list<employee>> 6: (() => GetEmployees(model)); 7: int t2 = Thread.CurrentThread.ManagedThreadId; 8: EmployeeBusinessLayer bal = new EmployeeBusinessLayer(); 9: bal.UploadEmployees(employees); 10: EmployeeListViewModel vm = new EmployeeListViewModel(); 11: vm.Employees = new List<employeeviewmodel>(); 12: foreach (Employee item in employees) 13: { 14: EmployeeViewModel evm = new EmployeeViewModel(); 15: evm.EmployeeName = item.FirstName + " " + item.LastName; 16: evm.Salary = item.Salary.Value.ToString("C"); 17: if (item.Salary > 15000) 18: { 19: evm.SalaryColor = "yellow"; 20: } 21: else 22: { 23: evm.SalaryColor = "green"; 24: } 25: vm.Employees.Add(evm); 26: } 27: return Json(vm); 28: } 29: 30: private List<employee> GetEmployees(FileUploadViewModel model) 31: { 32: List<employee> employees = new List<employee>(); 33: StreamReader csvreader = new StreamReader(model.fileUpload.InputStream); 34: csvreader.ReadLine();// Assuming first line is header 35: while (!csvreader.EndOfStream) 36: { 37: var line = csvreader.ReadLine(); 38: var values = line.Split(',');//Values are comma separated 39: Employee e = new Employee(); 40: e.FirstName = values[0]; 41: e.LastName = values[1]; 42: e.Salary = int.Parse(values[2]); 43: employees.Add(e); 44: } 45: return employees; 46: }
8. 建立Upload 函數
打開」~/Areas/Spa/Views/SpaBulkUpload」的Index View。建立JavaScript函數,命名爲「Upload」
1: <script> 2: function Upload() { 3: debugger; 4: var fd = new FormData(); 5: var file = $('#MyFileUploader')[0]; 6: fd.append("fileUpload", file.files[0]); 7: $.ajax({ 8: url: "/Spa/SpaBulkUpload/Upload", 9: type: 'POST', 10: contentType: false, 11: processData: false, 12: data: fd 13: }).then(function (e) { 14: debugger; 15: for (i = 0; i < e.Employees.length; i++) 16: { 17: var newTr = $('<tr></tr>'); 18: var nameTD = $('<td></td>'); 19: var salaryTD = $('<td></td>'); 20: 21: nameTD.text(e.Employees[i].EmployeeName); 22: salaryTD.text(e.Employees[i].Salary); 23: 24: salaryTD.css("background-color", e.Employees[i].SalaryColor); 25: 26: newTr.append(nameTD); 27: newTr.append(salaryTD); 28: 29: $('#EmployeeTable').append(newTr); 30: } 31: $('#DivBulkUpload').dialog('close'); 32: }); 33: } 34: </script>
9. 運行
以上本系列的七篇文章就是介紹MVC知識的所有內容了,看到這裏你是否已經對MVC的知識有了較爲全面的掌握?在具有MVC知識的同時,使用一些開發工具將會使咱們的開發過程變得事半功倍,藉助 ComponentOne Studio ASP.NET MVC 這款輕量級控件,開發效率大大提升的同時,工做量也會大大減小。
七天學會MVC 就到這裏結束了,謝謝你們的支持,但願你們都可以掌握所講述的MVC知識,但願都可以進步!
原文連接:http://www.codeproject.com/Articles/1010152/Learn-MVC-Project-in-Days-Day