RSS feed
Apresentando o "Razor" - um novo motor de visões para a ASP.NET - ScottGu's Blog em Português

Apresentando o "Razor" - um novo motor de visões para a ASP.NET


Uma das coisas em que minha equipe tem trabalhado tem sido uma nova opção de motor de visões para a ASP.NET.

A ASP.NET MVC sempre suportou o conceito de "view engines" (motores de visão) - que são os módulos plugáveis que implementam diferentes opções de sintaxe para templates/modelos de páginas/visões. O motor de visão "padrão" para a ASP.NET MVC hoje usa os mesmos modelos de arquivo .aspx/.ascx/.master usados com ASP.NET Web Forms. Outros motores de visão populares da ASP.NET MVC usados hoje incluem Spark e NHaml.

A nova opção de motor de visão na qual temos trabalhado é otimizada para geração de HTML usando uma abordagem de modelagem centrada em código. O codinome para este novo motor de visões é "Razor" (Navalha), e estaremos lançando a primeira versão beta pública em breve.

Objetivos do Projeto

Tivemos vários objetivos de projeto em mente de acordo com a criação de protótipos e avaliações feitas ao longo da implementação do "Razor":

  • Compacto, Expressivo, e Fluente: o Razor minimiza o número de caracteres e teclas digitadas necessárias em um arquivo, e permite um fluxo de trabalho de codificação rápido e fluente. Ao contrário das sintaxes de outros modelos, você não precisa interromper sua codificação para explicitamente indicar blocos do servidor dentro do código HTML. O analisador é inteligente o suficiente para inferir isso a partir do seu código. Isto permite uma sintaxe muito compacta e expressiva, que é limpa, rápida e divertida para digitar.

  • Fácil para Aprender: o Razor é fácil de aprender e te permite ser produtivo rapidamente com um mínimo de conceitos. Você usa todas as suas habilidades existentes de linguagens de programação e HTML.

  • Não é uma nova linguagem: Nós conscientemente optamos por não criar uma nova linguagem imperativa com o Razor. Em vez disso, queríamos permitir que os desenvolvedores utilizassem seus atuais conhecimentos de linguagens de programação C#/VB (ou outras) com o Razor, entregando uma sintaxe de marcação para modelagem que permite um fluxo de trabalho de construção de código HTML bem legal com a sua linguagem de preferência.

  • Funciona com qualquer Editor de Texto: o Razor não necessita de uma ferramenta específica e te permite ser produtivo em qualquer editor de texto velho e simples (notepad funciona muito bem).

  • Tem ótimo suporte à Intellisense: o Razor foi projetado para não necessitar de uma ferramenta específica ou editor de código, mas ainda assim ele terá um excelente suporte para intellisense dentro do Visual Studio.

  • Unidade Testável: A nova implementação deste motor de visões suportará a capacidade de testar visões de maneira unitária (sem a necessidade de um controlador ou de um servidor web, e pode ser hospedado em qualquer projeto de teste unitário - não há necessidade de um app-domain [domínio de aplicação] especial).

Passamos os últimos meses construindo aplicações com ele e fazendo muitos estudos de usabilidade com vários voluntários (incluindo vários grupos de desenvolvedores web que não trabalham com .NET). O retorno obtido das pessoas que estão usando o Razor tem sido realmente ótimo até agora.

Escolha e Flexibilidade

Uma das melhores coisas sobre a ASP.NET é que a maioria das coisas nela são conectáveis/plugáveis. Se você encontra alguma coisa que não funciona do jeito que você quer, você pode trocar por outra coisa.

A próxima versão da ASP.NET MVC vai incluir uma nova janela de diálogo "Add-> View" (Adicionar->Visão) que torna mais fácil para você escolher a sintaxe que você deseja usar quando você cria um novo arquivo de modelo de visão. Ela te permitirá selecionar facilmente qualquer um dos motores de visão disponíveis que você tenha instalado na sua máquina - o que lhe dá a opção de usar a abordagem de visão que pareça mais natural para você:

AddView9

O Razor será uma das opções de motores de visão que estará incluído na ASP.NET MVC. Todos os métodos de ajuda das visões e recursos do modelo de programação estarão disponíveis com ambos os motores de visão: Razor e .ASPX. 

Você também será capaz de misturar e combinar modelos de visão escritos usando múltiplos motores de visão dentro de uma única aplicação ou site. Por exemplo, você poderia escrever algumas visões usando arquivos .aspx, algumas com arquivos .cshtml ou .vbhtml (as extensões de arquivo para arquivos do Razor - C# e VB, respectivamente), e algumas visões com Spark ou NHaml. Você também pode ter um modelo de visão de tal forma que um motor de visão utilize um modelo de visão parcial escrito em outro motor de visão. Você terá uma opção de escolha completa e flexibilidade.

Exemplo Hello World com o Razor

O Razor permite que você comece com HTML estático (ou qualquer conteúdo textual), tornando-o dinâmico em seguida, adicionando código do servidor nele. Um dos objetivos principais do projeto Razor é tornar este processo de codificação fluente, permitindo que você rapidamente integre código do servidor em sua marcação HTML com um mínimo de digitação.

Para ver um exemplo rápido disto, vamos criar um simples exemplo "Hello World" (Olá Mundo) que gera uma mensagem assim:

imagem

Construindo o exemplo com blocos de código .ASPX

Se fôssemos construir o exemplo "Hello World" acima usando a sintaxe de marcação existente .ASPX, podemos escrevê-lo usando blocos <%= %> para indicar "pedaços de código" dentro da nossa marcação HTML assim:

imagem

Uma observação a fazer sobre esse exemplo "Hello World" é que cada bloco de código requer 5 caracteres (<%= %>) para indicar o início e o fim da sequência de código. Alguns desses caracteres (em especial a tecla % - a qual fica na parte central no topo da maioria dos teclados) não é uma das mais fáceis para se digitar.

Construindo o exemplo com a Sintaxe do Razor

Você indica o início de um bloco de código com o Razor usando um caractere @. Ao contrário de blocos de código <% %>, o Razor não requer que você explicitamente feche o bloco de código:

imagem

O parser/analisador do Razor tem conhecimento semântico do código C#/VB utilizado dentro dos blocos de código - é por isso que não precisamos fechar explicitamente os blocos de código acima. O Razor foi capaz de identificar as instruções de código acima como blocos de código auto-contidos e, implicitamente, fechou os mesmos para nós.

Mesmo neste exemplo trivial "Hello World" conseguimos evitar a digitação de 12 teclas se compararmos com as que tínhamos que digitar antes. O caractere @ também é mais fácil de ser alcançado no teclado se comparamos com o caractere %, o que torna a digitação mais rápida e mais fluida. 

Exemplo com Loops e HTML Aninhado

Vejamos outro cenário simples, onde nós queremos listar alguns produtos (e o preço de cada produto ao lado):

imagem

Construindo o exemplo com blocos de código .ASPX

Se fôssemos implementar esse exemplo usando a sintaxe de marcação HTML .ASPX da ASP.NET existente, poderíamos escrever o código mostrado a seguir para gerar dinamicamente uma lista <ul> com itens <li> para cada produto dentro da lista:

imagem 

Construindo o exemplo com a Sintaxe do Razor

A seguir é mostrado como gerar uma saída HTML equivalente usando o Razor:

imagem

Observe acima como nós começamos com um loop (estrutura de repetição) "foreach" usando o símbolo @ e, em seguida mantivemos uma linha de conteúdo HTML com blocos de código dentro dele. Porque o analisador do Razor entende a semântica da linguagem C# no nosso bloco de código, ele foi capaz de determinar que o conteúdo <li> deve ser contido dentro do loop foreach e tratado como conteúdo que deve ser repetido. Ele também reconheceu que o delimitador } terminou a instrução foreach.

O Razor também foi inteligente o suficiente para identificar as intruções @p.Name e @ p.Price dentro do elemento <li> como código do servidor - executando as instruções a cada vez através do loop. Observe como o Razor foi inteligente o bastante para automaticamente fechar os blocos de código @p.Name e @ p.Price inferindo como o HTML e o código estão sendo usados em conjunto.

A capacidade de escrever código desse jeito sem ter que adicionar um monte de marcadores para abrir/fechar blocos de código em seus modelos de visão acaba tornando todo o processo de codificação muito fluído e rápido.

Blocos If e Instruções em Múltiplas Linhas

A seguir estão alguns exemplos de outros cenários comuns:

Instruções If

Igual ao nosso exemplo do foreach acima, você pode inserir conteúdo dentro de instruções if (ou dentro de qualquer outro bloco da linguagem C# ou VB), sem ter que ser explícito sobre o início/fim do bloco de código. Por exemplo:

imagem

Instruções em Múltiplas Linhas

Você pode estipular múltiplas linhas de código, englobando-as dentro de um bloco @{ código } assim:

imagem 

Observe acima como variáveis podem abranger vários blocos de código do servidor - a variável "message" (mensagem) definida dentro do bloco de múltiplas linhas @{ }, por exemplo, está sendo usada também dentro do bloco de código @message. Isso é conceitualmente o mesmo que a sintaxe <% %> e <%= %> dentro de arquivos de marcação HTML .aspx.

Instruções com Múltiplos Tokens

A sintaxe @( ) permite que um bloco de código tenha múltiplos tokens (partes). Por exemplo, poderíamos reescrever o código acima para concatenar uma string e o número juntos dentro de um bloco @( código ):

imagem 

Integrando Conteúdo e Código

O analisador/parser do Razor tem muita inteligência nativa com relação à linguagem de programação - que lhe permite contar com ele para fazer o trabalho mais pesado, ao contrário de você ter de fazê-lo explicitamente. 

Será que ele para de funcionar com endereços de e-mail e outros usos do caracter @ no código HTML?

A analisador de linguagem do Razor é inteligente o suficiente na maioria dos casos para inferir se um caractere @ dentro de um modelo está sendo usado para código ou para conteúdo estático. Por exemplo, a seguir estou usando um caractere @ como parte de um endereço de e-mail:

imagem

Ao analisar um arquivo, o Razor examina o conteúdo do lado direito de qualquer caractere @ e tenta determinar se ele é código C# (se for um arquivo CSHTML) ou código VB (se for um arquivo VBHTML) ou se é apenas conteúdo estático. O código acima irá gerar o seguinte código HTML (onde o endereço de e-mail é gerado como conteúdo estático e @DateTime.Now é avaliado como código:

imagem

Nos casos em que o conteúdo é válido como código também (e você quer tratá-lo como conteúdo), você pode explicitamente escapar caracteres @ digitando @@.

Identificando Conteúdo Aninhado

Quando você aninhar conteúdo HTML dentro de um bloco de instrução if/else, foreach ou outro, você deve prestar atenção para abranger o conteúdo interno dentro de um elemento HTML ou elemento XML, para melhor identificar que este é o início de um bloco de conteúdo.

Por exemplo, a seguir eu envolvi um bloco de conteúdo multi-linha (que inclui um bloco de código) com um elemento <span>:

imagem

Isso vai exibir o conteúdo a seguir para o cliente - note que a tag <span> está incluída:

imagem

Você pode, opcionalmente, envolver o conteúdo aninhado com um bloco <text> em casos onde você tem conteúdo que você deseja exibir para o cliente sem uma tag que envolva o conteúdo:

imagem

O código acima irá exibir o conteúdo a seguir para o cliente - note que o mesmo não inclui qualquer tag:

imagem 

Convertendo o conteúdo HTML

Por padrão o conteúdo emitido usando um bloco @ é automaticamente codificado em HTML para uma melhor proteção contra cenários de ataque XSS.

Cenários de Layout/MasterPage - O Básico

É importante ter uma aparência consistente em todas as páginas dentro do seu web-site/aplicaçã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 este conceito usando "páginas de layout" - que permitem que você defina um modelo comum para o site, e então herde a sua aparência em todos as visões/páginas do seu site.

Exemplo de Layout Simples

A seguir está um exemplo simples de uma página de layout - a qual vamos salvar em um arquivo chamado "SiteLayout.cshtml". Ela pode conter qualquer conteúdo HTML estático que quisermos incluir na mesma, bem como o código dinâmico do servidor. Vamos então adicionar uma chamada para o método de ajuda "RenderBody()" na ponto exato do modelo onde queremos "preencher" o conteúdo específico do corpo (body) da página para uma URL solicitada:

imagem

Podemos, então, criar um modelo de visão chamado "Home.cshtml" que contém somente o conteúdo/código necessário para construir o corpo/body específico de uma página solicitada, e que se baseia no modelo de layout para o seu conteúdo exterior:

imagem

Observe acima como estamos definindo explicitamente a propriedade "LayoutPage" no código dentro do nosso arquivo Home.cshtml. Isso indica que queremos usar o modelo SiteLayout.cshtml como o layout para essa visão. Poderíamos alternativamente, indicar o arquivo de layout que queremos utilizar dentro de um Controlador ASP.NET MVC invocando Home.cshtml como um modelo de visão, ou configurando-o como o layout padrão para ser usado no nosso site (caso em que podemos especificá-lo em um arquivo em nosso projeto fazendo com que todos os modelos de visão selecionem este layout automaticamente).

Quando exibimos Home.cshtml como um modelo de visão, ele vai combinar o conteúdo do layout e da sub-página enviando o seguinte conteúdo para o cliente:

imagem

Código Compacto, Limpo e Expressivo

Uma das coisas a notar no código acima é que a sintaxe para definir layouts e para usá-los em visões/páginas é limpa e mínima. As capturas das telas de código acima com referência aos arquivos SiteLayout.cshtml e Home.cshtml contêm literalmente todo o conteúdo presente nos dois arquivos .cshtml - não há nenhuma configuração extra ou tags adicionais, nenhum prefixo <%@ Page %>, nem qualquer outra marcação HTML ou propriedades que precisam ser definidas.

Estamos tentando manter o código que você escreve, compacto, fácil e fluente. Queremos também permitir que qualquer pessoa com um editor de texto possa abrir, editar e facilmente ajustar/personalizar os arquivos. Nenhuma geração de código ou intellisense é necessária.

Cenários de Layout/MasterPage - Adicionando Substituições de Seção

Páginas de layout, opcionalmente, suportam a capacidade para definir diferentes "seções" dentro delas. Modelos de visão baseados no layout podem substituir e "preencher" estas seções com conteúdo customizado. Isso permite que você facilmente substitua/preencha regiões de conteúdo não contíguo dentro de uma página de layout, oferecendo uma grande flexibilidade para montar o layout do seu site.

Por exemplo, podemos voltar ao nosso arquivo SiteLayout.cshtml e definir duas seções dentro do nosso layout que os modelos de visão dentro do nosso site podem, opcionalmente, escolher para preencher. Chamaremos estas seções "menu" e "footer" (rodapé) - e indicaremos que elas são opcionais (não obrigatórias) dentro do nosso site passando um parâmetro optional=true para a chamada do método de ajuda RenderSection() (estamos fazendo isso usando a nova sintaxe para parâmetros opcionais da C# sobre a qual eu já escrevi).

imagem

Como essas duas seções são marcadas como "opcional", eu não sou obrigado a defini-las dentro do meu arquivo Home.cshtml. Meu site continuará funcionando sem problemas se elas não estiverem lá. 

Vamos voltar no arquivo Home.cshtml, onde definiremos seções personalizadas para o menu e rodapé para elas. A imagem a seguir contém todo o conteúdo presente no arquivo Home.cshtml - não há nada mais necessário no arquivo. Nota: mudei a configuração da propriedade LayoutPage para que esta seja um propriedade aplicada em todo site - é por isso que esta propriedade não aparece mais no arquivo.

imagem

Nossas seções customizadas "menu" e "footer" substitutas estão sendo definidas dentro de blocos nomeados @section {} dentro do arquivo. Optamos por não exigir que você envolva o conteúdo "main/body" dentro de uma seção e, ao invés disso, simplesmente mantemos o conteúdo em linha (o que economiza digitação e permite que você facilmente adicione seções nas suas páginas de layout sem ter que voltar em todas as páginas existentes para mudar a sintaxe). 

Quando exibimos Home.cshtml como um modelo de visão novamente, ele vai agora combinar o conteúdo do layout e da sub-página, integrando as duas novas seções customizadas substitutas nele, e em seguida enviará o seguinte conteúdo para o cliente:

imagem

Encapsulamento e Reuso com HTML Helpers

Nós cobrimos como manter uma aparência consistente em todo o site usando páginas de layout. Vamos agora ver como podemos criar também "HTML Helpers" (Métodos de ajuda HTML) que nos permitem encapsular de maneira limpa a funcionalidade de geração de HTML em bibliotecas que podemos reutilizar em todo o nosso site - ou até mesmo em múltiplos sites diferentes.

Código Baseado em Métodos de Ajuda HTML

A ASP.NET MVC tem hoje o conceito de "HTML Helpers" também conhecidos como métodos de ajuda HTML - que são métodos que podem ser chamados dentro dos blocos de código, e que encapsulam a geração de código HTML. Estes métodos hoje são implementados usando puramente código (tipicamente como métodos de extensão). Todos os métodos de extensão HTML existentes construídos com a ASP.NET MVC (tanto aqueles que nós construímos quanto aqueles criados por outros) funcionarão com o motor de visão "Razor" (mudanças no código não são necessárias):

imagem

Métodos de Ajuda HTML Declarativos

Gerar saída HTML usando uma abordagem de classe com apenas código funciona - mas não é o ideal.

Um dos recursos que estamos pensando em habilitar com o Razor é uma maneira fácil para criar métodos de ajuda HTML reutilizáveis usando uma abordagem mais declarativa. Nosso plano é permitir que você defina métodos de ajuda reusáveis usando um sintaxe declarativa @helper {} igual a seguir: 

imagem

Você será capaz de colocar arquivos .cshtml que contenham esses métodos de ajuda em um diretório \Views\Helpers e depois poderá reutilizá-los a partir de qualquer visão ou página no seu site (nenhuma etapa extra é necessária):

imagem

Note acima como o nosso método de ajuda ProductListing() é capaz de definir os argumentos e parâmetros. Isto te permite passar qualquer parâmetro que você queira para eles (e tirar o máximo proveito dos recursos existentes nas linguagens de programação como parâmetros opcionais, tipos anuláveis, genéricos, etc.). Você também terá suporte à depuração de código para eles dentro do Visual Studio.

Nota: A sintaxe @helper não vai aparecer na primeira versão beta do Razor - mas é algo que esperamos que venha a ser habilitado com o próximo lançamento. Métodos de ajuda baseados em código funcionarão com a primeira versão beta.

Passando Modelos em Linha como Parâmetros

Um outro recurso útil (e extremamente poderoso) que estamos permitindo com o Razor é a capacidade de passar parâmetros de um "inline template" (modelo em linha) para métodos de ajuda. Estes "modelos em linha" podem conter marcação HTML e código, e podem ser chamados sob demanda por métodos de ajuda.

A seguir está um exemplo desse recurso em ação usando um método de ajuda HTML chamado "Grid" que exibe um DataGrid para o cliente:

imagem

A chamada do método Grid.Render() acima foi escrita em C#. Estamos usando a nova sintaxe de parâmetros nomeados da C# para passar argumentos fortemente tipados para o método Grid.Render - o que significa que temos a ajuda da intellisense para completar as instruções de código e temos também a verificação do código no tempo de compilação para a sintaxe acima.

O parâmetro "format" (formato) que estamos passando quando definimos as colunas é um "inline template" - que contém ambos HTML customizado e código, e que podemos usar para personalizar o formato dos dados. O que é poderoso aqui é que o método de ajuda do Grid pode invocar nosso modelo inline como um método delegate, invocando-o quantas vezes for necessário. No cenário acima, ele vai chamá-lo a cada vez que uma linha no grid for exibida - passando o "item" que nosso modelo pode usar para exibir a resposta adequada.

Esta capacidade permitirá que métodos de ajuda HTML muito mais ricos sejam desenvolvidos. Você será capaz de implementá-los usando ambos os tipos de abordagem: baseada em código (da mesma forma que você constrói hoje os métodos de extensão), bem como utilizando a abordagem declarativa @helper {}.

Suporte do Visual Studio

Como mencionei anteriormente, um dos nossos objetivos com o Razor é minimizar a digitação, e habilitá-lo para ser facilmente editado com nada mais do que um editor de texto simples (notepad funciona muito bem). Nós mantivemos a sintaxe limpa, compacta e simples para ajudar a viabilizar isso.

Nós também projetamos o Razor para que você obtenha uma experiência de edição de código rica dentro do Visual Studio. Forneceremos intellisense completa para HTML, JavaScript e código C#/VB dentro de arquivos baseados no Razor:

imagem

Observe acima como nós estamos provendo intellisense para um objeto Product no código "@p." dentro do elemento <li> dentro de um loop foreach. Além disso, observe como a nossa pasta \Views dentro do Solution Explorer contém ambos os modelos de visão .aspx e .cshtml. Você pode usar múltiplos motores de visão dentro de uma única aplicação - o que torna fácil escolher a sintaxe que você mais gosta.

Resumo

Achamos que o "Razor" oferece uma excelente nova opção de motor de visão que é otimizado para a modelagem focada em código. Ele permite um um fluxo de trabalho de codificação que é rápido, expressivo e divertido. Sua sintaxe é compacta e reduz a digitação - enquanto ao mesmo tempo, melhora a legibilidade do seu código e marcação HTML. Ele será lançado como um mecanismo de motor de visão nativo com a próxima versão da ASP.NET MVC. Você também pode colocar arquivos individuais .cshtml/.vbhtml em sua aplicação e executá-los como uma única página - o que permite que você tire proveito dele dentro das aplicações ASP.NET Web Forms também.

O retorno dos desenvolvedores que têm experimentado o Razor nos últimos meses tem sido extremamente positivo. Vamos lançar o primeiro beta público do Razor em breve, e estamos ansiosos para receber seus comentários sobre ele.

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.

Published Saturday, July 3, 2010 1:01 AM by Leniel Macaferi

Comments

# re: Apresentando o "Razor" - um novo motor de visões para a ASP.NET

Wednesday, May 4, 2011 5:35 PM by Fabio Oliveira

Boa Noite Leniel.

Parabéns pela incrivel publicação. Estou impressionado com a magnitude que o Razor está nos oferecendo, simplesmente demais.

Esse artigo sanou dúvidas sobre Razor, posso dizer que já estou fera sem mesmo ter escrito uma linha de código. Novamente Parabéns pela brilhante matéria.