O modo como desenvolvemos aplicações Web tem sofrido constantes modificações nos últimos anos, e isso não será diferente para os próximos anos. O ASP.NET foi sem dúvida uma das grandes novidades, que surgiu em 2002 e vem sendo revisto e atualizado anualmente. O AJAX veio para comprovar isso e mostrar que as novidades não vão parar por aí.

Guia do artigo:

Uma lacuna importante que não foi preenchida no desenvolvimento de aplicações ASP.NET, foi a questão do MVC. MVC, para quem não conhece é a sigla para Model - View - Controller, e compreende uma arquitetura muito utilizada no desenvolvimento de aplicações Web. Falaremos muito sobre ele neste artigo.

Para atender a essa necessidade surgiu o ASP.NET MVC Framework, que como o próprio nome diz é uma framework dedicada ao uso do MVC em aplicações ASP.NET. Esta framework já pode ser utilizada na versão 3.5 do ASP.NET, e é uma forma opcional de criarmos nossas aplicações ASP.NET no Visual Studio 2008.

Neste artigo iremos desenvolver uma aplicação com o uso do ASP.NET MVC Framework. Ele ainda está em Preview, o que significa que não está instalado na versão 3.5 do ASP.NET, e ainda está em desenvolvimento. Mas já podemos baixá-lo e testá-lo em aplicações desenvolvidas com o Visual Studio 2008.

Lembrando, é claro, que esta era a versão disponível até o fechamento deste artigo. Para acompanhar os exemplos deste artigo, faça o download e instale o ASP.NET MVC Framework Preview em seu computador. Você também vai precisar ter instalado o Visual Studio 2008.

MVC (Model-View-Controller)

A arquitetura MVC tem se tornado muito popular no desenvolvimento de aplicações Web, principalmente no meio do software livre. O MVC propõe que a aplicação seja dividida em três camadas ou partes:

Model: é a camada ou componentes da aplicação responsável por manter o estado dos dados. No Model temos uma representação em Objetos dos dados da nossa database. Por exemplo, podemos ter no Model uma classe Produtos que irá representar os dados da tabela Produtos do banco de dados.

View: é a camada responsável por exibir os dados ao usuário. É basicamente a interface da aplicação, e em uma aplicação ASP.NET a interface pode ser uma página ou controle de usuário. Como exemplo podemos ter uma página Produtos.aspx que terá os controles necessários (Labels, TextBoxes, CheckBoxes, DropDownLists, etc) para exibir e editar os dados de um objeto da classe Produto.

Controller: esta camada é responsável por gerenciar a interação com o usuário final, manipulando a camada Model, e até definindo qual View será utilizada para exibir a interface ao usuário. Em uma aplicação MVC, a camada View é usada apenas para a exibição dos dados, é o Controller que responde às entradas e interações do usuário.

TDD (Test Driven Development)

A utilização do MVC nos possibilita uma outra filosofia de desenvolvimento de aplicações, o TDD. TDD é a sigla para Test Driven Development, que quer dizer: Desenvolvimento Orientado a Testes.

Por mais incrível e impossível que possa parecer, com o TDD nós desenvolvemos nossas aplicações pensando primeiro nos mecanismos de testes. Ou seja, com o TDD você primeiro implementa Unit Tests automatizados, que irão definir e verificar (testar) os requerimentos do seu código. Só depois que você efetivamente irá codificar.

Nota do DevMan:

Os Unit-Tests ou testes unitários são uma ótima forma de automatizarmos os testes de nossas aplicações. Os Unit-Tests são classes que criamos para testar os nossos métodos. O código de um Unit-Test deve validar todas as possíveis entradas (parâmetros) e saídas (retornos) de um método, atestando de uma forma automática a eficiência do método.

No Visual Studio Team System 2008 temos uma suíte específica para testes, chamada Visual Studio Team Test (TT). Com ele temos diversas features que nos ajudam a criar e utilizar os Unit-Tests. Algumas dessas principais features compreendem:

  • Geração automática de código dos Unit-Tests, baseado é claro, nos métodos que queremos testar;
  • Execução dos testes pela própria IDE;
  • Incorporação de teste de leitura de dados de um database;
  • Ferramenta de Ánalise de Código;

O Conjunto de features relacionadas à Unit-Tests no Visual Studio está no Unit Testing Framework sob o namespace: Microsoft.VisualStudio.TestTools.UnitTesting. Maiores infomações sobre o Unit Testing Framework podem ser encontradas no seguinte link: http://msdn.microsoft.com/en-us/library/ms243147(VS.80).aspx ou nas edições 46 a 48.

Mural de Aniversários

Para colocarmos em prática o uso do ASP.NET MVC, vamos desenvolver uma aplicação bastante simples. Vamos criar uma aplicação onde será possível consultar o aniversário de todos os funcionários da empresa, com uma espécie de “Mural de Aniversários” para ser disponibilizado na intranet ou até publicado na Web.

Sendo assim, é importante começarmos definindo a nossa estrutura de tabelas, que será bem simples também. Na Figura 1 você vai encontrar um diagrama com as duas tabelas que precisamos ter na database MuralAniversarios.

Diagrama do database MuralAniversarios
Figura 1. Diagrama do database MuralAniversarios

Veja que é uma estrutura de tabelas que organiza os aniversariantes pelo seu Mês de aniversário. Crie essa mesma estrutura de tabelas no seu SQL Server, declarando inclusive a chave estrangeira para o atributo NroMes da tabela de Aniversariantes.

Depois que você já tiver criado essa estrutura de tabelas, é importante que as preencha com alguns dados de testes. Na tabela de Meses basta incluir todos os meses do Ano, como você pode ver na Figura 2. E para a tabela de Aniversariantes coloque alguns registros quaisquer. Na Figura 3 você verá um exemplo de alguns registros para essa tabela.

Registros da Tabela Meses
Figura 2. Registros da Tabela Meses
Registros da Tabela Aniversariantes
Figura 3. Registros da Tabela Aniversariantes

Criando uma nova Aplicação com o ASP.NET MVC

Acho que não há melhor maneira de se entender uma tecnologia do que a prática. Sendo assim, abra o seu Visual Studio 2008. Neste artigo eu irei utilizar o Visual Studio Team System, para utilizarmos algumas features de Testes, mas você pode utilizar qualquer edição do Visual Studio 2008 para criar aplicações ASP.NET MVC, inclusive o Visual Web Developer Express Edition.

Com o Visual Studio 2008 aberto, vá até a opção File > New > Project. E como você pode conferir na Figura 4, selecione o tipo Visual C# / Web à esquerda, e à direita escolha o template de projeto ASP.NET MVC Web Application. Veja que temos um template exclusivo para a criação de aplicações com a utilização do ASP.NET MVC Framework. Selecione o template informe MuralAniversarios em Name e clique em OK.

Criando novo projeto com template ASP.NET MVC Web Application
Figura 4. Criando novo projeto com template ASP.NET MVC Web Application

Em seguida temos uma característica bastante interessante dos projetos ASP.NET MVC. Veja na Figura 5 que ao confirmar a criação do projeto, aparecerá uma tela perguntando se desejamos criar um projeto de testes para a nossa aplicação, respeitando a filosofia de desenvolvimento orientada à testes (TDD).

Definindo Projeto de Testes
Figura 5. Definindo Projeto de Testes

Você pode inclusive definir qual a framework que será utilizada para a criação do projeto de testes. Neste exemplo estamos utilizando a framework padrão do Visual Studio. Clique em OK para confirmar a criação do projeto.

Observe na Solution Explorer que foi criada uma Solution com dois projetos (Figura 6). O primeiro é nosso projeto ASP.NET onde iremos desenvolver nossa aplicação com a utilização do MVC Framework. E o segundo projeto é onde podem ser criadas as Unit-Tests.

Projetos Web e Teste na Solution Explorer
Figura 6. Projetos Web e Teste na Solution Explorer

Dê uma olhada na estrutura de diretórios do projeto ASP.NET. Veja que temos três pastas importantes aí: Controllers, Models e Views. Como você já deve supor, devemos criar cada um dos componentes da nossa aplicação em cada uma destas pastas, respeitando a arquitetura de divisão de camadas do MVC.

Camada Model

Agora que já temos nosso projeto criado, podemos começar definindo a camada Model da nossa aplicação. No MVC a camada Model representa os componentes responsáveis por manter o “estado” de uma aplicação. Na maioria das aplicações, principalmente Web, este “estado” é persistido em um banco de dados. Falando de uma forma mais simples, podemos dizer que a camada Model irá conter as classes que serão responsáveis por recuperar e persistir os dados na database.

Essas classes serão o que chamamos de mapeamento objeto-relacional. Como por exemplo, podemos ter uma classe chamada Aniversariantes, para representar os dados da tabela Aniversariantes do nosso banco de dados no SQL Server.

O ASP.NET MVC Framework nos permite utilizar qualquer forma de acesso a dados que quisermos. Você pode, por exemplo, utilizar os datasets tipados com TableAdapters do ADO.NET. Mas você também pode utilizar uma ferramenta ORM como o NHibernate, LLBLGen, WilsonORMapper, LINQ to SQL / LINQ to Entities.

Neste nosso exemplo, para a criação da nossa camada Model, vamos utilizar o LINQ to SQL.

Nota do DevMan:

O LINQ (Language Integrated Query) é uma nova linguagem que oferece suporte à consulta de dados, que podem estar armazenados nas mais diversas formas possíveis.

Os dados a serem consultados podem estar em XML (LINQ para XML), Banco de dados diversos (LINQ-enabled ADO.NET, que inclui LINQ to SQL, LINQ to DataSet e LINQ to Entities) e Objetos (LINQ to Objects). Ou seja, podemos realizar consultas a estas e outras fontes de dados, através de uma linguagem fortemente tipada, como é o LINQ.

O Linq é parte integrante das linguagens do .NET Framework, e integra novos conceitos, como é o caso das Lambda Expressions e dos Extension Methods. Através destas novas características, por exemplo, será possível realizar um “SELECT” através de código C#.

O LINQ to SQL é uma das variações do LINQ, e é basicamente uma ferramenta de mapeamento Objeto-Relacional (O/RM) que já é disponível na versão 3.5 da framework. Com ele é possível criar um modelo de classes que representam um conjunto de tabelas de um banco de dados do SQL Server.

Na Solution Explorer clique com o botão direito do mouse na pasta Model, e escolha a opção Add New Item. Com você pode conferir na Figura 7, selecione o template Linq to SQL Classes, informe MuralAniversarios.dbml em Name e clique em Add.

Criando MuralAniversario.dbml
Figura 7. Criando MuralAniversario.dbml

Veja que o MuralAniversario.dbml foi criado dentro da pasta Model e também já está com o seu designer aberto, para podermos “desenhar” o nosso modelo de classes. O designer do Linq to SQL tem uma característica similar ao dos DataSets tipados, que é muito útil. Podemos criar o nosso modelo de classes apenas arrastando as tabelas do banco de dados.

Sendo assim, vá até a Server Explorer e crie uma nova conexão apontando para o database MuralAniversarios. Em seguida, como você pode ver na Figura 8, arraste as duas tabelas (Meses e Aniversarios) para o designer do Linq to SQL.

Criando Modelo de Classes com o LINQ to SQL
Figura 8. Criando Modelo de Classes com o LINQ to SQL

Observe que as classes foram criadas com a mesma estrutura das tabelas do banco de dados. A diferença principal que vemos é que aqui os campos da tabela são representados por propriedades da classe.

Note também que as duas classes foram criadas com os nomes Aniversariante e Mese. Os nomes estão dessa forma, pois o Linq to SQL tenta colocar o nome das classe no singular (diferente do que fazemos no nome das tabelas, que colocamos no plural). Porém nem sempre ele vai acertar esses nomes, como é o caso da classe Mese.

Uma vez que nós já definimos o nosso modelo de classes através do LINQ to SQL, vamos precisar criar uma classe parcial chamada MuralAnivesarioDataContext, veja na Figura 9.

Criando classe parcial MuralAniversarioDataContext
Figura 9. Criando classe parcial MuralAniversarioDataContext

Essa classe parcial é necessária para criarmos métodos que irão encapsular algumas expressões LINQ, para a recuperação das informações no banco de dados. Iremos precisar basicamente de três métodos. Um para retornar todos os registros da tabela Meses, outro para retornar todos os Aniversariantes de um específico Mês, e um terceiro para retornar os dados de um único Aniversariante.

Sendo assim, o código da classe parcial MuralAniversarioDataContext, deverá ficar exatamente como mostra a Listagem 1. Veja que estamos utilizando expressões LINQ para realizar o acesso aos dados no database. Como esta é uma classe parcial, podemos acessar as propriedades Aniversariantes e Meses, que nos dão acesso direto às respectivas tabelas na database, graças ao mapeamento feito pelo LINQ to SQL.

Esses métodos irão nos ajudar a recuperar os dados de uma forma muito mais simples. Assim não precisaremos escrever expressões LINQ na camada Controller.


using System;
 using System.Collections.Generic;
 using System.Linq;
  
 namespace MuralAniversarios.Models
 {
     public partial class MuralAniversarioDataContext
     {
         public List GetMeses()
         {
             return Meses.ToList();
         }
  
         public List GetAniversariantesByMes(int nroMes)
         {
             return Aniversariantes.Where(
 a => a.NroMes == nroMes).ToList();
         }
  
         public Aniversariante GetAniversarianteById(int id)
         {
             return Aniversariantes.Single(a => a.Id == id);
         }
     }
 }
Listagem 1. Expressões LINQ para acesso aos dados no database

Camada Controller

Na maioria das aplicações Web (ASP, ASP.NET WebForms, PHP, JSP etc.), as URLs apontam diretamente para arquivos armazenados em disco, que basicamente representam páginas.

Ou seja, quando o usuário digitar no browser a seguinte URL: www.minhaapp.com.br/Aniversariantes.aspx, a aplicação Web irá procurar o “template” Aniversariantes.aspx armazenado em disco, processá-lo, e devolver ao client o resultado desse processamento em formato HTML. Simplificando, essa é a forma como a maioria das aplicações Web trabalha.

O ASP.NET MVC Framework trabalha isso de uma forma bastante diferente. Em vez de mapear as URLs para templates armazenados em disco, as URLs apontam diretamente para classes. Estas classes são chamadas de Controllers.

Os Controllers no ASP.NET MVC, são responsáveis por processar todas as requisições, gerenciar os inputs do usuário, e acessar dados ou executar determinado código, baseado nessas entradas. E por fim, o Controller irá chamar um componente da camada View para gerar a saída necessária. Veja o diagrama da Figura 10, ele ilustra bem como funcionam as requisições neste modelo.

Como funciona o mapeamento das URLs no modelo ASP.NET MVC
Figura 10. Como funciona o mapeamento das URLs no modelo ASP.NET MVC

Essa é uma mudança de paradigma bastante importante, e que deve ser bem entendida se você pretende utilizar esse modelo. O ASP.NET MVC possui uma engine bastante flexível para o mapeamento de URLs para classes Controller.

Você pode inclusive, configurar uma série de regras que o ASP.NET irá utilizar para resolver as URLs e definir qual o Controller que deverá ser utilizado, além dos parâmetros que serão passados para esse Controller.

Para este exemplo iremos utilizar as regras de mapeamento padrão do ASP.NET MVC, que já são suficientes para conseguirmos criar nossa aplicação usando o modelo MVC.

A regra convencional de mapeamento de URLs irá procurar a classe Controller equivalente ao nome informado na URL. Assim a seguinte URL: www.minhaapp.com.br/Aniversariantes/ está mapeada para apontar para a classe AniversariantesController.cs.

Para darmos continuidade no nosso exemplo, vá até a Solution Explorer, clique com o botão direito do mouse sobre a pasta Controllers e escolha a opção Add New Item. Como você pode conferir na Figura 11, selecione a categoria Web / MVC, escolha o template MVC Controller Class, informe AniversariantesController.cs em Name e clique em Add.

Criando AniversariantesController.cs
Figura 11. Criando AniversariantesController.cs

É muito importante que o nosso Controller possua esse nome, para que esteja compatível com a regra de mapeamento de URLs do ASP.NET MVC.

Observe que foi criada uma classe que herda da classe Controller, membro do ASP.NET MVC Framework, que também pode ser reconhecido pelo namespace System.Web.Mvc. Veja na Listagem 2, como é a estrutura de uma classe Controller.

Agora que criamos a classe AniversariantesController.cs, sabemos que ela será utilizada por todas as URLs que tiverem o prefixo /Aniversariantes/.

Note apenas que foi incluída uma referência ao namespace MuralAniversarios.Models, para que seja possível acessar as classes do nosso Modelo.


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using MuralAniversarios.Models;
  
 namespace MuralAniversarios.Controllers
 {
     public class AniversariantesController : Controller
     {
         public void Index()
         {
             // Add action logic here
         }
     }
 }
Listagem 2. Classe AniversariantesController.cs vazia

Controller Action Methods

A nossa aplicação deverá disponibilizar três tipos de consulta:

  1. Listar todos os Meses do Ano;
  2. Listar todos os Aniversariantes de um determinado Mês e;
  3. Exibir os detalhes de um determinado Aniversariante.

Para atender a estas três consultas distintas, vamos utilizar o seguinte padrão de URLs, descrito na Tabela 1.

Formato da URL Exemplo Comportamento
/Aniversariantes/Meses /Aniversariantes/Meses Lista todos os Meses do Ano
/Aniversariantes/List/NroMes /Aniversariantes/6 Lista todos os Aniversariantes de um determinado Mês
/Aniversariantes/Detail/Id /Aniversariantes/Detail/15 Exibe os detalhes de um determinado aniversariante
Tabela 1. Padrão de URLs usados na Aplicação MuralAniversariantes

O ASP.NET MVC Framework possui uma feature muito interessante para nos ajudar a criar o código necessário para resolver estas três situações listadas anteriormente. São os chamados Action Methods. Assim, quando nossa classe herda da classe Controller, nós podemos criar Action Methods que serão executados automaticamente, de acordo com o formato da URL da chamada. Sendo assim, vamos incluir três métodos na nossa classe AniversariantesController.cs (Listagem 3).

Listagem 3. Action Methods da classe AniversariantesController.cs


 /// URL Exemplo: /Aniversariantes/Meses
 /// 
 public void Meses()
 {
 }
  
 /// URL Exemplo: /Aniversariantes/List/6
 /// 
 public void List(int NroMes)
 {
 }
  
 /// URL Exemplo: /Aniversariantes/Detail/15
 /// 
 public void Detail(int id)
 {
 }

Uma outra observação com relação às URLs é quanto aos parâmetros dos ActionMethods. Por default, o ASP.NET MVC vai interpretar as URLs da seguinte maneira: /[controller]/[action]/[id]. Isso significa que a seguinte URL: /aniversariantes/Detail/6 teria o mesmo efeito que esta: /aniversariantes/Detail?id=15.

Ou seja, por default após o ActionMethod, a próxima informação que vier na URL, será considerada um parâmetro. Podemos (e vamos) tirar vantagem disso para identificar de qual Mês que serão exibidos os aniversariantes no método List, e qual o Aniversariante que será exibido no método Detail.

A nossa classe Controller deverá recuperar os dados requisitados (de acordo com a URL enviada) e chamar a View mais adequada para a exibição destes dados. Sendo assim, precisamos implementar essas tarefas em cada um dos três métodos. Parece algo complexo, mas veremos que precisamos apenas de duas linhas para cada método.

Na Listagem 4 você encontra o código completo da classe AniversariantesController. Veja que estamos utilizando os métodos criados na classe parcial MuralAniversarioDataContext, que fizemos na camada Model. E em seguida, através do método RenderView estamos chamando a View respectiva para cada Action Method.


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using MuralAniversarios.Models;
  
 namespace MuralAniversarios.Controllers
 {
     public class AniversariantesController : Controller
     {
         MuralAniversarioDataContext mural = 
 new MuralAniversarioDataContext();
  
         /// URL Exemplo: /Aniversariantes/Meses
         /// 
         public void Meses()
         {
             List Meses = mural.GetMeses();
             RenderView("Meses", Meses);
         }
  
         /// URL Exemplo: /Aniversariantes/List/6
         /// 
         public void List(int NroMes)
         {
             List Aniversariantes = 
 mural.GetAniversariantesByMes(NroMes);
             RenderView("List", Aniversariantes);
         }
  
         /// URL Exemplo: /Aniversariantes/Detail/15
         /// 
         public void Detail(int id)
         {
             Aniversariante aniversariante = 
 mural.GetAniversarianteById(id);
             RenderView("Detail", aniversariante);
         }
     }
 }
Listagem 4. Implementação completa da classe AniversariantesController.cs

View Meses

Para o desenvolvimento da camada View no ASP.NET MVC Framework, podemos utilizar tranquilamente as páginas, controles e MasterPages (.aspx, .ascx, .master) que já estamos acostumados a usar.

Um ponto importante para a criação das Views é a estrutura de pastas que temos no projeto. Veja que dentro da pasta Views você vai encontrar duas pastas: Shared e Home. Em Shared devemos criar todas as páginas e componentes que podem ser compartilhados por mais de um Controller, como é o caso da MasterPage.

Para Views específicas de um Controller precisamos criar uma pasta específica. No nosso exemplo precisamos criar a pasta Aniversariantes, onde deveremos criar todas as Views utilizadas pelo AniversariantesController. Veja na Figura 12.

Estrutura de pastas da camada View
Figura 12. Estrutura de pastas da camada View

Veja que na pasta Shared já temos uma Master Page criada, que podemos modificar para utilizar em nossas páginas. Para facilitar o nosso trabalho, eu vou colocar aqui na Listagem 5 o código necessário para a página Site.master. Veja que é uma página bastante simples, e estamos utilizando o Html.ActionLink para as chamadas de Menu. O designer do Site.master deverá ficar como mostra a Figura 13.

Design do Site.master
Figura 13. Design do Site.master

<%@ Master Language="C#" AutoEventWireup="true" 
CodeBehind="Site.master.cs" Inherits="MuralAniversarios.Views.Shared.Site" %>
<%@ Master Language=”C#” AutoEventWireup=”true” CodeBehind=”Site.master.cs”
   Inherits=”MuralAniversarios.Views.Shared.Site” %>
   <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
     “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
     <html xmlns=”http://www.w3.org/1999/xhtml”>
       <head runat=”server”>
         <meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1” />
         <title>Mural de Aniversarios</title>
         <link href=”../../Content/Site.css” rel=”stylesheet” type=”text/css” />
       </head>
       <body>
        <div class=”page”>
          <div id=”header”>
            <p id=”logo”>
              <a href=””>Mural de Aniversarios</a></p>
            <ul id=”mainMenu”>
               <li><%= Html.ActionLink(“Home”, “../Home/Index”)%></li>
               <li><%= Html.ActionLink(“Aniversariantes”, 
               “../Aniversariantes/Meses”)%></li>
               <li><%= Html.ActionLink(“About”, “../Home/About”)%></li>
            </ul>
          </div>
          <div id=”mainContent”>
           <div> <asp:ContentPlaceHolder ID=”MainContentPlaceHolder” runat=”server”>
              </asp:ContentPlaceHolder>
           </div>
           <div id=”footer”>
             <p>Mural Aniversarios - Exemplo de Aplicação MVC © Copyright 2008</p>
           </div><!--/footer-->
          </div><!--/mainContent-->
        </div><!--/page-->
     </body>
</html>
Listagem 5. Site.master

Agora vamos criar a página Meses.aspx. Vá na Solution Explorer, clique com o botão direito sobre a pasta Aniversariantes que acabamos de criar, e selecione a opção Add New Item.

Veja na Figura 14 que temos templates exclusivos para a criação de componentes da camada View. Escolha o template MVC View Content Page, informe Meses.aspx em Name e clique em OK. Selecione em seguida a MasterPage Site.master que está na pasta Shared.

Criando nova View Meses.aspx
Figura 14. Criando nova View Meses.aspx

Quando estamos trabalhando com a arquitetura MVC devemos manter nossas Views o mais simples possível, e garantir que o código na View seja restrito apenas à renderização da interface. Acesso a Dados e a lógica da aplicação devem ser escritos dentro das classes Controller. E o Controller por sua vez irá passar para a View os dados que deverão ser exibidos.

MVC View Pages por default herdam da classe System.Web.Mvc.ViewPage, que possui uma série de recursos (métodos e propriedades) que nos ajudam a criar as nossas interfaces. Uma dessas propriedades é a ViewData, que é alimentada pelo Controller através do método RenderView: RenderView("Meses", Meses);

Podemos então, acessar os dados enviados pelo Controller através da propriedade ViewData. Podemos adicionalmente configurar a nossa View para que os dados contidos na propriedade ViewData sejam fortemente tipados. Para isso vá ao code-behind da página Meses.aspx e modifique o código da classe para que fique como demonstrado na Listagem 6. Note que incluímos uma referência ao namespace MuralAniversarios.Models e que mudamos a declaração de herança da classe.


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using MuralAniversarios.Models;
 namespace MuralAniversarios.Views.Aniversariantes
 {
    public partial class Meses : ViewPage>
     {
     }
 }
  
Listagem 6. Meses.aspx.cs

Note que incluímos uma referência ao namespace MuralAniversarios.Models e que mudamos a declaração de herança da classe. Temos duas formas de exibir os Meses na página. Podemos utilizar código inline dentro do arquivo .aspx, ou podemos utilizar Server Controls no .aspx e databinding no code-behind. Neste exemplo vamos utilizar a primeira opção. Para isso, no source da página Meses.aspx inclua o código da Listagem 7 dentro da tag <asp:Content>.


<asp:Content ID=”Content1” ContentPlaceHolderID=”MainContentPlaceHolder”
 unat=”server”>
 <p/>
<div class=”leftColumn”>
  <h2>Meses</h2>
  <ul>
   <% foreach (var mes in ViewData) { %>
    <li>
     <%= Html.ActionLink(mes.Nome, “List/” + mes.Nro.ToString())%>
    </li>
   <%}%>
  </ul>
</div>
<p/>
</asp:Content>

Listagem 7. Meses.aspx

Veja que através de um foreach estamos percorrendo todos os meses contidos na propriedade ViewData. E através do método ActionLink existende na propriedade Html da ViewPage, podemos criar facilmente os links que irão apontar para os ActionMethods das classes Controller.

View List

De uma forma bastante similar podemos criar a nossa View List.aspx. Crie a view List.aspx da mesma forma que criamos a view Meses.aspx. No code-behind da view List.aspx vamos precisar substituir a classe base, assim como fizemos em Meses.aspx.cs. Veja na Listagem 8.


 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Web;
 using System.Web.Mvc;
 using MuralAniversarios.Models;
  
 namespace MuralAniversarios.Views.Aniversariantes
 {
     public partial class List : ViewPage>
     {
     }
 }
  
Listagem 8. Modificando classe base da view List.aspx

Em seguida vamos exibir uma lista de todos os aniversariantes do mês informado na URL. Mas ao contrário do que fizemos em Meses.aspx, vamos utilizar um Server Control bastante conhecido, o GridView.

Para isso vamos precisar incluir a GridView dentro do ContentPlaceHolder. Como esta ainda é uma tecnologia em desenvolvimento, talvez você tenha alguma dificuldade em arrastar o controle na interface. Sendo assim, um método infalível é criar a GridView pelo Source da página, e em seguida fazer as formatações desejadas pelo Design. Aqui na Listagem 9 você vê o source completo da view List.aspx, incluindo o GridView já formatado.


<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
utoEventWireup="true" CodeBehind="List.aspx.cs" 
Inherits="MuralAniversarios.Views.Aniversariantes.List" %>

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master”
   AutoEventWireup=”true” CodeBehind=”List.aspx.cs” Inherits=”MuralAniversarios.Views.

   Aniversariantes.List” %>
   <asp:Content ID=”Content1” ontentPlaceHolderID=”MainContentPlaceHolder”   

     runat=”server”>
     <form id=”form1” runat=”server”>
      <div> <asp:GridView ID=”GridView1” runat=”server” ellPadding=”4”

        ForeColor=”#333333” GridLines=”None”>
        <FooterStyle BackColor=”#5D7B9D” Font-Bold=”True” ForeColor=”White” >
        <RowStyle BackColor=”#F7F6F3” ForeColor=”#333333” />
        <PagerStyle BackColor=”#284775” ForeColor=”White” orizontalAlign=”Center” />
        <SelectedRowStyle BackColor=”#E2DED6” Font-Bold=”True” oreColor=”#333333” />
        <HeaderStyle BackColor=”#5D7B9D” Font-Bold=”True” ForeColor=”White” >
        <EditRowStyle BackColor=”#999999” />
        <AlternatingRowStyle BackColor=”White” ForeColor=”#284775” />
    </asp:GridView>
   </div>
 </form>
</asp:Content>
Listagem 9. Source da view List.aspx

Veja que apenas foi colocado o GridView sem nenhuma configuração adicional, fique à vontade para formatar o GridView da forma que achar mais apropriada. Nosso objetivo aqui é só verificarmos se a aplicação vai funcionar corretamente, através das chamadas feitas diretamente no Controller. Para concluir essa view, vá ao design e dê um duplo-clique na página, para criarmos o evento Page_Load. E neste evento inclua o código da Listagem 10, que faz o DataBinding dos dados para o GridView.


 protected void Page_Load(object sender, EventArgs e)
 {
 GridView1.DataSource = ViewData;
       GridView1.DataBind();
 }
  
Listagem 10. Código do evento Page_Load da List.aspx

Adicionalmente, antes de realizarmos os testes, você pode alterar as views Index e About substituindo os textos que existem nelas, para textos mais condizentes com a aplicação Mural de Aniversariantes.

Testando

Com isso já podemos realizar um teste em nossa aplicação. Salve, compile e execute o projeto. Na página principal clique na opção de menu Aniversariantes, e como você pode conferir na Figura 15, uma lista com todos os Meses do ano será exibida.

Note que a URL acessada para a exibição dos Meses (http://localhost:49225/Aniversariantes/Meses) não aponta para uma página .aspx, e sim para o método Meses da classe AniversariantesController.

Lista de Meses
Figura 15. Lista de Meses

Com isso estamos validando na prática uma aplicação ASP.NET MVC, que aponta suas URLs para as classes Controller e não diretamente para as páginas da camada View. Em seguida, clique em um mês qualquer que contenha aniversariantes, e veja como mostra a Figura 16, que apenas os aniversariantes do mês escolhido é que são listados na GridView. Veja também que a URL, neste caso, está passando um parâmetro para o método List, utilizando as regras de mapeamento de URL discutidas anteriormente.

Lista de Aniversariantes do Mês de Maio
Figura 16. Lista de Aniversariantes do Mês de Maio

Conclusão

Antes de qualquer coisa você deve estar perguntando onde está a terceira view, chamada Detail que foi proposta anteriormente. Essa eu deixo para você fazer, o processo é bastante parecido com o que foi feito nas outras duas views, a diferença é que nesta você deve exibir os dados de um único Aniversariante, no formato de formulário.

Eu penso que deu pra ter uma idéia de qual é a proposta do ASP.NET MVC Framework. No início confesso que essa é uma idéia um pouco assustadora. Veja por exemplo, que não vamos ter PostBacks com este modelo, pois todas os requests são tratados no Controller, e não mais nas páginas.

Porém, o fato de controlarmos o estado da aplicação através de uma classe Controller, nos traz outros benefícios que não tínhamos no modelo tradicional. Além dos benefícios de utilizarmos uma view que herda da classe ViewPage, como é o caso da propriedade ViewData, que em conjunto com o LINQ to SQL nos oferece uma forma bastante simples e eficiente de lidar com os dados da aplicação.

Mas como já foi dito, essa framework ainda está em desenvolvimento, e ainda teremos muitas novidades. O design das views ainda deixa a desejar, e muita coisa acaba tendo que ser feita via código. Além disso, a criação das Unit Tests está mais complexo do que o esperado, e por isso não foi demonstrado aqui.

Mas como todas tecnologias relacionadas ao ASP.NET que surgiram nos últimos anos, essa é uma das que promete muitas novidades e principalmente benefícios para o desenvolvimento de aplicações Web.

Confira também