Layout no ASP.NET CoreLayout in ASP.NET Core

Por Steve Smith e Dave BrockBy Steve Smith and Dave Brock

Páginas e exibições com frequência compartilham elementos visuais e programáticos.Pages and views frequently share visual and programmatic elements. Este artigo demonstra como:This article demonstrates how to:

  • Usar layouts comuns.Use common layouts.
  • Compartilhar diretivas.Share directives.
  • Executar o código comum antes de renderizar páginas ou modos de exibição.Run common code before rendering pages or views.

Este documento discute os layouts para as duas abordagens diferentes ao ASP.NET Core MVC: Razor Pages e controladores com exibições.This document discusses layouts for the two different approaches to ASP.NET Core MVC: Razor Pages and controllers with views. Para este tópico, as diferenças são mínimas:For this topic, the differences are minimal:

  • Razor Pages estão na pasta Pages.Razor Pages are in the Pages folder.
  • Controladores com exibições usam uma pasta Views pasta exibições.Controllers with views uses a Views folder for views.

O que é um layoutWhat is a Layout

A maioria dos aplicativos Web tem um layout comum que fornece aos usuários uma experiência consistente durante sua navegação de uma página a outra.Most web apps have a common layout that provides the user with a consistent experience as they navigate from page to page. O layout normalmente inclui elementos comuns de interface do usuário, como o cabeçalho do aplicativo, elementos de menu ou de navegação e rodapé.The layout typically includes common user interface elements such as the app header, navigation or menu elements, and footer.

Exemplo de layout da página

Estruturas HTML comuns, como scripts e folhas de estilo, também são usadas com frequência por muitas páginas em um aplicativo.Common HTML structures such as scripts and stylesheets are also frequently used by many pages within an app. Todos esses elementos compartilhados podem ser definidos em um arquivo de layout, que pode então ser referenciado por qualquer exibição usada no aplicativo.All of these shared elements may be defined in a layout file, which can then be referenced by any view used within the app. Os layouts reduzem o código duplicado em exibições.Layouts reduce duplicate code in views.

Por convenção, o layout padrão de um aplicativo ASP.NET Core é chamado _Layout.cshtml.By convention, the default layout for an ASP.NET Core app is named _Layout.cshtml. O arquivo de layout para novos projetos do ASP.NET Core criados com os modelos:The layout file for new ASP.NET Core projects created with the templates:

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

    pasta de páginas no gerenciador de soluções

  • Controlador com exibições: Views/Shared/_Layout.cshtmlController with views: Views/Shared/_Layout.cshtml

pasta de exibições no gerenciador de soluções

O layout define um modelo de nível superior para exibições no aplicativo.The layout defines a top level template for views in the app. Os aplicativos não exigem um layout.Apps don't require a layout. Os aplicativos podem definir mais de um layout, com diferentes exibições especificando diferentes layouts.Apps can define more than one layout, with different views specifying different layouts.

O código a seguir mostra o arquivo de layout para um modelo de projeto criado com um controlador e exibições: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>

Especificando um layoutSpecifying a Layout

As exibições do Razor têm uma propriedade Layout.Razor views have a Layout property. As exibições individuais especificam um layout com a configuração dessa propriedade:Individual views specify a layout by setting this property:

@{
    Layout = "_Layout";
}

O layout especificado pode usar um caminho completo (por exemplo, /Pages/Shared/_Layout.cshtml ou /Views/Shared/_Layout.cshtml) ou um nome parcial (exemplo: _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). Quando um nome parcial for fornecido, o mecanismo de exibição do Razor pesquisará o arquivo de layout usando seu processo de descoberta padrão.When a partial name is provided, the Razor view engine searches for the layout file using its standard discovery process. A pasta em que o método do manipulador (ou controlador) existe é pesquisada primeiro, seguida pela pasta Shared.The folder where the handler method (or controller) exists is searched first, followed by the Shared folder. Esse processo de descoberta é idêntico àquele usado para descobrir exibições parciais.This discovery process is identical to the process used to discover partial views.

Por padrão, todo layout precisa chamar RenderBody.By default, every layout must call RenderBody. Sempre que a chamada a RenderBody for feita, o conteúdo da exibição será renderizado.Wherever the call to RenderBody is placed, the contents of the view will be rendered.

SeçõesSections

Um layout, opcionalmente, pode referenciar uma ou mais seções, chamando RenderSection.A layout can optionally reference one or more sections, by calling RenderSection. As seções fornecem uma maneira de organizar o local em que determinados elementos da página devem ser colocados.Sections provide a way to organize where certain page elements should be placed. Cada chamada a RenderSection pode especificar se essa seção é obrigatória ou opcional:Each call to RenderSection can specify whether that section is required or optional:

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

Se uma seção obrigatória não for encontrada, uma exceção será gerada.If a required section isn't found, an exception is thrown. As exibições individuais especificam o conteúdo a ser renderizado em uma seção usando a sintaxe Razor @section.Individual views specify the content to be rendered within a section using the @section Razor syntax. Se uma página ou exibição definir uma seção, ela precisará ser renderizada (ou ocorrerá um erro).If a page or view defines a section, it must be rendered (or an error will occur).

Uma definição @section de exemplo na exibição do Razor Pages:An example @section definition in Razor Pages view:

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

No código anterior, scripts/main.js é adicionado à seção scripts em uma página ou exibição.In the preceding code, scripts/main.js is added to the scripts section on a page or view. Outras páginas ou exibições no mesmo aplicativo podem não exigir esse script e não definirão uma seção de scripts.Other pages or views in the same app might not require this script and wouldn't define a scripts section.

A marcação a seguir usa o Auxiliar de Marca Parcial para renderizar _ValidationScriptsPartial.cshtml:The following markup uses the Partial Tag Helper to render _ValidationScriptsPartial.cshtml:

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

A marcação anterior foi gerada pela Identidade de scaffolding.The preceding markup was generated by scaffolding Identity.

As seções definidas em uma página ou exibição estão disponíveis apenas em sua página de layout imediata.Sections defined in a page or view are available only in its immediate layout page. Elas não podem ser referenciadas em parciais, componentes de exibição ou outras partes do sistema de exibição.They cannot be referenced from partials, view components, or other parts of the view system.

Ignorando seçõesIgnoring sections

Por padrão, o corpo e todas as seções de uma página de conteúdo precisam ser renderizados pela página de layout.By default, the body and all sections in a content page must all be rendered by the layout page. O mecanismo de exibição do Razor impõe isso acompanhando se o corpo e cada seção foram renderizados.The Razor view engine enforces this by tracking whether the body and each section have been rendered.

Para instruir o mecanismo de exibição a ignorar o corpo ou as seções, chame os métodos IgnoreBody e IgnoreSection.To instruct the view engine to ignore the body or sections, call the IgnoreBody and IgnoreSection methods.

O corpo e cada seção em uma página do Razor precisam ser renderizados ou ignorados.The body and every section in a Razor page must be either rendered or ignored.

Importando diretivas compartilhadasImporting Shared Directives

Exibições e páginas podem usar diretivas do Razor para importar namespaces e usar injeção de dependência.Views and pages can use Razor directives to importing namespaces and use dependency injection. Diretivas compartilhadas por diversas exibições podem ser especificadas em um arquivo _ViewImports.cshtml comum.Directives shared by many views may be specified in a common _ViewImports.cshtml file. O arquivo _ViewImports dá suporte às seguintes diretivas:The _ViewImports file supports the following directives:

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

O arquivo não dá suporte a outros recursos do Razor, como funções e definições de seção.The file doesn't support other Razor features, such as functions and section definitions.

Um arquivo _ViewImports.cshtml de exemplo: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

O arquivo _ViewImports.cshtml para um aplicativo ASP.NET Core MVC normalmente é colocado na pasta Pages (ou Views).The _ViewImports.cshtml file for an ASP.NET Core MVC app is typically placed in the Pages (or Views) folder. Um arquivo _ViewImports.cshtml pode ser colocado em qualquer pasta, caso em que só será aplicado a páginas ou exibições nessa pasta e em suas subpastas.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. Arquivos _ViewImports são processados começando no nível raiz e, em seguida, para cada pasta até o local da página ou da exibição em si._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. As configurações _ViewImports especificadas no nível raiz podem ser substituídas no nível da pasta._ViewImports settings specified at the root level may be overridden at the folder level.

Por exemplo, suponha:For example, suppose:

  • O arquivo _ViewImports.cshtml no nível de raiz inclui @model MyModel1 e @addTagHelper *, MyTagHelper1.The root level _ViewImports.cshtml file includes @model MyModel1 and @addTagHelper *, MyTagHelper1.
  • Um arquivo _ViewImports.cshtml de subpasta inclui @model MyModel2 e @addTagHelper *, MyTagHelper2.A subfolder _ViewImports.cshtml file includes @model MyModel2 and @addTagHelper *, MyTagHelper2.

Páginas e exibições na subpasta terão acesso a Auxiliares de Marca e ao modelo MyModel2.Pages and views in the subfolder will have access to both Tag Helpers and the MyModel2 model.

Se vários arquivos _ViewImports.cshtml forem encontrados na hierarquia de arquivos, o comportamento combinado das diretivas será:If multiple _ViewImports.cshtml files are found in the file hierarchy, the combined behavior of the directives are:

  • @addTagHelper, @removeTagHelper: todos são executados, em ordem@addTagHelper, @removeTagHelper: all run, in order
  • @tagHelperPrefix: o mais próximo à exibição substitui todos os outros@tagHelperPrefix: the closest one to the view overrides any others
  • @model: o mais próximo à exibição substitui todos os outros@model: the closest one to the view overrides any others
  • @inherits: o mais próximo à exibição substitui todos os outros@inherits: the closest one to the view overrides any others
  • @using: todos são incluídos; duplicatas são ignoradas@using: all are included; duplicates are ignored
  • @inject: para cada propriedade, o mais próximo à exibição substitui todos os outros com o mesmo nome de propriedade@inject: for each property, the closest one to the view overrides any others with the same property name

Executando o código antes de cada exibiçãoRunning Code Before Each View

Código que precisa ser executado antes de cada exibição ou página precisa ser colocada no arquivo _ViewStart.cshtml.Code that needs to run before each view or page should be placed in the _ViewStart.cshtml file. Por convenção, o arquivo _ViewStart.cshtml está localizado na pasta Pages (ou Views).By convention, the _ViewStart.cshtml file is located in the Pages (or Views) folder. As instruções listadas em _ViewStart.cshtml são executadas antes de cada exibição completa (não layouts nem exibições parciais).The statements listed in _ViewStart.cshtml are run before every full view (not layouts, and not partial views). Como ViewImports.cshtml, _ViewStart.cshtml é hierárquico.Like ViewImports.cshtml, _ViewStart.cshtml is hierarchical. Se um arquivo _ViewStart.cshtml for definido na pasta de exibições ou páginas, ele será executado depois daquele definido na raiz da pasta Pages (ou Views) (se houver).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).

Um arquivo _ViewStart.cshtml de amostra:A sample _ViewStart.cshtml file:

@{
    Layout = "_Layout";
}

O arquivo acima especifica que todas as exibições usarão o layout _Layout.cshtml.The file above specifies that all views will use the _Layout.cshtml layout.

_ViewStart.cshtml é _ViewImports.cshtml normalmente não são colocados na pasta /Pages/Shared (ou /Views/Shared)._ViewStart.cshtml and _ViewImports.cshtml are not typically placed in the /Pages/Shared (or /Views/Shared) folder. As versões no nível do aplicativo desses arquivos devem ser colocadas diretamente na pasta /Pages (ou /Views).The app-level versions of these files should be placed directly in the /Pages (or /Views) folder.