[ASP.NET MVC]解決Controller相同名稱衝突問題

ASP.ENT MVC 不像他牌MVC那麼囉嗦要設定東設定西,在ASP.NET MVC Controller只要繼承System.Web.Mvc.IController,且名稱後綴是Controller,什麼都不用設定,DefaultControllerFactory就會將MVC Project中所參考的組件(也就是說將Controller寫到別的dll中,也會自動註冊),將符合條件的Controller做自動註冊,當Request進來Route在Map時只比對Controller的Name,如果有寫通用Controller(如LoginController),很有可能有相同名稱,比對出一筆以上的Controller,因為系統不知道要使用那一個而照成衝突,這一點就不如他牌MVC方便,可以設定這個Route是對應到那一個Controller,它只能設定以那些命名空間為優先比對,以此方法解決衝突,雖然自由度沒那麼高,不過應該可以解決大部份問題。

ASP.ENT MVC 不像他牌MVC那麼囉嗦要設定東設定西,在ASP.NET MVC Controller只要繼承System.Web.Mvc.IController,且名稱後綴是Controller,什麼都不用設定,DefaultControllerFactory就會將MVC Project中所參考的組件(也就是說將Controller寫到別的dll中,也會自動註冊),將符合條件的Controller做自動註冊,當Request進來Route在Map時只比對Controller的Name,如果有寫通用Controller(如LoginController),很有可能有相同名稱,比對出一筆以上的Controller,因為系統不知道要使用那一個而照成衝突,這一點就不如他牌MVC方便,可以設定這個Route是對應到那一個Controller,它只能設定以那些命名空間為優先比對,以此方法解決衝突,雖然自由度沒那麼高,不過應該可以解決大部份問題。

 

image

圖一 範例專案結構

 

圖一中Test1Controller,同時存在DllTest與MvcTes專案t中,因為沒有設定優先命名空間而產生衝突,如圖二

image

 

請打開Global.ascx.cs,在如下範行中的第九行中,加上要使用Controller的命名空間,問題就決解了。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
        new[] { "MvcTest.Controllers" }
    );
}

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

 

這個設定只是要讓系統知道,當發生衝突時,有優先順序可以讓系統判斷出要使用那麼個Controller,不是說只能使用這個命名空間下Controller,所以Test2Controller還是可以正常運作,順便說一下,雖然Controller可以寫在不同的專案中,但View還是使用執行專案中的View。

 

猜謎時間


同一範例中,Test1Controller的二個命名空間都加上,如下圖,猜猜會怎麼樣?

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

答案是

發生衝突,因為DefaultControllerFactory會先找有設定命名空間下的Controller,陣列新增的順序並沒有優先相關,最後還是找到二個Controller,還是爆,只能說太方便也是一種罪。