Aree in ASP.NET Core

Di Dhananjay Kumar e Rick Anderson

Le aree sono una funzionalità di ASP.NET usata per organizzare le funzionalità correlate in un gruppo come separato:

  • Spazio dei nomi per il routing.
  • Struttura di cartelle per visualizzazioni e Razor pagine.

L'uso di aree crea una gerarchia per lo scopo del routing aggiungendo un altro parametro di route, area, a controller e action o una Razor pagina page.

Le aree consentono di partizionare un'app Web core ASP.NET in gruppi funzionali più piccoli, ognuno con un proprio set di Razor pagine, controller, visualizzazioni e modelli. Un'area è in effetti una struttura all'interno di un'app. In un progetto Web ASP.NET Core i componenti logici come pagine, modello, controller e visualizzazione si trovano in cartelle diverse. Il runtime di ASP.NET Core crea una relazione tra questi componenti usando convenzioni di denominazione. Per un'app di grandi dimensioni può risultare utile suddividere l'app in aree di funzionalità di alto livello distinte. È 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. Ognuna di queste unità ha una propria area per contenere visualizzazioni, controller, Razor pagine e modelli.

In un progetto è consigliabile usare le aree quando:

  • L'app è costituita da più componenti funzionali di alto livello che possono rimanere logicamente separati.
  • Si vuole suddividere l'app in modo da poter lavorare su ogni area funzionale in modo indipendente.

Se si usano Razor pagine, vedere Aree con Razor pagine in questo documento.

Aree per i controller con visualizzazioni

Una tipica app Web ASP.NET Core che usa aree, controller e visualizzazioni contiene quanto segue:

  • Una struttura di cartelle dell'area.

  • Controller con l'attributo [Area] per associare il controller all'area:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • Percorso dell'area aggiunto a 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();
    

Struttura di cartelle dell'area

Si consideri un'applicazione che ha due gruppi logici, Prodotti e Servizi. Usando le aree, la struttura delle cartelle sarebbe simile alla seguente:

  • Nome progetto
    • Aree
      • Prodotti
        • Controller
          • HomeController.cs
          • ManageController.cs
        • Visualizzazioni
          • Home
            • Index.cshtml
          • Amministrare
            • Index.cshtml
            • About.cshtml
      • Servizi
        • Controller
          • HomeController.cs
        • Visualizzazioni
          • Home
            • Index.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. L'individuazione delle visualizzazioni cercherà un file di visualizzazione area corrispondente in quest'ordine:

/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'area

I controller di area sono designati con l'attributo [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();
    }
}

Aggiungere una route di area

Le route di area usano in genere il routing convenzionale anziché il routing degli attributi. Il routing convenzionale dipende dall'ordinamento. 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.

{area:...} può essere usato come token nei modelli di route se lo spazio URL è uniforme in tutte le aree:

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

Nel codice precedente, exists applica il vincolo che la route deve corrispondere a un'area. Uso di {area:...} con MapControllerRoute:

  • Meccanismo meno complesso per l'aggiunta del routing alle aree.
  • Corrisponde a tutti i controller con l'attributo [Area("Area name")] .

Il codice seguente usa MapAreaControllerRoute per creare due route di area denominate:

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

Per altre informazioni, vedere Aree.

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata:

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

Il download di esempio include una visualizzazione parziale che contiene:

  • Collegamenti precedenti.
  • I collegamenti simili a quelli precedenti, ad eccezione area del fatto che non sono specificati.

La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo quando sono referenziati da una pagina nella stessa area e controller.

Quando l'area o il controller non sono specificati, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti con il markup che non specifica l'area.

Per altre informazioni, vedere Routing ad azioni del controller.

Layout condiviso per le aree tramite il file _ViewStart.cshtml

Per condividere un layout comune per l'intera app, mantenere il _ViewStart.cshtml nella cartella radice dell'applicazione. Per altre informazioni, vedere Layout in ASP.NET Core

Cartella radice dell'applicazione

La cartella radice dell'applicazione è la cartella contenente il Program.cs file in un'app Web creata con i modelli ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, per MVC e /Pages/_ViewImports.cshtml per Razor Pages, non viene importato nelle visualizzazioni nelle aree. Usare uno degli approcci seguenti per fornire le importazioni di visualizzazione a tutte le visualizzazioni:

  • Aggiungere _ViewImports.cshtml alla cartella radice dell'applicazione. Un _ViewImports.cshtml nella cartella radice dell'applicazione verrà applicato a tutte le visualizzazioni nell'app.
  • Copiare il file _ViewImports.cshtml nella cartella di visualizzazione appropriata nelle aree. Ad esempio, un'app Razor Pages creata con singoli account utente ha un file _ViewImports.cshtml nelle cartelle seguenti:
    • /Areas/Identity/Pages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

Il file _ViewImports.cshtml contiene in genere istruzioni Tag Helpers imports, @using, e @inject . Per altre informazioni, vedere Importazione di direttive condivise.

Modificare la cartella dell'area predefinita in cui sono archiviate le visualizzazioni

Il codice seguente modifica la cartella dell'area predefinita da "Areas" a "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();

Aree con Razor pagine

Le aree con Razor Pagine richiedono una Areas/<area name>/Pages cartella nella radice dell'app. La struttura di cartelle seguente viene usata con l'app di esempio:

  • Nome progetto
    • Aree
      • Prodotti
        • Pagine
          • _ViewImports
          • Informazioni su
          • Indice
      • Servizi
        • Pagine
          • Amministrare
            • Informazioni su
            • Indice

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata (ad esempio, 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>

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo in caso di riferimento da una pagina nella stessa area.

Quando l'area non è specificata, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti. Si considerino, ad esempio, i collegamenti generati dal codice seguente:

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

Per il codice precedente:

  • Il collegamento generato da <a asp-page="/Manage/About"> è corretto solo quando l'ultima richiesta riguarda una pagina nell'area Services. Ad esempio, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • Il collegamento generato da <a asp-page="/About"> è corretto solo quando l'ultima richiesta riguarda una pagina in /Home.
  • Il codice deriva dal download di esempio.

Importare lo spazio dei nomi e gli helper tag con il file _ViewImports

È possibile aggiungere un file _ViewImports.cshtml a ogni cartella Pagine dell'area per importare lo spazio dei nomi e gli helper tag in ogni Razor pagina della cartella.

Prendere in considerazione l'area Services del codice di esempio, che non contiene un file _ViewImports.cshtml. Il markup seguente mostra la pagina /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>

Nel markup precedente:

  • Il nome completo della classe deve essere usato per specificare il modello (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Gli helper tag sono abilitati da @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Nel download di esempio, l'area Products contiene il file _ViewImports.cshtml seguente:

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

Il markup seguente mostra la pagina /Products/AboutRazor :

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

Nel file precedente lo spazio dei nomi e la direttiva @addTagHelper vengono importati dal file Areas/Products/Pages/_ViewImports.cshtml.

Per altre informazioni, vedere Gestione dell'ambito dell'helper tag e Importazione delle direttive condivise.

Layout condiviso per Razor le aree pagine

Per condividere un layout comune per l'intera app, spostare _ViewStart.cshtml nella cartella radice dell'applicazione.

Pubblicazione di aree

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.

Aggiungere un'area MVC con Visual Studio

In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere AGGIUNGI nuovo elemento con scaffolding, quindi selezionare Area MVC.>

Risorse aggiuntive

Le aree sono una funzionalità di ASP.NET usata per organizzare le funzionalità correlate in un gruppo come separato:

  • Spazio dei nomi per il routing.
  • Struttura di cartelle per visualizzazioni e Razor pagine.

L'uso di aree crea una gerarchia per lo scopo del routing aggiungendo un altro parametro di route, area, a controller e action o una Razor pagina page.

Le aree consentono di partizionare un'app Web core ASP.NET in gruppi funzionali più piccoli, ognuno con un proprio set di Razor pagine, controller, visualizzazioni e modelli. Un'area è in effetti una struttura all'interno di un'app. In un progetto Web ASP.NET Core i componenti logici come pagine, modello, controller e visualizzazione si trovano in cartelle diverse. Il runtime di ASP.NET Core crea una relazione tra questi componenti usando convenzioni di denominazione. Per un'app di grandi dimensioni può risultare utile suddividere l'app in aree di funzionalità di alto livello distinte. È 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. Ognuna di queste unità ha una propria area per contenere visualizzazioni, controller, Razor pagine e modelli.

In un progetto è consigliabile usare le aree quando:

  • L'app è costituita da più componenti funzionali di alto livello che possono rimanere logicamente separati.
  • Si vuole suddividere l'app in modo da poter lavorare su ogni area funzionale in modo indipendente.

Visualizzare o scaricare il codice di esempio (procedura per il download). Il download di esempio fornisce un'app di base per testare le aree.

Se si usano Razor pagine, vedere Aree con Razor pagine in questo documento.

Aree per i controller con visualizzazioni

Una tipica app Web ASP.NET Core che usa aree, controller e visualizzazioni contiene quanto segue:

  • Una struttura di cartelle dell'area.

  • Controller con l'attributo [Area] per associare il controller all'area:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La route di area aggiunta all'avvio:

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

Struttura di cartelle dell'area

Si consideri un'applicazione che ha due gruppi logici, Prodotti e Servizi. Usando le aree, la struttura delle cartelle sarebbe simile alla seguente:

  • Nome progetto
    • Aree
      • Prodotti
        • Controller
          • HomeController.cs
          • ManageController.cs
        • Visualizzazioni
          • Home
            • Index.cshtml
          • Amministrare
            • Index.cshtml
            • About.cshtml
      • Servizi
        • Controller
          • HomeController.cs
        • Visualizzazioni
          • Home
            • Index.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. L'individuazione delle visualizzazioni cercherà un file di visualizzazione area corrispondente in quest'ordine:

/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'area

I controller di area sono designati con l'attributo [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();
        }
    }
}

Aggiungere una route di area

Le route di area usano in genere il routing convenzionale anziché il routing degli attributi. Il routing convenzionale dipende dall'ordinamento. 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.

{area:...} può essere usato come token nei modelli di route se lo spazio URL è uniforme in tutte le aree:

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

Nel codice precedente, exists applica il vincolo che la route deve corrispondere a un'area. Uso di {area:...} con MapControllerRoute:

  • Meccanismo meno complesso per l'aggiunta del routing alle aree.
  • Corrisponde a tutti i controller con l'attributo [Area("Area name")] .

Il codice seguente usa MapAreaControllerRoute per creare due route di area denominate:

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

Per altre informazioni, vedere Aree.

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata:

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

Il download di esempio include una visualizzazione parziale che contiene:

  • Collegamenti precedenti.
  • I collegamenti simili a quelli precedenti, ad eccezione area del fatto che non sono specificati.

La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo quando sono referenziati da una pagina nella stessa area e controller.

Quando l'area o il controller non sono specificati, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti con il markup che non specifica l'area.

Per altre informazioni, vedere Routing ad azioni del controller.

Layout condiviso per le aree tramite il file _ViewStart.cshtml

Per condividere un layout comune per l'intera app, mantenere _ViewStart.cshtml nella cartella radice dell'applicazione. Per altre informazioni, vedere Layout in ASP.NET Core

Cartella radice dell'applicazione

La cartella radice dell'applicazione è la cartella contenente Startup.cs nell'app Web creata con i modelli di base ASP.NET.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, per MVC e /Pages/_ViewImports.cshtml per Razor Pages, non viene importato nelle visualizzazioni nelle aree. Usare uno degli approcci seguenti per fornire le importazioni di visualizzazione a tutte le visualizzazioni:

  • Aggiungere _ViewImports.cshtml alla cartella radice dell'applicazione. Un _ViewImports.cshtml nella cartella radice dell'applicazione verrà applicato a tutte le visualizzazioni nell'app.
  • Copiare il _ViewImports.cshtml file nella cartella di visualizzazione appropriata nelle aree.

Il _ViewImports.cshtml file contiene in genere importazioni di helper tag, @usingistruzioni e @inject . Per altre informazioni, vedere Importazione di direttive condivise.

Modificare la cartella dell'area predefinita in cui sono archiviate le visualizzazioni

Il codice seguente modifica la cartella dell'area predefinita da "Areas" a "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();
}

Aree con Razor pagine

Le aree con Razor Pagine richiedono una Areas/<area name>/Pages cartella nella radice dell'app. La struttura di cartelle seguente viene usata con l'app di esempio:

  • Nome progetto
    • Aree
      • Prodotti
        • Pagine
          • _ViewImports
          • Informazioni su
          • Indice
      • Servizi
        • Pagine
          • Amministrare
            • Informazioni su
            • Indice

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata (ad esempio, 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>

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo in caso di riferimento da una pagina nella stessa area.

Quando l'area non è specificata, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti. Si considerino, ad esempio, i collegamenti generati dal codice seguente:

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

Per il codice precedente:

  • Il collegamento generato da <a asp-page="/Manage/About"> è corretto solo quando l'ultima richiesta riguarda una pagina nell'area Services. Ad esempio, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • Il collegamento generato da <a asp-page="/About"> è corretto solo quando l'ultima richiesta riguarda una pagina in /Home.
  • Il codice deriva dal download di esempio.

Importare lo spazio dei nomi e gli helper tag con il file _ViewImports

È possibile aggiungere un _ViewImports.cshtml file a ogni cartella Pagine dell'area per importare lo spazio dei nomi e gli helper tag in ogni Razor pagina della cartella.

Si consideri l'area Servizi del codice di esempio, che non contiene un _ViewImports.cshtml file. Il markup seguente mostra la pagina /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>

Nel markup precedente:

  • Il nome completo della classe deve essere usato per specificare il modello (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Gli helper tag sono abilitati da @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Nel download di esempio l'area Prodotti contiene il file seguente _ViewImports.cshtml :

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

Il markup seguente mostra la pagina /Products/AboutRazor :

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

Nel file precedente lo spazio dei nomi e @addTagHelper la direttiva viene importato nel file dal Areas/Products/Pages/_ViewImports.cshtml file .

Per altre informazioni, vedere Gestione dell'ambito dell'helper tag e Importazione delle direttive condivise.

Layout condiviso per Razor le aree pagine

Per condividere un layout comune per l'intera app, spostarlo _ViewStart.cshtml nella cartella radice dell'applicazione.

Pubblicazione di aree

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.

Aggiungere un'area MVC con Visual Studio

In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere AGGIUNGI nuovo elemento con scaffolding, quindi selezionare Area MVC.>

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). L'uso di aree crea una gerarchia per lo scopo del routing aggiungendo un altro parametro di route, area, a controller e action o una Razor pagina page.

Le aree consentono di partizionare un'app Web core ASP.NET in gruppi funzionali più piccoli, ognuno con un proprio set di Razor pagine, controller, visualizzazioni e modelli. Un'area è in effetti una struttura all'interno di un'app. In un progetto Web ASP.NET Core i componenti logici come pagine, modello, controller e visualizzazione si trovano in cartelle diverse. Il runtime di ASP.NET Core crea una relazione tra questi componenti usando convenzioni di denominazione. Per un'app di grandi dimensioni può risultare utile suddividere l'app in aree di funzionalità di alto livello distinte. È 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. Ognuna di queste unità ha una propria area per contenere visualizzazioni, controller, Razor pagine e modelli.

In un progetto è consigliabile usare le aree quando:

  • L'app è costituita da più componenti funzionali di alto livello che possono rimanere logicamente separati.
  • Si vuole suddividere l'app in modo da poter lavorare su ogni area funzionale in modo indipendente.

Visualizzare o scaricare il codice di esempio (procedura per il download). Il download di esempio fornisce un'app di base per testare le aree.

Se si usano Razor pagine, vedere Aree con Razor pagine in questo documento.

Aree per i controller con visualizzazioni

Una tipica app Web ASP.NET Core che usa aree, controller e visualizzazioni contiene quanto segue:

  • Una struttura di cartelle dell'area.

  • Controller con l'attributo [Area] per associare il controller all'area:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La route di area aggiunta all'avvio:

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

Struttura di cartelle dell'area

Si consideri un'applicazione che ha due gruppi logici, Prodotti e Servizi. Usando le aree, la struttura delle cartelle sarebbe simile alla seguente:

  • Nome progetto
    • Aree
      • Prodotti
        • Controller
          • HomeController.cs
          • ManageController.cs
        • Visualizzazioni
          • Home
            • Index.cshtml
          • Amministrare
            • Index.cshtml
            • About.cshtml
      • Servizi
        • Controller
          • HomeController.cs
        • Visualizzazioni
          • Home
            • Index.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. L'individuazione delle visualizzazioni cercherà un file di visualizzazione area corrispondente in quest'ordine:

/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'area

I controller di area sono designati con l'attributo [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();
        }
    }
}

Aggiungere una route di area

Le route di area usano in genere il routing convenzionale anziché il routing con attributi. Il routing convenzionale dipende dall'ordinamento. 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.

{area:...} può essere usato come token nei modelli di route se lo spazio URL è uniforme in tutte le aree:

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. L'uso di {area:...} è il meccanismo meno complesso per l'aggiunta del routing alle aree.

Il codice seguente usa MapAreaRoute per creare due route di area denominate:

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.

Per altre informazioni, vedere Aree.

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata:

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

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo quando sono referenziati da una pagina nella stessa area e controller.

Quando l'area o il controller non sono specificati, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti.

Per altre informazioni, vedere Routing ad azioni del controller.

Layout condiviso per le aree tramite il file _ViewStart.cshtml

Per condividere un layout comune per l'intera app, spostarlo _ViewStart.cshtml nella cartella radice dell'applicazione.

_ViewImports.cshtml

Nella sua posizione /Views/_ViewImports.cshtml standard, non si applica alle aree. Per usare gli helper tag comuni, @usingo @inject nell'area, assicurarsi che un file appropriato _ViewImports.cshtml si applichi alle visualizzazioni dell'area. Se si vuole lo stesso comportamento in tutte le visualizzazioni, passare /Views/_ViewImports.cshtml alla radice dell'applicazione.

Modificare la cartella dell'area predefinita in cui sono archiviate le visualizzazioni

Il codice seguente modifica la cartella dell'area predefinita da "Areas" a "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 Razor pagine

Le aree con Razor Pagine richiedono una Areas/<area name>/Pages cartella nella radice dell'app. La struttura di cartelle seguente viene usata con l'app di esempio:

  • Nome progetto
    • Aree
      • Prodotti
        • Pagine
          • _ViewImports
          • Informazioni su
          • Indice
      • Servizi
        • Pagine
          • Amministrare
            • Informazioni su
            • Indice

Il codice seguente dal download di esempio mostra la generazione di collegamenti con l'area specificata (ad esempio, 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.

Il download di esempio include una visualizzazione parziale che contiene i collegamenti precedenti e gli stessi collegamenti senza specificare l'area. La visualizzazione parziale viene referenziata nel file di layout, in modo che ogni pagina nell'app mostri i collegamenti generati. I collegamenti generati senza specificare l'area sono validi solo in caso di riferimento da una pagina nella stessa area.

Quando l'area non è specificata, il routing dipende dai valori di ambiente. I valori di route correnti della richiesta corrente sono considerati valori di ambiente per la generazione del collegamento. In molti casi per l'app di esempio, l'uso dei valori di ambiente genera collegamenti non corretti. Si considerino, ad esempio, i collegamenti generati dal codice seguente:

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

Per il codice precedente:

  • Il collegamento generato da <a asp-page="/Manage/About"> è corretto solo quando l'ultima richiesta riguarda una pagina nell'area Services. Ad esempio, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • Il collegamento generato da <a asp-page="/About"> è corretto solo quando l'ultima richiesta riguarda una pagina in /Home.
  • Il codice deriva dal download di esempio.

Importare lo spazio dei nomi e gli helper tag con il file _ViewImports

È possibile aggiungere un _ViewImports.cshtml file a ogni cartella Pagine dell'area per importare lo spazio dei nomi e gli helper tag in ogni Razor pagina della cartella.

Si consideri l'area Servizi del codice di esempio, che non contiene un _ViewImports.cshtml file. Il markup seguente mostra la pagina /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>

Nel markup precedente:

  • Il nome di dominio completo deve essere usato per specificare il modello (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Gli helper tag sono abilitati da @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Nel download di esempio l'area Prodotti contiene il file seguente _ViewImports.cshtml :

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

Il markup seguente mostra la pagina /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>

Nel file precedente lo spazio dei nomi e @addTagHelper la direttiva viene importato nel file dal Areas/Products/Pages/_ViewImports.cshtml file .

Per altre informazioni, vedere Gestione dell'ambito dell'helper tag e Importazione delle direttive condivise.

Layout condiviso per Razor le aree pagine

Per condividere un layout comune per l'intera app, spostarlo _ViewStart.cshtml nella cartella radice dell'applicazione.

Pubblicazione di aree

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.