RSS feed
Preview Atualizado do Código Fonte ASP.NET MVC - ScottGu's Blog em Português

Preview Atualizado do Código Fonte ASP.NET MVC

Nós recentemente abrimos um novo projeto ASP.NET no CodePlex, o qual estaremos usando para prover previews (com código fonte construível) para vários novos recursos e lançamentos da ASP.NET.

No mês passado nós usamos o CodePlex para publicar a primeira preview do código fonte ASP.NET MVC. Esta primeira preview incluiu o código fonte da ASP.NET MVC Preview 2 que nós lançamos na MIX, juntamente com os arquivos do projeto do Visual Studio para permitir que você conserte e construa o projeto por conta própria.

Poucas horas atrás nós publicamos uma atualização no site para o código fonte da ASP.NET MVC. Esta atualização do código não é um lançamento oficial de preview ASP.NET MVC - ao invés disso é um download provisório que prove uma visão atual do estado da árvore de código. Nós lançaremos o pacote oficial "ASP.NET MVC Preview 3" dentro de poucas semanas após terminarmos mais algum trabalho (mais recursos e melhoramentos nos já existentes, melhor integração com as ferramentas do VS, suporte às verões express do VS, documentação, etc). Se você é do tipo que quer uma instalação da ASP.NET MVC que não ofereça dificuldades para usar e que contenha a documentação e suporte total das ferramentas, você provavelmente irá querer esperar pelo lançamento oficial. Se você for alguém que quer uma chance para ver uma preview da "preview" e tem a oportunidade de começar a usar e dar feedback referente a algumas das novidades, então a atualização de hoje é provavelmente interessante para você.

Melhorias da atualização da ASP.NET MVC

A atualização desta semana (a qual você pode fazer o download aqui) inclui várias melhorias na ASP.NET MVC. Dentre elas:

  • Além de postarmos o código fonte do framework da ASP.NET MVC, nós também estamos postando o código fonte para os testes unitários que nós usamos para testar o framework. Estes testes são implementados usando MSTest e o framework de simulação de código livre Moq. Um arquivo de projeto do VS 2008 para testes unitários está incluído para tornar fácil construir e rodar os testes localmente dentro da IDE do VS 2008.
  • Suporte significativamente mais fácil para testar as classes dos Controladores. Você pode agora testar unitariamente cenários do Controlador sem ter que simular nenhum objeto (mais detalhes de como isto funciona logo a seguir).
  • Várias adições de recursos e melhorias na usabilidade referente ao sistema de rotas de URL (mais detalhes a seguir).

Criando um Novo Projeto ASP.NET MVC

Você pode construir sua própria cópia dos assemblies da ASP.NET MVC fazendo o download do código fonte MVC e compilando este localmente, ou alternativamente você pode fazer o download de um pacote do Template do VS para pegar uma versão pré-construída juntamente com um template de projeto do Visual Studio que você pode usar para rapidamente construir um novo projeto ASP.NET MVC que usa os bits mais recentes.

Após a instalação do template .VSI da atualização do código fonte ASP.NET MVC, um novo projeto "ASP.NET MVC Application" aparecerá na seção "My Templates" na janela de diálogo "New Project":

Esta nova versão de "My Templates" do projeto MVC convive lado a lado com o lançamento anterior da ASP.NET MVC Preview 2 (o qual você pode ver acima na seção principal das templates de projeto na janela de diálogo). Isto permite que você seguramente crie novos projetos e use ambas as versões na mesma máquina: última versão do código fonte e a última preview oficial.

Quando você criar um novo projeto usando este template atualizado do Projeto ASP.NET MVC você irá por padrão obter um projeto que se apresenta como a seguir:

Esta nova solução de projeto contém um Controlador ("HomeController") abaixo do diretório "\Controllers" e dois templates de Visões ("About" e "Index") abaixo do sub-diretório "\Views\Home". Ambos os templates de visão estão baseadas em uma master page (página mestra) comum para o site ("Site.master"), e todos os seus estilos estão definidos dentro de um arquivo "Site.css" localizado dentro do diretório "\Content".

Quando você executar a aplicação o web-server integrado ao framework irá automaticamente inicializar e você verá o conteúdo da página "Home":

Clicando na tab "About us" ("Sobre nós") você então verá o conteúdo da página "About": 

A classe do "HomeController" do projeto é responsável por tratar de ambas as URLs acima e tem dois métodos de ação iguais a seguir:

O template padrão "Site.master" procura por um valor "Title" na coleção ViewData e usa este para mostrar o elemento <title> da página HTML. O template padrão "Index" procura por um valor "Message" e usa este para mostrar a mensagem de bem-vindo da homepage. Você pode obviamente customizar estes arquivos da maneira como quiser.

Mudanças do Controlador nesta preview da "preview" da ASP.NET MVC

Se você leu o código acima com muita atenção você pode ter percebido algumas mudanças em como as classes de Controlador são por padrão implementadas usando o novo código da ASP.NET MVC.

Com o lançamento da ASP.NET MVC Preview 2 os métodos de ação mostrados acima teriam sido implementados como a seguir:

O time de funções da MVC está experimentando algumas idéias na preview desta semana e estão tentenado algumas novas idéias:

  1. Métodos de ação nos Controladores agora retornam por padrão um objeto "ActionResult" (ao invés de void (vazio/nada)). Este objeto ActionResult indica o resultado de uma ação (uma visão para ser renderizada, uma URL para ser redirecionada, outra ação/rota para executar, etc).

  2. Os métodos de ajuda RenderView(), RedirectToAction() e Redirect() na classe base do Controlador retornam objetos tipificados do tipo ActionResult (os quais você pode usar para manipular ou retornar a partir de métodos de ação).

  3. O método de ajuda RenderView() pode agora ser chamado sem ter que explicitamente passar o nome do template da visão a ser renderizada. Quando você omite o nome do template o método RenderView() irá por padrão usar o nome do método de ação como o nome do template da visão a ser renderizada. Assim, chamando "RenderView()" sem parâmetros dentro do método de ação "About()", agora é a mesma coisa que explicitamente escrever "RenderView("About").

É muito fácil atualizar classes de Controlador existentes construídas com a Preview 2 para usar este novo padrão (simplesmente mude void para ActionResult e adicione uma instrução de retorno na frente de qualquer chamada aos métodos de ajuda RenderView ou RedirectToAction).

Retornando Objetos do tipo ActionResult a partir dos Métodos de Ação

Então porque mudar os métodos de ação do Controlador para retornar objetos do tipo ActionResult por padrão ao invés de retornar void? Alguns frameworks populares MVC usam a abordagem de retorno de objeto (incluindo Django, Tapestry e outros), e nós entendemos que isto trás para a ASP.NET MVC alguns benefícios interessantes:

  1. Isto permite testar unitariamente os Controladores de forma mais limpa e fácil. Você não precisa mais simular métodos no objeto Response ou objetos ViewEngine para testar unitariamente o comportamento dos métodos de ação. Ao invés disso, você simplesmente verifica condições usando o objeto ActionResult retornado a partir da chamada do método de ação dentro do teste unitário (veja a próxima seção a seguir).

  2. Isto pode fazer com que a lógica de fluxo do Controlador seja mais limpa e mais explícita em cenários onde possa existir duas saídas diferentes dependendo de alguma condição (por exemplo: redirecionar se a condição A é verdadeira, de outro modo renderizar o template da visão se falso). Isto pode fazer com que o código dos métodos de ação não triviais do controlador fiquem mais fáceis para a leitura e acompanhamento.

  3. Isto permite boas condições de composição onde um FilterActionAttribute pode receber o resultado de um método de ação e modificar/transformar o mesmo ante de executá-lo. Por exemplo: uma ação "Browse" em um controlador ProductCatalog pode retornar um RenderActionResult que indica que este quer renderizar uma visão de produtos "List". Um FilterActionAttribute declarativamente setado na classe do controlador poderia então ter a chance de customizar o template específico da visão "List" renderizando-o para ser ou List-html.aspx ou List-xml.aspx. dependendo do tipo MIME preferido pelo cliente. Múltiplos FilterActionAttributes podem também opcionalmente serem encadeados para que os resultados fluam de um para outro.

  4. Isto provê um bom mecanismo de extensibilidade para pessoas (incluindo nós mesmos) para adicionar recursos adicionais no futuro. Novos tipos de ActionResult podem ser facilmente criados através de sub-classes da classe base ActionResult bastando para tanto sobrecarregar o método "ExecuteResult". Seria fácil criar um método de ajuda "RenderFile()", para que um desenvolvedor, por exemplo, escrevendo uma ação possa chamar o método para retornar um novo objeto "FileActionResult".

  5. Isto permitirá cenários de execução Assíncrona no futuro. Métodos de ação serão capazes de retornar um objeto AsyncActionResult o qual indica que eles estão aguardando uma operação de rede e querem retornar à thread executora do trabalho. Asso, a ASP.NET poderá usá-lo para executar outra requisição até que a chamada de rede seja completada. Isto permitirá que desenvolvedores evitem bloquear threads no servidor, havendo suporte a código muito eficiente e escalável.

Um dos objetivos deste ínterim é dar às pessoas uma chance para trabalhar com esta nova abordagem, permitindo-as construir aplicações do mundo real ao mesmo tempo em que aprendem com a experiência.

Nos também iremos postar uma classe base do Controlador alternativa que você possa usá-la se ainda preferir a abordagem anterior do retorno "void" da ação. Nós deliberadamente não incluímos esta classe base do Controlador nesta "preview" da preview. Isto é porque nós queremos encorajar as pessoas a tentar a abordagem do tipo de retorno "ActionResult" com o intuito de que elas nos enviem feedback.

Como Testar Unitariamente os Métodos de Ação

Eu mencionei acima que uma nova abordagem ActionResult pode tornar o teste unitário de controladores muito mais fácil (e evita a necessidade de simulação para cenários comuns). Vamos ver um exemplo disto em ação.

Considere a simples classe NumberController a seguir:

Esta classe Controladora tem um método de ação "IsEvenNumber" que recebe um número como um argumento URL. Este método de ação IsEvenNumber primeiramente verifica se o número é negativo - se for o método redireciona para uma página de erro. Se for um número positivo este determina se o número é par ou ímpar e renderiza um template de visão que mostra a mensagem apropriada: 

Escrever testes unitários para nosso método de ação "IsEvenNumber" é muito fácil graças a nova abordagem ActionResult. 

A seguir está um exemplo de um teste unitário que verifica se a correta redireção Http ocorre quando um número negativo é fornecido (por exemplo: /Number/IsEvenNumber/-1):

Note acima como nós não precisamos simular nenhum objeto para testar nosso método de ação. Ao invés disso nós simplesmente instanciamos a classe NumberController e chamamos o método de ação diretamente (passando um número negativo) e atribuímos o valor retornado para a variável local "result". Eu usei a sintaxe da linguagem C# "as type" acima para converter a variável "result" para um tipo fortemente tipificado "HttpRedirectResult".  

O que é legal com respeito à palavra chave de C# "as" é que esta irá atribuir o valor como nulo ao invés de lançar uma exceção se a conversão falhar (por exemplo: se o método de ação retornasse um RenderViewResult). Isto significa que eu posso facilmente adicionar uma verificação de asserção no meu teste para confirmar que o resultado não é nulo visando saber se a redireção Http realmente aconteceu. Eu posso então adicionar uma segunda asserção para verificar se a URL de redireção apropriada foi especificada.

Testar os cenários onde número não zero são passados também é fácil. Para fazer isto nós iremos criar dois métodos de teste - um testando números pares e um testando números ímpares. Em ambos os testes nós iremos aferir se uma RenderViewResult foi retornada e então verificaremos se a string da "Mensagem" correta foi passada dentro da ViewData associada com a visão:

Nós podemos então clicar com o botão direito do mouse em nossa classe NumberClontrollerTest dentro do VS 2008 e escolher o item do menu "Run Tests" ("Executar Testes"):

Isto irá executar nossos três testes unitários em-memória (sem a necessidade do web-server) e reportará se o nosso método de ação NumberController.IsEvenNumber() está se comportando da maneira esperada:

Nota: com o código fonte desta semana você ainda precisa usar simulação para testar a propriedade TempData nos Controladores. Nosso plano é não necessitar de simulação com a ASP.NET MVC Preview 3 dentro de algumas semanas.

Método de Ajuda MapRoute

As regras de roteamento de URL dentro de aplicações ASP.NET MVC são tipicamente declaradas dentro do método "RegisterRoutes" da classe Global.asax.  

Com as Previews 1 e 2 da ASP.NET MVC rotas são adicionadas à coleção de rotas através da instanciação direta de um objeto Route, ligando o mesmo em uma classe MvcRouteHandler e então setando as propriedades apropriadas neste para declarar as regras de rota:

O código acima irá funcionar ainda. De qualquer modo, você pode agora aproveitar o novo método de ajuda "MapRoute" o qual prove uma sintaxe muito mais simples para fazer a mesma coisa. Abaixo está a rota de URL baseada em convenção configurada por padrão quando você cria um novo projeto ASP.NET MVC (a qual substitui o código acima):

O método de ajuda MapRoute() é sobrecarregado e recebe dois, três ou quatro parâmetros (nome da rota, sintaxe da URL, parâmetro padrão da URL, e parâmetro de restrições da expressão regular).

Você pode chamar MapRoute() quantas vezes você quiser para registrar múltiplas rotas nomeadas no sistema. Por exemplo, em adição a regra de convenção padrão, nós poderíamos adicionar uma regra de rota chamada "Products-Browse" igual a seguir:

Nós podemos então referenciar para esta regra "Products-Browse" explicitamente dentro de nossos Controles e Visões quando nós quisermos gerar uma nova URL. Por exemplo, nós poderíamos usar o método de ajuda Html.RouteLink da visão para indicar que nós queremos criar um link para nossa rota "Products-Browse" e passar a esta um parâmetro de categoria "Food" usando código no nosso template da visão igual a seguir:

Este novo método ajudante da visão acessaria o sistema de rotas e teria como saída um hyperlink HTML apropriado para a URL igual a seguir (nota: veja como houve a substituição automática de parâmetro da categoria dentro da URL usando a regra de rota):

Nota: com o código fonte desta semana você precisa passar os parâmetros do controle e ação (além do parâmetro Category) para o método de ajuda Html.RouteLink(). Somente assim ele poderá determinar qual é a correta rota de URL a ser gerada. A próxima versão da ASP.NET MVC Preview 3 não necessitará disso, e permitirá que você use a chamada a Html.RouteLink exatamente como eu escrevi acima para determinar a rota.

Outros Recursos de Mapeamento de Rotas de URL

O código fonte MVC desta semana também suporta um monte de novos recursos para o mapeamento de rotas de URL. Você pode agora incluir "-", ".", ";" ou qualquer outro caracter que você queira como parte de suas regras de rota. 

Por exemplo, usando um separador "-" você pode agora traduzir os valores de linguagem e localidade de suas URLs separadamente usando uma regra igual a seguir:

Isto passaria os parâmetros apropriados de "language" (linguagem), "locale" (local) e "category" (categoria) para método de ação ProductsController.Browse quando este fosse invocado:

Regra de Rota da URL URL de exemplo Parâmetros Passados para o Método de Ação
{language}-{locale}/products/browse/{category} /en-us/products/browse/food language=en, locale=us, category=food
  /en-uk/products/browse/food language=en, locale=uk, category=food

Ou você pode usar o tipo de extensão de arquivo "." no final de uma URL para determinar se o resultado será renderizado em um formato XML ou HTML: 

Isto passaria ambos os parâmetros "category" e "format" para o método de ação ProductsController.Browse quando este for invocado: 

 

Regra de Rota da URL URL de exemplo Parâmetros Passados para o Método de Ação
products/browse/{category}.{format} /products/browse/food.xml category=food, format=xml
  /products/browse/food.html category=food, format=html

A ASP.NET MVC Preview 2 introduziu regras de rota universais. Por exemplo, você pode indicar em uma regra que você quer passar todo o conteúdo restante do URI como um parâmetro nomeado para um método de ação:

Isto passaria um parâmetro "contentUrl" para o método de ação WikiController.DisplayPage quando invocado:

 

URL Route Rule URL de exemplo Parâmetros Passados para o Método de Ação
Wiki/Pages/{*contentUrl} /Wiki/Pages/People/Scott contentUrl="People/Scott"
  /Wiki/Pages/Countries/UK contentUrl="Countries/UK"

Estas regras universais continuam funcionando com a preview desta semana - e são muito úteis se você estiver construindo um sistema de blog, wiki, cms ou outro sistema baseado em conteúdo. 

Note que além de usar o novo sistema de rotas para cenários ASP.NET MVC, nós também estamos agora usando o mesmo sistema de rotas dentro do projeto ASP.NET Dados Dinâmicos (o qual usa ASP.NET Web Forms).

Sumário

Esperançosamente o post acima prove uma rápida atualização em alguns dos novos recursos e mudanças expostos com o código fonte ASP.NET MVC desta semana. 

Você pode fazer o download aqui se quiser começar a usar o código imediatamente. Alternativamente, você pode aguardar algumas semanas pelo lançamento oficial da ASP.NET MVC Preview 3 - a qual terá mais alguns recursos (e incorporará o feedback que as pessoas derem a respeito do código desta semana), entregará um instalador sem costuras, proverá uma boa integração com o VS e entregará documentação atualizada.

Para qualquer pergunta/problema com o código ASP.NET MVC desta semana, tenha certeza de verificar o fórum ASP.NET MVC em http://www.asp.net/.

Espero que ajude,

Scott

(Texto traduzido do post original por Leniel Macaferi.)

Published Wednesday, April 16, 2008 11:56 PM by Leniel Macaferi
Filed under: , ,

Comments

No Comments