前面幾話都講的一些有關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.可以看到我們已經消滅之前的黃頁了,項目開始就先搞怎麼些東西,後續繼續完善。要是那裡描述有誤還請路過的前輩牛人給點指點,這樣才能更好的進步,謝謝!