Layouts e sections aninhados em uma aplicação ASP.NET MVC 5

Alguns detalhes de layout em uma aplicação ASP.NET MVC podem ser desafiadores, especialmente quando se trata de algum site com uma estrutura um pouco mais complexa, que possua layouts aninhados.

Um dos problemas que podem surgir em aplicações desse tipo é como adicionar um JavaScript específico para uma sub página respeitando a diretiva de adicionar os scripts no final do código HTML da página, logo antes do fechamento da tag body.

Ao criarmos uma nova aplicação ASP.NET MVC utilizando o layout fornecido pelo Visual Studio, obtemos uma página de layout padrão, chamada _Layout.cshtml. Nela, existe uma section chamada “scripts”, conforme mostra a imagem abaixo, que é renderizada logo antes do fechamento da tag body do HTML da página.

Scripts Section
Scripts Section

É importante concentrar a escrita de scripts específicos de página nessa section, pois dessa forma o código JavaScript da página fica centralizado em um local específico, sendo mais fácil de localizar e de manter. Além disso, temos a garantia de que todos os arquivos de script incluídos na página foram carregados antes da execução do JavaScript específico da página, evitando erros devido a falta de referência.

Vamos a um exemplo prático. Suponha que temos uma aplicação que possui o seu layout padrão, _Layout.cshtml. Essa página de layout possui a section “scripts”. Além da página de layout padrão, também temos a necessidade de criar uma outra página de layout, que vai herdar os estilos da _Layout.cshtml, mas também vai adicionar elementos específicos. Vamos chamar essa página de _LayoutCustomizado.cshtml. Agora imagine que temos duas páginas que precisam utilizar esse layout customizado: Pagina1.cshtml e Pagina2.cshtml. A página 1 está ok, funciona corretamente, mas a página 2 possui um campo que utiliza o componente Date Picker, do jQuery UI. Como poderíamos fazer isso? Poderíamos adicionar o script diretamente no corpo da página, conforme imagem abaixo:

Script
Script no corpo da página.

Ao tentarmos executar a página, algo inesperado acontece. O Date Picker não funciona, pois ele depende do arquivo do jQuery UI referenciado pela _Layout.cshtml, só que esse arquivo ainda não foi carregado, pois a sua referência está localizada algumas linhas abaixo  da tag <script> que adicionamos na página 2:

Script2
Script no corpo da página não funciona. Clique para ver maior.

Ou seja, precisamos adicionar essa tag script na section “scripts”. Só que há outro problema aqui: a Pagina2.cshtml não herda diretamente da _Layout.cshtml, que contém a section “scripts”, e sim da _LayoutCustomizado.cshtml. Se tentarmos renderizar a section “scripts” na página 2, obteremos um erro em tempo de execução:

Script3
Erro em tempo de execução por falta de definição de section na página.

Como resolver esse problema? Adicionando a section “scripts” na página _LayoutCustomizado.cshtml, conforme imagem abaixo:

Script4
Redefinindo a section “scripts”

O “pulo do gato” aqui é que estamos redefinindo a section “scripts” da _Layout.cshtml dentro da _LayoutCustomizado.cshtml.

Dessa forma, ao rodar a aplicação, a página 2 funciona corretamente, exibindo o Date Picker:

 Script5
jQuery UI Date Picker funcionando corretamente. Clique para ver maior.

É uma solução simples, mas não tão óbvia assim. O código de exemplo se encontra no GitHub.