Disposition dans ASP.NET CoreLayout in ASP.NET Core

Article rédigé par Steve Smith et Dave BrockBy Steve Smith and Dave Brock

Les pages et les vues ont souvent des éléments visuels et programmatiques en commun.Pages and views frequently share visual and programmatic elements. Cet article montre comment :This article demonstrates how to:

  • Utiliser des dispositions communes.Use common layouts.
  • Partager des directives.Share directives.
  • Exécuter du code commun avant d’afficher des pages ou des vues.Run common code before rendering pages or views.

Ce document traite des dispositions pour les deux approches différentes d’ASP.NET Core MVC : Razor Pages et les contrôleurs avec vues.This document discusses layouts for the two different approaches to ASP.NET Core MVC: Razor Pages and controllers with views. Pour cette rubrique, les différences sont minimes :For this topic, the differences are minimal:

  • Razor Pages se trouve dans le dossier Pages.Razor Pages are in the Pages folder.
  • Les contrôleurs avec vues utilisent un dossier Views pour les vues.Controllers with views uses a Views folder for views.

Qu’est-ce qu’une disposition ?What is a Layout

La plupart des applications web ont une disposition commune pour offrir aux utilisateurs une expérience homogène quand ils naviguent de page en page.Most web apps have a common layout that provides the user with a consistent experience as they navigate from page to page. En général, la disposition inclut des éléments d’interface utilisateur communs à toute l’application, tels que l’en-tête, des éléments de menu ou de navigation et le pied de page.The layout typically includes common user interface elements such as the app header, navigation or menu elements, and footer.

Exemple de disposition de page

Les structures HTML communes comme les scripts et les feuilles de style sont aussi fréquemment utilisées par bon nombre de pages dans une application.Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. Tous ces éléments partagés peuvent être définis dans un fichier de disposition, qui peut ensuite être référencé par n’importe quelle vue utilisée dans l’application.All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Les dispositions réduisent les doublons de code dans les vues.Layouts reduce duplicate code in views.

Par convention, la disposition par défaut d’une application ASP.NET Core se nomme _Layout.cshtml.By convention, the default layout for an ASP.NET Core app is named _Layout.cshtml. Les fichiers de disposition pour les projets ASP.NET Core créés avec les modèles sont les suivants :The layout files for new ASP.NET Core projects created with the templates are:

  • Pages Razor : Pages/Shared/_Layout.cshtmlRazor Pages: Pages/Shared/_Layout.cshtml

    Dossier Pages dans l’Explorateur de solutions

  • Contrôleur avec vues : Views/Shared/_Layout.cshtmlController with views: Views/Shared/_Layout.cshtml

    Dossier Views dans l’Explorateur de solutions

La disposition définit un modèle général pour les vues dans l’application.The layout defines a top level template for views in the app. Les applications ne nécessitent pas de disposition.Apps don't require a layout. Les applications peuvent définir plusieurs dispositions, avec des vues différentes spécifiant des dispositions différentes.Apps can define more than one layout, with different views specifying different layouts.

Le code suivant montre le fichier de disposition pour un projet créé avec un modèle, avec un contrôleur et des vues :The following code shows the layout file for a template created project with a controller and views:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication1</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">WebApplication1</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-page="/Index">Home</a></li>
                    <li><a asp-page="/About">About</a></li>
                    <li><a asp-page="/Contact">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 - WebApplication1</p>
        </footer>
    </div>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
        </script>
        <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
        </script>
        <script src="~/js/site.min.js" asp-append-version="true"></script>
    </environment>

    @RenderSection("Scripts", required: false)
</body>
</html>

Spécification d’une dispositionSpecifying a Layout

Les vues Razor ont une propriété Layout.Razor views have a Layout property. Chaque vue spécifie une disposition en définissant cette propriété :Individual views specify a layout by setting this property:

@{
    Layout = "_Layout";
}

La disposition spécifiée peut utiliser un chemin complet (par exemple, /Pages/Shared/_Layout.cshtml ou /Views/Shared/_Layout.cshtml) ou un nom partiel (exemple : _Layout).The layout specified can use a full path (for example, /Pages/Shared/_Layout.cshtml or /Views/Shared/_Layout.cshtml) or a partial name (example: _Layout). Quand un nom partiel est fourni, le moteur de vue Razor recherche le fichier de disposition en utilisant son processus de détection habituel.When a partial name is provided, the Razor view engine searches for the layout file using its standard discovery process. Le dossier où se trouve la méthode de gestionnaire (ou contrôleur) est parcouru en premier, suivi du dossier Shared.The folder where the handler method (or controller) exists is searched first, followed by the Shared folder. Ce processus de détection est le même que celui utilisé pour détecter les vues partielles.This discovery process is identical to the process used to discover partial views.

Par défaut, chaque disposition doit appeler RenderBody.By default, every layout must call RenderBody. À chaque appel de RenderBody, le contenu de la vue est affiché.Wherever the call to RenderBody is placed, the contents of the view will be rendered.

SectionsSections

Une disposition peut éventuellement faire référence à une ou plusieurs sections, en appelant RenderSection.A layout can optionally reference one or more sections, by calling RenderSection. Les sections sont un moyen d’organiser certains éléments dans la page.Sections provide a way to organize where certain page elements should be placed. Chaque appel à RenderSection peut spécifier si cette section est obligatoire ou facultative :Each call to RenderSection can specify whether that section is required or optional:

@section Scripts {
    @RenderSection("Scripts", required: false)
}

Si une section obligatoire est introuvable, une exception est levée.If a required section isn't found, an exception is thrown. Chacune des vues spécifient le contenu à afficher dans une section à l’aide de la syntaxe Razor @section.Individual views specify the content to be rendered within a section using the @section Razor syntax. Si une page ou vue définit une section, elle doit être affichée (sinon, une erreur se produit).If a page or view defines a section, it must be rendered (or an error will occur).

Exemple de définition @section dans une vue Razor Pages :An example @section definition in Razor Pages view:

@section Scripts {
     <script type="text/javascript" src="/scripts/main.js"></script>
}

Dans le code précédent, scripts/main.js est ajouté à la section scripts sur une page ou vue.In the preceding code, scripts/main.js is added to the scripts section on a page or view. Il est possible que les autres pages ou vues de la même application ne nécessitent pas ce script et ne définissent pas de section de scripts.Other pages or views in the same app might not require this script and wouldn't define a scripts section.

Le balisage suivant utilise le Tag Helper Partial pour afficher _ValidationScriptsPartial.cshtml :The following markup uses the Partial Tag Helper to render _ValidationScriptsPartial.cshtml:

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

Le balisage précédent était le résultat de la génération d’un modèle automatique d’identité.The preceding markup was generated by scaffolding Identity.

Les sections définies dans une page ou vue sont disponibles uniquement dans sa page de disposition la plus proche.Sections defined in a page or view are available only in its immediate layout page. Elles ne peuvent pas être référencées à partir de vues partielles, de composants de vue ou d’autres parties du système de vue.They cannot be referenced from partials, view components, or other parts of the view system.

Ignorer des sectionsIgnoring sections

Par défaut, le corps et toutes les sections dans une page de contenu doivent intégralement être affichés par la page de disposition.By default, the body and all sections in a content page must all be rendered by the layout page. Le moteur de vue Razor s’assure que c’est bien le cas en vérifiant que le corps et chaque section ont été affichés.The Razor view engine enforces this by tracking whether the body and each section have been rendered.

Pour indiquer au moteur de vue d’ignorer le corps ou les sections, appelez les méthodes IgnoreBody et IgnoreSection.To instruct the view engine to ignore the body or sections, call the IgnoreBody and IgnoreSection methods.

Le corps et toutes les sections dans une page Razor doivent être soit affichés, soit ignorés.The body and every section in a Razor page must be either rendered or ignored.

Importation de directives partagéesImporting Shared Directives

Les vues et les pages peuvent utiliser des directives Razor pour importer des espaces de noms et utiliser l’injection de dépendances.Views and pages can use Razor directives to importing namespaces and use dependency injection. Les directives partagées par plusieurs vues peuvent être spécifiées dans un fichier _ViewImports.cshtml commun.Directives shared by many views may be specified in a common _ViewImports.cshtml file. Le fichier _ViewImports prend en charge les directives suivantes :The _ViewImports file supports the following directives:

  • @addTagHelper
  • @removeTagHelper
  • @tagHelperPrefix
  • @using
  • @model
  • @inherits
  • @inject

Le fichier ne prend pas en charge les autres fonctionnalités Razor, telles que les fonctions et les définitions de section.The file doesn't support other Razor features, such as functions and section definitions.

Exemple de fichier _ViewImports.cshtml :A sample _ViewImports.cshtml file:

@using WebApplication1
@using WebApplication1.Models
@using WebApplication1.Models.AccountViewModels
@using WebApplication1.Models.ManageViewModels
@using Microsoft.AspNetCore.Identity
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Le fichier _ViewImports.cshtml pour une application ASP.NET Core MVC est généralement créé dans le dossier Pages (ou Views).The _ViewImports.cshtml file for an ASP.NET Core MVC app is typically placed in the Pages (or Views) folder. Un fichier _ViewImports.cshtml peut être créé dans un autre dossier ; dans ce cas, il s’applique uniquement aux pages ou vues contenues dans ce dossier et ses sous-dossiers.A _ViewImports.cshtml file can be placed within any folder, in which case it will only be applied to pages or views within that folder and its subfolders. Les fichiers _ViewImports sont traités à partir de la racine, puis pour chaque dossier conduisant à l’emplacement de la page ou vue elle-même._ViewImports files are processed starting at the root level and then for each folder leading up to the location of the page or view itself. Les paramètres _ViewImports spécifiés au niveau de la racine peuvent être remplacés au niveau du dossier._ViewImports settings specified at the root level may be overridden at the folder level.

Par exemple, supposons que :For example, suppose:

  • Le fichier _ViewImports.cshtml au niveau de la racine inclut @model MyModel1 et @addTagHelper *, MyTagHelper1.The root level _ViewImports.cshtml file includes @model MyModel1 and @addTagHelper *, MyTagHelper1.
  • Le fichier _ViewImports.cshtml dans un sous-dossier inclut @model MyModel2 et @addTagHelper *, MyTagHelper2.A subfolder _ViewImports.cshtml file includes @model MyModel2 and @addTagHelper *, MyTagHelper2.

Les pages et vues dans le sous-dossier ont accès aux Tag Helpers et au modèle MyModel2.Pages and views in the subfolder will have access to both Tag Helpers and the MyModel2 model.

Si la hiérarchie des fichiers comprend plusieurs fichiers _ViewImports.cshtml, le comportement combiné des directives est le suivant :If multiple _ViewImports.cshtml files are found in the file hierarchy, the combined behavior of the directives are:

  • @addTagHelper, @removeTagHelper : les deux directives sont exécutées, dans l’ordre@addTagHelper, @removeTagHelper: all run, in order
  • @tagHelperPrefix : la directive la plus proche de la vue se substitue aux autres@tagHelperPrefix: the closest one to the view overrides any others
  • @model : la directive la plus proche de la vue se substitue aux autres@model: the closest one to the view overrides any others
  • @inherits : la directive la plus proche de la vue se substitue aux autres@inherits: the closest one to the view overrides any others
  • @using : toutes les directives sont incluses ; les doublons sont ignorés@using: all are included; duplicates are ignored
  • @inject : pour chaque propriété, la plus proche de la vue se substitue aux autres propriétés ayant le même nom@inject: for each property, the closest one to the view overrides any others with the same property name

Exécution du code avant chaque vueRunning Code Before Each View

Le code qui doit s’exécuter avant chaque vue ou page doit être placé dans le fichier _ViewStart.cshtml.Code that needs to run before each view or page should be placed in the _ViewStart.cshtml file. Par convention, le fichier _ViewStart.cshtml se trouve dans le dossier Pages (ou Views).By convention, the _ViewStart.cshtml file is located in the Pages (or Views) folder. Les instructions contenues dans _ViewStart.cshtml sont exécutées avant chaque vue complète (donc hors dispositions et vues partielles).The statements listed in _ViewStart.cshtml are run before every full view (not layouts, and not partial views). Comme ViewImports.cshtml, _ViewStart.cshtml est hiérarchique.Like ViewImports.cshtml, _ViewStart.cshtml is hierarchical. Si un fichier _ViewStart.cshtml est défini dans le dossier des vues ou des pages, il est exécuté après celui qui est défini à la racine du dossier Pages (ou Views) (le cas échéant).If a _ViewStart.cshtml file is defined in the view or pages folder, it will be run after the one defined in the root of the Pages (or Views) folder (if any).

Exemple de fichier _ViewStart.cshtml :A sample _ViewStart.cshtml file:

@{
    Layout = "_Layout";
}

Le fichier ci-dessus spécifie que toutes les vues doivent utiliser la disposition _Layout.cshtml.The file above specifies that all views will use the _Layout.cshtml layout.

_ViewStart.cshtml et _ViewImports.cshtml ne sont pas généralement placés dans le dossier /Pages/Shared (ou /Views/Shared)._ViewStart.cshtml and _ViewImports.cshtml are not typically placed in the /Pages/Shared (or /Views/Shared) folder. Les versions de ces fichiers qui sont au niveau de l’application doivent être placées directement dans le dossier /Pages (ou /Views).The app-level versions of these files should be placed directly in the /Pages (or /Views) folder.