ASP.NET Core의 영역

작성자: Dhananjay KumarRick Anderson

영역은 관련 기능을 별개의

  • 네임스페이스(라우팅용) 및
  • 폴더 구조(보기 및 Razor Pages용)의 그룹으로 구성하는 데 사용되는 ASP.NET 기능입니다.

영역을 사용하면 controlleraction 또는 Razor Page page에 또 다른 경로 매개 변수인 area를 추가하여 라우팅을 위한 계층 구조를 만들 수 있습니다.

영역은 ASP.NET Core 웹앱을 자체적인 Razor Pages, 컨트롤러, 보기 및 모델 세트를 갖는 각각의 작은 기능 그룹으로 분할하는 방법을 제공합니다. 영역은 사실상 앱 내부의 구조입니다. ASP.NET Core 웹 프로젝트에서 페이지, 모델, 컨트롤러 및 보기와 같은 논리적 구성 요소는 서로 다른 폴더에 보관됩니다. ASP.NET Core 런타임은 명명 규칙을 사용하여 이러한 구성 요소 간의 관계를 만듭니다. 대형 앱의 경우 앱을 높은 수준의 개별적인 영역으로 나누는 것이 유리할 수 있습니다. 결제, 청구 및 검색과 같은 여러 비즈니스 단위가 있는 전자상거래 앱을 예로 들 수 있습니다. 이러한 각 단위는 보기, 컨트롤러, Razor Pages 및 모델을 포함한 고유의 영역을 갖습니다.

다음과 같은 경우 프로젝트에서 영역을 사용하는 것이 좋습니다.

  • 앱은 논리적으로 분리할 수 있는 여러 개의 고급 기능 구성 요소로 이루어져 있습니다.
  • 각 기능 영역을 독립적으로 작업할 수 있도록 앱을 나누고자 합니다.

Razor Pages를 사용하는 경우 이 문서의 Razor Pages를 사용한 영역을 참조하세요.

보기가 있는 컨트롤러 영역

영역, 컨트롤러 및 보기를 사용하는 일반적인 ASP.NET Core 웹앱은 다음을 포함합니다.

  • 영역 폴더 구조.

  • 컨트롤러를 영역과 연결하는 [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();
    

영역 폴더 구조

ProductsServices의 두 논리 그룹이 존재하는 앱을 고려해보세요. 영역을 사용할 경우 폴더 구조는 다음과 유사할 것입니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 컨트롤러
          • 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는 경로가 영역과 일치해야 한다는 제약 조건을 적용합니다. MapControllerRoute와 함께 {area:...} 사용:

  • 영역에 라우팅을 추가하는 가장 간단한 메커니즘입니다.
  • [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 템플릿으로 만든 웹앱의 Program.cs 파일을 포함하는 폴더입니다.

_ViewImports.cshtml

MVC의 경우 /Views/_ViewImports.cshtml, Razor Pages의 경우 /Pages/_ViewImports.cshtml은 영역의 보기로 가져오지 않습니다. 모든 보기에 보기 가져오기를 제공하려면 다음 방법 중 하나를 사용합니다.

  • _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 폴더가 있어야 합니다. 예제 앱에서는 다음 폴더 구조가 사용됩니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 페이지
          • _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>

이전 코드에서:

  • <a asp-page="/Manage/About">에서 생성된 링크는 Services 영역의 페이지를 마지막으로 요청한 경우에만 유효합니다. 예를 들어 /Services/Manage/, /Services/Manage/Index 또는 /Services/Manage/About입니다.
  • <a asp-page="/About">에서 생성된 링크는 /Home의 페이지를 마지막으로 요청한 경우에만 유효합니다.
  • 이 코드는 예제 다운로드에서 가져온 것입니다.

_ViewImports 파일을 사용하여 네임스페이스 및 태그 도우미 가져오기

_ViewImports.cshtml 파일을 각 영역의 Pages 폴더에 추가하여 네임스페이스 및 태그 도우미를 폴더의 각 Razor Page로 가져올 수 있습니다.

_ViewImports.cshtml 파일이 없는 샘플 코드의 Services 영역을 살펴보겠습니다. 다음 태그는 /Services/Manage/AboutRazor Page를 보여 줍니다.

@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를 보여 줍니다.

@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 영역 추가

솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가 > 새 스캐폴드 항목을 선택한 다음, MVC 영역을 선택합니다.

추가 리소스

영역은 관련 기능을 별개의

  • 네임스페이스(라우팅용) 및
  • 폴더 구조(보기 및 Razor Pages용)의 그룹으로 구성하는 데 사용되는 ASP.NET 기능입니다.

영역을 사용하면 controlleraction 또는 Razor Page page에 또 다른 경로 매개 변수인 area를 추가하여 라우팅을 위한 계층 구조를 만들 수 있습니다.

영역은 ASP.NET Core 웹앱을 자체적인 Razor Pages, 컨트롤러, 보기 및 모델 세트를 갖는 각각의 작은 기능 그룹으로 분할하는 방법을 제공합니다. 영역은 사실상 앱 내부의 구조입니다. ASP.NET Core 웹 프로젝트에서 페이지, 모델, 컨트롤러 및 보기와 같은 논리적 구성 요소는 서로 다른 폴더에 보관됩니다. ASP.NET Core 런타임은 명명 규칙을 사용하여 이러한 구성 요소 간의 관계를 만듭니다. 대형 앱의 경우 앱을 높은 수준의 개별적인 영역으로 나누는 것이 유리할 수 있습니다. 결제, 청구 및 검색과 같은 여러 비즈니스 단위가 있는 전자상거래 앱을 예로 들 수 있습니다. 이러한 각 단위는 보기, 컨트롤러, Razor Pages 및 모델을 포함한 고유의 영역을 갖습니다.

다음과 같은 경우 프로젝트에서 영역을 사용하는 것이 좋습니다.

  • 앱은 논리적으로 분리할 수 있는 여러 개의 고급 기능 구성 요소로 이루어져 있습니다.
  • 각 기능 영역을 독립적으로 작업할 수 있도록 앱을 나누고자 합니다.

예제 코드 살펴보기 및 다운로드 (다운로드 방법). 다운로드 예제는 영역을 테스트하기 위한 기초적인 앱을 제공합니다. 다운로드 샘플은 테스트 영역에 대한 기본 앱을 제공합니다.

Razor Pages를 사용하는 경우 이 문서의 Razor Pages를 사용한 영역을 참조하세요.

보기가 있는 컨트롤러 영역

영역, 컨트롤러 및 보기를 사용하는 일반적인 ASP.NET Core 웹앱은 다음을 포함합니다.

  • 영역 폴더 구조.

  • 컨트롤러를 영역과 연결하는 [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?}");
    });
    

영역 폴더 구조

ProductsServices의 두 논리 그룹이 존재하는 앱을 고려해보세요. 영역을 사용할 경우 폴더 구조는 다음과 유사할 것입니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 컨트롤러
          • 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는 경로가 영역과 일치해야 한다는 제약 조건을 적용합니다. MapControllerRoute와 함께 {area:...} 사용:

  • 영역에 라우팅을 추가하는 가장 간단한 메커니즘입니다.
  • [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 템플릿으로 만든 웹앱에 포함된 Startup.cs 폴더입니다.

_ViewImports.cshtml

/Views/_ViewImports.cshtmlMVC 및 /Pages/_ViewImports.cshtml Pages의 경우 Razor 영역의 보기로 가져오지 않습니다. 모든 보기에 보기 가져오기를 제공하려면 다음 방법 중 하나를 사용합니다.

  • 애플리케이션 루트 폴더에 추가 _ViewImports.cshtml 합니다. 애플리케이션 루트 폴더의 A _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 폴더가 있어야 합니다. 예제 앱에서는 다음 폴더 구조가 사용됩니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 페이지
          • _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>

이전 코드에서:

  • <a asp-page="/Manage/About">에서 생성된 링크는 Services 영역의 페이지를 마지막으로 요청한 경우에만 유효합니다. 예를 들어 /Services/Manage/, /Services/Manage/Index 또는 /Services/Manage/About입니다.
  • <a asp-page="/About">에서 생성된 링크는 /Home의 페이지를 마지막으로 요청한 경우에만 유효합니다.
  • 이 코드는 예제 다운로드에서 가져온 것입니다.

_ViewImports 파일을 사용하여 네임스페이스 및 태그 도우미 가져오기

_ViewImports.cshtml 각 영역 Pages 폴더에 파일을 추가하여 폴더의 각 Razor 페이지에 네임스페이스 및 태그 도우미를 가져올 수 있습니다.

파일이 없는 _ViewImports.cshtml 샘플 코드의 서비스 영역을 고려합니다. 다음 태그는 /Services/Manage/AboutRazor Page를 보여 줍니다.

@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를 보여 줍니다.

@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 영역 추가

솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가 > 새 스캐폴드 항목을 선택한 다음, MVC 영역을 선택합니다.

영역은 관련 기능을 별개의 네임스페이스(라우팅용) 및 폴더 구조(보기용)의 그룹으로 구조화하는 데 사용되는 ASP.NET 기능입니다. 영역을 사용하면 controlleraction 또는 Razor Page page에 또 다른 경로 매개 변수인 area를 추가하여 라우팅을 위한 계층 구조를 만들 수 있습니다.

영역은 ASP.NET Core 웹앱을 자체적인 Razor Pages, 컨트롤러, 보기 및 모델 세트를 갖는 각각의 작은 기능 그룹으로 분할하는 방법을 제공합니다. 영역은 사실상 앱 내부의 구조입니다. ASP.NET Core 웹 프로젝트에서 페이지, 모델, 컨트롤러 및 보기와 같은 논리적 구성 요소는 서로 다른 폴더에 보관됩니다. ASP.NET Core 런타임은 명명 규칙을 사용하여 이러한 구성 요소 간의 관계를 만듭니다. 대형 앱의 경우 앱을 높은 수준의 개별적인 영역으로 나누는 것이 유리할 수 있습니다. 결제, 청구 및 검색과 같은 여러 비즈니스 단위가 있는 전자상거래 앱을 예로 들 수 있습니다. 이러한 각 단위는 보기, 컨트롤러, Razor Pages 및 모델을 포함한 고유의 영역을 갖습니다.

다음과 같은 경우 프로젝트에서 영역을 사용하는 것이 좋습니다.

  • 앱은 논리적으로 분리할 수 있는 여러 개의 고급 기능 구성 요소로 이루어져 있습니다.
  • 각 기능 영역을 독립적으로 작업할 수 있도록 앱을 나누고자 합니다.

예제 코드 살펴보기 및 다운로드 (다운로드 방법). 다운로드 예제는 영역을 테스트하기 위한 기초적인 앱을 제공합니다. 다운로드 샘플은 테스트 영역에 대한 기본 앱을 제공합니다.

Razor Pages를 사용하는 경우 이 문서의 Razor Pages를 사용한 영역을 참조하세요.

보기가 있는 컨트롤러 영역

영역, 컨트롤러 및 보기를 사용하는 일반적인 ASP.NET Core 웹앱은 다음을 포함합니다.

  • 영역 폴더 구조.

  • 컨트롤러를 영역과 연결하는 [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?}");
    });
    

영역 폴더 구조

ProductsServices의 두 논리 그룹이 존재하는 앱을 고려해보세요. 영역을 사용할 경우 폴더 구조는 다음과 유사할 것입니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 컨트롤러
          • 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 폴더가 있어야 합니다. 예제 앱에서는 다음 폴더 구조가 사용됩니다.

  • 프로젝트 이름
    • 영역
      • 제품
        • 페이지
          • _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>

이전 코드에서:

  • <a asp-page="/Manage/About">에서 생성된 링크는 Services 영역의 페이지를 마지막으로 요청한 경우에만 유효합니다. 예를 들어 /Services/Manage/, /Services/Manage/Index 또는 /Services/Manage/About입니다.
  • <a asp-page="/About">에서 생성된 링크는 /Home의 페이지를 마지막으로 요청한 경우에만 유효합니다.
  • 이 코드는 예제 다운로드에서 가져온 것입니다.

_ViewImports 파일을 사용하여 네임스페이스 및 태그 도우미 가져오기

_ViewImports.cshtml 각 영역 Pages 폴더에 파일을 추가하여 폴더의 각 Razor 페이지에 네임스페이스 및 태그 도우미를 가져올 수 있습니다.

파일이 없는 _ViewImports.cshtml 샘플 코드의 서비스 영역을 고려합니다. 다음 태그는 /Services/Manage/AboutRazor 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>

이전 태그에서:

  • 모델(@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를 보여 줍니다.

@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 디렉터리 내의 모든 파일이 출력에 게시됩니다.