﻿# 如何使用 .NET CLI 快速產生 ASP.NET Core 的 MVC Area 區域

跨平台的 Visual Studio Code 工具日益強大，現在用來開發 ASP.NET Core 3.1 網站完全沒有問題。本篇文章我將分享如何在 Visual Studio Code 裡面搭配一些好用工具，快速建立 MVC Area 必要的目錄與檔案，以及所有開發時需要知道的注意事項。

### 建立範例 ASP.NET Core MVC 專案

```bash
dotnet new mvc -n mvc1 && cd mvc1

dotnet tool update -g dotnet-aspnet-codegenerator
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design

dotnet tool update -g dotnet-ignore
dotnet ignore get -n visualstudio

git init && git add . && git commit -m "Initial commit"

code .
```

### 設定 ASP.NET Core MVC 的 Area 目錄結構

如果你要建立一個名為 `Admin` 的區域 (Area)，最簡單的方式，就是透過 [dotnet-aspnet-codegenerator](https://www.nuget.org/packages/dotnet-aspnet-codegenerator) 全域工具來產生相關目錄：

```bash
dotnet aspnet-codegenerator area Admin
```

```log
Building project ...
Finding the generator 'area'...
Running the generator 'area'...
RunTime 00:00:07.47
```

執行完畢後，會看到以下結果：

![建立 ASP.NET Core MVC 的 Area 目錄結構](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/1116320f4cedcaf35085-92994726-5a91e400-f52f-11ea-88ce-8bb5b3b0a44b.png)

> 注意：上述工具可以幫你建立一組**沒有檔案**的空資料夾，資料夾裡面如果沒有檔案的話，目錄是無法加入 Git 版控的！

### 設定 Area 路由

這裡會有個 `ScaffoldingReadMe.txt` 檔案，有說明該如何進一步設定 Area 的路由，不過目前 [dotnet-aspnet-codegenerator](https://www.nuget.org/packages/dotnet-aspnet-codegenerator) 最新版 `v3.1.4` 所建立的 `ScaffoldingReadMe.txt` 檔案內容有問題，他使用了 .NET Core 2.1 的 `app.UseMvc()` Middleware，但從 .NET Core 3 開始就已經改到 `app.UseEndpoints()` 了，因此千萬不能參考這個建議來設定。

> 這個問題我已經建立 [dotnet aspnet-codegenerator area's ScaffoldingReadMe.txt #1414](https://github.com/dotnet/Scaffolding/issues/1414) 追蹤，預計未來會修正。

你應該要從 `Startup.cs` 的 `Configure()` 最後面的 `app.UseEndpoints()`，加入一個新的 `areas` 路由定義，如下範例：

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

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

上述這種屬於「萬用」的 Area 路由，如果你想針對個別的 Area 設定不同的路由樣式 (`pattern`)，可以利用 `MapAreaControllerRoute` 進行設定，但請務必記得加上 `areaName` 屬性。請參考以下範例：

```csharp
app.UseEndpoints(endpoints =>
{
    endpoints.MapAreaControllerRoute(
        name: "AreaAdmin",
        areaName: "Admin",
        pattern: "Admin128395048473/{controller=Home}/{action=Index}/{id?}");

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

### 建立控制器 (Controller)、動作方法 (Action)、檢視頁面 (View)

我們建立一個 `HomeController` 在 `Admin` 區域內，並新增一個 `Index` 動作方法：

-   `Areas/Admin/Controllers/HomeController.cs`
    
    ```csharp
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    
    namespace Admin.Controllers
    {
        [Area("Admin")]
        public class HomeController : Controller
        {
            public HomeController()
            {
            }
    
            public IActionResult Index()
            {
                return View();
            }
        }
    }
    ```
    
    這裡最重要的地方，就是控制器類別一定要加上 `[Area("Admin")]` 屬性 (Attribute)，否則執行會有問題。
    
-   建立 `Index` 動作方法相對應的 View 檔案 (`.cshtml`)
    
    這個步驟可以透過 VSCode 幫我們完成，你只要在 `Index()` 動作方法上，按下滑鼠右鍵，選擇 **Add View** 即可自動建立 View 檔案，然後點擊 **Go to View** 即可進入 View 頁面！
    
    ![在  動作方法上，按下滑鼠右鍵，選擇 Add View 即可自動建立 View 檔案！](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/b78b0014ebc9a812854f-92995218-1d7c2080-f534-11ea-9806-d1bd322de381.png)
    
    > 請安裝 VSCode 的 [.NET Core Extension Pack](https://marketplace.visualstudio.com/items?itemName=doggy8088.netcore-extension-pack) 擴充套件，確保你可以正確使用文章提到的功能。
    

### 範例程式

完整的專案範例在此：[https://github.com/doggy8088/aspnetcore31-mvcarea-demo](https://github.com/doggy8088/aspnetcore31-mvcarea-demo)

原始碼可以參考這裡：[https://github.com/doggy8088/aspnetcore31-mvcarea-demo/commit/ed2abb0c20e76e5f5a8f0693dfd28826f7ae5869](https://github.com/doggy8088/aspnetcore31-mvcarea-demo/commit/ed2abb0c20e76e5f5a8f0693dfd28826f7ae5869)

### 相關連結

-   [Areas in ASP.NET Core | Microsoft Docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/areas?view=aspnetcore-3.1)
-   [Routing to controller actions in ASP.NET Core | Microsoft Docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1#areas)
