前面幾話都講的一些有關MVC相關東西,從這話開始應用實戰的項目開始。
實戰一個簡單的購物流程的項目吧!
首先創建一個空白的解決方案,如下圖1.
圖1.我們預計創建3個模塊,一個模塊包含我們的域模型(DoMain),一個模塊包含我的MVC Web應用程序,還有一個單元測試的模塊。
我們的域模型(DoMain)是一個類庫項目,然后是一個Asp.Net MVC3 的Web應用程序(Razor引擎)項目,然后添加一個測試項目進來,添加測試項目如下圖2.
圖2.當我們創建好我們的域模型(DoMain)類庫項目和測試項目(類庫項目),VS會自動創建一個Class1.cs的文件和UnitTest1.cs的文件,這個對我們來說沒有多大的用處,可以直接干掉。之后我們的行么如下圖3.
圖3.下一步就是添加項目引用,可項目需要用到包(擴展工具/第三方插件),我們項目具體要用到的第三方插件如下:
| 具體項目 | 第三插件名稱 |
| SportsStore.Domain | Ninject |
| SportsStore.UI | Ninject |
| SportsStore.Domain | Moq |
| SportsStore.UI | Moq |
可以在VS里面的"程序包控制管理"用下面的命令導入第三方插件包,命令如下:
Install-Package Ninject -Project SportsStore.WebUI
Install-Package Ninject -Project SportsStore.Domain
Install-Package Moq -Project SportsStore.WebUI
Install-Package Moq -Project SportsStore.Domain
也可以在相關項目上右鍵,使用NuGet程序包管理一個一個導入,方法根據自己所好,不在啰嗦!
然后就是我們項目的依賴關系,如下表所示:
| 具體項目 | 依賴項目 |
| SportsStore.Domain | 無 |
| SportsStore.UI | SportsStore.Domain |
| SportsStore.UnitTests | SportsStore.Domain SportsStore.UI |
因為我們將使用Ninject創建我們的MVC應用程序控制器和處理DI,所以我們需要創建一個新的類更改配置。在SportsStore.UI應用程序里創建一個文件夾(命名"Infrastructure")然后在改文件里創建一個類叫NinjectControllerFactory,它的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Ninject; using System.Web.Routing; using Moq; using SportsStore.Domain.Abstract; using SportsStore.Domain.Entities; namespace SportsStore.WebUI.Infrastructure { public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { this.ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { //綁定額外數據 } } }
我們需要注冊NinjectControllerFactory到MVC框架,所以我們也需要在Global.asax.cs里給它注冊進去,具體代碼如下:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); //注冊路由 ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); }
我們可以試着啟動跑下我的MVC Web項目,結果如下圖4.
圖4.如果真出現這個錯誤頁面也是預計必然的結果,接下來的任務就是讓這個頁面消失吧!
從我們的域模型(DoMain)開始吧!既然我們搞的是一個購物流程的項目,那我們肯定需要商品才能購物,那就在域模型(Domain)里創建一個文件夾(命名"Entities")放相應的模型在該文件夾來創建一個Product類吧!Product類的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace SportsStore.Domain.Entities { public class Product : Object { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal Price { get; set; } public string Category { get; set; } } }
接下來創建一個抽象存儲庫,我們知道我們用一些方法可以是Prodcut和數據交互,這里我們使用存儲庫模式,我們不需要擔心他是如何去實現,所以在域模型(DoMain)項目里建立一個文件夾(命名"Abstract")在該文件里創建一個接口"IProductRepository",它的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using SportsStore.Domain.Entities; namespace SportsStore.Domain.Abstract { public interface IProductRepository { IQueryable<Product> Products { get; } } }
這個接口使用這個IQueryable < T >可以獲取Product對象,它沒有說任何關於如何或數據存儲在哪里或者它將如何被檢索。一個類,它使用IProductRepository接口就可以獲得Product對象,但是不需要知道任何關於它們來自於哪兒,或者他們如何將被交付到那兒,這是最基本的存儲庫的模式。
然后我們使用模擬庫,因為我們一定定義了一個接口那么我接着就實現它,讓他跟數據交互,我們模擬一下實現IProductRepository接口,代碼如下:
private void AddBindings() { //綁定額外數據 //模擬IProductRepository實現 Mock<IProductRepository> mock = new Mock<IProductRepository>(); mock.Setup(h => h.Products).Returns(new List<Product>{ new Product {Name="FootBall",Price=25}, new Product {Name="Surf Board",Price=179}, new Product {Name="Running shoes",Price=95} }.AsQueryable()); this.ninjectKernel.Bind<IProductRepository>().ToConstant(mock.Object); }
准備工作的差不多了我們需要要能展現的東西出來才不算前功盡棄,我們要展示出我們的商品,首先要來創建相應的控制器(命名"ProductController"),代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using SportsStore.Domain.Abstract; namespace SportsStore.WebUI.Controllers { public class ProductController : Controller { private IProductRepository repository; public ProductController(IProductRepository productReposittory) { this.repository = productReposittory; } } }
這個只不過是一個的空的控制器,我們創建了一個構造函數,該函數接收IProductRepository來的參數,這里也就方便Ninject在Product對象實例化的時候的注入(構造注入)。然后我需要返回一個視圖展示出來,所以修改ProductController控制器如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using SportsStore.Domain.Abstract; namespace SportsStore.WebUI.Controllers { public class ProductController : Controller { private IProductRepository repository; public ProductController(IProductRepository productReposittory) { this.repository = productReposittory; } //返回一個視圖 public ViewResult List() { return this.View(this.repository.Products); } } }
接下來,需要添加一個視圖(View),我們需要創建一個強類型視圖,如下圖5.
圖5.當然在我們選擇模型類的時候,下拉框並不能找到IEnumerable<SportsStore.Domain.Entities.Product>,因為他不會包含枚舉的域模型(DoMain)對象,所以需要我們手動輸入。
IEnumerable<Product>意味着我們可以創建一個列表,現在就用犀利Razor引擎來搞這個頁面,List.cshtml頁面代碼如下:
@model IEnumerable<SportsStore.Domain.Entities.Product> @{ ViewBag.Title = "Product List"; } @foreach (var Product in Model) { <div class="item"> <h3>@Product.Name</h3> @Product.Description <h4>@Product.Price.ToString("C")</h4> </div> }
說明:@Product.Price.ToString("C"),ToString("C")根據你的服務器將數字轉換為相應的貨幣。
然后我們需要修改一下默認的路由,具體的修改如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; using SportsStore.WebUI.Infrastructure; namespace SportsStore.WebUI { // 注意: 有關啟用 IIS6 或 IIS7 經典模式的說明, // 請訪問 http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // 路由名稱 "{controller}/{action}/{id}", // 帶有參數的 URL new { controller = "Product", action = "List", id = UrlParameter.Optional } // 參數默認值 ); } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); //注冊路由 ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); } } }
注明:修改就是上面代碼紅色部分里標識為藍色的控制器名稱和相應方法(Action)名稱。
接下來,在跑下我們的MVC Web應用程序,運行結果如下圖6所示.
圖6.可以看到我們已經消滅之前的黃頁了,項目開始就先搞怎么些東西,后續繼續完善。要是那里描述有誤還請路過的前輩牛人給點指點,這樣才能更好的進步,謝謝!
