ASP.NET Core 中的區域

作者:Dhananjay KumarRick Anderson

區域是一項 ASP.NET 功能,用來將相關功能組織成個別的群組以進行區隔:

  • 路由的命名空間。
  • 檢視和 Razor 頁面的資料夾結構。

使用區域可基於路由的目的,藉由將另一個路由參數 (area) 新增至 controlleraction 或是 Razor 頁面 page 來建立階層。

區域可提供一種方式來將 ASP.NET Core Web 應用程式分割成較小的功能群組,每個都有一組自己的 Razor 頁面、控制器、檢視和模型。 一個區域基本上是應用程式內的一個結構。 在 ASP.NET Core Web 專案中,Pages、模型、控制器和檢視等邏輯元件都會保留在不同的資料夾中。 ASP.NET Core 執行階段會使用命名慣例來建立這些元件之間的關聯性。 針對大型應用程式,將應用程式分割成個別高階區域可能較有利。 舉例來說,一個電子商務應用程式可具有多個業務單位,例如結帳、計費和搜尋。 這其中的每個單位都有自己的區域,以包含檢視、控制器、Razor 頁面和模型。

處於下列情況時,請考慮在專案中使用區域:

  • 應用程式是由可以邏輯方式區隔的多個高階功能性元件所組成的。
  • 您想要分割應用程式,讓每個功能區域都可獨立運作。

如果您使用 Razor Pages,請參閱本文件中具有 Razor 頁面的區域

適用於控制器與檢視的區域

使用區域、控制器及檢視的典型 ASP.NET Core Web 應用程式包含下列項目:

  • 一個區域資料夾結構

  • 控制器具有 [Area] 屬性,用於建立控制器與區域的關聯:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • 新增至 Program.cs 的區域路由

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllersWithViews();
    
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapControllerRoute(
        name: "MyArea",
        pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    app.Run();
    

區域資料夾結構

假設應用程式具有兩個邏輯群組:「產品」和「服務」。 使用區域,資料夾結構應該如下:

  • Project name
    • 區域
      • 產品
        • 控制器
          • HomeController.cs
          • ManageController.cs
        • 檢視
          • Home
            • Index.cshtml
          • 管理
            • Index.cshtml
            • About.cshtml
      • 服務
        • 控制器
          • HomeController.cs
        • 檢視
          • Home
            • Index.cshtml

儘管上述配置通常會在使用區域時使用,但是只需有檢視檔案,就能使用此資料夾結構。 檢視探索會依下列順序搜尋相符的區域檢視檔案:

/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

使控制器與區域產生關聯

區域控制器會透過 [Area] 屬性來指定:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Docs.Samples;

namespace MVCareas.Areas.Products.Controllers;

[Area("Products")]
public class ManageController : Controller
{
    public IActionResult Index()
    {
        ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
        return View();
    }

    public IActionResult About()
    {
        ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
        return View();
    }
}

新增區域路由

區域路由通常會使用慣例路由,而非屬性路由。 慣例路由與順序息息相關。 一般而言,具有區域的路由應該放在路由表前面,因為這些路由比沒有區域的路由更明確。

如果 URL 空間在所有區域中都是統一的,則可使用 {area:...} 作為路由範本中的語彙基元:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

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

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "MyArea",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

在上述程式碼中,exists 會套用路由必須與區域相符的條件約束。 使用 {area:...} 搭配 MapControllerRoute

  • 若要將路由新增至區域,這是最簡單的機制。
  • 使所有控制器符合 [Area("Area name")] 屬性。

下列程式碼會使用 MapAreaControllerRoute 來建立兩個具名的區域路由:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

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

app.UseRouting();

app.UseAuthorization();

app.MapAreaControllerRoute(
    name: "MyAreaProducts",
    areaName: "Products",
    pattern: "Products/{controller=Home}/{action=Index}/{id?}");

app.MapAreaControllerRoute(
    name: "MyAreaServices",
    areaName: "Services",
    pattern: "Services/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

如需詳細資訊,請參閱區域路由

以下來自範例下載的程式碼會顯示使用指定的區域來產生連結:

<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>

範例下載包括部分檢視,其中包含:

  • 上述連結。
  • 與上述類似的連結,但未指定 area

部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域與控制器中的頁面進行參考時才有效。

未指定區域或控制站時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在範例應用程式的許多情況下,使用環境值會產生不正確的連結,且標記不會指定區域。

如需詳細資訊,請參閱路由至控制器動作

使用 _ViewStart.cshtml 檔案共用區域的配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 保留在應用程式根資料夾。 如需詳細資訊,請參考 ASP.NET Core 中的配置

應用程式根資料夾

應用程式根資料夾是使用 ASP.NET Core 範本所建立 Web 應用程式中包含 Program.cs 檔案的資料夾。

_ViewImports.cshtml

/Views/_ViewImports.cshtml (MVC) 和 /Pages/_ViewImports.cshtml (Razor Pages) 不會匯入至區域中的檢視。 使用下列其中一種方法為所有檢視提供檢視匯入:

  • _ViewImports.cshtml 新增至應用程式根資料夾。 應用程式根資料夾中的 _ViewImports.cshtml 將會套用至應用程式中的所有檢視。
  • 請將 _ViewImports.cshtml 檔案複製到區域下方的適當檢視資料夾。 例如,由個別使用者帳戶建立的 Razor Pages 應用程式在下列資料夾中具有 _ViewImports.cshtml 檔案:
    • /Areas/Identity/Pages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

_ViewImports.cshtml 檔案通常包含標籤協助程式匯入、@using@inject 陳述式。 如需詳細資訊,請參閱匯入共用指示詞

變更檢視儲存所在的預設區域資料夾

下列程式碼會將預設的區域資料夾從 "Areas" 變更為 "MyAreas"

using Microsoft.AspNetCore.Mvc.Razor;

var builder = WebApplication.CreateBuilder(args);

builder.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");
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

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

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "MyArea",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

具有 Razor Pages 的區域

具有 Razor Pages 的區域需要在應用程式的根目錄中建立 Areas/<area name>/Pages 資料夾。 下列資料夾結構搭配範例應用程式一起使用:

  • Project name
    • 區域
      • 產品
        • 頁面
          • _ViewImports
          • 關於
          • 索引
      • 服務
        • 頁面
          • 管理
            • 關於
            • 索引

以下來自範例下載的程式碼會顯示使用指定的區域 (例如 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>

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域中的頁面進行參考時才有效。

未指定區域時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。 例如,試想從下列程式碼產生的連結:

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

針對上述程式碼:

  • 僅當最後一個要求是針對 Services 區域中的頁面時,從 <a asp-page="/Manage/About"> 產生的連結才是正確的。 例如 /Services/Manage//Services/Manage/Index/Services/Manage/About
  • 僅當最後一個要求是針對 /Home 中的頁面時,從 <a asp-page="/About"> 產生的連結才是正確的。
  • 程式碼來自下載範例

使用 _ViewImports 檔案匯入命名空間和標記協助程式

可以將 _ViewImports.cshtml 檔案新增至每個區域 Pages 資料夾,以將命名空間和標記協助程式匯入到資料夾中的每個 Razor 頁面。

請考慮範例程式碼的 Services 區域,該區域不包含 _ViewImports.cshtml 檔案。 下列標記示範 /Services/Manage/AboutRazor Pages:

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

<div>
  ViewData["routeInfo"]:  @ViewData["routeInfo"]
</div>

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

在上述標記中:

  • 必須使用完整的類別名稱來指定此模型 (@model RPareas.Areas.Services.Pages.Manage.AboutModel)。
  • 標記協助程式@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 啟用

在範例下載中,Products 區域包含下列 _ViewImports.cshtml 檔案:

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

下列標記示範 /Products/AboutRazor 頁面:

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

在上述檔案中,命名空間和 @addTagHelper 指示詞會由 Areas/Products/Pages/_ViewImports.cshtml 檔案匯入到檔案。

如需詳細資訊,請參閱管理標籤協助程式範圍匯入共用指示詞

Razor Pages 區域的共用版面配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。

發行區域

當 *.csproj 檔案中包含 <Project Sdk="Microsoft.NET.Sdk.Web"> 時,會將所有 *.cshtml 檔案及 wwwroot 目錄內的檔案發佈至輸出。

使用 Visual Studio 新增 MVC 區域

在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增] > [新增 Scaffolded 專案],然後選取 [MVC 區域]

其他資源

區域是一項 ASP.NET 功能,用來將相關功能組織成個別的群組以進行區隔:

  • 路由的命名空間。
  • 檢視和 Razor 頁面的資料夾結構。

使用區域可基於路由的目的,藉由將另一個路由參數 (area) 新增至 controlleraction 或是 Razor 頁面 page 來建立階層。

區域可提供一種方式來將 ASP.NET Core Web 應用程式分割成較小的功能群組,每個都有一組自己的 Razor 頁面、控制器、檢視和模型。 一個區域基本上是應用程式內的一個結構。 在 ASP.NET Core Web 專案中,Pages、模型、控制器和檢視等邏輯元件都會保留在不同的資料夾中。 ASP.NET Core 執行階段會使用命名慣例來建立這些元件之間的關聯性。 針對大型應用程式,將應用程式分割成個別高階區域可能較有利。 舉例來說,一個電子商務應用程式可具有多個業務單位,例如結帳、計費和搜尋。 這其中的每個單位都有自己的區域,以包含檢視、控制器、Razor 頁面和模型。

處於下列情況時,請考慮在專案中使用區域:

  • 應用程式是由可以邏輯方式區隔的多個高階功能性元件所組成的。
  • 您想要分割應用程式,讓每個功能區域都可獨立運作。

檢視或下載範例程式碼 (如何下載)。 下載範例提供基本的應用程式來測試區域。

如果您使用 Razor Pages,請參閱本文件中具有 Razor 頁面的區域

適用於控制器與檢視的區域

使用區域、控制器及檢視的典型 ASP.NET Core Web 應用程式包含下列項目:

  • 一個區域資料夾結構

  • 控制器具有 [Area] 屬性,用於建立控制器與區域的關聯:

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "MyArea",
            pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
    

區域資料夾結構

假設應用程式具有兩個邏輯群組:「產品」和「服務」。 使用區域,資料夾結構應該如下:

  • Project name
    • 區域
      • 產品
        • 控制器
          • HomeController.cs
          • ManageController.cs
        • 檢視
          • Home
            • Index.cshtml
          • 管理
            • Index.cshtml
            • About.cshtml
      • 服務
        • 控制器
          • HomeController.cs
        • 檢視
          • Home
            • Index.cshtml

儘管上述配置通常會在使用區域時使用,但是只需有檢視檔案,就能使用此資料夾結構。 檢視探索會依下列順序搜尋相符的區域檢視檔案:

/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

使控制器與區域產生關聯

區域控制器會透過 [Area] 屬性來指定:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Docs.Samples;

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

        public IActionResult About()
        {
            ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
            return View();
        }
    }
}

新增區域路由

區域路由通常會使用慣例路由,而非屬性路由。 慣例路由與順序息息相關。 一般而言,具有區域的路由應該放在路由表前面,因為這些路由比沒有區域的路由更明確。

如果 URL 空間在所有區域中都是統一的,則可使用 {area:...} 作為路由範本中的語彙基元:

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "MyArea",
            pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

在上述程式碼中,exists 會套用路由必須與區域相符的條件約束。 使用 {area:...} 搭配 MapControllerRoute

  • 若要將路由新增至區域,這是最簡單的機制。
  • 使所有控制器符合 [Area("Area name")] 屬性。

下列程式碼會使用 MapAreaControllerRoute 來建立兩個具名的區域路由:

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

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapAreaControllerRoute(
            name: "MyAreaProducts",
            areaName: "Products",
            pattern: "Products/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapAreaControllerRoute(
            name: "MyAreaServices",
            areaName: "Services",
            pattern: "Services/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

如需詳細資訊,請參閱區域路由

以下來自範例下載的程式碼會顯示使用指定的區域來產生連結:

<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>

範例下載包括部分檢視,其中包含:

  • 上述連結。
  • 與上述類似的連結,但未指定 area

部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域與控制器中的頁面進行參考時才有效。

未指定區域或控制站時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在範例應用程式的許多情況下,使用環境值會產生不正確的連結,且標記不會指定區域。

如需詳細資訊,請參閱路由至控制器動作

使用 _ViewStart.cshtml 檔案共用區域的配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 儲存在應用程式根資料夾。 如需詳細資訊,請參考 ASP.NET Core 中的配置

應用程式根資料夾

應用程式根資料夾是使用 ASP.NET Core 範本所建立 Web 應用程式中包含 Startup.cs 的資料夾。

_ViewImports.cshtml

/Views/_ViewImports.cshtml (針對 MVC) 和 /Pages/_ViewImports.cshtml (針對 Razor Pages) 不會匯入至區域中的檢視。 使用下列其中一種方法為所有檢視提供檢視匯入:

  • _ViewImports.cshtml 新增至應用程式根資料夾。 應用程式根資料夾中的 _ViewImports.cshtml 將會套用至應用程式中的所有檢視。
  • _ViewImports.cshtml 檔案複製到區域下方的適當檢視資料夾。

檔案 _ViewImports.cshtml 通常包含標記協助程式匯入、@using@inject 陳述式。 如需詳細資訊,請參閱匯入共用指示詞

變更檢視儲存所在的預設區域資料夾

下列程式碼會將預設的區域資料夾從 "Areas" 變更為 "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.AddControllersWithViews();
}

具有 Razor Pages 的區域

具有 Razor Pages 的區域需要在應用程式的根目錄中建立 Areas/<area name>/Pages 資料夾。 下列資料夾結構搭配範例應用程式一起使用:

  • Project name
    • 區域
      • 產品
        • 頁面
          • _ViewImports
          • 關於
          • 索引
      • 服務
        • 頁面
          • 管理
            • 關於
            • 索引

以下來自範例下載的程式碼會顯示使用指定的區域 (例如 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>

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域中的頁面進行參考時才有效。

未指定區域時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。 例如,試想從下列程式碼產生的連結:

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

針對上述程式碼:

  • 僅當最後一個要求是針對 Services 區域中的頁面時,從 <a asp-page="/Manage/About"> 產生的連結才是正確的。 例如 /Services/Manage//Services/Manage/Index/Services/Manage/About
  • 僅當最後一個要求是針對 /Home 中的頁面時,從 <a asp-page="/About"> 產生的連結才是正確的。
  • 程式碼來自下載範例

使用 _ViewImports 檔案匯入命名空間和標記協助程式

可以將 _ViewImports.cshtml 檔案新增至每個區域 Pages 資料夾,以將命名空間和標記協助程式匯入到資料夾中的每個 Razor 頁面。

請考慮範例程式碼的 Services 區域,該區域不包含 _ViewImports.cshtml 檔案。 下列標記示範 /Services/Manage/AboutRazor Pages:

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

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

在上述標記中:

  • 必須使用完整的類別名稱來指定此模型 (@model RPareas.Areas.Services.Pages.Manage.AboutModel)。
  • 標記協助程式@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 啟用

在範例下載中,Products 區域包含下列 _ViewImports.cshtml 檔案:

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

下列標記示範 /Products/AboutRazor 頁面:

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

在上述檔案中,命名空間和 @addTagHelper 指示詞會由 Areas/Products/Pages/_ViewImports.cshtml 檔案匯入到檔案。

如需詳細資訊,請參閱管理標籤協助程式範圍匯入共用指示詞

Razor Pages 區域的共用版面配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。

發行區域

當 *.csproj 檔案中包含 <Project Sdk="Microsoft.NET.Sdk.Web"> 時,會將所有 *.cshtml 檔案及 wwwroot 目錄內的檔案發佈至輸出。

使用 Visual Studio 新增 MVC 區域

在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [新增] > [新增 Scaffolded 專案],然後選取 [MVC 區域]

區域是 ASP.NET 功能,可用來將相關功能組織為群組,以作為個別的命名空間 (適用於路由) 和資料夾結構 (適用於檢視)。 使用區域可基於路由的目的,藉由將另一個路由參數 (area) 新增至 controlleraction 或是 Razor 頁面 page 來建立階層。

區域可提供一種方式來將 ASP.NET Core Web 應用程式分割成較小的功能群組,每個都有一組自己的 Razor 頁面、控制器、檢視和模型。 一個區域基本上是應用程式內的一個結構。 在 ASP.NET Core Web 專案中,Pages、模型、控制器和檢視等邏輯元件都會保留在不同的資料夾中。 ASP.NET Core 執行階段會使用命名慣例來建立這些元件之間的關聯性。 針對大型應用程式,將應用程式分割成個別高階區域可能較有利。 舉例來說,一個電子商務應用程式可具有多個業務單位,例如結帳、計費和搜尋。 這其中的每個單位都有自己的區域,以包含檢視、控制器、Razor 頁面和模型。

處於下列情況時,請考慮在專案中使用區域:

  • 應用程式是由可以邏輯方式區隔的多個高階功能性元件所組成的。
  • 您想要分割應用程式,讓每個功能區域都可獨立運作。

檢視或下載範例程式碼 (如何下載)。 下載範例提供基本的應用程式來測試區域。

如果您使用 Razor Pages,請參閱本文件中具有 Razor 頁面的區域

適用於控制器與檢視的區域

使用區域、控制器及檢視的典型 ASP.NET Core Web 應用程式包含下列項目:

  • 一個區域資料夾結構

  • 控制器具有 [Area] 屬性,用於建立控制器與區域的關聯:

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

    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?}");
    });
    

區域資料夾結構

假設應用程式具有兩個邏輯群組:「產品」和「服務」。 使用區域,資料夾結構應該如下:

  • Project name
    • 區域
      • 產品
        • 控制器
          • HomeController.cs
          • ManageController.cs
        • 檢視
          • Home
            • Index.cshtml
          • 管理
            • Index.cshtml
            • About.cshtml
      • 服務
        • 控制器
          • HomeController.cs
        • 檢視
          • Home
            • Index.cshtml

儘管上述配置通常會在使用區域時使用,但是只需有檢視檔案,就能使用此資料夾結構。 檢視探索會依下列順序搜尋相符的區域檢視檔案:

/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

使控制器與區域產生關聯

區域控制器會透過 [Area] 屬性來指定:

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();
        }
    }
}

新增區域路由

區域路由通常會使用慣例路由,而非屬性路由。 慣例路由與順序息息相關。 一般而言,具有區域的路由應該放在路由表前面,因為這些路由比沒有區域的路由更明確。

如果 URL 空間在所有區域中都是統一的,則可使用 {area:...} 作為路由範本中的語彙基元:

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 會套用路由必須與區域相符的條件約束。 若要將路由新增至區域,使用 {area:...} 是最簡單的機制。

下列程式碼會使用 MapAreaRoute 來建立兩個具名的區域路由:

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 問題 \(英文\)。

如需詳細資訊,請參閱區域路由

以下來自範例下載的程式碼會顯示使用指定的區域來產生連結:

<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>

使用上述程式碼產生的連結,在應用程式中的任何位置都是有效的。

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域與控制器中的頁面進行參考時才有效。

未指定區域或控制站時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。

如需詳細資訊,請參閱路由至控制器動作

使用 _ViewStart.cshtml 檔案共用區域的配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。

_ViewImports.cshtml

在其標準位置中,/Views/_ViewImports.cshtml 不會套用至區域。 若要在您的區域中使用一般標記協助程式@using@inject,請確定適當的 _ViewImports.cshtml 檔案套用至您的區域檢視。 如果您希望在所有檢視中都有相同的行為,請將 /Views/_ViewImports.cshtml 移至應用程式根目錄。

變更檢視儲存所在的預設區域資料夾

下列程式碼會將預設的區域資料夾從 "Areas" 變更為 "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 的區域

具有 Razor Pages 的區域需要在應用程式的根目錄中建立 Areas/<area name>/Pages 資料夾。 下列資料夾結構搭配範例應用程式一起使用:

  • Project name
    • 區域
      • 產品
        • 頁面
          • _ViewImports
          • 關於
          • 索引
      • 服務
        • 頁面
          • 管理
            • 關於
            • 索引

以下來自範例下載的程式碼會顯示使用指定的區域 (例如 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>

使用上述程式碼產生的連結,在應用程式中的任何位置都是有效的。

範例下載包括部分檢視,其中可在未指定區域的情況下包含上述連結和相同連結。 部分檢視會在配置檔案中進行參考,因此,應用程式中的每個頁面都會顯示產生的連結。 在未指定區域的情況下產生的連結,只有在從相同區域中的頁面進行參考時才有效。

未指定區域時,路由即會取決於「環境」值。 目前要求的目前路由值被視為用於連結產生的環境值。 在許多適用於範例應用程式的案例中,使用環境值會產生不正確的連結。 例如,試想從下列程式碼產生的連結:

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

針對上述程式碼:

  • 僅當最後一個要求是針對 Services 區域中的頁面時,從 <a asp-page="/Manage/About"> 產生的連結才是正確的。 例如 /Services/Manage//Services/Manage/Index/Services/Manage/About
  • 僅當最後一個要求是針對 /Home 中的頁面時,從 <a asp-page="/About"> 產生的連結才是正確的。
  • 程式碼來自下載範例

使用 _ViewImports 檔案匯入命名空間和標記協助程式

可以將 _ViewImports.cshtml 檔案新增至每個區域 Pages 資料夾,以將命名空間和標記協助程式匯入到資料夾中的每個 Razor 頁面。

請考慮範例程式碼的 Services 區域,該區域不包含 _ViewImports.cshtml 檔案。 下列標記示範 /Services/Manage/AboutRazor Pages:

@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>

在上述標記中:

  • 必須使用完整的網域名稱來指定此模型 (@model RPareas.Areas.Services.Pages.Manage.AboutModel)。
  • 標記協助程式@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 啟用

在範例下載中,Products 區域包含下列 _ViewImports.cshtml 檔案:

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

下列標記示範 /Products/AboutRazor 頁面:

@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 檔案匯入到檔案。

如需詳細資訊,請參閱管理標籤協助程式範圍匯入共用指示詞

Razor Pages 區域的共用版面配置

若要針對整個應用程式共用通用的配置,請將 _ViewStart.cshtml 移至應用程式根資料夾。

發行區域

當 *.csproj 檔案中包含 <Project Sdk="Microsoft.NET.Sdk.Web"> 時,會將所有 *.cshtml 檔案及 wwwroot 目錄內的檔案發佈至輸出。