最近的一段時間,讓我喜歡上了mvc,對mvc又是一番見解,佩服著微軟給.net帶來的技術,mvc,ef 1、創建項目內置了Bootsrap Bootsrap是一個響應式的UI界面庫,能快速的搭建響應式界面,如果沒有美工,對界面要求不是很高的話完全可以直接作用,很方便。 Bootsrap的推薦網站 h ...
最近的一段時間,讓我喜歡上了mvc,對mvc又是一番見解,佩服著微軟給.net帶來的技術,mvc,ef
1、創建項目內置了Bootsrap
Bootsrap是一個響應式的UI界面庫,能快速的搭建響應式界面,如果沒有美工,對界面要求不是很高的話完全可以直接作用,很方便。
Bootsrap的推薦網站
2、url路由控制靈活,對seo友好
- public class RouteConfig
- {
- public static void RegisterRoutes(RouteCollection routes)
- {
- routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
- routes.MapRoute(
- name: "Default",
- url: "{controller}/{action}/{id}",
- defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
- );
- }
- }
這個是RouteConfig註冊預設路由。這個類的靜態方法RegisterRoutes是在網站啟動的時候調用的。
MVC不像webform那樣,一個動態url地址是對應到一個本地的一個aspx文件,而mvc是對應一個Controller(控制器)的裡面的一個Action(public方法)。mvc是對應的”/Home/About“對應的就是HomeController的名字為About的Action。這種url地址到Controller的Action的對應關係你完全可以按照你的要求設置,甚至可以配置成.html結尾的偽靜態
我之前寫的一篇文章可以看一下”自定義route路由機制“
3、視圖引擎的靈活
預設情況下創建mvc視圖文件.cshtml會自動把這些同一個Controller的Action的視圖放在一個文件夾。
對應視圖文件結構
mvc視圖自帶的視圖是razor引擎,可以強類型綁定視圖,安全,性能方面都有保證。
要指定視圖對應的model類型很簡單
在Contoller裡面用return View(xx)
xx為對應的一個model對象。
視圖使用:
@model xxx.Models.xx
這樣視圖就可以用@Model.欄位綁定了。
視圖可以像可以定義一個共用的部分Layout(就像Webform的master母版頁),頭部、頁腳、菜單導航等這些共用的html都可以放在Layout裡面,對於局部多個地方相同的html,可以用@Html.Action("actionName","controllerName")方法來綁定一個局部視圖(就像Webform的用戶控制項)
Action對應的局部視圖也可以定義輸出緩存OutputCache單位是分鐘,這樣下次請求直接在緩存中取出來,提高了程式的效率。 一般對變化不頻繁的Action我都這樣會加上緩存。加上[ChildActionOnly]表示只能通過視圖來引用,不能直接在瀏覽器訪問。
3.1、自定義視圖引擎
這樣可以實現mvc視圖主題,網站可以製作不同風格的主題,每個主題分別綁定視圖就可以了。
要使自定義的視圖引擎生效還需要在Global.asax加入下麵的代碼把預設視圖引擎禁用。
- ViewEngines.Engines.Clear();
- ViewEngines.Engines.Add(new CustomRazorViewEngine());
4、Model綁定
Action的參數可以是一個個單獨的參數,也可以是一個model對象,mvc可以從請求中獲取到參數綁定相應的欄位到model中去。這樣實現了表單提交的時候,自動裝配的功能,而不需要類似這樣:Request.Form["xx"]獲取值賦值給model。
mvc預設的參數綁定是按照以下順序的。
Request.Form=》RouteData.Values=》Request.QueryString=》Request.Files
假設Action的一個參數id,會從下麵按順序獲致id的值,一旦找到就不會再往下麵尋找。
1. Request.Form["id"]
2. RouteData.Values["id"]
3. Request.QueryString["id"]
4. Request.Files["id"]
實踐開發過程中的一個添加功能,綁定一個model對象,視圖代碼:
@model MvcModels.Models.Person @{ ViewBag.Title = "CreatePerson"; } <h2>Create Person</h2> @using(Html.BeginForm()) { <div>@Html.LabelFor(m => m.PersonId)@Html.EditorFor(m=>m.PersonId)</div> <div>@Html.LabelFor(m => m.FirstName)@Html.EditorFor(m=>m.FirstName)</div> <div>@Html.LabelFor(m => m.LastName)@Html.EditorFor(m=>m.LastName)</div> <div>@Html.LabelFor(m => m.Role)@Html.EditorFor(m=>m.Role)</div> <button type="submit">Submit</button> }
後臺代碼
[HttpPost] public ActionResult CreatePerson(Person model) { return View("Index", model); } 這樣前臺的表單的值會對應到model的相應的欄位裡面。當然也可以指定哪些欄位要綁定 public ActionResult AddSummary( [Bind(Include = "HomeAddress", Exclude = "Country")]AddressSummary summary) { //do something return View(summary); }
MVC的校驗非常的好,自帶非空檢驗,類型檢驗,也可以寫複雜的正則表達式。
[Requred]
Public string Name{get;set;}
以上表示Name欄位必填。
4.1自定義Binder綁定
使用IModelBinder介面自定義一個購物車的Binder類
public class CartModelBinder : IModelBinder { private const string sessionKey = "Cart"; public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { //從Session讀取購物車對象 Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey]; if (cart == null) { cart = new Cart(); controllerContext.HttpContext.Session[sessionKey] = cart; } return cart; } }
在Global.asax裡面的Application_Start方法加入代碼為Model綁定集合加入上面自定義的CartModelBinder類。
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
這樣以後的Action的Cart對象如:
- public ViewResult Summary(Cart cart)
- {
- return View(cart);
- }
就會自動綁定,也就是從Session裡面取key為Cart的對象。
5、控制器靈活
mvc的Controller拓展也很靈活
上面就是MVC框架程式的執行流程,上面圖中的ControllerFactory,Controller,Action Invoker都可以完全自定義拓展。
我們創建的Controller是其實預設繼承System.Web.Mvc.Controller的,這是一個抽象類,其實它為我們提供了很多基礎實現
它的很多方法都定義為虛方法,所以如果我們要實現自己個性化的東西也可以重寫裡面的方法。
5.1、自定義一個ControllerFactory
using System; using System.Web.Mvc; using System.Web.Routing; using System.Web.SessionState; using ControllerExtensibility.Controllers; namespace ControllerExtensibility.Infrastructure { public class CustomControllerFactory: IControllerFactory { public IController CreateController(RequestContext requestContext, string controllerName) { Type targetType = null; switch (controllerName) { case "Product": targetType = typeof(ProductController); break; case "Customer": targetType = typeof(CustomerController); break; default: requestContext.RouteData.Values["controller"] = "Product"; targetType = typeof(ProductController); break; } return targetType == null ? null : (IController)DependencyResolver.Current.GetService(targetType); } public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) { return SessionStateBehavior.Default; } public void ReleaseController(IController controller) { IDisposable disposable = controller as IDisposable; if (disposable != null) { disposable.Dispose(); } } } }
CustomControllerFactory職責是根據請於的獲取到路由信息來創建相應的Controller對象
要使自定義的CustomControllerFactory生效還需要在在Application_Start()方法中加入註冊代碼
- ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
6、AOP面向方面編程
Java的Spring框架的AOP(面向方面編程)很強大,AOP的優點是大大的降低了軟體模塊的耦合性,提高了代碼的復用和維護性。
ASP.NET MVC有各種Filter過濾器,就相當於AOP的技術。可以把應用於身份驗證,日誌記錄,異常處理,這樣核心業務只關心自己的邏輯代碼就是了,最後的代碼不會參雜有業務代碼身份驗證、日誌相關的代碼。
我這之前寫了一篇介紹mvc的aop文章,AOP實踐--利用MVC5 Filter實現登錄狀態判斷
7、IOC控制反轉
.Net方面的IOC框架是也是不少的主流的有Autofac、Castle Windsor、Unity、Spring.NET、StructureMap、Ninject等。MVC使用這些框架也很好集成。有的都不用自己寫IOC框架與MVC集成代碼了。像Autofac有MVC5和MVC2、3、4都有現有集成代碼,如下圖。
直接安裝就可以在自己的MVC項目中用了,如果你用的IOC框架沒有在nuget中找到MVC集成包,自己寫有也很容易。
具體請看我這前的文章IOC實踐--用Autofac實現MVC5.0的IOC控制反轉方法
8、單元測試容易
你可以不通過Web伺服器IIS之類的來測試Action和Controller,利用moq框架很容易的就mock模擬出真實的Web請求。
mvc的Controller和Action方法都可以很方便的進行單元測試。
你如果要測試一個Action方法的返回值,你都可以不用解析任何的HTML的。 只需要監視Action的返回值ActionResult類型的對象。
不用模擬用戶請求,MVC框架的model綁定對象,做為Action方法的參數,然後返回相應的結果 。最簡單的測試就是你傳入具體的參數直接調
Action方法,就可以了。比如要測試一個Action是真能返回一個指定的View
- public ViewResult Index() {
- return View("Homepage");
- }
測試代碼:
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using ControllersAndActions.Controllers; using System.Web.Mvc; namespace ControllersAndActions.Tests { [TestClass] public class ActionTests { [TestMethod] public void ViewSelectionTest() { // 創建要測試的 Controller ExampleController target = new ExampleController(); // 調用Action ViewResult result = target.Index(); // 判斷測試結果 Assert.AreEqual("Homepage", result.ViewName); } } }
9、開源
MVC是開源的框架,而NuGet是一個VS很有用的一個包管理工具,上面有很多有用的類庫,搜mvc出現下麵的結果。
可以看到很多有用的類庫,分頁(PagedList.Mvc),Grid.Mvc。
9、entityframework完美配合
MVC5項目添加Controller可以選擇”包含視圖的MVC5控制器(使用Entity Framework)“,這樣一個Model的增、刪、改、查這些相關的View和Action自動給你生成好了,只需要根據自己需要改一下基本上就能用了。這樣大大的提高的開發速度,對於開發管理後臺這個太好用了。
10、總結
總結:我之前一直都覺得.net是入門比較容易,因為很多東西微軟都給你封裝好了,要成為高手比較難,不像java的好多開源的框架,從中可以學到好多的軟體架構和設計模式這類的東西,例如,面向介面編程,AOP,IOC這類的。但是伴隨著.Net的相關東西開源,比如MVC、EF、甚至現在.NET Framework也開源了,研究的越來越多,這些.net現在也可以,我上面寫就可以看到MVC的每個部分都很靈活,完全可以根據自己的需要重寫,訂製。建議想成為高手或架構師,完全有必要仔細研究MVC的源碼和原來,因為從裡面可以學到很多設計模式、軟體架構、軟體設計相關的技巧,對於提升我們的技術能力很有幫助。