Aree in ASP.NET CoreAreas in ASP.NET Core

Di Dhananjay Kumar e Rick AndersonBy Dhananjay Kumar and Rick Anderson

Le aree sono una funzionalità di ASP.NET che consente di organizzare le funzioni correlate in un gruppo come spazio dei nomi separato (per il routing) e struttura di cartelle (per le visualizzazioni).Areas are an ASP.NET feature used to organize related functionality into a group as a separate namespace (for routing) and folder structure (for views). Usando le aree si crea una gerarchia per il routing aggiungendo un altro parametro di route, area, a controller e action o a una pagina Razor page.Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area, to controller and action or a Razor Page page.

Le aree consentono di suddividere un'app Web ASP.NET Core in gruppi funzionali più piccoli, ognuno con un proprio set di pagine Razor, controller, visualizzazioni e modelli.Areas provide a way to partition an ASP.NET Core Web app into smaller functional groups, each with its own set of Razor Pages, controllers, views, and models. Un'area è in effetti una struttura all'interno di un'app.An area is effectively a structure inside an app. In un progetto Web ASP.NET Core i componenti logici come pagine, modello, controller e visualizzazione si trovano in cartelle diverse.In an ASP.NET Core web project, logical components like Pages, Model, Controller, and View are kept in different folders. Il runtime di ASP.NET Core crea una relazione tra questi componenti usando convenzioni di denominazione.The ASP.NET Core runtime uses naming conventions to create the relationship between these components. Per un'app di grandi dimensioni può risultare utile suddividere l'app in aree di funzionalità di alto livello distinte.For a large app, it may be advantageous to partition the app into separate high level areas of functionality. È il caso, ad esempio, di un'app di e-commerce con più business unit, ad esempio per il completamento della transazione, la fatturazione e la ricerca.For instance, an e-commerce app with multiple business units, such as checkout, billing, and search. Ognuna di queste business unit avrà la propria area in cui contenere visualizzazioni, controller, pagine Razor e modelli.Each of these units have their own area to contain views, controllers, Razor Pages, and models.

In un progetto è consigliabile usare le aree quando:Consider using Areas in a project when:

  • L'app è costituita da più componenti funzionali di alto livello che possono rimanere logicamente separati.The app is made of multiple high-level functional components that can be logically separated.
  • Si vuole suddividere l'app in modo da poter lavorare su ogni area funzionale in modo indipendente.You want to partition the app so that each functional area can be worked on independently.

Visualizzare o scaricare il codice di esempio (procedura per il download).View or download sample code (how to download). Il download di esempio fornisce un'app di base per testare le aree.The download sample provides a basic app for testing areas.

Se si usa Razor Pages, vedere Aree con pagine Razor in questo documento.If you're using Razor Pages, see Areas with Razor Pages in this document.

Aree per i controller con visualizzazioniAreas for controllers with views

Una tipica app Web ASP.NET Core che usa aree, controller e visualizzazioni contiene quanto segue:A typical ASP.NET Core web app using areas, controllers, and views contains the following:

Struttura di cartelle dell'areaArea folder structure

Si consideri un'applicazione che ha due gruppi logici, Prodotti e Servizi.Consider an app that has two logical groups, Products and Services. Usando le aree, la struttura delle cartelle sarebbe simile alla seguente:Using areas, the folder structure would be similar to the following:

  • Nome progettoProject name
    • AreeAreas
      • ProdottiProducts
        • ControllersControllers
          • HomeController.csHomeController.cs
          • ManageController.csManageController.cs
        • VisualizzazioniViews
          • HomeHome
            • Index.cshtmlIndex.cshtml
          • GestisciManage
            • Index.cshtmlIndex.cshtml
            • About.cshtmlAbout.cshtml
      • ServiziServices
        • ControllersControllers
          • HomeController.csHomeController.cs
        • VisualizzazioniViews
          • HomeHome
            • Index.cshtmlIndex.cshtml

Anche se il layout precedente è tipico quando si usano le aree, per usare questa struttura di cartelle sono necessari solo i file delle visualizzazioni.While the preceding layout is typical when using Areas, only the view files are required to use this folder structure. L'individuazione delle visualizzazioni cercherà un file di visualizzazione area corrispondente in quest'ordine:View discovery searches for a matching area view file in the following order:

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

Associare il controller a un'areaAssociate the controller with an Area

I controller di area sono identificati dall'attributo [Area]:Area controllers are designated with the [Area] attribute:

using Microsoft.AspNetCore.Mvc;

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

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

Aggiungere una route di areaAdd Area route

Le route di area usano in genere il routing convenzionale anziché il routing con attributi.Area routes typically use conventional routing rather than attribute routing. Il routing convenzionale dipende dall'ordinamento.Conventional routing is order-dependent. In generale, le route con aree devono essere posizionate prima delle altre nella tabella di route poiché sono più specifiche rispetto alle route senza un'area.In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

{area:...} può essere usato come token nei modelli di route se lo spazio URL è uniforme in tutte le aree:{area:...} can be used as a token in route templates if url space is uniform across all areas:

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

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

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

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

Nel codice precedente, exists applica il vincolo che la route deve corrispondere a un'area.In the preceding code, exists applies a constraint that the route must match an area. L'uso di {area:...} è il meccanismo meno complesso per l'aggiunta del routing alle aree.Using {area:...} is the least complicated mechanism to adding routing to areas.

Il codice seguente usa MapAreaRoute per creare due route di area denominate:The following code uses MapAreaRoute to create two named area routes:

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

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

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

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

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

Quando si usa MapAreaRoute con ASP.NET Core 2.2, vedere questo problema su GitHub.When using MapAreaRoute with ASP.NET Core 2.2, see this GitHub issue.

Per altre informazioni, vedere Aree.For more information, see Area routing.

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata:The following code from the sample download shows link generation with the area specified:

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

I collegamenti generati con il codice precedente sono validi ovunque nell'app.The links generated with the preceding code are valid anywhere in the app.

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area.The sample download includes a partial view that contains the preceding links and the same links without specifying the area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati.The partial view is referenced in the layout file, so every page in the app displays the generated links. I collegamenti generati senza specificare l'area sono validi solo quando sono referenziati da una pagina nella stessa area e controller.The links generated without specifying the area are only valid when referenced from a page in the same area and controller.

Quando l'area o il controller non sono specificati, il routing dipende dai valori di ambiente.When the area or controller is not specified, routing depends on the ambient values. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento.The current route values of the current request are considered ambient values for link generation. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti.In many cases for the sample app, using the ambient values generates incorrect links.

Per altre informazioni, vedere Routing ad azioni del controller.For more information, see Routing to controller actions.

Layout condiviso per le aree tramite il file _ViewStart.cshtmlShared layout for Areas using the _ViewStart.cshtml file

Per condividere un layout comune per l'intera app, spostare _ViewStart.cshtml nella cartella radice dell'applicazione.To share a common layout for the entire app, move the _ViewStart.cshtml to the application root folder.

_ViewImports.cshtml_ViewImports.cshtml

Nella posizione standard /Views/_ViewImports.cshtml non si applica alle aree.In its standard location, /Views/_ViewImports.cshtml doesn't apply to areas. Per usare gli helper tag comuni, @using o @inject nella propria area, assicurarsi che un file _ViewImports.cshtml appropriato venga applicato alle visualizzazioni dell'area.To use common Tag Helpers, @using, or @inject in your area, ensure a proper _ViewImports.cshtml file applies to your area views. Se si vuole lo stesso comportamento in tutte le visualizzazioni, spostare /Views/_ViewImports.cshtml nella radice dell'applicazione.If you want the same behavior in all your views, move /Views/_ViewImports.cshtml to the application root.

Modificare la cartella dell'area predefinita in cui sono archiviate le visualizzazioniChange default area folder where views are stored

Il codice seguente modifica la cartella dell'area predefinita da "Areas" a "MyAreas":The following code changes the default area folder from "Areas" to "MyAreas":

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

    services.AddMvc();
}

Aree con pagine RazorAreas with Razor Pages

Per le aree con pagine Razor è richiesta una cartella Areas//Pages nella radice dell'app.Areas with Razor Pages require an Areas//Pages folder in the root of the app. La struttura di cartelle seguente viene usata con l'app di esempio:The following folder structure is used with the sample app:

  • Nome progettoProject name
    • AreeAreas
      • ProdottiProducts
        • PagesPages
          • _ViewImports_ViewImports
          • Informazioni suAbout
          • IndiceIndex
      • ServiziServices
        • PagesPages
          • GestisciManage
            • Informazioni suAbout
            • IndiceIndex

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata (ad esempio, asp-area="Products"):The following code from the sample download shows link generation with the area specified (for example, asp-area="Products"):

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

I collegamenti generati con il codice precedente sono validi ovunque nell'app.The links generated with the preceding code are valid anywhere in the app.

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area.The sample download includes a partial view that contains the preceding links and the same links without specifying the area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati.The partial view is referenced in the layout file, so every page in the app displays the generated links. I collegamenti generati senza specificare l'area sono validi solo in caso di riferimento da una pagina nella stessa area.The links generated without specifying the area are only valid when referenced from a page in the same area.

Quando l'area non è specificata, il routing dipende dai valori di ambiente.When the area is not specified, routing depends on the ambient values. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento.The current route values of the current request are considered ambient values for link generation. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti.In many cases for the sample app, using the ambient values generates incorrect links. Si considerino, ad esempio, i collegamenti generati dal codice seguente:For example, consider the links generated from the following code:

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

Per il codice precedente:For the preceding code:

  • Il collegamento generato da <a asp-page="/Manage/About"> è corretto solo quando l'ultima richiesta riguarda una pagina nell'area Services.The link generated from <a asp-page="/Manage/About"> is correct only when the last request was for a page in Services area. Ad esempio, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.For example, /Services/Manage/, /Services/Manage/Index, or /Services/Manage/About.
  • Il collegamento generato da <a asp-page="/About"> è corretto solo quando l'ultima richiesta riguarda una pagina in /Home.The link generated from <a asp-page="/About"> is correct only when the last request was for a page in /Home.
  • Il codice deriva dal download di esempio.The code is from the sample download.

Importare lo spazio dei nomi e gli helper tag con il file _ViewImportsImport namespace and Tag Helpers with _ViewImports file

È possibile aggiungere un file _ViewImports.cshtml nella cartella Pages di ogni area per importare lo spazio dei nomi e gli helper tag in ogni pagina Razor nella cartella.A _ViewImports.cshtml file can be added to each area Pages folder to import the namespace and Tag Helpers to each Razor Page in the folder.

Prendere in considerazione l'area Services del codice di esempio, che non contiene un file _ViewImports.cshtml.Consider the Services area of the sample code, which doesn't contain a _ViewImports.cshtml file. Il markup seguente mostra la pagina Razor /Services/Manage/About:The following markup shows the /Services/Manage/About Razor Page:

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

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

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

Nel markup precedente:In the preceding markup:

  • Il nome di dominio completo deve essere usato per specificare il modello (@model RPareas.Areas.Services.Pages.Manage.AboutModel).The fully qualified domain name must be used to specify the model (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Gli helper tag sono abilitati da @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpersTag Helpers are enabled by @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Nel download di esempio, l'area Products contiene il file _ViewImports.cshtml seguente:In the sample download, the Products area contains the following _ViewImports.cshtml file:

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

Il markup seguente mostra la pagina Razor /Products/About:The following markup shows the /Products/About Razor Page:

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

<h2>Products/About</h2>

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

Nel file precedente lo spazio dei nomi e la direttiva @addTagHelper vengono importati dal file Areas/Products/Pages/_ViewImports.cshtml.In the preceding file, the namespace and @addTagHelper directive is imported to the file by the Areas/Products/Pages/_ViewImports.cshtml file.

Per altre informazioni, vedere Gestione dell'ambito dell'helper tag e Importazione delle direttive condivise.For more information, see Managing Tag Helper scope and Importing Shared Directives.

Layout condiviso per le aree di pagine RazorShared layout for Razor Pages Areas

Per condividere un layout comune per l'intera app, spostare _ViewStart.cshtml nella cartella radice dell'applicazione.To share a common layout for the entire app, move the _ViewStart.cshtml to the application root folder.

Pubblicazione di areePublishing Areas

Tutti i file *.cshtml e i file all'interno della directory wwwroot vengono pubblicati nell'output quando <Project Sdk="Microsoft.NET.Sdk.Web"> è incluso nel file *.csproj.All *.cshtml files and files within the wwwroot directory are published to output when <Project Sdk="Microsoft.NET.Sdk.Web"> is included in the *.csproj file.