Partilhar via


Layout no ASP.NET Core

Por Steve Smith e Dave Brock

Páginas e vistas partilham frequentemente elementos visuais e programáticos. Este artigo demonstra como:

  • Use layouts comuns.
  • Diretivas de compartilhamento.
  • Executa código comum antes de renderizar páginas ou visualizações.

Este documento discute layouts para as duas abordagens diferentes ao ASP.NET Core MVC: Razor Páginas e controladores com vistas. Para este tema, as diferenças são mínimas:

  • Razor As páginas estão na pasta Páginas .
  • Controladores com vistas usam uma pasta Views para visualizações.

O que é um layout

A maioria das aplicações web tem um layout comum que proporciona ao utilizador uma experiência consistente enquanto navega de página em página. O layout inclui tipicamente elementos comuns da interface do utilizador, como o cabeçalho da aplicação, elementos de navegação ou menu, e rodapés.

Exemplo de layout de página

Estruturas HTML comuns, como scripts e folhas de estilo, também são frequentemente usadas por muitas páginas dentro de uma aplicação. Todos estes elementos partilhados podem ser definidos num ficheiro de layout , que pode depois ser referenciado por qualquer vista usada na aplicação. Os layouts reduzem o código duplicado nas vistas.

Por convenção, o layout padrão de uma aplicação ASP.NET Core chama-se _Layout.cshtml. Os ficheiros de layout para novos projetos ASP.NET Core criados com os modelos são:

  • Razor Páginas: Pages/Shared/_Layout.cshtml

    pasta Páginas no Explorador de Soluções

  • Controlador com visualizações: Views/Shared/_Layout.cshtml

    Pasta de Vistas no Explorador de Soluções

O layout define um modelo de topo para as visualizações na aplicação. As aplicações não precisam de layout. As aplicações podem definir mais do que um layout, especificando vistas diferentes para layouts distintos.

O código seguinte mostra o ficheiro de layout de um projeto criado por template com um controlador e visualizações:

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

Especificação de um layout

Razor As visualizações têm uma Layout propriedade. As vistas individuais especificam um layout definindo esta propriedade:

@{
    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). Quando é fornecido um nome parcial, o Razor motor de visualização procura o ficheiro de layout usando o seu processo padrão de descoberta. A pasta onde existe o método handler (ou controlador) é pesquisada primeiro, seguida da pasta Partilhada . Este processo de descoberta é idêntico ao utilizado para descobrir vistas parciais.

Por defeito, cada layout deve chamar RenderBody. Onde quer que a chamada RenderBody seja feita, o conteúdo da visualização será renderizado.

Secções

Um layout pode, opcionalmente, referenciar uma ou mais secções, chamando RenderSection. As secções fornecem uma forma de organizar onde certos elementos da página devem ser colocados. Cada chamada a RenderSection pode especificar se essa secção é obrigatória ou opcional:

<script type="text/javascript" src="~/scripts/global.js"></script>

@RenderSection("Scripts", required: false)

Se não for encontrada uma secção obrigatória, é lançada uma exceção. As vistas individuais especificam o conteúdo a ser renderizado dentro de uma secção usando a @sectionRazor sintaxe. Se uma página ou vista define uma secção, esta deve ser renderizada (caso contrário ocorrerá um erro).

Um exemplo @section de definição na Razor visualização de Páginas:

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

No código anterior, scripts/main.js é adicionado à scripts secção numa página ou visualização. Outras páginas ou vistas na mesma aplicação podem não precisar deste script e não definiriam uma secção de scripts.

A marcação seguinte utiliza o Partial Tag Helper para renderizar _ValidationScriptsPartial.cshtml:

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

A marcação anterior foi gerada por scaffolding Identity.

As secções definidas numa página ou vista estão disponíveis apenas na sua página de layout imediato. Não podem ser referenciados a partir de fragmentos, componentes de visualização ou outras partes do sistema de visualização.

Ignorar secções

Por defeito, o corpo e todas as secções de uma página de conteúdo devem ser todos renderizados pela página de layout. O Razor motor de visualização reforça isto ao rastrear se o corpo e cada secção foram renderizados.

Para instruir o motor de visualização a ignorar o corpo ou as secções, chame os métodos IgnoreBody e IgnoreSection.

O corpo e cada secção de uma Razor página devem ser renderizados ou ignorados.

Importação de Diretivas Partilhadas

Visualizações e páginas podem usar Razor diretivas para importar namespaces e usar injeção de dependências. Diretivas partilhadas por muitas vistas podem ser especificadas num ficheiro comum _ViewImports.cshtml . O _ViewImports ficheiro suporta as seguintes diretivas:

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

O ficheiro não suporta outras Razor funcionalidades, como funções e definições de secção.

Um ficheiro de exemplo _ViewImports.cshtml :

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

O _ViewImports.cshtml ficheiro de uma aplicação ASP.NET Core MVC é normalmente colocado na pasta Páginas (ou Vistas). Um _ViewImports.cshtml ficheiro pode ser colocado em qualquer pasta, caso em que só será aplicado a páginas ou vistas dentro dessa pasta e nas suas subpastas. _ViewImports Os ficheiros são processados começando pelo nível raiz e depois para cada pasta, até à localização da página ou da própria visualização. _ViewImports As configurações especificadas no nível da raiz podem ser substituídas ao nível da pasta.

Por exemplo, suponha:

  • O ficheiro de nível _ViewImports.cshtml raiz inclui @model MyModel1 e @addTagHelper *, MyTagHelper1.
  • Um ficheiro de subpasta _ViewImports.cshtml inclui @model MyModel2 e @addTagHelper *, MyTagHelper2.

As páginas e vistas na subpasta terão acesso tanto aos Ajudantes de Etiquetas como ao MyModel2 modelo.

Se forem encontrados múltiplos _ViewImports.cshtml ficheiros na hierarquia de ficheiros, o comportamento combinado das diretivas é:

  • @addTagHelper, @removeTagHelper: todos executam, em sequência
  • @tagHelperPrefix: a mais próxima da vista sobrepõe-se a qualquer outra
  • @model: a mais próxima da vista sobrepõe-se a qualquer outra
  • @inherits: a mais próxima da vista sobrepõe-se a qualquer outra
  • @using: todos estão incluídos; Duplicados são ignorados
  • @inject: para cada propriedade, a mais próxima da vista sobrepõe-se a quaisquer outras com o mesmo nome de propriedade

Executar código antes de cada vista

O código que precisa de ser executado antes de cada vista ou página deve ser colocado no _ViewStart.cshtml ficheiro. Por convenção, o _ViewStart.cshtml ficheiro está localizado na pasta Páginas (ou Vistas). As instruções listadas em _ViewStart.cshtml são executadas antes de cada visualização completa (nem layouts, nem vistas parciais). Tal como o ViewImports.cshtml, _ViewStart.cshtml é hierárquico. Se um _ViewStart.cshtml ficheiro estiver definido na pasta View ou Pages, será executado depois daquele definido na raiz da pasta Pages (ou Views) (se houver).

Um ficheiro de exemplo _ViewStart.cshtml :

@{
    Layout = "_Layout";
}

O ficheiro acima especifica que todas as vistas usarão o _Layout.cshtml layout.

_ViewStart.cshtml e _ViewImports.cshtmlnormalmente não são colocados na pasta /Pages/Shared (ou /Views/Shared). As versões ao nível da aplicação destes ficheiros devem ser colocadas diretamente na pasta /Pages (ou /Views).