Desenvolvimento - ASP. NET

ASP.NET 3.5 Extensions: Desvendando o ASP.NET MVC Framework

Veja como funciona na prática e como desenvolver uma aplicação utilizando o ASP.NET MVC Framework, além de suas pricipais características e diferenças em relação ao modelo WebForms.

por Ricardo Oneda



Em meu artigo anterior, discuti algumas características do ASP.NET MVC Framework, que traz para a plataforma .NET uma nova maneira de se desenvolver aplicações Web, diferente do modelo de WebForms existente até então no ASP.NET. Como na época em que o artigo foi escrito o acesso ao framework não era público, limitei-me a abordar alguns aspectos conceituais. Em meados de dezembro de 2007, a Microsoft lançou a versão CTP - Community Technology Preview – do ASP.NET 3.5 Extensions, que é um pacote contendo novas funcionalidades relativas ao ASP.NET 3.5. Dentre essas novidades, o principal destaque é o ASP.NET MVC Framework. O objetivo deste artigo é apresentar esse novo modelo, suas principais características, as diferenças em relação ao modelo anterior e como utilizá-lo na prática.

Pré-requisitos

Neste artigo, foram utilizados os seguintes recursos:

    Visual Studio 2008 – nesta versão, o template de projeto do ASP.NET MVC Framework não está disponível para o Visual Web Developer 2008 Express. A Microsoft pretende lançar futuramente uma versão que atenda essa ferramenta.
  • ASP.NET 3.5 Extensions CTP de dezembro de 2007 – contém o ASP.NET MVC Framework.
  • ASP.NET MVC Toolkit – contém algumas funcionalidades adicionadas na última hora ao ASP.NET 3.5 Extensions. Futuramente, será incorporado ao mesmo, não sendo necessária a instalação separada.

Em alguns momentos do artigo, utilizaremos um arquivo XML para armazenar alguns dados. Para fazer o acesso e a manipulação do arquivo XML, será utilizado o LINQ to XML. Apesar de não ser fundamental para o entendimento do exemplo, o conhecimento prévio dessa tecnologia poderá ajudar. O exemplo será desenvolvido na linguagem C# 3.0/.NET Framework 3.5 e utilizará novas funcionalidades dessa versão, como inferência de tipos, propriedades automáticas, tipos anônimos, etc. Caso o leitor não esteja familiarizado com essas funcionalidades, na seção Referências no final do artigo, há links para artigos nos quais podem ser encontrados mais detalhes.

Vale citar que, por ser uma versão CTP, as informações aqui apresentadas estão sujeitas a alterações até o lançamento da versão final. Além disso, apesar dela ter se apresentado bem estável até o momento, recomenda-se que a mesma seja instalada em um computador do qual você não dependa para a realização de seus trabalhos, já que problemas e bugs podem (e provavelmente vão) aparecer. Pode-se, por exemplo, utilizar uma máquina virtual para os testes.

A arquitetura MVC

O MVC - Model-View-Controller - é uma arquitetura que divide uma aplicação em três partes:

1) o Model, contém a lógica de negócios e também é responsável pela manutenção do estado dos dados (por exemplo, armazenando os dados em um banco de dados);

2) a View, responsável pela interface com o usuário e que não deve possuir nenhuma lógica de negócios e nem de acesso a dados;

3) o Controller, que é o componente mais importante, pois responde pela interação com o usuário, manipula os dados do Model e escolhe a View a ser utilizada. Assim, é o componente que controla as demais partes do sistema.

Entre os benefícios desse padrão, está a clara separação dos papéis de cada componente, o que facilita a manutenção e a execução de testes unitários na aplicação. O ASP.NET MVC Framework implementa essa arquitetura em aplicações ASP.NET.

Você pode estar se perguntando o porquê de se introduzir esse novo modelo, já que até o momento, o ASP.NET gira em torno dos WebForms. Apesar dos WebForms terem apresentado avanços e inovações, como um estilo de desenvolvimento mais parecido com o de aplicações desktop orientado a eventos, abstração de detalhes de implementações de aplicações web (principalmente HTML e o protocolo HTTP) e maior produtividade, essas vantagens tiveram um preço. Foi introduzido o ciclo de vida de uma página ASP.NET e toda uma série de conceitos (como PostBacks e Viewstate) que, para muitos, acabou tirando um pouco o domínio que o desenvolvedor tinha e adicionando uma complexidade que nem sempre é necessária. Além disso, com o modelo de WebForms, fica muito fácil misturar as responsabilidades de cada componente, como por exemplo, adicionando lógica de negócios diretamente nos eventos das páginas.

Então seria esse o fim dos WebForms? Teremos que esquecer tudo o que aprendemos nesses anos? Definitivamente, “Não” é a resposta para as duas perguntas. A Microsoft tem deixado bem claro que os WebForms continuarão existindo e sofrendo evoluções. O ASP.NET MVC Framework será uma alternativa, mas o seu uso não será obrigatório. Caberá aos responsáveis analisar as vantagens e desvantagens de cada modelo e escolher aquele que atenda melhor os requisitos e necessidades do sistema.

O processo de instalação do ASP.NET 3.5 Extensions CTP não é complicado, bastando seguir o assistente de instalação (o link para download pode ser encontrado na seção Referências). Após ter sido instalado, abra o Visual Studio 2008 e acesse o menu File > New Project para criarmos um novo projeto. Na janela que se abre, escolha a linguagem Visual C# e depois a pasta Web. Você irá notar novos templates de projetos que foram adicionados pelo ASP.NET 3.5 Extensions. Particularmente, veja os templates ASP.NET MVC Web Application e o ASP.NET MVC Web Application and Test. Ambos criam um projeto com a estrutura necessária para uma aplicação do tipo MVC. A diferença entre eles é que o segundo template também adiciona automaticamente um projeto de testes unitários à solution da aplicação MVC. A utilização de testes unitários em uma aplicação ASP.NET MVC está fora do escopo deste artigo. Portanto, escolha o template ASP.NET MVC Web Application e crie-o no local e com o nome que mais lhe agradar.

Figura 1 - Criando um projeto do tipo ASP.NET MVC Web Application

Após a aplicação ter sido criada, no Solution Explorer, você irá perceber uma estrutura diferente da utilizada por uma aplicação ASP.NET tradicional, conforme é mostrado na figura 2. As principais novidades são as pastas Controllers, Models e Views. Como você pode deduzir, são nessas pastas que ficam agrupados os componentes que compõem a arquitetura MVC. Na aplicação de exemplo criada com o projeto, temos um controller (HomeController.cs) e duas views (About.aspx e Index.aspx). Essas duas views estão associadas a uma Master Page (Site.Master), que está dentro da pasta Shared, a qual está sob a pasta Views.

Figura 2 - Estrutura de um projeto ASP.NET MVC

Antes de fazermos qualquer alteração na aplicação, vamos executá-la para ver como ela se comporta. Vá ao menu Debug e escolha Start Without Debugging. O browser será aberto com o resultado da operação. A aplicação não possui nada de especial, somente uma página com dois links, Home e About Us. Entretanto, se analisarmos bem, poderemos notar a primeira diferença de uma aplicação MVC em relação ao modelo WebForms. Na barra de endereços do browser, como é mostrado na figura 3, nenhuma página com extensão .aspx está sendo chamada explicitamente. Isso acontece porque em uma aplicação ASP.NET MVC, a URL é mapeada diretamente para uma classe que faz o papel do controller, e não para uma página física em disco. Neste caso, o controller que está sendo chamado é o HomeController, definido dentro da pasta Controllers do projeto.

Figura 3 - URL de uma aplicação ASP.NET MVC

Esse mapeamento entre a URL e o controller é feito por um mecanismo do próprio ASP.NET MVC Framework, que nos permite definir as regras a serem utilizadas para direcionar cada URL ao controller apropriado. Essas regras ficam definidas no evento Application_Start, do arquivo Global.asax.cs. Ao abrirmos esse arquivo, encontramos o seguinte código:

Figura 4 - Mecanismo de rotas do ASP.NET MVC Framework

Nele, são inseridas duas rotas na coleção Routes do objeto RouteTable, do namespace System.Web.Mvc, responsável pelo mapeamento entre URLs e Controllers. A primeira rota define que as URLs seguirão um padrão do tipo [controller]/[action]/[id]. Isso significa que, após o endereço do site, o primeiro parâmetro é o nome do controller, o segundo é o action (método do controller a ser executado - um controller pode ter vários actions) e por último, um identificador [id] qualquer, que é um parâmetro passado para o método definido no action. A propriedade Defaults permite que sejam especificados valores padrão para os parâmetros. Caso o action não seja fornecido, seu valor padrão será Index. Para o id, o valor padrão será null. Assim, ao acessarmos a URL http://localhost:64701/Home/About do nosso exemplo, o ASP.NET MVC Framework chama o método About do controller chamado HomeController. Como não foi passado o parâmetro [id], o mesmo assumiu seu valor default, que nesse caso era null.

A segunda rota estabelece que, quando houver uma chamada à página Default.aspx (que normalmente é a página retornada pelo servidor web quando chamamos a raiz da aplicação), o mecanismo de mapeamento do ASP.NET MVC Framework deve chamar o método Index do HomeController. Assim, a URL http://localhost:64701/ será tratada dessa maneira.

Esse mecanismo de mapeamento funciona através de um módulo HTTP, definido no arquivo web.config de uma aplicação ASP.NET MVC:

Figura 5 - Módulo HTTP responsável pelo mecanismo de rotas

Cada requisição feita a uma aplicação passa pelo módulo HTTP UrlRoutingModule, que faz a análise da URL e determina para qual handler passar a requisição. Para aplicações MVC, esse handler é do tipo MvcRouteHandler (veja o parâmetro RouteHandler no código da figura 4), que irá então executar o controller especificado.

Uma informação importante é que as rotas são analisadas na ordem em que são adicionadas ao objeto RouteTable. Quando uma URL atende a um padrão definido de rota, o mecanismo deixa de pesquisar as demais rotas. Assim, a ordem em que as rotas são adicionadas deve ser cuidadosamente avaliada, ficando as rotas mais específicas em primeiro, e as rotas mais genéricas por último. Caso a URL não atenda os requisitos de nenhuma rota cadastrada, a requisição não é tratada pelo MVC Framework e é passada adiante. Isso permite que aplicações MVC e WebForms convivam simultaneamente sem problemas.

Após a rota ter sido encontrada, o controller associado a ela é então executado. O padrão de nome dos controllers é utilizar uma parte do caminho da URL juntamente com o sufixo Controller. Assim, no nosso exemplo, as requisições para /Home/ são direcionadas para HomeController. Abrindo o arquivo HomeController.cs do projeto, encontraremos o seguinte código:

Figura 6 - HomeController

Nele, pode-se notar que o HomeController é uma classe que herda da classe Controller, que pertence ao namespace System.Web.Mvc. Essa classe é a responsável por executar o método apropriado (definido no action) e passar possíveis parâmetros para ele. Um controller, como qualquer classe, pode ter vários métodos. No exemplo, há dois métodos: Index e About. Esses métodos estão decorados com o atributo [ControllerAction], que indica que os métodos são do tipo action. Isso significa que esses métodos estarão expostos publicamente pela aplicação e poderão ser utilizados quando uma requisição for feita. Assim, quando o caminho da URL for /Home/About/ o método About de HomeController será executado. Caso algum método do controller não tenha este atributo, então o mesmo não poderá ser consumido diretamente da URL.

Nenhum dos dois métodos espera algum tipo de parâmetro. Ao desenvolvermos o exemplo ao longo do artigo, será mostrado como trabalhar com parâmetros nos métodos action.

Após o controller definir qual método foi requisitado, o mesmo é executado. No exemplo, o conteúdo dos métodos é muito simples, contendo apenas uma chamada para o método RenderView, que será o responsável por processar uma view. Em uma aplicação real, o método executaria mais ações, como por exemplo, recuperar parâmetros ou manipular dados do model. Por padrão, o ASP.NET MVC Framework utiliza páginas .aspx, Master Pages (.master) e User Controls (.ascx) como mecanismos de views, mas nada impede que utilizemos outros frameworks para renderizar a interface com o usuário. É importante que as views contenham somente código relacionado à lógica de apresentação, funcionando somente como templates, ou seja, não deve possuir lógica de aplicação ou de acesso a dados. Todo esse fluxo pode ser resumido na seguinte figura:

Figura 7 - Fluxo de execução

As views de uma aplicação ASP.NET MVC ficam dentro da pasta Views do projeto, dentro de um subdiretório com o prefixo do nome do controller. Assim, as views utilizadas por HomeController para gerar a interface com o usuário ficam no subdiretório Views\Home. Esse é o primeiro lugar que o framework irá procurar pela view quando o método RenderView for chamado por HomeController. Caso o template não seja encontrado, o framework faz a busca na pasta Shared, que fica dentro de Views. Esse é o lugar onde ficam as Master Pages, User Controls e ou outros templates que serão utilizados por mais de um controller.

Se você abrir alguma view que já acompanha o projeto de exemplo, irá perceber que é muito parecida com uma página .aspx tradicional (no caso do exemplo, ela é parecida com um Web Content Form, já que a view está associada a uma Master Page). Inclusive, ela possui um arquivo code-behind associado. A principal diferença é que a view herda da classe System.Web.Mvc.ViewPage, diferentemente de um WebForm.

Exemplo

Agora chegou o momento de desenvolver um exemplo mais elaborado, que permitirá entender na prática o funcionamento de uma aplicação ASP.NET MVC, além de possibilitar o uso de algumas funcionalidades ainda não apresentadas. A aplicação será um leitor de feeds RSS bem simples, que armazenará os dados dos feeds e permitirá a consulta on-line dos mesmos, apresentando uma lista das últimas atualizações. Para isso, iremos utilizar a estrutura do projeto já criado. Não me preocuparei com a estética da aplicação, mas sim em apresentar os conceitos. O link para o download do exemplo encontra-se na seção Referências, no final do artigo. Depois de concluído o exemplo, teremos algo parecido com a figura 8.

Figura 8 - Leitor de RSS ASP.NET MVC Framework

A aplicação permitirá cadastrar novos feeds, apagar feeds já cadastrados, além de listá-los. Ao se clicar no nome de algum feed, o usuário será direcionado para uma página que listará todos os posts do feed selecionado, obtidos de maneira on-line. Assim, a aplicação terá as seguintes ações:

Ação

Formato da URL

Listar os feeds cadastrados

/Feeds/List

Mostrar tela de cadastro de novo feed

/Feeds/New

Criar novo feed

/Feeds/Create

Apagar um feed

/Feeds/Delete/[id]

Listar os posts de um feed

/Posts/List/[id]

Considerando o formato da URL como sendo [controller]/[action]/[id], podemos concluir que teremos um controller chamado Feeds (que possuirá ações/métodos List, New, Create e Delete) e um controller chamado Posts (com a ação/método List).

Para efeitos de simplicidade, os dados dos feeds serão armazenados em um arquivo XML, que conterá um número identificador do feed (que deverá ser único), o nome e a URL do feed. No Visual Studio 2008, vá ao Solution Explorer e clique com o botão direito do mouse sobre a pasta App_Data. Escolha a opção Add > New Item e selecione o template XML File, cujo nome deverá ser Feeds.xml. Adicione alguns dados, como no exemplo:

Figura 9 - Arquivo XML com os dados dos feeds

Agora, vamos criar o model de nossa aplicação. Ele será composto das classes Feed (que representará cada feed cadastrado) e Post (cada post de um determinado feed). No Solution Explorer, clique com o botão direito do mouse sobre a pasta Models, escolhendo a opção Add > New Item. Na janela que se abre, escolha o template Class e dê o nome de Feed.cs. Ao ser criada a nova classe, o Visual Studio já adiciona automaticamente um namespace baseado no nome do projeto. Nesse caso, o namespace chama-se MvcApplication.Models. A classe Feed terá somente três propriedades, chamadas Id, Name e Url, conforme figura 10.

Figura 10 - Definição da classe Feed

Note que, para declarar a classe, foi utilizada uma nova funcionalidade do C# 3.0 chamada de Propriedades Automáticas, que permite que as propriedades sejam declaradas sem a necessidade da existência de campos privados da classe.

Agora, siga o mesmo procedimento e adicione uma nova classe chamada Post. Essa classe possuirá as propriedades Title (título do post), Link (URL do post) e Date (data de publicação).

Figura 11 - Definição da classe Post

Outra classe que fará parte do model será a FeedRepository, responsável por gravar e ler as informações do arquivo XML. Os métodos dessa classe utilizarão o LINQ to XML e Generics para trabalhar com esses dados. Portanto, após adicionar o arquivo de classe FeedRepository.cs na pasta Models do projeto, inclua referências aos respectivos namespaces, como mostrado na figura 12.

Figura 12 - Namespaces do LINQ to XML e Generics

Não entrarei em detalhes do funcionamento do LINQ to XML, pois não faz parte do escopo do artigo, mas o importante é saber que há um método para inserir um novo feed no arquivo XML – AddFeed, para apagar um determinado feed DeleteFeed, para listar todos os feeds cadastrados – GetAllFeeds e outro para obter todos os posts de um feedGetAllPosts. A implementação de todos esses métodos pode ser vista a figura 13. Uma análise mais detalhada pode ser feita através do código-fonte do exemplo, disponível para download na seção Referências, no final do artigo.

Figura 13 - Classe FeedRepository

O próximo passo é criar os controllers. Vá ao Solution Explorer, clique com o botão direito do mouse sobre a pasta Controllers, escolha Add > New Item e selecione o template MVC Controller Class, nomeando-o FeedsController.cs, conforme figura 14.

Figura 14 - Criando um controller

O primeiro método a ser criado será o List, que irá obter os feeds cadastrados através do model e chamar a view FeedList, que será criada posteriormente e vai ser a responsável por montar a página HTML com o resultado. Antes de qualquer coisa, precisamos referenciar os namespaces dos Generics e do nosso modelo:

Figura 15 - Namespaces do model e Generics

A classe FeedsController também terá um objeto do tipo FeedRepository, que será o responsável por persistir as alterações no arquivo XML. A implementação da classe e do método List ficará assim:

Figura 16 - Método List do controller Feeds

Note que o método List possui o atributo [ControllerAction], indicando que esse método pode ser invocado a partir de uma URL. Além disso, na linha 16 da figura 16, o retorno do método GetAllFeeds é associado a um objeto ViewData. Esse objeto é uma propriedade do tipo dicionário da classe Controller que permite adicionar dados para que sejam recuperados na view. Por último, o método RenderView é executado, recebendo como parâmetro o nome da view a ser processada.

Vamos agora criar a view FeedList. No Solution Explorer, na pasta Views, crie um subdiretório com o nome do controller para o qual iremos criar a view, ou seja, Feeds (botão direito do mouse sobre a pasta Views > Add > New Folder). Adicione então o arquivo FeedList.aspx clicando com o botão direito do mouse sobre a pasta Feeds e escolhendo Add > New Item e selecionando o template MVC View Content Page. Este template foi escolhido porque queremos que essa view esteja vinculada à Master Page Site.Master. Caso não desejássemos utilizar uma Master Page, escolheríamos o template MVC View Page.

Figura 17 - Criando uma MVC View Content Page

Aqui também precisamos referenciar os namespaces dos Generics e do nosso modelo. Portanto, na parte HTML da página, adicione as seguintes linhas logo após a diretiva <@ Page %>:

Figura 18 - Namespaces do model e Generics

A página deverá então recuperar a lista de objetos Feed passada através da propriedade ViewData e exibi-los em uma tabela HTML com duas colunas. Na primeira coluna será exibido o nome do feed, que será um link para o método List do controller Posts. Na segunda coluna, será montado um link com a literal “Apagar” que, quando clicado, executará o método Delete do controller Feeds. Ao final da lista de feeds, haverá outro link com o texto “Novo Feed”, que chamará o método New do controller Feeds. Todos esses métodos serão implementados no decorrer do artigo. O código que teremos será o seguinte:

Figura 19 - View FeedList

Perceba que os links são criados através do método Html.ActionLink. Esse método gera um link HTML dinamicamente, de acordo com os parâmetros passados para ele. O primeiro parâmetro é o texto que será visível para o usuário da aplicação. O segundo parâmetro pode ser um tipo anônimo (uma novidade do C# 3.0 e VB 9.0 que permite utilizar um tipo sem ter que defini-lo explicitamente), como acontece nas linhas 18 e 21 do código, ou então o nome do método a ser chamado, como na linha 29. O método Html.ActionLink ainda permite uma terceira sobrecarga, na qual um terceiro parâmetro representa o nome do controller. A vantagem de se utilizar esse método ao invés de montarmos o link manualmente é que o link gerado pelo método Html.ActionLink baseia-se no mecanismo de rotas do ASP.NET MVC Framework e nas regras que foram especificados no evento Application_Start do Global.asax, que foi visto anteriormente. Assim, qualquer mudança no formato das rotas faz com que automaticamente o método Html.ActionLink gere links no novo formato.

Na view também há uma lógica para alternar o estilo CSS de cada linha. É preciso então criar essas classes de estilo, chamadas de linhaPar e linhaImpar, no arquivo Content\Site.css. Isso pode ser feito manualmente ou então a partir da nova janela de gerenciamento de estilos do Visual Studio 2008 (menu View > Manage Styles). Você pode seguir a sugestão apresentada ou utilizar a configuração de formatação que mais lhe agradar.

Figura 20 - Estilos CSS

Para concluir a implementação do método List, precisamos disponibilizar um link para que o mesmo seja chamado. No Solution Explorer, dê um duplo clique no arquivo Site.master da pasta Shared do projeto. Após a Master Page ser aberta, insira uma chamada ao método Html.ActionLink entre os links Home e About Us. Esse novo link será o responsável por chamar o método List do controller Feeds. Veja como deve ficar:

Figura 21 - Inserindo um link na Master Page

Agora a aplicação já pode ser testada. Note que o link “Feeds” apareceu no menu. Perceba também que a URL do link que aparece na barra de status do browser foi montada corretamente, seguindo o formato [controller]/[action].

Figura 22 - Menu para o controller Feeds

Clique no link e uma página com os feeds cadastrados no seu arquivo XML deve ser montada, semelhante a que havia sido mostrada na figura 8. Abra o código fonte da página (botão direito sobre a página > View Source) e veja que somente foi gerado HTML estritamente necessário, ou seja, o ASP.NET não inseriu nada além do esperado (como viewstate ou outras tags, por exemplo).

Figura 23 - Código HTML gerado pelo método List

Como você deve se lembrar, nesse exemplo, utilizamos o objeto ViewData para passar a lista de objetos Feed para a view FeedList. Na view, tivemos que obter essa lista e convertê-la para o tipo de dados correto, para que então pudéssemos manipulá-los. Outra forma de passar dados entre o controller e a view é através de uma classe fortemente tipada, o que nos permite usufruir de todas as vantagens que esse modelo proporciona, como checagem de tipos em tempo de compilação, não precisar fazer a conversão, intellisense no editor de código do Visual Studio, etc. Para isso, é preciso que a view, ao invés de herdar da classe ViewPage, que é o comportamento padrão, derive da classe genérica ViewPage<T>, onde <T> é o tipo de dados do ViewData que o controller irá passar para view.

Para utilizar uma classe fortemente tipada para a passagem de dados, abra o arquivo code-behind da view, chamado FeedList.aspx.cs. Adicione referências aos namespaces do model e dos Generics e mude a classe base de FeedList de ViewPage para ViewPage<List<Feed>>, ou seja, uma lista de objetos Feed.

Figura 24 - View fortemente tipada

Volte ao arquivo FeedList.aspx e remova as referências de namespaces ilustradas na figura 18. Altere o código conforme mostrado na figura 25. Note que não mais é necessário fazer a conversão do tipo de dados.

Figura 25 - Acessando dados do ViewData fortemete tipado

Por último, vá ao método List do controller Feeds e passe como segundo parâmetro do método RenderView a lista de feeds obtida anteriormente. Execute novamente a aplicação e certifique-se que tudo está funcionando como antes.

Figura 26 - Passando dados para a view

Agora vamos implementar o método New e sua respectiva view. Esse método será chamado quando o link “Novo Feed” for clicado. Ele não possui nada de mais, contendo apenas uma chamada do método RenderView, que irá montar a página na qual será possível informar os dados do novo feed. Na classe FeedsController, adicione o seguinte código:

Figura 27 - Método New do controller Feeds

Para criar a view, na pasta Views\Feeds do projeto, adicione um MVC View Content Page chamado NewFeed.aspx. Essa view conterá um formulário HTML com apenas dois campos para entrada de texto (um para o nome e o outro para a URL do feed) e um botão para salvar os dados. Note que o código contém somente controles HTML padrão, ou seja, nenhum controle é do ASP.NET.

Figura 28 - View NewFeed

Note que o conteúdo do atributo action do formulário é obtido através do método Url.Action. Esse método é semelhante ao Html.ActionLink visto anteriormente, mas enquanto esse último gera uma tag HTML de link completa, o método Url.Action gera somente a URL. Por exemplo, o comando Html.ActionLink(“Novo Feed”, “New”) gera a seguinte string:

<a href="/Feeds/New">Novo Feed</a>

Já o comando Url.Action(“Create”) irá gerar somente:

/Feeds/Create

O método Create será o responsável por armazenar os dados fornecidos na view NewFeed no arquivo XML. Portanto, adicione o seguinte código na classe FeedsController:

Figura 29 - Método Create do controller Feeds

Esse código cria um novo objeto Feed e altera as propriedades Name e Url para o que foi digitado na view. Depois, o método AddFeed é chamado para que o novo feed seja gravado no arquivo XML. Por fim, o método RedirectToAction é executado. Esse método redireciona o fluxo de execução para outro método. Nesse caso, será chamado o método List, implementado anteriormente. No código da figura 29, estamos obtendo os parâmetros do novo feed através da coleção Request. Outra maneira de se fazer isso seria definir os parâmetros que o método Create espera e deixar o ASP.NET MVC Framework mapear automaticamente os valores fornecidos nos campos para os parâmetros do método. O código ficaria assim:

Figura 30 - Passando parâmetros para o método automaticamente

Perceba que os nomes dos parâmetros do método (Name e Url) são os mesmos utilizados como nomes dos campos do formulário HTML da figura 27. Execute a aplicação, clique no link “Feeds” do menu e depois em “Novo Feed”. Você verá uma página parecida com a da figura 31. Entre com os dados e clique no botão “Salvar”. O feed será salvo e aparecerá na lista de feeds que será montada.

Figura 31 - Página para cadastro de feed

Para montarmos essa view, codificamos as tags HTML diretamente na página. Outra maneira de se obter o mesmo resultado é através de métodos fornecidos pelo MVC Toolkit que geram automaticamente as tags HTML. Na versão atual do ASP.NET MVC Framework, o download do MVC Toolkit tem que ser feito a parte. Nas versões futuras, ele será integrado ao framework (veja o link para download na seção Referências, no final do artigo). Após ter feito o download, copie o arquivo MVCToolkit.dll que se encontra na pasta Binaries para a pasta bin do projeto. Em seguida, adicione uma referência a este arquivo clicando com o botão direito sobre a pasta References do Solution Explorer e escolhendo Add Reference > guia Browse.

Figura 32 - Referência ao MVCToolkit

Abra novamente o arquivo NewFeed.aspx, no qual iremos substituir as tags HTML pelos métodos do MVC Toolkit. Esses métodos podem ser acessados através do objeto Html. Pelo intellisense do Visual Studio, após adicionar a referência, você vai perceber que aparecem métodos (na verdade, extension methods) que antes não existiam.

Figura 33 - Extension methods inseridos pelo MVC Toolkit

Existem métodos correspondentes a várias tags HTML, como form, button, checkbox, image, textarea, select, etc. Nesse caso, iremos utilizar os métodos para montar o formulário, duas caixas de texto e um botão. Teremos o seguinte código (com destaque em vermelho para as alterações):

Figura 34 - Utilizando extension methods do MVC Toolkit para montar tags HTML

Outro ponto no qual podemos nos beneficiar do MVC Toolkit é a forma como se atribui valores às propriedades de um objeto. Tome como exemplo o método Create do controller Feeds, apresentado na figura 30. Para cada propriedade do objeto feed, tivemos que associar um valor que veio no formulário (linhas 25 e 26 do código). Nesse caso, só havia duas propriedades, mas se existissem muitas, o trabalho seria grande. Para essas situações, podemos utilizar o extension method UpdateFrom, do namespace System.Web.Mvc.BindingHelpers. Primeiro, no arquivo FeedsController.cs, adicione a referência ao namespace citado. Depois, substitua as linhas 25 e 26 do código da figura 30 por uma chamada ao método UpdateFrom:

Figura 35 - Preenchendo as propriedades do objeto através do método UpdateFrom

Esse método recebe como parâmetro um dicionário (nesse caso, Request.Form, contendo os campos passados pelo formulário HTML de cadastramento de feed) e automaticamente associa os valores desse dicionário com as propriedades do objeto, baseado nos nomes das propriedades. Execute novamente a aplicação e verifique que tudo continua funcionando exatamente como antes. Abra o código fonte da página e analise também o código HTML gerado pelos métodos do MVC Toolkit.

Para concluir o controller Feeds, falta o método Delete. Essa ação será chamada quando se clicar no link “Apagar” montado pela view FeedList e irá receber um id que identifica qual feed se quer excluir. Após a chamada do método responsável pela exclusão (DeleteFeed), a lista com os feeds cadastrados será montada novamente, dessa vez sem o feed que acabou de ser excluído.

Figura 36 - Método Delete do controller Feeds

Execute a aplicação e clique no link “Apagar” de algum feed. Abra o arquivo Feeds.xml em App_Data para certificar-se que o feed foi realmente apagado.

Ainda falta implementarmos a ação List do controller Posts, que será responsável por listar todos os posts retornados por um feed RSS. Primeiro, na pasta Controllers no Solution Explorer, adicione um MCV Controller Class chamado PostsController.cs. O controller Posts terá somente o método List, que obterá uma lista de objetos Post de um determinado feed e processará a view PostList, passando essa lista como parâmetro. Não se esqueça de adicionar as referências para os namespaces do model e dos Generics.

Figura 37 - Controller Posts

Resta-nos a codificação da view PostList. No Solution Explorer, na pasta Views, crie um subdiretório com o nome do controller para o qual iremos criar a view, ou seja, Posts. Depois, na pasta Posts, adicione um MVC View Content Page chamado PostList.aspx. Essa view irá utilizar o mesmo conceito de view fortemente tipada apresentado anteriormente. Portanto, abra o arquivo de code-behind PostList.aspx.cs e derive a classe PostList de ViewPage<List<Post>>. É necessário adicionar referências aos namespaces dos Generics e do model.

Figura 38 - View PostList fortemete tipada

Na view FeedList, para mostrar a lista de feeds, foi utilizado o conceito de código inline, ou seja, o código que será executado no servidor, identificado pelas tags <% %>, está junto do código HTML. Nesta view, será utilizado outro conceito, que é o de server controls. Assim, poderemos manipular a maneira de exibição como se estivéssemos em uma aplicação ASP.NET tradicional, utilizando WebForms. Nesse caso, iremos utilizar um Repeater para listar os posts de um feed. Acrescente um controle Repeater (que se encontra na guia Data da Toolbox do Visual Studio) e nomeie-o PostRepeater. Acrescente a ele um ItemTemplate e um AlternateItemTemplate, conforme a figura 39.

Figura 39 - Utilizando um Repeater para exibir os dados

As propriedades passadas para o método Eval são as mesmas existentes na classe Post, pois será um objeto desse tipo o DataSource do Repeate, que será definido no evento Page_Load da view, no code-behind. Se você simplesmente for para o code-behind e tentar acessar o Repeater, não terá sucesso. Isso acontece por causa de um bug do ASP.NET MVC Framework que impede que se tenha acesso aos server controls a partir do code-behind de uma view (lembre que se trata de uma versão CTP e que o problema será corrigido em versões futuras). Para que se possa ter acesso a eles, no Solution Explorer, clique com o botão direito do mouse sobre o arquivo PostList.aspx e escolha a opção Convert to Web Application. Isso irá criar o arquivo PostList.aspx.designer.cs, que contém a declaração dos server controls da página.

Figura 40 - Corrigindo bug para acessar server controls

Agora é possível acessar o Repeater no code-behind. Estamos associando o objeto ViewData ao DataSource do Repeater. Lembre-se de que estamos utilizando uma view fortemente tipada, ou seja, o objeto ViewData, neste caso, é do tipo <List<Post>>:

Figura 41 - Associando um DataSource no code-behind

Algumas observações importantes:

nem todos server controls podem ser utilizados em uma aplicação ASP.NET MVC. Server controls que dependem da infra-estrutura dos WebForms (ciclo de vida da página, viewstate, etc), como o GridView, não são suportados;

existe uma polêmica sobre qual modelo utilizar: código inline ou code-behind. Muitos acreditam que utilizar código inline é um retrocesso, comparando este estilo ao do ASP clássico, no qual o código VBScript ficava misturado com HTML. Uma diferença fundamental é que no ASP clássico não havia uma clara divisão de responsabilidades, ficando o model, view e controller, na maior parte das vezes, em um único local: a página. Em uma aplicação ASP.NET MVC isso não acontece (ou pelo menos, é mais difícil acontecer). O código inline acaba sendo utilizado somente na implementação de lógica relativa à interface com o usuário, que é a especialidade da view, e não deve ser utilizado para acessar diretamente os dados e nem possuir lógica de negócios. Portanto, não vejo problemas em utilizá-lo, respeitando essas limitações.

Ao se executar a aplicação e clicar no nome de algum dos feeds disponíveis, será mostrada uma página com os posts do feed escolhido.

Figura 42 - Lista de posts

Conclusão

Neste artigo, vimos de maneira prática como desenvolver uma aplicação utilizando o novo ASP.NET MVC Framework. Foi mostrado como funciona o mecanismo de mapeamento de URLs do framework, como implementar os controllers e passar dados desses para as views, maneiras de se gerar o HTML e algumas funcionalidades do MVC Toolkit. Você deve ter percebido que muito trabalho que hoje é feito automaticamente no modelo WebForms, tem que ser feito manualmente no padrão MVC. Em compensação, esse modelo dá maior controle sobre a aplicação. Destaco novamente que o modelo MVC não vai substituir o modelo de WebForms. Ele será uma alternativa, com suas vantagens e desvantagens, que deverão ser analisadas no momento de decidir qual arquitetura utilizar. Espero que este artigo tenha lhe dado uma boa visão inicial do assunto, a partir da qual seja possível aprofundar seus estudos.

Referências

Download do código fonte do exemplo

Download do ASP.NET 3.5 Extensions e MVC Toolkit

ASP.NET MVC Framework Quickstart

.NET Language-Integrated Query for XML Data

Implicitly Typed Local Variables

Extension Methods

Anonymous Types

Auto-Implemented Properties

Ricardo Oneda

Ricardo Oneda - Formado em Processamento de Dados pela Faculdade de Tecnologia de São Paulo, é Microsoft MVP (Most Valuable Professional) em ASP/ASP.NET e MCAD (Microsoft Certified Application Developer), com ênfase em aplicações Web com C# e Banco de Dados SQL Server 2000. Atualmente, trabalha como Analista de Sistemas no desenvolvimento de aplicações Web.
Blog:
http://oneda.mvps.org/blog.