ASP.NET Core 中的區域Areas in ASP.NET Core

作者:Dhananjay KumarRick AndersonBy Dhananjay Kumar and Rick Anderson

區域是 ASP.NET 功能,可用來將相關功能組織為群組,以作為個別的命名空間 (適用於路由) 和資料夾結構 (適用於檢視)。Areas are an ASP.NET feature used to organize related functionality into a group as a separate namespace (for routing) and folder structure (for views). 使用區域可基於路由的目的,藉由將另一個路由參數 area 新增至 controlleraction 或 Razor 頁面 page 來建立階層。Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area, to controller and action or a Razor Page page.

區域可提供一種方式來將 ASP.NET Core Web 應用程式分割成較小的功能群組,每個都有一組自己的 Razor Pages、控制器、檢視和模型。Areas provide a way to partition an ASP.NET Core Web app into smaller functional groups, each with its own set of Razor Pages, controllers, views, and models. 一個區域基本上是應用程式內的一個結構。An area is effectively a structure inside an app. 在 ASP.NET Core Web 專案中,Pages、模型、控制器和檢視等邏輯元件都會保留在不同的資料夾中。In an ASP.NET Core web project, logical components like Pages, Model, Controller, and View are kept in different folders. ASP.NET Core 執行階段會使用命名慣例來建立這些元件之間的關聯性。The ASP.NET Core runtime uses naming conventions to create the relationship between these components. 針對大型應用程式,將應用程式分割成個別高功能層級區域可能較有利。For a large app, it may be advantageous to partition the app into separate high level areas of functionality. 舉例來說,一個電子商務應用程式可具有多個業務單位,例如結帳、計費和搜尋。For instance, an e-commerce app with multiple business units, such as checkout, billing, and search. 這其中的每個單位都有自己的區域,以包含檢視、控制器、Razor Pages 和模型。Each of these units have their own area to contain views, controllers, Razor Pages, and models.

處於下列情況時,請考慮在專案中使用區域:Consider using Areas in a project when:

  • 應用程式是由可以邏輯方式區隔的多個高階功能性元件所組成的。The app is made of multiple high-level functional components that can be logically separated.
  • 您想要分割應用程式,讓每個功能區域都可獨立運作。You want to partition the app so that each functional area can be worked on independently.

檢視或下載範例程式碼 (如何下載)。View or download sample code (how to download). 下載範例提供基本的應用程式來測試區域。The download sample provides a basic app for testing areas.

如果您使用 Razor Pages,請參閱此文件中的使用 Razor Pages 的區域If you're using Razor Pages, see Areas with Razor Pages in this document.

適用於控制器與檢視的區域Areas for controllers with views

使用區域、控制器及檢視的典型 ASP.NET Core Web 應用程式包含下列項目:A typical ASP.NET Core web app using areas, controllers, and views contains the following:

  • 一個區域資料夾結構An Area folder structure.

  • 使用 [Area] 屬性裝飾的控制器可使控制器與區域產生關聯:Controllers decorated with the [Area] attribute to associate the controller with the area:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • 已新增至啟動的區域路由The area route added to startup:

    app.UseMvc(routes =>
    {
        routes.MapRoute(
          name: "MyArea",
          template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    
        routes.MapRoute(
           name: "default",
           template: "{controller=Home}/{action=Index}/{id?}");
    });
    

區域資料夾結構Area folder structure

假設應用程式具有兩個邏輯群組:「產品」 和「服務」 。Consider an app that has two logical groups, Products and Services. 使用區域,資料夾結構應該如下:Using areas, the folder structure would be similar to the following:

  • Project nameProject name
    • 區域Areas
      • 產品Products
        • ControllersControllers
          • HomeController.csHomeController.cs
          • ManageController.csManageController.cs
        • 檢視Views
          • 首頁Home
            • Index.cshtmlIndex.cshtml
          • 管理Manage
            • Index.cshtmlIndex.cshtml
            • About.cshtmlAbout.cshtml
      • 服務Services
        • ControllersControllers
          • HomeController.csHomeController.cs
        • 檢視Views
          • 首頁Home
            • Index.cshtmlIndex.cshtml

儘管上述配置通常會在使用區域時使用,但是只需有檢視檔案,就能使用此資料夾結構。While the preceding layout is typical when using Areas, only the view files are required to use this folder structure. 檢視探索會依下列順序搜尋相符的區域檢視檔案:View discovery searches for a matching area view file in the following order:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

使控制器與區域產生關聯Associate the controller with an Area

區域控制器會透過 [Area] 屬性來指定:Area controllers are designated with the [Area] attribute:

using Microsoft.AspNetCore.Mvc;

namespace MVCareas.Areas.Products.Controllers
{
    [Area("Products")]
    public class ManageController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

        public IActionResult About()
        {
            return View();
        }
    }
}

新增區域路由Add Area route

區域路由通常會使用慣例路由,而非屬性路由。Area routes typically use conventional routing rather than attribute routing. 慣例路由與順序息息相關。Conventional routing is order-dependent. 一般而言,具有區域的路由應該放在路由表前面,因為這些路由比沒有區域的路由更明確。In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

如果 URL 空間在所有區域中都是統一的,則可使用 {area:...} 作為路由範本中的語彙基元:{area:...} can be used as a token in route templates if url space is uniform across all areas:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
          name: "MyArea",
          template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

        routes.MapRoute(
           name: "default",
           template: "{controller=Home}/{action=Index}/{id?}");
    });
}

在上述程式碼中,exists 會套用路由必須與區域相符的條件約束。In the preceding code, exists applies a constraint that the route must match an area. 若要將路由新增至區域,使用 {area:...} 是最簡單的機制。Using {area:...} is the least complicated mechanism to adding routing to areas.

下列程式碼會使用 MapAreaRoute 來建立兩個具名的區域路由:The following code uses MapAreaRoute to create two named area routes:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapAreaRoute(
            name: "MyAreaProducts",
            areaName:"Products",
            template: "Products/{controller=Home}/{action=Index}/{id?}");

        routes.MapAreaRoute(
            name: "MyAreaServices",
            areaName: "Services",
            template: "Services/{controller=Home}/{action=Index}/{id?}");

        routes.MapRoute(
           name: "default",
           template: "{controller=Home}/{action=Index}/{id?}");
    });
}

搭配 ASP.NET Core 2.2 使用 MapAreaRoute 時,請參閱這個 GitHub 問題 (英文)。When using MapAreaRoute with ASP.NET Core 2.2, see this GitHub issue.

如需詳細資訊,請參閱區域路由For more information, see Area routing.

以下來自範例下載的程式碼會顯示使用指定的區域來產生連結:The following code from the sample download shows link generation with the area specified:

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-controller="Home" asp-action="About">
            Products/Home/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-controller="Home" asp-action="About">
            Services About
        </a>
    </li>
    <li>
        <a asp-area="" asp-controller="Home" asp-action="About">
            /Home/About
        </a>
    </li>
</ul>
<li>Html.ActionLink generated links</li>
<ul>
    <li>
        @Html.ActionLink("Product/Manage/About", "About", "Manage", 
                                                new { area = "Products" })
    </li>
</ul>
<li>Url.Action generated links</li>
<ul>
    <li>
        <a href='@Url.Action("About", "Manage", new { area = "Products" })'>
            Products/Manage/About
        </a>
    </li>
</ul>

使用上述程式碼產生的連結,在應用程式中的任何位置都是有效的。The links generated with the preceding code are valid anywhere in the app.

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。The sample download includes a partial view that contains the preceding links and the same links without specifying the area. 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。The partial view is referenced in the layout file, so every page in the app displays the generated links. 在未指定區域的情況下產生的連結,只有在從相同區域與控制器中的頁面進行參考時才有效。The links generated without specifying the area are only valid when referenced from a page in the same area and controller.

未指定區域或控制站時,路由即會取決於「環境」 值。When the area or controller is not specified, routing depends on the ambient values. 目前要求的目前路由值被視為用於連結產生的環境值。The current route values of the current request are considered ambient values for link generation. 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。In many cases for the sample app, using the ambient values generates incorrect links.

如需詳細資訊,請參閱路由至控制器動作For more information, see Routing to controller actions.

使用 _ViewStart.cshtml 檔案共用區域的配置Shared layout for Areas using the _ViewStart.cshtml file

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。To share a common layout for the entire app, move the _ViewStart.cshtml to the application root folder.

_ViewImports.cshtml_ViewImports.cshtml

在其標準位置中, /Views/_ViewImports.cshtml 不適用於區域。In its standard location, /Views/_ViewImports.cshtml doesn't apply to areas. 若要在您的區域中使用一般標記協助程式@using@inject,請確定適當的 _ViewImports 檔案適用於您的區域檢視To use common Tag Helpers, @using, or @inject in your area, ensure a proper _ViewImports.cshtml file applies to your area views. 如果您希望在所有檢視中都有相同的行為,請將 /Views/_ViewImports.cshtml 移至應用程式根目錄。If you want the same behavior in all your views, move /Views/_ViewImports.cshtml to the application root.

變更檢視儲存所在的預設區域資料夾Change default area folder where views are stored

下列程式碼會將預設的區域資料夾從 "Areas" 變更為 "MyAreas"The following code changes the default area folder from "Areas" to "MyAreas":

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.AreaViewLocationFormats.Clear();
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
    });

    services.AddMvc();
}

使用 Razor Pages 的區域Areas with Razor Pages

使用 Razor Pages 的區域,在應用程式的根目錄中需要有 Areas//Pages 資料夾。Areas with Razor Pages require an Areas//Pages folder in the root of the app. 下列資料夾結構搭配範例應用程式一起使用:The following folder structure is used with the sample app:

  • Project nameProject name
    • 區域Areas
      • 產品Products
        • 頁面Pages
          • _ViewImports_ViewImports
          • 關於About
          • 索引Index
      • 服務Services
        • 頁面Pages
          • 管理Manage
            • 關於About
            • 索引Index

以下來自範例下載的程式碼會顯示使用指定的區域 (例如 asp-area="Products") 來產生連結:The following code from the sample download shows link generation with the area specified (for example, asp-area="Products"):

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-page="/About">
            Products/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-page="/Manage/About">
            Services/Manage/About
        </a>
    </li>
    <li>
        <a asp-area="" asp-page="/About">
            /About
        </a>
    </li>
</ul>
<li>Url.Page generated links</li>
<ul>
    <li>
        <a href='@Url.Page("/Manage/About", new { area = "Services" })'>
            Services/Manage/About
        </a>
    </li>
    <li>
        <a href='@Url.Page("/About", new { area = "Products" })'>
            Products/About
        </a>
    </li>
</ul>

使用上述程式碼產生的連結,在應用程式中的任何位置都是有效的。The links generated with the preceding code are valid anywhere in the app.

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。The sample download includes a partial view that contains the preceding links and the same links without specifying the area. 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。The partial view is referenced in the layout file, so every page in the app displays the generated links. 在未指定區域的情況下產生的連結,只有在從相同區域中的頁面進行參考時才有效。The links generated without specifying the area are only valid when referenced from a page in the same area.

未指定區域時,路由即會取決於「環境」 值。When the area is not specified, routing depends on the ambient values. 目前要求的目前路由值被視為用於連結產生的環境值。The current route values of the current request are considered ambient values for link generation. 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。In many cases for the sample app, using the ambient values generates incorrect links. 例如,試想從下列程式碼產生的連結:For example, consider the links generated from the following code:

<li>
    <a asp-page="/Manage/About">
        Services/Manage/About
    </a>
</li>
<li>
    <a asp-page="/About">
        /About
    </a>
</li>

針對上述程式碼:For the preceding code:

  • 僅當最後一個要求是針對 Services 區域中的頁面時,從 <a asp-page="/Manage/About"> 產生的連結才是正確的。The link generated from <a asp-page="/Manage/About"> is correct only when the last request was for a page in Services area. 例如 /Services/Manage//Services/Manage/Index/Services/Manage/AboutFor example, /Services/Manage/, /Services/Manage/Index, or /Services/Manage/About.
  • 僅當最後一個要求是針對 /Home 中的頁面時,從 <a asp-page="/About"> 產生的連結才是正確的。The link generated from <a asp-page="/About"> is correct only when the last request was for a page in /Home.
  • 程式碼來自下載範例The code is from the sample download.

使用 _ViewImports 檔案匯入命名空間和標記協助程式Import namespace and Tag Helpers with _ViewImports file

可以將 _ViewImports.cshtml 檔案新增至每個區域 Pages 資料夾,以將命名空間和標記協助程式匯入到資料夾中的每個 Razor 頁面。A _ViewImports.cshtml file can be added to each area Pages folder to import the namespace and Tag Helpers to each Razor Page in the folder.

請考慮範例程式碼的 Services 區域,該區域不包含 _ViewImports.cshtml 檔案。Consider the Services area of the sample code, which doesn't contain a _ViewImports.cshtml file. 下列標記示範 /Services/Manage/About Razor頁面:The following markup shows the /Services/Manage/About Razor Page:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model RPareas.Areas.Services.Pages.Manage.AboutModel
@{
    ViewData["Title"] = "Srv Mng About";
}

<h2>/Services/Manage/About</h2>

<a asp-area="Products" asp-page="/Index">
    Products/Index
</a>

在上述標記中:In the preceding markup:

  • 必須使用完整的網域名稱來指定此模型 (@model RPareas.Areas.Services.Pages.Manage.AboutModel)。The fully qualified domain name must be used to specify the model (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • 標記協助程式@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 啟用Tag Helpers are enabled by @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

在範例下載中,Products 區域包含下列 _ViewImports.cshtml 檔案:In the sample download, the Products area contains the following _ViewImports.cshtml file:

@namespace RPareas.Areas.Products.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

下列標記示範 /Products/About Razor 頁面:The following markup shows the /Products/About Razor Page:

@page
@model AboutModel
@{
    ViewData["Title"] = "Prod About";
}

<h2>Products/About</h2>

<a asp-area="Services" asp-page="/Manage/About">
    Services/Manage/About
</a>

在上述檔案中,命名空間和 @addTagHelper 指示詞會由 Areas/Products/Pages/_ViewImports.cshtml 檔案匯入到檔案。In the preceding file, the namespace and @addTagHelper directive is imported to the file by the Areas/Products/Pages/_ViewImports.cshtml file.

如需詳細資訊,請參閱管理標籤協助程式範圍匯入共用指示詞For more information, see Managing Tag Helper scope and Importing Shared Directives.

Razor Pages 區域的共用版面配置Shared layout for Razor Pages Areas

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。To share a common layout for the entire app, move the _ViewStart.cshtml to the application root folder.

發行區域Publishing Areas

當 *.csproj 檔案中包含 <Project Sdk="Microsoft.NET.Sdk.Web"> 時,會將所有 *.cshtml 檔案及 wwwroot 目錄內的檔案發佈至輸出。All *.cshtml files and files within the wwwroot directory are published to output when <Project Sdk="Microsoft.NET.Sdk.Web"> is included in the *.csproj file.