Obszary na platformie ASP.NET Core

Przez Dhananjay Kumar i Rick Anderson

Obszary to funkcja ASP.NET używana do organizowania powiązanych funkcji w grupie jako oddzielnej:

  • Przestrzeń nazw na potrzeby routingu.
  • Struktura folderów dla widoków i Razor stron.

Użycie obszarów tworzy hierarchię na potrzeby routingu przez dodanie innego parametru trasy, area, do controller i action lub Razor strony page.

Obszary umożliwiają partycjonowanie aplikacji internetowej ASP.NET Core w mniejsze grupy funkcjonalne, z których każdy ma własny zestaw Razor stron, kontrolerów, widoków i modeli. Obszar jest skutecznie strukturą wewnątrz aplikacji. W projekcie internetowym ASP.NET Core składniki logiczne, takie jak Strony, Model, Kontroler i Widok, są przechowywane w różnych folderach. Środowisko uruchomieniowe ASP.NET Core używa konwencji nazewnictwa w celu utworzenia relacji między tymi składnikami. W przypadku dużej aplikacji korzystne może być podzielenie aplikacji na oddzielne obszary funkcjonalności wysokiego poziomu. Na przykład aplikacja do handlu elektronicznego z wieloma jednostkami biznesowymi, takimi jak wyewidencjonowanie, rozliczenia i wyszukiwanie. Każda z tych jednostek ma własny obszar zawierający widoki, kontrolery, Razor strony i modele.

Rozważ użycie obszarów w projekcie, gdy:

  • Aplikacja składa się z wielu składników funkcjonalnych wysokiego poziomu, które mogą być logicznie oddzielone.
  • Chcesz podzielić aplikację na partycje, aby można było niezależnie pracować nad poszczególnymi obszarami funkcjonalnymi.

Jeśli używasz Razor stron, zobacz Obszary ze stronami Razor w tym dokumencie.

Obszary dla kontrolerów z widokami

Typowa aplikacja internetowa ASP.NET Core korzystająca z obszarów, kontrolerów i widoków zawiera następujące elementy:

  • Struktura folderów Obszaru.

  • Kontrolery z atrybutem [Area] , aby skojarzyć kontroler z obszarem:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • Trasa obszaru dodana do Program.cselementu :

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

Struktura folderów warstwowych

Rozważmy aplikację z dwiema grupami logicznymi, produktami i usługami. Korzystając z obszarów, struktura folderów będzie podobna do następującej:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Kontrolery
          • HomeController.cs
          • ManageController.cs
        • Widoki
          • Home
            • Index.cshtml
          • Zarządzanie
            • Index.cshtml
            • About.cshtml
      • Usług
        • Kontrolery
          • HomeController.cs
        • Widoki
          • Home
            • Index.cshtml

Chociaż poprzedni układ jest typowy w przypadku korzystania z obszarów, do korzystania z tej struktury folderów wymagane są tylko pliki widoku. Wyświetl wyszukiwanie odnajdywania dla pasującego pliku widoku obszaru w następującej kolejności:

/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

Kojarzenie kontrolera z obszarem

Kontrolery obszaru są oznaczone atrybutem [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();
    }
}

Dodawanie trasy obszaru

Trasy obszaru zwykle używają routingu konwencjonalnego, a nie routingu atrybutów. Routing konwencjonalny jest zależny od kolejności. Ogólnie rzecz biorąc, trasy z obszarami powinny być umieszczane wcześniej w tabeli tras, ponieważ są one bardziej szczegółowe niż trasy bez obszaru.

{area:...} Można użyć jako tokenu w szablonach tras, jeśli przestrzeń adresu URL jest jednolita we wszystkich obszarach:

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

W poprzednim kodzie stosuje ograniczenie, exists które trasa musi odpowiadać obszarowi. Za pomocą polecenia {area:...}MapControllerRoute:

  • Jest najmniej skomplikowanym mechanizmem dodawania routingu do obszarów.
  • Pasuje do wszystkich kontrolerów z atrybutem [Area("Area name")] .

Poniższy kod używa MapAreaControllerRoute metody do utworzenia dwóch nazwanych tras obszaru:

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

Aby uzyskać więcej informacji, zobacz Routing warstwowy.

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem:

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

Przykładowy plik do pobrania zawiera widok częściowy zawierający:

  • Powyższe linki.
  • Łącza podobne do powyższego z wyjątkiem area nie są określone.

Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze i kontrolerze.

Jeśli obszar lub kontroler nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki z znacznikiem, który nie określa obszaru.

Aby uzyskać więcej informacji, zobacz Routing do akcji kontrolera.

Układ udostępniony obszarów przy użyciu pliku _ViewStart.cshtml

Aby udostępnić wspólny układ całej aplikacji, zachowaj plik _ViewStart.cshtml w folderze głównym aplikacji. Aby uzyskać więcej informacji, zobacz Layout in ASP.NET Core (Układ w programie ASP.NET Core)

Folder główny aplikacji

Folder główny aplikacji to folder zawierający Program.cs plik w aplikacji internetowej utworzonej przy użyciu szablonów ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, dla MVC i /Pages/_ViewImports.cshtml dla Razor stron, nie jest importowany do widoków w obszarach. Użyj jednej z następujących metod, aby zapewnić importowanie widoku do wszystkich widoków:

  • Dodaj plik _ViewImports.cshtml do folderu głównego aplikacji. Plik _ViewImports.cshtml w folderze głównym aplikacji będzie stosowany do wszystkich widoków w aplikacji.
  • Skopiuj plik _ViewImports.cshtml do odpowiedniego folderu widoku w obszarze obszarów. Na przykład aplikacja Pages utworzona Razor przy użyciu poszczególnych kont użytkowników ma plik _ViewImports.cshtml w następujących folderach:
    • /Areas//IdentityPages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

Plik _ViewImports.cshtml zwykle zawiera instrukcje i @inject importy @usingpomocników tagów. Aby uzyskać więcej informacji, zobacz Importowanie dyrektyw udostępnionych.

Zmień domyślny folder obszaru, w którym są przechowywane widoki

Poniższy kod zmienia domyślny folder obszaru z "Areas" na "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();

Obszary ze stronami Razor

Obszary ze stronami Razor wymagają Areas/<area name>/Pages folderu w katalogu głównym aplikacji. Następująca struktura folderów jest używana z przykładową aplikacją:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Stron
          • _ViewImports
          • Informacje
          • Indeks
      • Usług
        • Stron
          • Zarządzanie
            • Informacje
            • Indeks

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem (na przykład 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>

Przykładowy plik do pobrania zawiera widok częściowy zawierający powyższe linki i te same linki bez określania obszaru. Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze.

Jeśli obszar nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki. Rozważmy na przykład linki wygenerowane na podstawie następującego kodu:

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

W poprzednim kodzie:

  • Link wygenerowany na <a asp-page="/Manage/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w Services obszarze. Na przykład, /Services/Manage/, /Services/Manage/Index lub /Services/Manage/About.
  • Link wygenerowany na <a asp-page="/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w pliku /Home.
  • Kod pochodzi z przykładowego pobierania.

Importowanie przestrzeni nazw i pomocników tagów przy użyciu pliku _ViewImports

Do każdego folderu pages można dodać plik _ViewImports.cshtml, aby zaimportować przestrzeń nazw i pomocników tagów do każdej Razor strony w folderze.

Rozważ obszar Usługi przykładowego kodu, który nie zawiera pliku _ViewImports.cshtml. Poniższy znacznik pokazuje stronę /Services/Manage/AboutRazor :

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

W poprzednim znaczniku:

  • W pełni kwalifikowana nazwa klasy musi być używana do określenia modelu (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Pomocnicy tagów są włączani przez @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

W przykładowym pobraniu obszar Products zawiera następujący plik _ViewImports.cshtml :

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

Na poniższej adiustacji jest wyświetlana strona /Products/AboutRazor :

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

W poprzednim pliku przestrzeń nazw i @addTagHelper dyrektywa są importowane do pliku przez plik Areas/Products/Pages/_ViewImports.cshtml .

Aby uzyskać więcej informacji, zobacz Zarządzanie zakresem pomocnika tagów i Importowanie dyrektyw udostępnionych.

Układ udostępniony dla Razor obszarów stron

Aby udostępnić wspólny układ całej aplikacji, przenieś plik _ViewStart.cshtml do folderu głównego aplikacji.

Obszary publikowania

Wszystkie pliki *.cshtml i pliki w katalogu wwwroot są publikowane do danych wyjściowych, gdy <Project Sdk="Microsoft.NET.Sdk.Web"> znajdują się w pliku *.csproj.

Dodawanie obszaru MVC za pomocą programu Visual Studio

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie DODAJ > nowy element szkieletowy, a następnie wybierz pozycję Obszar MVC.

Dodatkowe zasoby

Obszary to funkcja ASP.NET używana do organizowania powiązanych funkcji w grupie jako oddzielnej:

  • Przestrzeń nazw na potrzeby routingu.
  • Struktura folderów dla widoków i Razor stron.

Użycie obszarów tworzy hierarchię na potrzeby routingu przez dodanie innego parametru trasy, area, do controller i action lub Razor strony page.

Obszary umożliwiają partycjonowanie aplikacji internetowej ASP.NET Core w mniejsze grupy funkcjonalne, z których każdy ma własny zestaw Razor stron, kontrolerów, widoków i modeli. Obszar jest skutecznie strukturą wewnątrz aplikacji. W projekcie internetowym ASP.NET Core składniki logiczne, takie jak Strony, Model, Kontroler i Widok, są przechowywane w różnych folderach. Środowisko uruchomieniowe ASP.NET Core używa konwencji nazewnictwa w celu utworzenia relacji między tymi składnikami. W przypadku dużej aplikacji korzystne może być podzielenie aplikacji na oddzielne obszary funkcjonalności wysokiego poziomu. Na przykład aplikacja do handlu elektronicznego z wieloma jednostkami biznesowymi, takimi jak wyewidencjonowanie, rozliczenia i wyszukiwanie. Każda z tych jednostek ma własny obszar zawierający widoki, kontrolery, Razor strony i modele.

Rozważ użycie obszarów w projekcie, gdy:

  • Aplikacja składa się z wielu składników funkcjonalnych wysokiego poziomu, które mogą być logicznie oddzielone.
  • Chcesz podzielić aplikację na partycje, aby można było niezależnie pracować nad poszczególnymi obszarami funkcjonalnymi.

Wyświetl lub pobierz przykładowy kod (jak pobrać). Przykład pobierania zawiera podstawową aplikację dla obszarów testowych.

Jeśli używasz Razor stron, zobacz Obszary ze stronami Razor w tym dokumencie.

Obszary dla kontrolerów z widokami

Typowa aplikacja internetowa ASP.NET Core korzystająca z obszarów, kontrolerów i widoków zawiera następujące elementy:

  • Struktura folderów Obszaru.

  • Kontrolery z atrybutem [Area] , aby skojarzyć kontroler z obszarem:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • Trasa obszaru dodana do uruchomienia:

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

Struktura folderów warstwowych

Rozważmy aplikację z dwiema grupami logicznymi, produktami i usługami. Korzystając z obszarów, struktura folderów będzie podobna do następującej:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Kontrolery
          • HomeController.cs
          • ManageController.cs
        • Widoki
          • Home
            • Index.cshtml
          • Zarządzanie
            • Index.cshtml
            • About.cshtml
      • Usług
        • Kontrolery
          • HomeController.cs
        • Widoki
          • Home
            • Index.cshtml

Chociaż poprzedni układ jest typowy w przypadku korzystania z obszarów, do korzystania z tej struktury folderów wymagane są tylko pliki widoku. Wyświetl wyszukiwanie odnajdywania dla pasującego pliku widoku obszaru w następującej kolejności:

/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

Kojarzenie kontrolera z obszarem

Kontrolery obszaru są wyznaczone za pomocą atrybutu [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();
        }
    }
}

Dodawanie trasy obszaru

Trasy obszaru zwykle używają routingu konwencjonalnego, a nie routingu atrybutów. Routing konwencjonalny jest zależny od kolejności. Ogólnie rzecz biorąc, trasy z obszarami powinny być umieszczane wcześniej w tabeli tras, ponieważ są one bardziej szczegółowe niż trasy bez obszaru.

{area:...} Można użyć jako tokenu w szablonach tras, jeśli przestrzeń adresu URL jest jednolita we wszystkich obszarach:

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

W poprzednim kodzie stosuje ograniczenie, exists które trasa musi odpowiadać obszarowi. Za pomocą polecenia {area:...}MapControllerRoute:

  • Jest najmniej skomplikowanym mechanizmem dodawania routingu do obszarów.
  • Pasuje do wszystkich kontrolerów z atrybutem [Area("Area name")] .

Poniższy kod używa MapAreaControllerRoute metody do utworzenia dwóch nazwanych tras obszaru:

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

Aby uzyskać więcej informacji, zobacz Routing warstwowy.

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem:

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

Przykładowy plik do pobrania zawiera widok częściowy zawierający:

  • Powyższe linki.
  • Łącza podobne do powyższego z wyjątkiem area nie są określone.

Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze i kontrolerze.

Jeśli obszar lub kontroler nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki z znacznikiem, który nie określa obszaru.

Aby uzyskać więcej informacji, zobacz Routing do akcji kontrolera.

Układ udostępniony obszarów przy użyciu pliku _ViewStart.cshtml

Aby udostępnić wspólny układ całej aplikacji, zachowaj folder _ViewStart.cshtmlgłówny aplikacji. Aby uzyskać więcej informacji, zobacz Layout in ASP.NET Core (Układ w programie ASP.NET Core)

Folder główny aplikacji

Folder główny aplikacji to folder zawierający Startup.cs w aplikacji internetowej utworzony za pomocą szablonów ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, w przypadku wzorca MVC i /Pages/_ViewImports.cshtmlRazor stron nie jest importowany do widoków w obszarach. Użyj jednej z następujących metod, aby zapewnić importowanie widoku do wszystkich widoków:

  • Dodaj _ViewImports.cshtml do folderu głównego aplikacji. Element _ViewImports.cshtml w folderze głównym aplikacji będzie stosowany do wszystkich widoków w aplikacji.
  • _ViewImports.cshtml Skopiuj plik do odpowiedniego folderu widoku w obszarze obszary.

Plik _ViewImports.cshtml zazwyczaj zawiera instrukcje i @inject importy @usingpomocników tagów. Aby uzyskać więcej informacji, zobacz Importowanie dyrektyw udostępnionych.

Zmień domyślny folder obszaru, w którym są przechowywane widoki

Poniższy kod zmienia domyślny folder obszaru z "Areas" na "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();
}

Obszary ze stronami Razor

Obszary ze stronami Razor wymagają Areas/<area name>/Pages folderu w katalogu głównym aplikacji. Następująca struktura folderów jest używana z przykładową aplikacją:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Stron
          • _ViewImports
          • Informacje
          • Indeks
      • Usług
        • Stron
          • Zarządzanie
            • Informacje
            • Indeks

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem (na przykład 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>

Przykładowy plik do pobrania zawiera widok częściowy zawierający powyższe linki i te same linki bez określania obszaru. Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze.

Jeśli obszar nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki. Rozważmy na przykład linki wygenerowane na podstawie następującego kodu:

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

W poprzednim kodzie:

  • Link wygenerowany na <a asp-page="/Manage/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w Services obszarze. Na przykład, /Services/Manage/, /Services/Manage/Index lub /Services/Manage/About.
  • Link wygenerowany na <a asp-page="/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w pliku /Home.
  • Kod pochodzi z przykładowego pobierania.

Importowanie przestrzeni nazw i pomocników tagów przy użyciu pliku _ViewImports

Plik _ViewImports.cshtml można dodać do każdego folderu Pages obszaru w celu zaimportowania przestrzeni nazw i pomocników tagów do każdej Razor strony w folderze.

Rozważ obszar Usługi przykładowego kodu, który nie zawiera _ViewImports.cshtml pliku. Poniższy znacznik pokazuje stronę /Services/Manage/AboutRazor :

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

W poprzednim znaczniku:

  • W pełni kwalifikowana nazwa klasy musi być używana do określenia modelu (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Pomocnicy tagów są włączani przez @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

W przykładowym pobraniu obszar Products zawiera następujący _ViewImports.cshtml plik:

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

Na poniższej adiustacji jest wyświetlana strona /Products/AboutRazor :

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

W poprzednim pliku przestrzeń nazw i @addTagHelper dyrektywa są importowane do pliku przez Areas/Products/Pages/_ViewImports.cshtml plik.

Aby uzyskać więcej informacji, zobacz Zarządzanie zakresem pomocnika tagów i Importowanie dyrektyw udostępnionych.

Układ udostępniony dla Razor obszarów stron

Aby udostępnić wspólny układ całej aplikacji, przenieś _ViewStart.cshtml folder do folderu głównego aplikacji.

Obszary publikowania

Wszystkie pliki *.cshtml i pliki w katalogu wwwroot są publikowane do danych wyjściowych, gdy <Project Sdk="Microsoft.NET.Sdk.Web"> znajdują się w pliku *.csproj.

Dodawanie obszaru MVC za pomocą programu Visual Studio

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie DODAJ > nowy element szkieletowy, a następnie wybierz pozycję Obszar MVC.

Obszary to funkcja ASP.NET używana do organizowania powiązanych funkcji w grupie jako oddzielnej przestrzeni nazw (na potrzeby routingu) i struktury folderów (dla widoków). Użycie obszarów tworzy hierarchię na potrzeby routingu przez dodanie innego parametru trasy, area, do controller i action lub Razor strony page.

Obszary umożliwiają partycjonowanie aplikacji internetowej ASP.NET Core w mniejsze grupy funkcjonalne, z których każdy ma własny zestaw Razor stron, kontrolerów, widoków i modeli. Obszar jest skutecznie strukturą wewnątrz aplikacji. W projekcie internetowym ASP.NET Core składniki logiczne, takie jak Strony, Model, Kontroler i Widok, są przechowywane w różnych folderach. Środowisko uruchomieniowe ASP.NET Core używa konwencji nazewnictwa w celu utworzenia relacji między tymi składnikami. W przypadku dużej aplikacji korzystne może być podzielenie aplikacji na oddzielne obszary funkcjonalności wysokiego poziomu. Na przykład aplikacja do handlu elektronicznego z wieloma jednostkami biznesowymi, takimi jak wyewidencjonowanie, rozliczenia i wyszukiwanie. Każda z tych jednostek ma własny obszar zawierający widoki, kontrolery, Razor strony i modele.

Rozważ użycie obszarów w projekcie, gdy:

  • Aplikacja składa się z wielu składników funkcjonalnych wysokiego poziomu, które mogą być logicznie oddzielone.
  • Chcesz podzielić aplikację na partycje, aby można było niezależnie pracować nad poszczególnymi obszarami funkcjonalnymi.

Wyświetl lub pobierz przykładowy kod (jak pobrać). Przykład pobierania zawiera podstawową aplikację dla obszarów testowych.

Jeśli używasz Razor stron, zobacz Obszary ze stronami Razor w tym dokumencie.

Obszary dla kontrolerów z widokami

Typowa aplikacja internetowa ASP.NET Core korzystająca z obszarów, kontrolerów i widoków zawiera następujące elementy:

  • Struktura folderów Obszaru.

  • Kontrolery z atrybutem [Area] , aby skojarzyć kontroler z obszarem:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • Trasa obszaru dodana do uruchomienia:

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

Struktura folderów warstwowych

Rozważmy aplikację z dwiema grupami logicznymi, produktami i usługami. Korzystając z obszarów, struktura folderów będzie podobna do następującej:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Kontrolery
          • HomeController.cs
          • ManageController.cs
        • Widoki
          • Home
            • Index.cshtml
          • Zarządzanie
            • Index.cshtml
            • About.cshtml
      • Usług
        • Kontrolery
          • HomeController.cs
        • Widoki
          • Home
            • Index.cshtml

Chociaż poprzedni układ jest typowy w przypadku korzystania z obszarów, do korzystania z tej struktury folderów wymagane są tylko pliki widoku. Wyświetl wyszukiwanie odnajdywania dla pasującego pliku widoku obszaru w następującej kolejności:

/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

Kojarzenie kontrolera z obszarem

Kontrolery obszaru są wyznaczone za pomocą atrybutu [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();
        }
    }
}

Dodawanie trasy obszaru

Trasy obszaru zwykle używają routingu konwencjonalnego, a nie routingu atrybutów. Routing konwencjonalny jest zależny od kolejności. Ogólnie rzecz biorąc, trasy z obszarami powinny być umieszczane wcześniej w tabeli tras, ponieważ są one bardziej szczegółowe niż trasy bez obszaru.

{area:...} Można użyć jako tokenu w szablonach tras, jeśli przestrzeń adresu URL jest jednolita we wszystkich obszarach:

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

W poprzednim kodzie stosuje ograniczenie, exists które trasa musi odpowiadać obszarowi. Użycie {area:...} jest najmniej skomplikowanym mechanizmem dodawania routingu do obszarów.

Poniższy kod używa MapAreaRoute metody do utworzenia dwóch nazwanych tras obszaru:

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

W przypadku korzystania MapAreaRoute z programu ASP.NET Core 2.2 zobacz ten problem z usługą GitHub.

Aby uzyskać więcej informacji, zobacz Routing warstwowy.

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem:

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

Linki wygenerowane za pomocą powyższego kodu są prawidłowe w dowolnym miejscu w aplikacji.

Przykładowy plik do pobrania zawiera widok częściowy zawierający powyższe linki i te same linki bez określania obszaru. Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze i kontrolerze.

Jeśli obszar lub kontroler nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki.

Aby uzyskać więcej informacji, zobacz Routing do akcji kontrolera.

Układ udostępniony obszarów przy użyciu pliku _ViewStart.cshtml

Aby udostępnić wspólny układ całej aplikacji, przenieś _ViewStart.cshtml folder do folderu głównego aplikacji.

_ViewImports.cshtml

W standardowej lokalizacji /Views/_ViewImports.cshtml nie ma zastosowania do obszarów. Aby użyć typowych pomocników tagów, @usinglub @inject w twoim obszarze, upewnij się, że odpowiedni _ViewImports.cshtml plik ma zastosowanie do widoków obszaru. Jeśli chcesz to samo zachowanie we wszystkich widokach, przejdź /Views/_ViewImports.cshtml do katalogu głównego aplikacji.

Zmień domyślny folder obszaru, w którym są przechowywane widoki

Poniższy kod zmienia domyślny folder obszaru z "Areas" na "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();
}

Obszary ze stronami Razor

Obszary ze stronami Razor wymagają Areas/<area name>/Pages folderu w katalogu głównym aplikacji. Następująca struktura folderów jest używana z przykładową aplikacją:

  • Nazwa projektu
    • Obszary
      • Produktów
        • Stron
          • _ViewImports
          • Informacje
          • Indeks
      • Usług
        • Stron
          • Zarządzanie
            • Informacje
            • Indeks

Poniższy kod z przykładowego pobierania pokazuje generowanie linków z określonym obszarem (na przykład 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>

Linki wygenerowane za pomocą powyższego kodu są prawidłowe w dowolnym miejscu w aplikacji.

Przykładowy plik do pobrania zawiera widok częściowy zawierający powyższe linki i te same linki bez określania obszaru. Widok częściowy jest przywołyany w pliku układu, więc każda strona w aplikacji wyświetla wygenerowane linki. Łącza generowane bez określania obszaru są prawidłowe tylko wtedy, gdy odwołuje się do strony w tym samym obszarze.

Jeśli obszar nie zostanie określony, routing zależy od wartości otoczenia . Bieżące wartości tras bieżącego żądania są uznawane za wartości otoczenia dla generowania linków. W wielu przypadkach dla przykładowej aplikacji użycie wartości otoczenia generuje nieprawidłowe linki. Rozważmy na przykład linki wygenerowane na podstawie następującego kodu:

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

W poprzednim kodzie:

  • Link wygenerowany na <a asp-page="/Manage/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w Services obszarze. Na przykład, /Services/Manage/, /Services/Manage/Index lub /Services/Manage/About.
  • Link wygenerowany na <a asp-page="/About"> podstawie jest poprawny tylko wtedy, gdy ostatnie żądanie dotyczyło strony w pliku /Home.
  • Kod pochodzi z przykładowego pobierania.

Importowanie przestrzeni nazw i pomocników tagów przy użyciu pliku _ViewImports

Plik _ViewImports.cshtml można dodać do każdego folderu Pages obszaru w celu zaimportowania przestrzeni nazw i pomocników tagów do każdej Razor strony w folderze.

Rozważ obszar Usługi przykładowego kodu, który nie zawiera _ViewImports.cshtml pliku. Poniższy znacznik pokazuje stronę /Services/Manage/AboutRazor :

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

W poprzednim znaczniku:

  • W pełni kwalifikowana nazwa domeny musi być używana do określenia modelu (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Pomocnicy tagów są włączani przez @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

W przykładowym pobraniu obszar Products zawiera następujący _ViewImports.cshtml plik:

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

Na poniższej adiustacji jest wyświetlana strona /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>

W poprzednim pliku przestrzeń nazw i @addTagHelper dyrektywa są importowane do pliku przez Areas/Products/Pages/_ViewImports.cshtml plik.

Aby uzyskać więcej informacji, zobacz Zarządzanie zakresem pomocnika tagów i Importowanie dyrektyw udostępnionych.

Układ udostępniony dla Razor obszarów stron

Aby udostępnić wspólny układ całej aplikacji, przenieś _ViewStart.cshtml folder do folderu głównego aplikacji.

Obszary publikowania

Wszystkie pliki *.cshtml i pliki w katalogu wwwroot są publikowane do danych wyjściowych, gdy <Project Sdk="Microsoft.NET.Sdk.Web"> znajdują się w pliku *.csproj.