首頁  >  文章  >  後端開發  >  [ASP.NET MVC 小牛之路]08 - Area 使用

[ASP.NET MVC 小牛之路]08 - Area 使用

黄舟
黄舟原創
2016-12-30 14:35:241532瀏覽

[ASP.NET
MVC 小牛之路]08 - Area 使用

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

本文目錄


建立Area

右鍵工程選擇新增->區域,彈出如下填入Area的對話框:

[ASP.NET MVC 小牛之路]08 - 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,並重寫[ASP.NET MVC 小牛之路]08 - Area 使用

了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>
    <p>
        <h2>Admin Area Index</h2>
    </p>
</body>
</html>

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

到這,我們已經看到,Area中的工作流程其實就是和根目錄下的流程是一樣的。但Area並不是一個完全獨立的工作空間,我們下面來看看。 [ASP.NET MVC 小牛之路]08 - Area 使用

Controller的歧義問題
試想一下,如果我們現在在根目錄的Controller 資料夾中也加入一個名為Home 的Controller,然後我們透過把URL定位到/Home/Index,路由系統能匹配到根目錄下的Controller 嗎?

在根目錄的Controllers 資料夾中添加好HomeController 後,為Index添加View,內容隨意:

...
<body>
    <p>
        <h2>Root Index</h2>
    </p>
</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" }
    );
}

运行程序,如下结果说明解决了同名歧义问题:

[ASP.NET MVC 小牛之路]08 - Area 使用

添加了 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>

 以上就是[ASP.NET MVC 小牛之路]08 - Area 使用的内容,更多相关内容请关注PHP中文网(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn