更改MVC注冊Areas的順序,掌控Areas的運作
一、前言
首先,有人要問,為什么要更改Areas的注冊順序呢?
使用Areas的時候一般會在前面加標識符,比如:admin/{controller}/{action}/{id}
而且Areas的注冊早于默認的網站 (就是不放在Areas文件夾中的那個網站)
但是,我想,能不能干脆就不用外部的那個默認網站,而是把所有部分都放Areas中呢?
然后,把其中一個的標識符去掉,變成默認的網站

這時候,項目根目錄就少了2個文件夾,Controller和View

是不是很整潔?的確…但問題也隨之而來
二、把所有網站都放在Areas里的一個大問題
簡單的來說,這個問題就是你無法指定不同Area的注冊順序,那會出現什么問題呢?
如果我有2個Area:
一個是帶標識符的,叫admin,地址是 admin/{controller}/{action}/{id}
一個是默認的,叫web,地址是 {controller}/{action}/{id}
這時候,如果web注冊比admin早,就會出現問題了,就算我輸入 admin.aspx,按照次序,會先被web捕捉,被認為是web中的一個controller
所以我們需要想辦法更改areas的注冊順序
至于為什么默認的時候不能確定順序?看一下MVC源代碼就知道了,它是利用反射來獲得Areas的,放到一個集合后用foreach注冊
三、設定注冊順序的2種方法
1)第一種方法是昨天看到以為博友寫了篇關于Areas的文章,我在下面問他后他告訴我的
傳送門,看下面留言即可知道了:www.rzrgm.cn/terrysun/archive/2010/04/13/1711218.html
他的方法是把Areas的注冊移出來,放在同一個地方,這樣就可以隨意地更改順序了
2)第二種方法是我昨天剛試驗成功的,雖然看似麻煩,但是看起來更清楚一點,我個人推薦
首先,我重寫了一個 AreaRegistration 類,這個類是用來注冊Areas的
AreaRegistrationOrder
/// <summary>
/// 根據順序注冊Areas
/// </summary>
abstract public class AreaRegistrationOrder : AreaRegistration
{
/// <summary>
/// 存放AreaContent
/// </summary>
protected static List<AreaRegistrationContext> areaContent = new List<AreaRegistrationContext>();
/// <summary>
/// 存放AreaRegistration
/// </summary>
protected static List<AreaRegistrationOrder> areaRegistration = new List<AreaRegistrationOrder>();
/// <summary>
/// 劫持
/// </summary>
/// <param name="context"></param>
public override void RegisterArea(AreaRegistrationContext context)
{
areaContent.Add(context);
areaRegistration.Add(this);
}
/// <summary>
/// 注冊
/// </summary>
/// <param name="context"></param>
public abstract void RegisterAreaOrder(AreaRegistrationContext context);
/// <summary>
/// 順序
/// </summary>
public abstract int Order { get; }
/// <summary>
/// 按照順序注冊Areas
/// </summary>
public static void RegisterAllAreasOrder()
{
RegisterAllAreas();
Register();
}
/// <summary>
/// 注冊
/// </summary>
private static void Register()
{
List<int[]> order = new List<int[]>();
for(int k=0;k<areaRegistration.Count;k++)
{
order.Add(new int[] { areaRegistration[k].Order, k });
}
order = order.OrderBy(o => o[0]).ToList();
foreach (var o in order)
{
areaRegistration[o[1]].RegisterAreaOrder(areaContent[o[1]]);
}
}
}
}
那接下來怎么使用這個抽象類呢?
你只需要改2個地方
1)首先,你需要把Global.asax中原來那個注冊全部Areas的函數換掉,并且把RegisterRoutes函數中的代碼刪掉

(上圖注釋中有一個錯別字,應該是”代碼也刪除“,不是”代碼頁刪除“)
2)接下來,你就可以新建一個Areas了,對于新建的Areas,你需要做如下修改:


總結一下你總共要做那些事:
. 把原來繼承的類換掉,換乘上面那個類,并實現抽象函數
.. 把RegisterArea刪掉,換成RegisterAreaOrder,原來的操作寫在RegisterAreaOrder中
... Order中,指定它的順序,越小越就早執行,可以是負數
四、Ending
源代碼下載:https://files.cnblogs.com/dozer/MVC-AREAS.zip
感謝大家的閱讀,如果收獲,請點支持~謝謝~

本作品采用知識共享署名-非商業性使用 3.0 Unported許可協議進行許可。


浙公網安備 33010602011771號