Em Maio/2014 a Microsoft anunciaria o primeiro release de uma versão reformulada da tecnologia ASP.NET. Batizado de “ASP.NET vNext”, este projeto possui um forte enfoque no desenvolvimento voltado a cloud computing. Outro ponto que merece destaque é o fato do ASP.NET vNext ter sido construído de uma forma que prioriza a performance na execução de aplicações, abrindo mão para isto de recursos do .NET Framework outrora habilitados por default em soluções Web.

Já em Junho/2014 seria também disponibilizada uma versão de avaliação (CTP 1) da nova IDE de desenvolvimento: trata-se do Visual Studio "14". Contando com templates que possibilitam a construção de aplicações baseadas no ASP.NET vNext, o Visual Studio "14" encontra-se atualmente (Outubro/2014) na versão CTP 4.

Em um outro artigo, tratamos sobre as principais novidades trazidas pelo ASP.NET vNext e o Visual Studio "14", neste novo artigo será demonstrado, através de um exemplo simplificado, como uma aplicação ASP.NET vNext pode ser construída a partir desta nova versão do Visual Studio. O projeto em questão permitirá a consulta a alguns pontos turísticos por meio do Google Maps, conforme descrito nas próximas seções.

Exemplo de utilização do ASP.NET vNext

Para implementar a solução demonstrada nesta seção foram utilizados os seguintes recursos:

  • O Microsoft Visual Studio "14" CTP como IDE de desenvolvimento;
  • O .NET Framework 4.5.3;
  • O framework ASP.NET vNext para a criação de uma Web Application;
  • A biblioteca Google Maps API v3.

O projeto TesteASPNETvNext será do tipo “ASP.NET vNext Web Application”, conforme indicado na Figura 1. O objetivo desta aplicação é demonstrar de que forma gráficos do Google Maps podem ser incorporados a uma página HTML. Vale destacar ainda que o site em questão permitirá a visualização de mapas para alguns pontos turísticos brasileiros.

Criando uma
ASP.NET vNext Web Application no Visual Studio
Figura 1. Criando uma ASP.NET vNext Web Application no Visual Studio "14"

Implementando as classes de acesso a dados

Uma vez que o projeto TesteASPNETvNext tenha sido gerado, o próximo passo consistirá na implementação das classes Atracao e AtracaoCollection (ambas deverão ser criadas na pasta Models da aplicação).

Na Listagem 1 está o código que define o tipo Atracao. Esta classe será utilizada na manipulação de informações sobre pontos turísticos, contando com dados como o nome da atração, o ano em que a mesma foi fundada, a localidade, além da latitude e longitude para o local considerado.

Listagem 1. Classe Atracao

  using System;
   
  namespace TesteASPNETvNext.Models
  {
      public class Atracao
      {
          public string CodAtracao { get; set; }
          public string NomeAtracao { get; set; }
          public int AnoFundacao { get; set; }
          public string Localidade { get; set; }
          public double Latitude { get; set; }
          public double Longitude { get; set; }
   
          public Atracao(
              string _codAtracao, string _nomeAtracao, int _anoFundacao,
              string _localidade, double _latitude, double _longitude)
          {
              this.CodAtracao = _codAtracao;
              this.NomeAtracao = _nomeAtracao;
              this.AnoFundacao = _anoFundacao;
              this.Localidade = _localidade;
              this.Latitude = _latitude;
              this.Longitude = _longitude;
          }
      }
  }

Já na Listagem 2 está a implementação da classe AtracaoCollection. Constam neste tipo:

  • Uma variável estática privada chamada “_Atracoes”. Esta referência conterá uma coleção de instâncias da classe Atracao, a qual servirá de base para a geração de uma relação com as diferentes atrações consideradas pelo projeto TesteASPNETvNext;
  • Um construtor estático, no qual acontecerá a inicialização da coleção que armazenará as atrações controladas pela aplicação de testes;
  • O método estático ListarAtracoes, que ao ser acessado retornará a coleção de objetos associada ao atributo privado “_Atracoes”;
  • A operação estática ObterAtracao, a qual receberá como parâmetro um código de atração, a fim de retornar uma instância do tipo Atracao com os dados relativos a tal ponto turístico.
Listagem 2. Classe AtracaoCollection

  using System;
  using System.Collections.Generic;
  using System.Linq;
   
  namespace TesteASPNETvNext.Models
  {
      public static class AtracaoCollection
      {
          private static List<Atracao> _Atracoes;
   
          static AtracaoCollection()
          {
              _Atracoes = new List<Atracao>();
   
              _Atracoes.Add(new Atracao(
                  "MASP", "Museu de Arte de São Paulo (MASP)", 1968,
                  "São Paulo - SP", -23.561632, -46.655958));
   
              _Atracoes.Add(new Atracao(
                  "CATSESP", "Catedral Metropolitana de São Paulo (Sé)", 1954,
                  "São Paulo - SP", -23.55128, -46.634343));
   
              _Atracoes.Add(new Atracao(
                  "MATOSI", "Santuário do Bom Jesus de Matosinhos", 1808,
                  "Congonhas - MG", -20.507797, -43.860572));
   
              _Atracoes.Add(new Atracao(
                  "PLPLANAL", "Palácio do Planalto", 1960,
                  "Brasília - DF", -15.799049, -47.860769));
          }
   
          public static IEnumerable<Atracao> ListarAtracoes()
          {
              return _Atracoes;
          }
   
          public static Atracao ObterAtracao(string codAtracao)
          {
              return _Atracoes.Where(a => a.CodAtracao == codAtracao).First();
          }
      }
  }

OBSERVAÇÃO: a classe AtracaoCollection foi criada por questões de simplificação. Em um cenário real, este tipo seria substituído por uma estrutura que se comunicaria com um banco de dados, por exemplo.

Implementando o Controller e a View para a visualização de um mapa

Com os tipos da camada Model definidos, deve-se proceder agora com a implementação do Controller que permitirá a exibição de mapas sobre atrações turísticas.

Um novo Controller pode ser criado por meio da janela Solution Explorer: para isto clicar com o botão direito do mouse sobre a pasta Controllers, selecionando em seguida no menu de atalho a opção “Add” e, em seguida, “New Item”. Aparecerá então a janela “Add New Item”; selecionar o template “MVC Controller Class”, preenchendo o campo “Name” com o valor "AtracaoController" (Figura 2).

Criando um novo
Controller
Figura 2. Criando um novo Controller

O código que define o Controller AcaoController está na Listagem 3:

  • Conforme é possível observar, o namespace Microsoft.AspNet.Mvc substitui as antigas referências que apontam para System.Web (esta foi uma das mudanças arquiteturais mais significativas nesta nova versão do framework ASP.NET);
  • A Action ExibirMapa recebe como parâmetro uma string correspondente ao código de uma atração/ponto turístico (tal valor é associado ao objeto ViewBag para uso posterior, através da propriedade CodAtracao). O retorno desta operação será uma instância do tipo IActionResult, a qual é gerada a partir da invocação do método View;
  • Também recebendo como parâmetro um código de atração, a Action ObterAtracao devolve como resultado de sua execução um objeto do tipo Atracao. A ideia é que tal referência seja consumida no padrão JSON. Diferentemente de versões anteriores do framework MVC, o ASP.NET vNext dispensa o uso da classe JsonResult, assim como de instruções convertendo instâncias para o formato JSON.
Listagem 3. Controller AtracaoController

  using Microsoft.AspNet.Mvc;
  using TesteASPNETvNext.Models;
   
  namespace TesteASPNETvNext.Controllers
  {
      public class AtracaoController : Controller
      {
          public IActionResult ExibirMapa(string codAtracao)
          {
              ViewBag.CodAtracao = codAtracao;
   
              return View();
          }
   
          public Atracao ObterAtracao(string codAtracao)
          {
              return AtracaoCollection.ObterAtracao(codAtracao);
          }
      }
  }

Para gerar a View empregada na exibição de mapas, criar dentro da pasta “Views” uma nova subpasta chamada “Atracoes” (como indicado na Figura 3). A View ExibirMapa.cshtml será criada neste local, por meio da utilização do template “MVC 5 View Page (Razor)”, como mostra a Figura 4.

Controller e View
para a exibição de um mapa
Figura 3. Controller e View para a exibição de um mapa.
Criando a View ExibirMapa.cshtml
Figura 4. Criando a View ExibirMapa.cshtml.

Quanto à codificação da View ExibirMapa.cshtml (Listagem 4), nota-se:

  • No início da seção “scripts” foi incluída uma referência que aponta para a biblioteca Google Maps API v3 (responsável pela renderização de mapas);
  • O método ready, executado durante o carregamento da página HTML de visualização de mapas. Tal função utiliza o código de atração associado ao objeto ViewBag, além de acionar por meio da instrução “$.ajax” a Action ObterAtracao (Controller AtracaoController). O retorno deste procedimento será um objeto JSON, o qual conterá os dados de uma atração. Esta referência servirá de base então para o preenchimento de um Label que identifica o nome da atração, assim como para se invocar o método renderizarMapaAtracao;
  • A função renderizarMapaAtracao faz uso de recursos da biblioteca Google Maps API v3, com o intuito de gerar um mapa baseado nas coordenadas de latitude e longitude de um ponto turístico.
Listagem 4. View ExibirMapa.cshtml

  @section scripts{
      <script type="text/javascript"
              src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
   
      <script type="text/javascript">
   
          $(document).ready(function () {
              var codAtracao = '@ViewBag.CodAtracao';
              var atracao;
   
              $.ajax({
                  type: 'GET',
                  url: '/Atracao/ObterAtracao?codAtracao=' + codAtracao,
                  dataType: 'json',
                  cache: false,
                  async: false,
                  success: function (data) { atracao = data; }
              });
   
              $("#lblNomeAtracao").text(atracao.NomeAtracao);
              renderizarMapaAtracao(atracao);
          });
   
          function renderizarMapaAtracao(atracao) {
              var canvas = $("#divExibicaoMapa");
   
              var opcoes = {
                  zoom: 16,
                  center: new google.maps.LatLng(
                      atracao.Latitude,
                      atracao.Longitude),
                  mapTypeId: google.maps.MapTypeId.ROADMAP
              };
   
              var mapa = new google.maps.Map(canvas[0], opcoes);
   
              var marcador = new google.maps.Marker({
                  position: new google.maps.LatLng(
                      atracao.Latitude,
                      atracao.Longitude),
                  map: mapa
              });
          }
   
      </script>
   
  }
   
  <div style="padding-top: 15px;">
      <b>Atração:</b>
      <label style="font-weight: normal;" id="lblNomeAtracao"></label>
      <div id="divExibicaoMapa"
           style="width:1100px; height:600px; border-color: black; border-width: 1px; border-style: solid;">
      </div>
      <br />
   
      @Html.ActionLink("Voltar", "Index", "Home")
  </div>

Implementando a View para a exibição das diferentes atrações turísticas

A visualização das diferentes atrações turísticas acontecerá a partir da View Index de HomeController. Essa estrutura corresponde à página inicial da aplicação, sendo que na mesma será incluída uma tabela com diferentes pontos turísticos (bem como links para acesso aos mapas destes últimos).

Em versões anteriores do framework ASP.NET, este trabalho poderia ser feito através do uso de uma Partial View referenciada em Index: o HTML produzido por este recurso seria incluído na página inicial, sem que isto implicasse em um grande esforço de codificação. Um dos grandes benefícios desta abordagem estava no potencial de reuso das Partial Views, com estas últimas podendo ser incorporadas a diferentes Views ao longo de uma aplicação.

Já com o ASP.NET vNext, as Partial Views deixam de estar disponíveis para utilização. Nesta nova versão um novo elemento foi introduzido para suprir este tipo de demanda: trata-se do recurso conhecido como View Component. View Components são também construções reutilizáveis, mas que dispensam a implementação de Actions em Controllers (algo que era obrigatório com as Partial Views), além de viabilizar o processamento assíncrono de conteúdo a ser inserido em Views convencionais.

Para o exemplo aqui proposto serão criados:

  • Um View Component chamado “ListagemAtracoes” (cuja estrutura será definida no arquivo ListagemAtracoesComponent.cs, dentro da pasta Components);
  • A visualização HTML de ListagemAtracoes (o código dessa estrutura - que não deixa de representar uma View - ficará no arquivo Default.cshtml, o qual estará localizado em \Shared\Components\ListagemAtracoes).

Importante ressaltar que a View Index de HomeController precisa ser modificada, de forma a utilizar o View Component detalhado nesta seção.

Na Figura 5 estão os arquivos e diretórios a serem criados para a implementação do View Component ListagemAtracoes.

Estrutura do View
Component ListagemAtracoes
Figura 5. Estrutura do View Component ListagemAtracoes.

Na Listagem 5 está a implementação do View Component ListagemAtracoes (arquivo ListagemAtracoesComponent.cs). Conforme é possível observar:

  • A classe ListagemAtracoesComponent deve herdar do tipo básico ViewComponent (namespace Microsoft.AspNet.Mvc). Essa estrutura também foi marcada com o atributo ViewComponentAttribute (namespace Microsoft.AspNet.Mvc), em cujo construtor é especificado o nome/identificação do View Component que se está criando (no caso, “ListagemAtracoes”);
  • O método InvokeAsync foi marcado com a palavra-chave “async”, devolvendo como resultado uma instância de IViewComponentResult (namespace Microsoft.AspNet.Mvc, gerada através da operação View) associada a uma Task (namespace System.Threading.Tasks). Antes de invocar o método View para retornar o resultado de InvokeAsync, uma coleção de instâncias do tipo Atracao é obtida assincronamente, acionando-se para isto a operação GetAtracoes em conjunto com a palavra-chave “await”;
  • O método GetAtracoes produz como resultado uma coleção de instâncias do tipo Atracao associadas a uma Task. Para isto, tal operação acessa o método ListarAtracoes de AtracaoCollection, utilizando o retorno desta ação como parâmetro ao se invocar o método FromResult da classe Task.
Listagem 5. Classe ListagemAtracoesComponent

  using System;
  using System.Threading.Tasks;
  using System.Collections.Generic;
  using Microsoft.AspNet.Mvc;
  using TesteASPNETvNext.Models;
   
  namespace TesteASPNETvNext.Components
  {
      [ViewComponent(Name = "ListagemAtracoes")]
      public class ListagemAtracoesComponent : ViewComponent
      {
          public async Task<IViewComponentResult> InvokeAsync()
          {
              var atracoes = await GetAtracoes();
              return View(atracoes);
          }
   
          private Task<IEnumerable<Atracao>> GetAtracoes()
          {
              return Task.FromResult(
                  AtracaoCollection.ListarAtracoes());
          }
      }
  }

Já na Listagem 6 está o código correspondente ao arquivo Default.cshtml, o qual representa a visualização em HTML gerada pelo View Component ListagemAtracoes:

  • Analisando este conjunto de instruções, nota-se que a visualização para este tipo de estrutura (View Components) não difere em nada de uma View tradicional;
  • O uso da instrução “@model” no início da Listagem indica o tipo de objeto a ser manipulado por meio da propriedade Model (no caso, uma coleção de instâncias da classe Atracao). Um loop será executado a partir de Model, gerando assim uma tabela com todas as atrações disponíveis. A chamada ao método ActionLink do objeto Html irá produzir como resultado um link, sendo que este último ao ser acionado redirecionará um usuário para o mapa de uma atração (a View ExibirMapa, vinculada a AtracaoController).
Listagem 6. Arquivo Default.cshtml (View Component ListagemAtracoes)

  @model IEnumerable<TesteASPNETvNext.Models.Atracao>
   
  Selecione uma das atrações abaixo para visualizar o mapa correspondente:
  <table class="table">
      <tr>
          <th>
              Atração
          </th>
          <th>
              Ano de Fundação
          </th>
          <th>
              Localidade
          </th>
      </tr>
   
      @foreach (var item in Model)
      {
          <tr>
              <td>
                  @Html.ActionLink(item.NomeAtracao,
                        "ExibirMapa", "Atracao",
                        new { codAtracao = item.CodAtracao })
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.AnoFundacao)
              </td>
              <td>
                  @Html.DisplayFor(modelItem => item.Localidade)
              </td>
          </tr>
      }
   
  </table>

Por fim, um último ajuste será realizado na View Index.cshtml, a qual está relacionada ao Controller HomeController (Listagem 7). O View Component também será acionado assincronamente:


  • A instrução em questão foi marcada com palavra-chave await;
  • O método InvokeAsync do objeto Component recebe como parâmetro o nome do View Component (“ListagemAtracoes”), incorporando o conteúdo produzido por esta ação ao código HTML da View Index.

Listagem 7. View Index.cshtml (Controller HomeController)

  <div class="jumbotron">
      <h1>ASP.NET vNext</h1>
      <p class="lead">Exemplo de aplicação MVC baseada no
                      ASP.NET vNext.</p>
      <p><a href="http://asp.net/vnext"
            class="btn btn-primary btn-lg">Saiba mais »</a></p>
  </div>
   
  @await Component.InvokeAsync("ListagemAtracoes")

OBSERVAÇÃO: O código referente às demais Views desta aplicação de testes foi omitido, já que não constam em tais estruturas instruções complexas que justifiquem uma discussão mais aprofundada. Os arquivos correspondentes a essas Views podem ser obtidos através do download da solução aqui implementada, bastando acessar o link contendo o material deste artigo. Este mesmo procedimento também foi adotado com a classe HomeController.

Teste da aplicação criada

Na Figura 6 é apresentada a tela inicial da aplicação TesteASPNETvNext.

Tela inicial da
aplicação TesteASPNETvNext
Figura 6. Tela inicial da aplicação TesteASPNETvNext.

Ao acionar o link “Museu de Arte de São Paulo (MASP)” será exibido o mapa para este ponto turístico, como indicado na Figura 7.

Visualizando o mapa
de uma atração turística
Figura 7. Visualizando o mapa de uma atração turística.

A intenção com este artigo foi demonstrar a implementação de um projeto simples baseado no ASP.NET vNext, empregando para isto o Visual Studio "14" como IDE de desenvolvimento. Embora mudanças tenham sido introduzidas na forma como uma aplicação Web pode ser construída (como o namespace Microsoft.AspNet.Mvc ao invés das inúmeras referências apontando para System.Web , View Components no lugar de Partial Views, maior simplicidade na implementação de métodos que retornem informações no padrão JSON), o aprendizado de versões anteriores do framework ASP.NET MVC e de Web API certamente será útil neste novo release da tecnologia ASP.NET.

Espero que o conteúdo aqui apresentado possa ser útil.

Até uma próxima oportunidade!

Links

Visão geral do ASP.NET

Asynchronous Programming with Async and Await (C# and Visual Basic)