ASP.NET MVC Area 的使用


  MVC提供Area機制,在同一個項目之內就能夠切割出不同的ASP.NET MVC網站。

  插入:首先在相同的位置,比如說同一個文件夾(如:Controllers)是不能創建倆個相同名稱的文件(如:HomeController),其次在不同的文件夾中如fold1和fold2,中各自創建一個TestController,程序能夠通過編譯,但當瀏覽器視圖執行/Test時,網站報出異常,如圖:

因為在默認情況下,路由會同時匹配兩個controller,造成無法訪問。

在項目上,右鍵,創建區域,問題解決。

 

出處:http://www.cnblogs.com/SharpL/p/4598589.html

=============================================================

ASP.NET MVC允許使用 Area(區域)來組織Web應用程序,每個Area代表應用程序的不同功能模塊。這對於大的工程非常有用,Area 使每個功能模塊都有各自的文件夾,文件夾中有自己的Controller、View和Model,但對於管理也增加了一定的難度。

創建Area

右鍵工程選擇 添加->區域,彈出如下填寫Area的對話框:

點擊添加后,工程目錄結構如下:

和創建一個空MVC工程結構類似,Admin Area 有自己的 Controllers、Models 和 Views 文件夾,不一樣的地方就是多了一個 AdminAreaRegistration.cs 文件,這個文件中定義了一個叫 AdminAreaRegistration 的類,它的內容如下:

復制代碼
namespace MvcApplication1.Areas.Admin {
    public class AdminAreaRegistration : AreaRegistration {
        public override string AreaName {
            get {
                return "Admin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}
復制代碼

系統自動生成的 AdminAreaRegistration 類繼承至抽象類 AreaRegistration,並重寫了 AreaName 屬性和 RegisterArea 方法。在 RegisterArea 方法中它為我們定義了一個默認路由,我們也可在這個方法中定義專屬於Admin Area的的其他路由。但有一點要注意,在這如果要給路由起名字,一定要確保它和整個應用程序不一樣。

AreaRegistrationContext 類的 MapRoute 方法和 RouteCollection 類的 MapRoute 方法的使用是一樣的,只是 AreaRegistrationContext 類限制了注冊的路由只會去匹配當前 Area 的 controller,所以,如果你把在 Area 中添加的 controller 的默認命名空間改了,路由系統將找不到這個controller 。

RegisterArea 方法不需要我們手動去調用,在 Global.asax 中的 Application_Start 方法已經有下面這樣一句代碼為我們做好了這件事:

復制代碼
protected void Application_Start() {
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}
復制代碼

調用 AreaRegistration.RegisterAllAreas 方法讓MVC應用程序在啟動后會尋找所有繼承自 AreaRegistration 的類,並為每個這樣的類調用它們的 RegisterArea 方法。

注意:不要輕易改變 Application_Start 中注冊方法的順序,如果你把RouteConfig.RegisterRoutes方法放到AreaRegistration.RegisterAllAreas方法之前,Area 路由的注冊將會在路由注冊之后,路由系統是按順序來匹配的,所以這樣做會讓請求 Area 的 Controller 匹配到錯誤的路由。

Area的運行

在Area中添加controller、view和model和一般的添加是一樣的。在這,我們在Admin Area中添加一個名為 Home 的controller,代碼如下:

public class HomeController : Controller {
        
    public ActionResult Index() {
        return View();
    }
}

然后我們再為Index Acton添加一個View,代碼如下:

復制代碼
@{ 
    ViewBag.Title = "Index";
    Layout = null; 
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <h2>Admin Area Index</h2>
    </div>
</body>
</html>
復制代碼

運行應用程序,然后將URL定位到/Admin/Home/Index,下面是運行結果:

到這,我們已經看到,Area中的的工作流程其實就是和根目錄下的流程是一樣的。但Area並不是一個完全獨立的工作空間,我們下面來看看。

Controller的歧義問題

試想一下,如果我們現在在根目錄的 Controller 文件夾中也添加一個名為 Home 的 Controller,然后我們通過把URL定位到 /Home/Index,路由系統能匹配到根目錄下的 Controller 嗎?

在根目錄的 Controllers 文件夾中添加好 HomeController 后,為Index添加View,內容隨意:

復制代碼
...
<body>
    <div>
        <h2>Root Index</h2>
    </div>
</body>
...
復制代碼

路由不改動,我們使用 RouteConfig.cs 文件中系統定義的默認路由:

復制代碼
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 }
    );
}
復制代碼

運行程序,將URL定位到 /Home/Index。結果我們會看到如下錯誤信息:

出現這個問題是因為路由系統進行匹配的時候出現了Controller同名的歧義。

當Area被注冊的時候,Area中定義的路由被限制了只尋找 Area 中的Controller,所以我們請求 /Admin/Home/Index 時能正常得到 MvcApplication1.Areas.Admin.Controllers 命名空間的 HomeController。然而我們在RouteConfig.cs文件的RegisterRoutes方法中定義的路由並沒有類似的限制。

為了解決這個問題,我們需要在RouteConfig.cs文件中定義的路由中加上對應的 namespaces 參數。RouteConfig.cs 中修改后的路由如下:

復制代碼
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 },
        namespaces: new[] { "MvcApplication1.Controllers" }
    );
}
復制代碼

運行程序,如下結果說明解決了同名歧義問題:

添加了 namespaces 參數后,路由系統在對這個路由進行匹配時,優先匹配指定命名空間的controller,如果匹配到則即刻停止查找,如果在指定的命名空間下沒有匹配到對應的controller,再按照一般的方式進行匹配。

生成Area URL鏈接

關於Area的URL鏈接生成,可以分為這么三種情況:第一種是在當前Area生成指向當前Area的鏈接;第二種是生成指向其他Area的鏈接;第三種是在某個Area中生成指向根目錄的鏈接。下面是這三種情況生成鏈接的方法,使用的路由定義是系統默認的。

如果要在Area中生成當前Area的URL鏈接,直接用下面的方法就行:

@Html.ActionLink("Click me", "About")

它根據當前所在的Area和Controller會生成如下Html代碼:

<a href="/Admin/Home/About">Click me</a>

如果要生成其他Area的URL鏈接,則需要在Html.ActionLink方法的匿名參數中使用一個名為area的變量來指定要生成鏈接的Area名稱,如下:

@Html.ActionLink("Click me to go to another area", "Index", new { area = "Support" }) 

它會根據被指定的Area去找路由的定義,假定在Support Area中定義了對應的路由,那么它會生成如下鏈接:

<a href="/Support/Home/Index">Click me to go to another area</a>

如果要在當前Area生成指根目錄某個controller的鏈接,那么只要把area變量置成空字符串就行,如下:

@Html.ActionLink("Click me to go to top-level part", "Index", new { area = "" })

它會生成如下Html鏈接:

<a href="/Home/Index">Click me to go to top-level part</a>

 


參考:《Pro ASP.NET MVC 4 4th Edition》

 

出處:http://www.cnblogs.com/willick/p/3331519.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM