Zones dans ASP.NET Core

Par Dhananjay Kumar et Rick Anderson

Les zones sont une fonctionnalité ASP.NET utilisée pour organiser des fonctionnalités connexes dans un groupe distinct :

  • Espace de noms pour le routage.
  • Structure des dossiers pour les vues et les pages Razor.

L’utilisation de zones a pour effet de créer une hiérarchie pour les besoins du routage en ajoutant un autre paramètre de route, area, à controller et action ou une Page Razorpage.

Les zones offrent un moyen de partitionner une application web ASP.NET Core en groupes fonctionnels plus petits, chacun avec son propre ensemble de Pages Razor, de contrôleurs, de vues et de modèles. Une zone est en réalité une structure au sein d’une application. Dans un projet web ASP.NET Core, les composants logiques comme Pages, Controller et View sont conservés dans différents dossiers. Le runtime ASP.NET Core utilise des conventions de nommage pour créer la relation entre ces composants. Pour une application volumineuse, il peut être avantageux de partitionner l’application en différentes zones de fonctionnalités de premier niveau. Par exemple, pour une application d’e-commerce à plusieurs entités, il peut s’agir de la caisse, de la facturation et de la recherche. Chacune de ces unités a sa propre zone pour accueillir les vues, les contrôleurs, les Pages Razor et les modèles.

Envisagez d’utiliser des zones dans un projet quand :

  • L’application est constituée de plusieurs composants fonctionnels globaux qui peuvent être logiquement séparés.
  • Vous pouvez partitionner l’application de façon à pouvoir travailler indépendamment sur chaque zone fonctionnelle.

Si vous utilisez les Pages Razor, consultez Zones avec Pages Razor dans ce document.

Zones pour contrôleurs avec vues

Une application web ASP.NET Core type qui utilise des zones, des contrôleurs et des vues est constituée des éléments suivants :

  • Une structure de dossiers Zone.

  • Des contrôleurs avec l’attribut [Area] associer le contrôleur à la zone :

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La route de zone ajoutée à 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();
    

Structure de dossiers Zone

Imaginez une application qui contient deux groupes logiques, Produits et Services. En utilisant des zones, la structure de dossiers se présenterait comme suit :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Contrôleurs
          • HomeController.cs
          • ManageController.cs
        • Vues
          • Home
            • Index.cshtml
          • Gérer
            • Index.cshtml
            • About.cshtml
      • Services
        • Contrôleurs
          • HomeController.cs
        • Vues
          • Home
            • Index.cshtml

Si la disposition précédente est classique dans les cas où des zones sont utilisées, seuls les fichiers de vues sont nécessaires pour utiliser cette structure de dossiers. La détection de vues recherche un fichier de vue de zone correspondant dans l’ordre suivant :

/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

Associer le contrôleur à une zone

Les contrôleurs de zone sont désignés à l’aide de l’attribut [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();
    }
}

Ajouter une route de zone

Les routes de zones utilisent généralement un routage conventionnel plutôt qu’un routage par attributs. Le routage conventionnel est dépendant de l’ordre. En général, les routes avec des zones doivent être placées plus haut dans la table de routage, car elles sont plus spécifiques que les routes sans zone.

{area:...} peut être utilisé comme jeton dans les modèles de route si l’espace d’url est uniforme dans toutes les zones :

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

Dans le code précédent, exists applique une contrainte qui impose à la route de correspondre à une zone. Utilisation de {area:...} avec MapControllerRoute :

  • Est le mécanisme le moins compliqué pour ajouter un routage à des zones.
  • Correspond à tous les contrôleurs avec l’attribut [Area("Area name")].

Le code suivant utilise MapAreaControllerRoute pour créer deux routes de zone nommées :

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

Pour plus d’informations, consultez Routage de zones.

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée :

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

L’exemple de téléchargement inclut une vue partielle qui contient :

  • Les liens précédents.
  • Les liens similaires aux précédents, sauf que area n’est pas spécifié.

La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone et le même contrôleur.

Quand la zone ou le contrôleur n’est pas spécifié, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects avec le balisage qui ne spécifie pas la zone.

Pour plus d’informations, consultez Routage vers des actions de contrôleur.

Disposition partagée pour les zones en utilisant le fichier _ViewStart.cshtml

Pour partager une disposition commune pour l’ensemble de l’application, conservez _ViewStart.cshtml dans le dossier racine de l’application. Pour plus d’informations, consultez Disposition dans ASP.NET Core

Dossier racine de l’application

Le dossier racine de l’application est le dossier contenant le fichier Program.cs dans une application web créée avec les modèles ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, pour MVC et /Pages/_ViewImports.cshtml pour les PagesRazor ne sont pas importés dans les vues des zones. Utilisez l’une des approches suivantes pour fournir des importations d’affichage vers toutes les vues :

  • Ajoutez _ViewImports.cshtml au dossier racine de l’application. Un _ViewImports.cshtml dans le dossier racine de l’application s’applique à toutes les vues de l’application.
  • Copiez le fichier _ViewImports.cshtml dans le dossier d’affichage approprié sous zones. Par exemple, une application Pages Razor créée avec des comptes d’utilisateur individuels a un fichier _ViewImports.cshtml dans les dossiers suivants :
    • /Areas/Identity/Pages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

Le fichier _ViewImports.cshtml contient généralement des importations Tag Helpers, @using et des instructions @inject. Pour plus d’informations, consultez Importation de directives partagées.

Changer le dossier de zone par défaut où sont stockées les vues

Le code suivant remplace le dossier de zone par défaut "Areas" par "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();

Zones avec pages Razor

Les zones avec les Pages Razor requièrent un dossier Areas/<area name>/Pages à la racine de l’application. La structure de dossiers suivante est utilisée avec l’exemple d’application :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Pages
          • _ViewImports
          • À propos de
          • Index
      • Services
        • Pages
          • Gérer
            • À propos de
            • Index

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée (par exemple, 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>

L’exemple de code téléchargeable comprend une vue partielle qui contient les liens précédents et les mêmes liens sans spécification de la zone. La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone.

Quand la zone n’est pas spécifiée, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas, pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects. Prenons l’exemple des liens générés à partir de l’extrait de code suivant :

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

Pour le code précédent :

  • Le lien généré à partir de <a asp-page="/Manage/About"> est correct uniquement lorsque la dernière requête concernait une page dans la zone Services. Par exemple, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • Le lien généré à partir de <a asp-page="/About"> est correct uniquement lorsque la dernière requête concernait une page dans /Home.
  • Le code est issu du téléchargement de l’exemple.

Importer l’espace de noms et les Tag Helpers avec le fichier _ViewImports

Un fichier _ViewImports.cshtml peut être ajouté à chaque dossier Pages pour importer l’espace de noms et des Tag Helpers à chaque page Razor dans le dossier.

Considérez la zone Services de l’exemple de code, qui ne contient pas de fichier _ViewImports.cshtml. Le balisage suivant montre la Page /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>

Dans le balisage précédent :

  • Le nom de classe complet doit être utilisé pour spécifier le modèle (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Les Tag Helpers sont activés par @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Dans l’exemple de téléchargement, la zone Products contient le fichier _ViewImports.cshtml suivant :

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

Le balisage suivant montre la Page /Products/AboutRazor :

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

Dans le fichier précédent, l’espace de noms et la directive @addTagHelper sont importés dans le fichier par le fichier Areas/Products/Pages/_ViewImports.cshtml.

Pour plus d’informations, consultez Gestion de l’étendue des Tag Helpers et Importation de directives partagées.

Disposition partagée pour les zones Pages Razor

Pour partager une disposition commune pour l’ensemble de l’application, déplacez _ViewStart.cshtml dans le dossier racine de l’application.

Zones de publication

Tous les fichiers *.cshtml et autres fichiers dans le répertoire wwwroot sont publiés en sortie quand <Project Sdk="Microsoft.NET.Sdk.Web"> est inclus dans le fichier *.csproj.

Ajouter une zone MVC avec Visual Studio

Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet, sélectionnez AJOUTER > Nouvel élément généré automatiquement, puis sélectionnez Zone MVC.

Ressources supplémentaires

Les zones sont une fonctionnalité ASP.NET utilisée pour organiser des fonctionnalités connexes dans un groupe distinct :

  • Espace de noms pour le routage.
  • Structure des dossiers pour les vues et les pages Razor.

L’utilisation de zones a pour effet de créer une hiérarchie pour les besoins du routage en ajoutant un autre paramètre de route, area, à controller et action ou une Page Razorpage.

Les zones offrent un moyen de partitionner une application web ASP.NET Core en groupes fonctionnels plus petits, chacun avec son propre ensemble de Pages Razor, de contrôleurs, de vues et de modèles. Une zone est en réalité une structure au sein d’une application. Dans un projet web ASP.NET Core, les composants logiques comme Pages, Controller et View sont conservés dans différents dossiers. Le runtime ASP.NET Core utilise des conventions de nommage pour créer la relation entre ces composants. Pour une application volumineuse, il peut être avantageux de partitionner l’application en différentes zones de fonctionnalités de premier niveau. Par exemple, pour une application d’e-commerce à plusieurs entités, il peut s’agir de la caisse, de la facturation et de la recherche. Chacune de ces unités a sa propre zone pour accueillir les vues, les contrôleurs, les Pages Razor et les modèles.

Envisagez d’utiliser des zones dans un projet quand :

  • L’application est constituée de plusieurs composants fonctionnels globaux qui peuvent être logiquement séparés.
  • Vous pouvez partitionner l’application de façon à pouvoir travailler indépendamment sur chaque zone fonctionnelle.

Affichez ou téléchargez un exemple de code (procédure de téléchargement). L’exemple de code téléchargeable fournit une application de base pour tester les zones.

Si vous utilisez les Pages Razor, consultez Zones avec Pages Razor dans ce document.

Zones pour contrôleurs avec vues

Une application web ASP.NET Core type qui utilise des zones, des contrôleurs et des vues est constituée des éléments suivants :

  • Une structure de dossiers Zone.

  • Des contrôleurs avec l’attribut [Area] associer le contrôleur à la zone :

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La route de zone ajoutée au démarrage :

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

Structure de dossiers Zone

Imaginez une application qui contient deux groupes logiques, Produits et Services. En utilisant des zones, la structure de dossiers se présenterait comme suit :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Contrôleurs
          • HomeController.cs
          • ManageController.cs
        • Vues
          • Home
            • Index.cshtml
          • Gérer
            • Index.cshtml
            • About.cshtml
      • Services
        • Contrôleurs
          • HomeController.cs
        • Vues
          • Home
            • Index.cshtml

Si la disposition précédente est classique dans les cas où des zones sont utilisées, seuls les fichiers de vues sont nécessaires pour utiliser cette structure de dossiers. La détection de vues recherche un fichier de vue de zone correspondant dans l’ordre suivant :

/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

Associer le contrôleur à une zone

Les contrôleurs de zone sont désignés à l’aide de l’attribut [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();
        }
    }
}

Ajouter une route de zone

Les routes de zones utilisent généralement un routage conventionnel plutôt qu’un routage par attributs. Le routage conventionnel est dépendant de l’ordre. En général, les routes avec des zones doivent être placées plus haut dans la table de routage, car elles sont plus spécifiques que les routes sans zone.

{area:...} peut être utilisé comme jeton dans les modèles de route si l’espace d’url est uniforme dans toutes les zones :

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

Dans le code précédent, exists applique une contrainte qui impose à la route de correspondre à une zone. Utilisation de {area:...} avec MapControllerRoute :

  • Est le mécanisme le moins compliqué pour ajouter un routage à des zones.
  • Correspond à tous les contrôleurs avec l’attribut [Area("Area name")].

Le code suivant utilise MapAreaControllerRoute pour créer deux routes de zone nommées :

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

Pour plus d’informations, consultez Routage de zones.

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée :

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

L’exemple de téléchargement inclut une vue partielle qui contient :

  • Les liens précédents.
  • Les liens similaires aux précédents, sauf que area n’est pas spécifié.

La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone et le même contrôleur.

Quand la zone ou le contrôleur n’est pas spécifié, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects avec le balisage qui ne spécifie pas la zone.

Pour plus d’informations, consultez Routage vers des actions de contrôleur.

Disposition partagée pour les zones en utilisant le fichier _ViewStart.cshtml

Pour partager une disposition commune pour l’ensemble de l’application, conservez _ViewStart.cshtml dans le dossier racine de l’application. Pour plus d’informations, consultez Disposition dans ASP.NET Core

Dossier racine de l’application

Le dossier racine de l’application est le dossier contenant Startup.cs dans une application web créée avec les modèles ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, pour MVC et /Pages/_ViewImports.cshtml pour les Pages Razor, ne sont pas importés dans les vues des zones. Utilisez l’une des approches suivantes pour fournir des importations d’affichage vers toutes les vues :

  • Ajoutez _ViewImports.cshtml au dossier racine de l’application. Un _ViewImports.cshtml dans le dossier racine de l’application s’applique à toutes les vues de l’application.
  • Copiez le fichier _ViewImports.cshtml dans le dossier d’affichage approprié sous zones.

Le fichier _ViewImports.cshtml contient généralement des importations Tag Helpers, @using et des instructions @inject. Pour plus d’informations, consultez Importation de directives partagées.

Changer le dossier de zone par défaut où sont stockées les vues

Le code suivant remplace le dossier de zone par défaut "Areas" par "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();
}

Zones avec pages Razor

Les zones avec les Pages Razor requièrent un dossier Areas/<area name>/Pages à la racine de l’application. La structure de dossiers suivante est utilisée avec l’exemple d’application :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Pages
          • _ViewImports
          • À propos de
          • Index
      • Services
        • Pages
          • Gérer
            • À propos de
            • Index

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée (par exemple, 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>

L’exemple de code téléchargeable comprend une vue partielle qui contient les liens précédents et les mêmes liens sans spécification de la zone. La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone.

Quand la zone n’est pas spécifiée, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas, pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects. Prenons l’exemple des liens générés à partir de l’extrait de code suivant :

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

Pour le code précédent :

  • Le lien généré à partir de <a asp-page="/Manage/About"> est correct uniquement lorsque la dernière requête concernait une page dans la zone Services. Par exemple, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • Le lien généré à partir de <a asp-page="/About"> est correct uniquement lorsque la dernière requête concernait une page dans /Home.
  • Le code est issu du téléchargement de l’exemple.

Importer l’espace de noms et les Tag Helpers avec le fichier _ViewImports

Un fichier _ViewImports.cshtml peut être ajouté à chaque dossier Pages pour importer l’espace de noms et des Tag Helpers à chaque page Razor dans le dossier.

Observez la zone Services de l’exemple de code, qui ne contient pas de fichier _ViewImports.cshtml. Le balisage suivant montre la Page /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>

Dans le balisage précédent :

  • Le nom de classe complet doit être utilisé pour spécifier le modèle (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Les Tag Helpers sont activés par @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Dans le téléchargement de l’exemple, la zone Products contient le fichier _ViewImports.cshtml suivant :

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

Le balisage suivant montre la Page /Products/AboutRazor :

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

Dans le fichier précédent, l’espace de noms et la directive @addTagHelper sont importés dans le fichier par le fichier Areas/Products/Pages/_ViewImports.cshtml.

Pour plus d’informations, consultez Gestion de l’étendue des Tag Helpers et Importation de directives partagées.

Disposition partagée pour les zones Pages Razor

Pour partager une disposition commune pour l’ensemble de l’application, déplacez _ViewStart.cshtml dans le dossier racine de l’application.

Zones de publication

Tous les fichiers *.cshtml et autres fichiers dans le répertoire wwwroot sont publiés en sortie quand <Project Sdk="Microsoft.NET.Sdk.Web"> est inclus dans le fichier *.csproj.

Ajouter une zone MVC avec Visual Studio

Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet, sélectionnez AJOUTER > Nouvel élément généré automatiquement, puis sélectionnez Zone MVC.

Les zones sont une fonctionnalité d’ASP.NET qui servent à organiser les fonctionnalités associées dans un groupe sous la forme d’un espace de noms (pour le routage) et d’une structure de dossiers (pour les vues) distincts. L’utilisation de zones a pour effet de créer une hiérarchie pour les besoins du routage en ajoutant un autre paramètre de route, area, à controller et action ou une Page Razorpage.

Les zones offrent un moyen de partitionner une application web ASP.NET Core en groupes fonctionnels plus petits, chacun avec son propre ensemble de Pages Razor, de contrôleurs, de vues et de modèles. Une zone est en réalité une structure au sein d’une application. Dans un projet web ASP.NET Core, les composants logiques comme Pages, Controller et View sont conservés dans différents dossiers. Le runtime ASP.NET Core utilise des conventions de nommage pour créer la relation entre ces composants. Pour une application volumineuse, il peut être avantageux de partitionner l’application en différentes zones de fonctionnalités de premier niveau. Par exemple, pour une application d’e-commerce à plusieurs entités, il peut s’agir de la caisse, de la facturation et de la recherche. Chacune de ces unités a sa propre zone pour accueillir les vues, les contrôleurs, les Pages Razor et les modèles.

Envisagez d’utiliser des zones dans un projet quand :

  • L’application est constituée de plusieurs composants fonctionnels globaux qui peuvent être logiquement séparés.
  • Vous pouvez partitionner l’application de façon à pouvoir travailler indépendamment sur chaque zone fonctionnelle.

Affichez ou téléchargez un exemple de code (procédure de téléchargement). L’exemple de code téléchargeable fournit une application de base pour tester les zones.

Si vous utilisez les Pages Razor, consultez Zones avec Pages Razor dans ce document.

Zones pour contrôleurs avec vues

Une application web ASP.NET Core type qui utilise des zones, des contrôleurs et des vues est constituée des éléments suivants :

  • Une structure de dossiers Zone.

  • Des contrôleurs avec l’attribut [Area] associer le contrôleur à la zone :

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La route de zone ajoutée au démarrage :

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

Structure de dossiers Zone

Imaginez une application qui contient deux groupes logiques, Produits et Services. En utilisant des zones, la structure de dossiers se présenterait comme suit :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Contrôleurs
          • HomeController.cs
          • ManageController.cs
        • Vues
          • Home
            • Index.cshtml
          • Gérer
            • Index.cshtml
            • About.cshtml
      • Services
        • Contrôleurs
          • HomeController.cs
        • Vues
          • Home
            • Index.cshtml

Si la disposition précédente est classique dans les cas où des zones sont utilisées, seuls les fichiers de vues sont nécessaires pour utiliser cette structure de dossiers. La détection de vues recherche un fichier de vue de zone correspondant dans l’ordre suivant :

/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

Associer le contrôleur à une zone

Les contrôleurs de zone sont désignés à l’aide de l’attribut [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();
        }
    }
}

Ajouter une route de zone

Les routes de zones utilisent généralement un routage conventionnel plutôt qu’un routage par attributs. Le routage conventionnel est dépendant de l’ordre. En général, les routes avec des zones doivent être placées plus haut dans la table de routage, car elles sont plus spécifiques que les routes sans zone.

{area:...} peut être utilisé comme jeton dans les modèles de route si l’espace d’url est uniforme dans toutes les zones :

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

Dans le code précédent, exists applique une contrainte qui impose à la route de correspondre à une zone. Pour ajouter un routage à des zones, le mécanisme le moins compliqué consiste à utiliser {area:...}.

Le code suivant utilise MapAreaRoute pour créer deux routes de zone nommées :

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

Si vous utilisez MapAreaRoute avec ASP.NET Core 2.2, prenez connaissance de ce problème sur GitHub.

Pour plus d’informations, consultez Routage de zones.

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée :

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

Les liens générés par le code précédent sont valides où que ce soit dans l’application.

L’exemple de code téléchargeable comprend une vue partielle qui contient les liens précédents et les mêmes liens sans spécification de la zone. La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone et le même contrôleur.

Quand la zone ou le contrôleur n’est pas spécifié, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas, pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects.

Pour plus d’informations, consultez Routage vers des actions de contrôleur.

Disposition partagée pour les zones en utilisant le fichier _ViewStart.cshtml

Pour partager une disposition commune pour l’ensemble de l’application, déplacez _ViewStart.cshtml dans le dossier racine de l’application.

_ViewImports.cshtml

Dans son emplacement standard, /Views/_ViewImports.cshtml ne s’applique pas aux zones. Pour utiliser des Tag Helpers courants, @using ou @inject dans votre zone, vérifiez qu’un fichier _ViewImports.cshtml correct s’applique à vos vues de zone. Si vous souhaitez obtenir le même comportement dans toutes vos vues, déplacez /Views/_ViewImports.cshtml vers la racine de l’application.

Changer le dossier de zone par défaut où sont stockées les vues

Le code suivant remplace le dossier de zone par défaut "Areas" par "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();
}

Zones avec pages Razor

Les zones avec les Pages Razor requièrent un dossier Areas/<area name>/Pages à la racine de l’application. La structure de dossiers suivante est utilisée avec l’exemple d’application :

  • Nom du projet
    • Zones (Areas)
      • Produits
        • Pages
          • _ViewImports
          • À propos de
          • Index
      • Services
        • Pages
          • Gérer
            • À propos de
            • Index

Le code suivant tiré de l’exemple de code téléchargeable illustre une génération de liens avec la zone spécifiée (par exemple, 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>

Les liens générés par le code précédent sont valides où que ce soit dans l’application.

L’exemple de code téléchargeable comprend une vue partielle qui contient les liens précédents et les mêmes liens sans spécification de la zone. La vue partielle étant référencée dans le fichier de disposition, chaque page de l’application affiche les liens générés. Les liens générés sans spécification de la zone sont valides uniquement quand ils sont référencés dans une page contenue dans la même zone.

Quand la zone n’est pas spécifiée, le routage dépend des valeurs ambiantes. Les valeurs de route actuelles de la requête actuelle sont considérées comme des valeurs ambiantes pour la génération de liens. Dans de nombreux cas, pour l’exemple d’application, l’utilisation des valeurs ambiantes génère des liens incorrects. Prenons l’exemple des liens générés à partir de l’extrait de code suivant :

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

Pour le code précédent :

  • Le lien généré à partir de <a asp-page="/Manage/About"> est correct uniquement lorsque la dernière requête concernait une page dans la zone Services. Par exemple, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • Le lien généré à partir de <a asp-page="/About"> est correct uniquement lorsque la dernière requête concernait une page dans /Home.
  • Le code est issu du téléchargement de l’exemple.

Importer l’espace de noms et les Tag Helpers avec le fichier _ViewImports

Un fichier _ViewImports.cshtml peut être ajouté à chaque dossier Pages pour importer l’espace de noms et des Tag Helpers à chaque page Razor dans le dossier.

Observez la zone Services de l’exemple de code, qui ne contient pas de fichier _ViewImports.cshtml. Le balisage suivant montre la Page /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>

Dans le balisage précédent :

  • Le nom de domaine complet doit être utilisé pour spécifier le modèle (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Les Tag Helpers sont activés par @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Dans le téléchargement de l’exemple, la zone Products contient le fichier _ViewImports.cshtml suivant :

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

Le balisage suivant montre la Page /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>

Dans le fichier précédent, l’espace de noms et la directive @addTagHelper sont importés dans le fichier par le fichier Areas/Products/Pages/_ViewImports.cshtml.

Pour plus d’informations, consultez Gestion de l’étendue des Tag Helpers et Importation de directives partagées.

Disposition partagée pour les zones Pages Razor

Pour partager une disposition commune pour l’ensemble de l’application, déplacez _ViewStart.cshtml dans le dossier racine de l’application.

Zones de publication

Tous les fichiers *.cshtml et autres fichiers dans le répertoire wwwroot sont publiés en sortie quand <Project Sdk="Microsoft.NET.Sdk.Web"> est inclus dans le fichier *.csproj.