ASP.NET MVC - 應用Area來組織MVC專案架構

當一個大型的網頁專案區分許多子系統模組時,整個系統加總起來或許有上千上百個ControllerView,按照MVC的精神,把Controller, View, Model分離,結果可能三個資料夾內有超多檔案,所有功能都混雜在一起,開發與維護起來相當不易,對網址的區隔與命名也想當困難,如果使用預設的Route(/{Controller}/{Action}),很難將相關的功能歸類。


仔細深入的探索MVC,就會發現MVC有提供區域(Area)的機制,讓相似的功能或整個子系統抽離,與其它子系統獨立,每個子系統有自己的設定,不會干預到其他子系統,在網址的分層上,也多了區域,使可讀性變得更高(/{Area}/{Controller}/{Action}),以下就來講解如何將Area分離:

1. MVC專案按下右鍵 ->[加入] -> [區域]。


2. 輸入區域名稱。

3. 可以看到在專案下多出了一個Areas的資料夾,Areas底下有剛剛建立的Admin區域,
Admin區域裡分別有ControllersViews, Models的資料夾,整個結構和外面的Controllers, Views, Models相同,另外,VSView裡也為此區域建了一個Web.config檔,打開仔細一看會發現和外層Views資料夾內的Web.config內容類似。


4. 在上圖中可以發現多一個沒看過的AdminAreaRegistration.cs檔,這個檔案是Admin區域自己的RouteConfigAdminAreaRegistration要繼承AreaRegistration,這樣在Global.asax.csApplication_Start()時,AreaRegistration.RegisterAllAreas()這行才會找到有繼承AreaRegistration,將各自的RouteConfig註冊。

AdminAreaRegistration.cs:


using System.Web.Mvc;

namespace RouteTest.Areas.Admin
{
 public class AdminAreaRegistration : AreaRegistration
 {
  public override string AreaName
  {
   get
   {
    return "Admin";
   }
  }

  public override void RegisterArea( AreaRegistrationContext context )
  {
   // Admin區域的Route
   context.MapRoute(
    name: "Admin_default",
    url: "Admin/{controller}/{action}/{id}",
    defaults: new { action = "Index", id = UrlParameter.Optional },
    namespaces: new[] { "RouteTest.Areas.Admin.Controllers" }
   );
  }
 }
}

Global.asax.cs:


using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace RouteTest
{
 public class MvcApplication : System.Web.HttpApplication
 {
  protected void Application_Start()
  {
   // 註冊所有區域的Route
   AreaRegistration.RegisterAllAreas();

   WebApiConfig.Register( GlobalConfiguration.Configuration );
   FilterConfig.RegisterGlobalFilters( GlobalFilters.Filters );
   RouteConfig.RegisterRoutes( RouteTable.Routes );
   BundleConfig.RegisterBundles( BundleTable.Bundles );
  }
 }
}
5. 接著再加入新的Controller(這裡限量加入一個AccountController)並在Controller裡加入Action與對應的View。

AccountController.cs:


using System.Web.Mvc;

namespace RouteTest.Areas.Admin.Controllers
{
    public class AccountController : Controller
    {
        //
        // GET: /Admin/Account/

        public ActionResult Index()
        {
            return View();
        }
    }
}
6. 為了測試區域之間的連結能正常運作,限量在共用Layout裡加入各區域Controller Index Action的連結,這裡要注意的是,因為_Layout.cshtml是在原本最外層的View裡,原本根據的是它原本的RouteConfig,就不用特別在意區域的問題,但有區域的分別時,所以會識別不了其他區域的RouteConfig,所以這時候就要在後面的RouteValue加入area的值,意思是該連接是會連結到該區域的某某Controller裡,areaRoute內部運作時使用的變數,代表區域的名稱。

_Layout.cshtml:


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
 <body>
  <header>
   <ul>
    @*/*@
    <li>@Html.ActionLink( "Home-Index", "Index", "Home", new { area = "" }, null )</li>
    @*/Admin/Account*@
    <li>@Html.ActionLink( "Account-Index", "Index", "Account", new { area = "Admin" }, null )</li>
   </ul>
  </header>
  @RenderBody()

  @Scripts.Render("~/bundles/jquery")
  @RenderSection("scripts", required: false)
 </body>
</html>
最後看看執行結果,Admin Area的網址上多了Admin這層。



參考來源:

留言