Este é outro post de uma série de posts que estou escrevendo, que cobrem alguns dos novos recursos da ASP.NET MVC 3:
No
post de hoje eu vou entrar em mais detalhes sobre como páginas de
Layout funcionam com o Razor. Em particular, eu cobrirei como você pode
ter múltiplas "seções", não-contíguas, substituíveis dentro de um
arquivo de layout - permitindo que as visões baseadas em layouts,
opcionalmente, "preencham" estas diferentes seções no tempo de
execução. A sintaxe do Razor para fazer isso é limpa e concisa.
Eu
também mostrarei como você pode verificar dinamicamente no tempo de
execução se uma seção de layout em especial foi definida, e como você
pode fornecer conteúdo alternativo (ou mesmo um layout alternativo) no
caso de uma seção não ter sido especificada dentro de um modelo de
visão. Isso fornece uma maneira poderosa e fácil para personalizar a
interface do usuário (UI) do seu site e torná-la limpa e DRY a partir de uma
perspectiva de implementação.
O que são Layouts?
Você
geralmente deseja manter uma aparência consistente em todas as páginas
dentro do seu web-site/applicação. A ASP.NET 2.0 introduziu o conceito
de "páginas-mestre", que ajudam a ativar esse recurso quando páginas
.aspx ou modelos baseados em .aspx são usados. O Razor também suporta
esse conceito com um recurso chamado "layouts" - que permite que você
defina um template/modelo comum para o site, e então herde sua aparência
em todas as visões/páginas do seu site.
Eu já escrevi sobre como funcionam os arquivos de layout com o Razor no meu post ASP.NET MVC 3: Layouts com Razor. O post de hoje vai mais fundo e detalha como você pode definir
múltiplas regiões, não-contíguas, substituíveis em um arquivo de layout
que você pode, opcionalmente, "preencher" no tempo de execução.
Cenário de Layout de um Site
Vejamos
como podemos implementar um cenário comum de layout de um site com a
ASP.NET MVC 3 e o Razor. Especificamente, vamos implementar alguma UI
onde temos um cabeçalho e rodapé comuns em todas as nossas páginas.
Também vamos adicionar uma seção "sidebar" (barra lateral) à direita do
nosso layout comum do site.
Em algumas páginas, vamos personalizar a barra lateral para incluir conteúdos específicos para a página que estamos visitando:
E
em outras páginas (que não tenham conteúdo personalizado para a barra
lateral), vamos recorrer a um "conteúdo padrão" para a barra lateral:
Nós vamos usar a ASP.NET MVC 3 e o Razor para permitir esta personalização de uma forma agradável e limpa.
A seguir estão algumas instruções passo-a-passo sobre como criar o site acima com a ASP.NET MVC 3 e o Razor.
Parte 1: Criar um Novo Projeto com um Layout para a seção "Body"
Vamos
começar usando o comando do menu "File->New Project"
(Arquivo->Novo Projeto) dentro do Visual Studio para criar um novo
projeto ASP.NET MVC 3. Nós vamos criar o novo projeto usando a opção de
modelo "Empty" (Vazio):
Isso irá criar um novo projeto que não tem controladores padrão:
Criando um HomeController
Nós,
então, clicaremos com o botão direito do mouse na pasta "Controllers"
do nosso projeto recém-criado e escolheremos o comando do menu de
contexto "Add-> Controller" (Adicionar->Controlador). Isso fará
com que a janela de diálogo "Add Controller" (Adicionar Controlador)
apareça:
Nós
vamos nomear o novo controlador que criamos com "HomeController". Quando clicamos no botão "Add", o Visual Studio irá adicionar uma classe
HomeController em nosso projeto com um método de ação "Index" padrão
que retorna uma visão:
Nós
não precisaremos escrever qualquer lógica no controlador para
implementarmos este exemplo - então vamos deixar o código padrão como
está.
Criando um Modelo de Visão
Nosso próximo
passo será implementar o modelo de visão associado ao método de ação
Index do controlador HomeController. Para implementar o modelo de visão, vamos
clicar com o botão direito do mouse no método "HomeController.Index()" e
selecionaremos o comando "Add View" (Adicionar Visão) para criar um
modelo de visão para a nossa home page:
Isso fará com que a janela de diálogo "Add View" (Adicionar Visão) apareça dentro do Visual Studio.
Nós
não precisamos alterar nenhuma das configurações padrão na janela de
diálogo acima (o nome do modelo de visão foi preenchido automaticamente
com Index porque invocamos o comando do menu de contexto "Add View"
dentro do método Index).
Quando clicamos no botão "Add" na
janela de diálogo, um modelo de visão do Razor chamado "Index.cshtml"
será adicionado na pasta \Views\Home\ dentro do nosso projeto. Vamos
adicionar algum conteúdo padrão simples e estático nele:
Observe
acima que não temos uma seção <html> ou <body> definida
dentro do nosso modelo de visão. Isto é porque nós vamos contar com um
modelo de layout para suprir esses elementos e o usaremos para definir o
layout e estrutura comuns para o nosso site (garantindo que ele seja
consistente em todas as páginas e URLs dentro do site).
Personalizando/Customizando o nosso Arquivo de Layout
Vamos
abrir e personalizar o arquivo padrão "_Layout.cshtml" que foi
adicionado automaticamente na pasta \Views\Shared quando criamos o nosso
novo projeto:
O
arquivo de layout padrão (acima) é bastante básico e simplesmente exibe
um título (se especificado no Controlador ou no modelo de Visão) e
adiciona links para uma folha de estilo CSS e para a biblioteca jQuery. A chamada para o método "RenderBody()" indica onde o conteúdo do corpo
(body) principal do nosso arquivo Index.cshtml será incorporado na saída
enviada ao navegador.
Vamos modificar o modelo de layout para adicionar um cabeçalho, rodapé e barra lateral comum para o site:
Vamos então editar o arquivo "Site.css" dentro da pasta\Content do nosso projeto para adicionar 4 regras de CSS nele:
E
agora, quando executamos o projeto e acessamos a URL da home page "/"
do nosso projeto, veremos uma página como a mostrada a seguir:
Observe
como o conteúdo da modelo de visão do método de ação Index do
HomeController e o modelo de Layout Compartilhado do site foram unidos
em uma única resposta HTML.
A seguir está o código HTML enviado do servidor:
Parte 2: Adicionando uma Seção "sidebar" (Barra lateral)
Nosso
site tem até agora um modelo de layout que tem apenas uma "seção" - a
qual chamamos de seção principal "body" (corpo) da resposta.
O
Razor também suporta a capacidade de adicionar "named sections" (seções
nomeadas) em modelos de layout. Essas seções podem ser definidas em
qualquer parte do arquivo de layout (inclusive dentro da seção
<head> da página HTML), e permitem que você gere conteúdo dinâmico
em múltiplas regiões, não-contíguas da resposta final.
Definindo a seção "Sidebar" em nosso Layout
Vamos
atualizar o nosso modelo de layout para definir uma seção de conteúdo
adicional "Sidebar" que será renderizada/mostrada dentro da região
<div id="sidebar"> presente em nosso código HTML. Podemos fazer
isso chamando o método de ajuda RenderSection(string sectionName, bool required) dentro do nosso arquivo Layout.cshtml igual ao mostrado a seguir:
O
primeiro parâmetro para o método de ajuda "RenderSection()" especifica o
nome da seção que queremos mostrar naquele local do modelo de layout. O
segundo parâmetro é opcional, e nos permite definir se a seção que
estamos mostrando é necessária ou não. Se a seção for "required"
(necessária), o Razor lançará um erro em tempo de execução se aquela
seção não estiver implementada dentro de um modelo de visão que é
baseado no arquivo de layout (o que pode tornar mais fácil rastrear
erros de conteúdo). Se uma seção não for exigida, então a sua presença
dentro de um modelo de visão é opcional, e o código do método
RenderSection() acima não mostrará nada no tempo de execução, se a seção
não estiver definida.
Agora que fizemos as alterações acima no
nosso arquivo de layout, vamos atualizar a página no nosso browser para
vermos a aparência atual da nossa home page:
Observe
como atualmente não temos nenhum conteúdo dentro do nosso <div>
SideBar - isto se deve ao fato de o modelo de visão Index.cshtml ainda
não implementar a nossa nova seção "sidebar".
Implementando a Seção "Sidebar" no nosso Modelo de Visão
Vamos
mudar a nossa home-page para que ela tenha uma seção SideBar que mostra
algum conteúdo personalizado. Podemos fazer isso abrindo o modelo de
visão Index.cshtml, e acrescentando um nova seção "SiderBar" nele. Nós
vamos fazer isso usando a sintaxe do Razor @section NomeDaSecao { }:
Poderíamos
ter colocado nossa seção SideBar @section em qualquer lugar dentro do
modelo de visão. Eu acho que o código parece ser mais limpo quando é
definido na parte superior ou inferior do arquivo - mas isso é
simplesmente preferência pessoal.
Você pode incluir qualquer
conteúdo ou código que você queira dentro de declarações @section.
Observe acima como eu tenho um trecho de código C# que mostra a hora
atual na parte inferior da seção SideBar. Eu poderia ter escrito também
algum código que usasse métodos de ajuda HTML/AJAX da ASP.NET MVC ou
que acessasse quaisquer objetos fortemente tipados do modelo passados
para o modelo de visão Index.cshtml.
Agora que fizemos as
alterações acima no modelo de visão, quando atualizarmos a página no
browser novamente, veremos que o nosso conteúdo da barra lateral
(SideBar) - que é específico para a página inicial do nosso site - está
agora incluído na resposta da página enviada de volta para o
cliente/usuário a partir do servidor:
O conteúdo da seção SideBar foi inserido/unido no local apropriado da resposta da página HTML:
Parte 3: Detectando Condicionalmente se uma Seção de Layout Foi Implementada
O Razor fornece a capacidade para você condicionalmente verificar (a
partir de dentro de um arquivo de layout) se uma seção foi definida
dentro de um modelo de visão, e te permite gerar um código de resposta
alternativo, caso a seção não tenha sido definida. Isso fornece uma
maneira conveniente para especificar uma interface de usuário UI padrão
para seções de layout opcionais.
Vamos modificar nosso arquivo
de layout para tirarmos proveito dessa capacidade. A seguir nós estamos
condicionalmente verificando se a seção "Sidebar" foi definida sem que o
modelo de visão seja mostrado (usando o método IsSectionDefined()), e
se ela estiver definida nós mostramos a seção. Se a seção não foi
definida, então, agora nós mostramos algum conteúdo padrão na barra
lateral:
Nota:
Você tem que ter certeza de prefixar as chamadas para o método
RenderSection() com um caractere @ - o que informará o Razor para que
ele execute o HelperResult que o método retorna e una/insira o conteúdo
da seção no local apropriado do código de saída HTML. Observe como escrevi @RenderSection ("Sidebar") acima, em vez de apenas RenderSection("Sidebar"). Caso contrário, você obterá um erro.
Acima,
estamos simplesmente mostrando uma string em linha estática (<p>
Default SideBar Content </ p>) se a seção não estiver definida. Um site do mundo real mais provavelmente refatoraria este conteúdo padrão
para que ele fosse armazenado dentro de um modelo parcial separado (o
qual mostraríamos usando o método de ajuda Html.RenderPartial() dentro
do bloco else) ou, alternativamente, utilizando o método de ajuda
Html.Action() dentro do bloco else para encapsular tanto a lógica quanto
a renderização da barra lateral padrão.
Quando
atualizamos a página da nossa home-page no browser, ainda veremos o mesmo
conteúdo da barra lateral que tínhamos antes. Isto é porque nós
implementamos a seção SideBar dentro do nosso modelo de visão
Index.cshtml (e assim nosso Layout mostrou a mesma):
Vamos
agora implementar uma URL "/Home/About" URL para o nosso site,
adicionando um novo método de ação "About" no nosso controlador
HomeController:
O
método de ação About() acima simplesmente mostra uma visão para o
cliente/usuário quando é chamado. Podemos implementar o modelo de visão
correspondente a esta ação clicando com o botão direito do mouse dentro
do método "About()" e usando a opção do menu de comando "Add View"
(como antes) para criar um novo modelo de visão About.cshtml.
Nós vamos implementar o modelo de visão About.cshtml como a seguir. Repare que não estamos definindo uma seção "SideBar" dentro dele:
Quanto
acessamos a URL /Home/About, veremos o conteúdo que fornecemos acima na
seção principal (body) da nossa resposta, e o conteúdo padrão da
SideBar será mostrado:
O
arquivo de layout determinou no tempo de execução que uma seção SideBar
customizada não estava presente no modelo de visão About.cshtml e, com
isso ele mostrou o conteúdo padrão da barra lateral.
Um último Acerto...
Vamos
supor que em um momento posterior nos decidimos que ao invés de mostrar
o conteúdo padrão da barra lateral, nós só queremos esconder a barra
lateral completamente nas páginas que não têm qualquer conteúdo
personalizado definido para a barra lateral. Poderíamos implementar
essa alteração, simplesmente fazendo uma pequena modificação em nosso
layout para que o conteúdo da barra lateral (e seu HTML do entorno) seja
mostrado somente se a seção da barra lateral for definida. O código
para fazer isso é mostrado a seguir:
O
Razor é flexível o suficiente para que possamos fazer alterações como
esta não necessitando modificar qualquer um dos nossos modelos de visão
(nem fazer qualquer alteração na lógica dos Controladores) para acomodar
isso. Podemos ao invés disso, fazer apenas esta modificação no nosso
arquivo de layout e o resto acontece de forma limpa. Este tipo de
flexibilidade torna o Razor incrivelmente poderoso e produtivo.
Resumo
As
capacidades de layout do Razor permitem que você defina um modelo de
layout comum para o site, e então herde a sua aparência em todas
as visões/páginas do seu site.
O Razor te permite definir múltiplas
seções não-contíguas dentro de modelos de layout que podem ser
"preenchidas" por modelos de visão. A sintaxe @section { } para
fazer isso é limpa e concisa. O Razor também suporta a habilidade para
dinamicamente verificar no tempo de execução se uma seção especial foi
definida, te permitindo fornecer um conteúdo alternativo (ou mesmo um
layout alternativo) caso a seção não tenha sido especificada. Isso
fornece uma maneira poderosa e fácil para personalizar a interface do
usuário (UI) do seu site - tornando-o limpo e DRY a partir de uma
perspectiva de implementação.
Espero que ajude,
Scott
PS
Além do blog, eu também estou agora utilizando o Twitter para
atualizações rápidas e para compartilhar links.Siga-me em:
twitter.com/ScottGu
Texto traduzido do post original por
Leniel Macaferi.