.NET/ASP.NET MVC(模組化開發AraeRegistration)

王清培發表於2013-10-14

閱讀目錄:

  • 1.開篇介紹
  • 2.AreaRegistration註冊路由(傳遞路由上下文進行模組化註冊)

1】開篇介紹

ASP.NET Routing 路由功能非常強大,設計的也很巧妙;如果說ASP.NETMVC是建立在ASP.NET之上還不如準確的說ASP.NETMVC是建立在Routing基礎之上的,才使得Controller順利被找到並且執行Action;

那麼今天這篇文章是一個簡短的介紹如何在ASP.NETMVC下進行很好的模組化開發,都知道ASP.NETMVC是分層架構中的UI層框架;而UI層的開發有著天生的難以控制性,尤其是WEBUI和WINFORMUI有著很大的區別;WEBUI的組成元素多,又是在遠端的瀏覽器中處理的,所以還是很考驗架構設計的;

那麼ASP.NETMVC的AreaRegistration是用來幹什麼呢,它是用來提供一個很好的介面讓我們可以將Controller定義在其他的Library專案中,這主要可以用來解決模組化開發;一般情況下我們很少將所有的東西都定義在WebApplication中,而是會根據業務需要或者架構需要劃分出一系列的Library專案來,從而讓我們的邏輯架構更清晰也讓物理架構的設計很靈活點,比如:橫向的擴充套件,動態設計業務模組,WEBAPI等等;

但是Routing跟MVC沒有必然的關係,都是可以通過擴充套件的方式嵌入各自想要的功能點,Routing是在提供自定義IHttpModule的方式將控制權拿到,而MVC是建立在Routing的基礎上讓Uri的路由為自己所用,其實準確點講AreaRegistration適當的擴充套件可以用在很多的場合下,但是畢竟AreaRegistration是在ASP.NETMVC中提供出來的;

2】AreaRegistration註冊路由(傳遞路由上下文進行模組化註冊)

簡單的解釋,AreaRegistration是用來在ASP.NETMVC裡面註冊多個區域的方式;就是可以將一個大型的MVC站點劃分成多個Area區域,然後各自的Area有著自己的Controller、Action、View等元素;但是一般情況我們並不會那麼做,因為將站點的所有UI層中的元素切開放會給維護工作帶來很大的工作量,而且我們約定俗成的是UI層的東西放在一個主的WebApplication中,然後是業務功能的劃分,但是大型站點也許需要這麼做;

2.1】AreaRegistration物件結構(典型的模板方法模式)

下面我們來分析一下AreaRegistration的物件結構,至少我們要搞清楚如何使用這個物件及相關的物件;

 1 using System;
 2 using System.Web.Routing; 
 3 
 4 namespace System.Web.Mvc
 5 {
 6     public abstract class AreaRegistration
 7     {
 8         protected AreaRegistration();        
 9 
10         public abstract string AreaName { get; } 
11         public static void RegisterAllAreas();
12         public static void RegisterAllAreas(object state);
13         public abstract void RegisterArea(AreaRegistrationContext context);
14     }
15 }

這是AreaRegistration物件的程式碼結構,兩個靜態的過載方法是用來在Gloab.asax檔案中啟動全域性註冊用的,而帶object state 引數的是用來傳遞到我們將要繼承的物件中去的;然後剩下的一個AreaName屬性、RegisterArea方法是需要我們去實現的;

其實熟悉設計模式的朋友都會對這種模式很熟悉,因為它是最典型的模板方法模式,也是設計原則中的依賴倒置原則,在內部MVC只依賴AreaRegistration物件,然後將通過RegisterArea方法將AreaRegistrationContext上下文傳遞到子類中去執行點東西;

這裡需要強調的是,一個AreaRegistration對應一個獨立的AreaRegistrationContext物件,相關的引數是在建構函式中傳入的,前提是你必須實現AreaName屬性;

2.2】實現AreaRegistration物件

我們來實現一個OrderAreaRegistration物件,讓其繼承AreaRegistration抽象類;

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Mvc; 
 7 
 8 namespace Api.Order
 9 {
10     public class OrderAreaRegistration : AreaRegistration
11     {
12         public override string AreaName
13         {
14             get { return "Aip/Order"; }
15         } 
16 
17         public override void RegisterArea(AreaRegistrationContext context)
18         {
19             context.MapRoute(name: "api.order.default", url: "api/order/{controller}/{action}/{orderid}",
20                 defaults: new { controller = "OrderController", action = "GetOrderOperationDatetime", orderid = "1001" },
21                 namespaces: new string[] { "Api.Order" });
22         }
23     }
24 }

定義在api專案中的Controller:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Mvc; 
 7 
 8 namespace Api.Order
 9 {
10     public class Order : Controller
11     {
12         public string GetOrderOperationDatetime(string orderId)
13         {
14             if (orderId.Equals("1001"))
15                 return DateTime.Now.ToString();
16             else
17                 return orderId;
18         }
19     }
20 }

然後我們得引用這個Library專案,這樣它才能在啟動的時候去自動的掃描到我們這個型別;

圖1:

AreaRegistrationContext是使用AreaRegistraton的實現類的引數AreaName作為引數的一部分來構造特定的Context物件的;AreaRegistratioContext是表示一個區域的上下文,我們在Context裡面註冊的動東西都是屬於當前Area的,它包括自己的Route集合;

圖2:

站點順利的路由到了我們在api.order專案中定義的OrderController;

圖3:

這麼來設計專案也是會多一中選擇的;

 

相關文章