ASP.NET MVC 6: Implementando uma aplicação básica

Veja neste artigo os novos recursos do framework ASP.NET MVC 6, em um tutorial sobre a implementação de um projeto deste tipo no Visual Studio 2015.

A Microsoft vem trabalhando desde o início de 2014 em atualizações do ASP.NET e do Visual Studio. Em Fevereiro/2015 foi disponibilizado o Visual Studio 2015 CTP 6, nova versão da IDE de desenvolvimento que conta com total suporte para a implementação de aplicações baseadas no ASP.NET 5 (inicialmente chamado de “ASP.NET vNext”).

No que se refere ao ASP.NET 5, a nova versão desta plataforma passou por mudanças bem significativas:

Este artigo tem por meta demonstrar a novas características do MVC 6. Dentre os recursos a serem abordados estão:

Um novo mecanismo nativo para injeção de dependências;

A fim de cumprir tal objetivo será construída uma aplicação Web de exemplo no Visual Studio 2015 CTP 6, com os detalhes de implementação desta última estando descritos nas próximas seções.

h3>Exemplo de implementação de uma aplicação MVC 6

Procurando demonstrar algumas das novidades disponibilizadas com o ASP.NET 5 será criada uma nova solução que faz uso dos seguintes recursos:

O exemplo apresentado a seguir consistirá na construção de um site para consulta à temperatura de algumas cidades num determinado instante. Para isto será implementado uma aplicação MVC chamada “TesteVS2015MVC”, a qual irá se conectar a um serviço de climatologia conhecido como Open Weather. O projeto TesteVS2015MVC será do tipo “ASP.NET Web Application”, sendo gerado a partir da seleção do template “ASP.NET 5 Preview Starter Web”, conforme a Figura 1.

Figura 1. Selecionando o template ASP.NET 5 Preview Starter Web no Visual Studio 2015

Na Figura 2 é possível visualizar a estruturação do projeto TesteVS2015MVC, com os diferentes arquivos gerados logo após a criação do mesmo.

Figura 2. Estrutura inicial do projeto TesteVS2015MVC

As próximas seções descrevem os diferentes ajustes e implementações que serão efetuados, de forma a detalhar as novidades e modificações na maneira como aplicações ASP.NET são concebidas.

Definindo os itens de configuração e o acesso aos mesmos

Uma das mudanças significativas em projetos MVC 6 foi a substituição do Web.config pelo arquivo config.json. Este último documento conta com declarações de itens de configuração no formato JSON, adotando um modelo mais flexível e que facilita a realização de customizações nas definições das quais uma aplicação depende.

Na Listagem 1 está o código esperado para o arquivo config.json. Conforme é possível observar, uma chave chamada “Teste” contém dois subníveis formados pelas propriedades “Cidade1” e “Cidade2”. O conteúdo destes dois últimos elementos servirá de base para as consultas ao serviço de climatologia Open Weather (no caso específico deste exemplo, para as cidades de Seattle e Paris).

Listagem 1. Arquivo config.json
{ "Teste": { "Cidade1": "Seattle, US", "Cidade2": "Paris, FR" } }

O tipo ConfigurationManager deixou de existir, tendo sido substituído por uma implementação derivada da interface IConfiguration (esta última pertencente ao namespace Microsoft.Framework.ConfigurationModel).

Por mais que o arquivo config.json represente o default para projetos ASP.NET 5, as configurações de uma aplicação podem contar com outras origens. A definição de quais arquivos com itens de configuração serão utilizados por uma aplicação acontece na classe Startup (um equivalente ao antigo Global.asax). Na Listagem 2 encontra-se a implementação deste tipo:

É importante destacar ainda que o suporte à injeção de dependências também foi remodelado no ASP.NET 5. Em versões anteriores, a opção por este tipo de prática exigia o uso de um container DI como Unity, NInjectou Spring.NET, dentre outras alternativas possíveis. Embora esta opção ainda esteja disponível, a nova versão da tecnologia ASP.NET também oferece um mecanismo nativo para a injeção de dependências.

Listagem 2. Classe Startup
using System; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Diagnostics; using Microsoft.AspNet.Diagnostics.Entity; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Identity; using Microsoft.Framework.ConfigurationModel; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Logging; using Microsoft.Framework.Logging.Console; using TesteVS2015MVC.Models; namespace TesteVS2015MVC { public class Startup { public Startup(IHostingEnvironment env) { Configuration = new Configuration() .AddJsonFile("config.json") .AddEnvironmentVariables(); } public IConfiguration Configuration { get; set; } public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IConfiguration>(_ => Configuration); ... } ... } }

Configurando o uso da biblioteca Open Weather

Nesta seção será demonstrada a utilização conjunta das ferramentas Bower, Grunt e npm, a fim de incluir os arquivos necessários para uso da biblioteca Open Weather ao projeto de testes. É importante ressaltar que no Visual Studio 2015 a manipulação de pacotes client-side (como bibliotecas de scripts e arquivos CSS) ficou a cargo destas soluções, com a própria IDE dispondo de funcionalidades que suportam a integração com tais gerenciadores.

Um primeiro ajuste deverá ser realizado no arquivo bower.json, o qual contém as dependências de pacotes client-side controladas por meio da ferramenta Bower.

A inclusão de novos packages no arquivo bower.json é facilitada graças ao suporte oferecido pelo IntelliSense. Acessando dados de um repositório que contém os plugins suportados pelo Bower, este recurso irá listar os diversos pacotes disponíveis, assim como as versões mais recentes dos mesmos (Figura 3).

Na seção exportsOverride do arquivo bower.json será necessário especificar ainda quais arquivos do plugin Open Weather serão carregados dentro da pasta wwwroot (além dos scripts, esta biblioteca também disponibiliza folhas de estilo CSS e imagens para a exibição de informações climáticas).

Na Listagem 3 encontram-se todas as mudanças realizadas no arquivo bower.json; outras dependências como o Bootstrap e jQuery já haviam sido incluídas anteriormente, durante a criação do projeto TesteVS2015MVC. O uso do símbolo “~” (til) antecedendo o número de versão do plugin Open Weather (1.2.0) indica a utilização de qualquer patch igual ou superior a 0 (considerando as versões 1.2 desta biblioteca).

Figura 3. O suporte do IntelliSense para a edição do arquivo bower.json
Listagem 3. Arquivo bower.json
{ "name": "WebApplication", "private": true, "dependencies": { "bootstrap": "3.0.0", "jquery": "1.10.2", "jquery-validation": "1.11.1", "jquery-validation-unobtrusive": "3.2.2", "hammer.js": "2.0.4", "bootstrap-touch-carousel": "0.8.0", "open-weather": "~1.2.0" }, "exportsOverride": { "bootstrap": { "js": "dist/js/*.*", "css": "dist/css/*.*", "fonts": "dist/fonts/*.*" }, "bootstrap-touch-carousel": { "js": "dist/js/*.*", "css": "dist/css/*.*" }, "jquery": { "": "jquery.{js,min.js,min.map}" }, "jquery-validation": { "": "jquery.validate.js" }, "jquery-validation-unobtrusive": { "": "jquery.validate.unobtrusive.{js,min.js}" }, "hammer": { "": "hammer.{js,min.js}" }, "open-weather": { "js": "src/openWeather.js", "css": "src/css/*.*", "img": "src/img/" } } }

Verificando a estrutura do projeto TesteVS2015MVC dentro do Solution Explorer, será possível constatar que o plugin Open Weather ainda não foi instalado (Figura 4). A inclusão dos arquivos da biblioteca Open Weather à aplicação de exemplo acontecerá através da funcionalidade Task Runner Explorer, conforme detalhado mais adiante.

Figura 4. Plugin Open Weather ainda não instalado

Para visualizar a janela Task Runner Explorer clicar com o botão direito do mouse sobre o arquivo gruntfile.js, acionando em seguida a opção de mesmo nome (Figura 5).

Figura 5. Acessando o Task Runner Explorer

Com a janela “Task Runner Explorer” ativa, clicar desta vez com o botão direito mouse sobre o item “bower” e selecionar a opção “Run” (Figura 6). As tarefas configuradas para a ferramenta Bower serão executadas (com base nas instruções definidas no arquivo gruntfile.js), com um prompt exibindo o resultado desta ação (Figura 7).

Figura 6. Executando as tarefas para a ferramenta Bower
Figura 7. Resultado da execução das tarefas no Task Runner Explorer

Ao verificar novamente a estrutura do projeto TesteVS2015MVC, será possível constatar que a instalação do plugin Open Weather foi concluída com sucesso (Figura 8).

Figura 8. Plugin Open Weather já instalado

Criando o View Component de informações climáticas

Com o ASP.NET 5 não é mais possível o uso de Partial Views. Um novo tipo de estrutura foi disponibilizado, de forma a substituir estes elementos: trata-se do recurso conhecido como View Component.

Assim como acontecia com as Partial Views em versões anteriores do framework MVC, os Views Components também foram projetados de forma a favorecer o reuso e possibilitar a inserção de conteúdo em pontos específicos das páginas de uma aplicação. A diferença no MVC 6 está na forma como estes componentes são definidos. Um View Component dispensa a codificação de um novo Controller com uma Action associada ao processamento do item ou, mesmo, a alteração de uma construção pré-existente.

A implementação de um novo View Component envolve:

Na Figura 9 está assinalada a organização esperada para a implementação do View Component ClimaCidade. A ideia é que este componente sirva de base para a exibição de informações climáticas de uma cidade específica.

Figura 9. Estrutura do View Component ClimaCidade

Já a Listagem 4 traz a definição do View Component ClimaCidade (arquivo ClimaCidade.cs):

OBSERVAÇÃO: Por convenção, nomes de classes que representam atributos terminam com o sufixo Attribute. A utilização de expressões que envolvam um atributo vinculando o mesmo a uma estrutura de código dispensa o uso de tal sufixo ao final do nome. Logo, ao se empregar o atributo ViewComponentAttribute, a classe marcada com essa construção estará associada apenas a uma instrução com o valor “ViewComponent” (entre colchetes).

Listagem 4. Classe ClimaCidade
using System; using Microsoft.AspNet.Mvc; namespace TesteVS2015MVC.Components { [ViewComponent(Name = "ClimaCidade")] public class ClimaCidadeComponent : ViewComponent { public IViewComponentResult Invoke(string referenciaCidade) { ViewBag.ReferenciaCidade = referenciaCidade; return View(); } } }

Na Listagem 5 encontra-se o conteúdo do arquivo Default.cshtml, o qual representa a visualização em HTML gerada pelo View Component ClimaCidade:

Listagem 5. Arquivo Default.cshtml (View Component ClimaCidade)
<style type="text/css"> .infoTemperatura { background-color: lightblue; padding-top: 30px; padding-bottom: 30px; width: 400px; } .legendaClima { font-size: 26pt; padding-top: 30px; } </style> <br /> <div class="infoTemperatura"> <img src="" class="icone-clima" alt="Weather Icon" /> <p class="legendaClima"> <strong>Localidade</b> <br /><span class="localidade"></span> </p> <p class="legendaClima"> <strong>Temperatura</b> <br /><span class="temperatura"></span> (<span class="temperatura-minima"></span> - <span class="temperatura-maxima"></span>) </p> <p class="legendaClima"> <strong>Umidade</b> <br /><span class="umidade"></span> </p> </div> <script src="~/lib/open-weather/js/openWeather.js"></script> <script> $('.temperatura').openWeather({ city: '@ViewBag.ReferenciaCidade', minTemperatureTarget: '.temperatura-minima', maxTemperatureTarget: '.temperatura-maxima', humidityTarget: '.umidade', placeTarget: '.localidade', iconTarget: '.icone-clima', customIcons: '/lib/open-weather/img/icons/weather/', success: function () { $('.infoTemperatura').show(); } }); </script>

Ajustes na View _Layout.cshtml

A View _Layout.cshtml (localizada em \Views\Shared\) também precisará ser alterada, a fim de que a referência para a biblioteca jQuery seja a primeira declaração de scripts neste arquivo. Na Listagem 6 é possível observar o código esperado para este arquivo.

Listagem 6. View _Layout.cshtml
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Exemplo de aplicação criada no ASP.NET MVC 6</title> <script src="~/lib/jquery/jquery.js"></script> <link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.css" /> <link rel="stylesheet" href="~/css/site.css" /> <link rel="stylesheet" href="~/lib/bootstrap-touch-carousel/css/bootstrap-touch-carousel.css" /> </head> <body> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("TesteVS2015MVC", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("Sobre", "About", "Home")</li> <li>@Html.ActionLink("Contato", "Contact", "Home")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>© 2015 - Renato Groffe</p> </footer> </div> <script src="~/lib/bootstrap/js/bootstrap.js"></script> <script src="~/lib/hammer.js/hammer.js"></script> <script src="~/lib/bootstrap-touch-carousel/js/bootstrap-touch-carousel.js"></script> @RenderSection("scripts", required: false) </body> </html>

Injeção de dependências e estruturas para a visualização do clima em cidades

O acesso às informações climáticas das cidades indicadas no arquivo config.json aconterá através do Controller CidadeController. Essa estrutura pode ser criada por meio da janela Solution Explorer: clicar para isto com o botão direito do mouse sobre a pasta Controllers, selecionando em seguida no menu de atalho a opção “Add” e, finalmente, “New Item...”. Aparecerá então a janela “Add New Item”; marcar o template “MVC Controller Class”, preenchendo o campo “Name” com o valor "CidadeController".

O próximo passo será a realização de ajustes neste novo Controller (Listagem 7):

Listagem 7. Controller CidadeController
using Microsoft.AspNet.Mvc; using Microsoft.Framework.ConfigurationModel; namespace TesteVS2015MVC.Controllers { public class CidadeController : Controller { private IConfiguration _configuration; public CidadeController(IConfiguration config) { this._configuration = config; } public IActionResult Cidade1() { ViewBag.Cidade1 = _configuration.Get("Teste:Cidade1"); return View(); } public IActionResult Cidade2() { return View(); } } }

OBSERVAÇÃO: Mais adiante serão demonstradas as outras possibilidades de uso do mecanismo de injeção de dependências do ASP.NET 5.

Para criar a View associada à Action Cidade1, criar dentro da pasta “Views” uma nova subpasta chamada “Cidade” (como indicado na Figura 10). O arquivo Cidade1.cshtml será gerado neste local, por meio da utilização do template “MVC View Page”, como mostra a Figura 11.

Figura 10. Estruturas para a visualização de informações climáticas
Figura 11. Criando a View Cidade1.cshtml

O código que define a View Cidade1.cshtml está na Listagem 8:

Listagem 8. View Cidade1.cshtml (Controller CidadeController)
<div > <center> @Component.Invoke("ClimaCidade", ViewBag.Cidade1) <br /> @Html.ActionLink("Voltar", "Index", "Home") </center> </div>

Ativando o uso de Tag Helpers e mais injeção de dependências

Outra das novidades do MVC 6 é a possibilidade de uso das Tag Helpers no lugar dos Html Helpers convencionais. Ao invés de exigir uma chamada a um método auxiliar no código de uma View, este recurso permite a obtenção do mesmo resultado a partir da utilização de uma sintaxe baseada em tags (em um modo similar àquele empregado com HTML padrão).

Até o presente momento (início de Março/2015) este novo mecanismo não se encontra ativo por default em projetos MVC 6. Diante disto, faz-se necessária a inclusão de referências ao projeto “Microsoft.AspNet.Mvc.TagHelpers” em soluções que venham a depender deste último. Este procedimento deve ser efetuado através do utilitário NuGet, o qual pode ser acessado com o botão direito do mouse sobre o item References de um projeto (Figura 12).

Figura 12. Gerenciando as dependências do projeto via NuGet

Na interface da ferramenta NuGet pesquisar por “Tag Helpers”. Selecionar o projeto Microsoft.AspNet.Mvc.TagHelpers (Figura 13), prosseguindo com a instalação do mesmo. Ao término destes passos, será possível constatar que a referência foi devidamente incluída na aplicação de testes (Figura 14).

Figura 13. Gerenciando as dependências do projeto via NuGet
Figura 14. Referência para uso de Tag Helpers já incluída na aplicação de testes

O arquivo _ViewStart.cshtml também deverá ser modificado, a fim de tornar possível o uso de Tag Helpers nas Views do projeto TesteVS2015MVC. É o que demonstra a Listagem 9, na qual a diretiva @addtaghelper referencia o namespace Microsoft.AspNet.Mvc.TagHelpers. Tal ajuste fará com que muitas das funcionalidades dos Html Helpers que integram o framework MVC possam ser acionadas por meio de tags nas Views da aplicação aqui apresentada.

Listagem 9. View _ViewStart.cshtml
@using TesteVS2015MVC; @addtaghelper "Microsoft.AspNet.Mvc.TagHelpers" @{ Layout = "/Views/Shared/_Layout.cshtml"; }

Embora possuindo finalidade idêntica à da View implementada na seção anterior, o conteúdo do arquivo Cidade2.cshtml (Listagem 10) apresenta novos detalhes que ainda não foram abordados neste artigo. Tais diferenças têm por objetivo demonstrar o uso do mecanismo de injeção de dependências e de Tag Helpers em Views:

Listagem 10. View Cidade2.cshtml (Controller CidadeController)
@using Microsoft.Framework.ConfigurationModel @inject IConfiguration config <div > <center> @Component.Invoke("ClimaCidade", config.Get("Teste:Cidade2")) <br /> <a asp-controller="Home" asp-action="Index">Voltar</a> </center> </div>

Ajustes finais e últimas considerações sobre injeção de dependências

A classe HomeController também precisará ser ajustada, sendo que na Listagem 11 está o código esperado para essa estrutura:

Listagem 11. Controller HomeController
using Microsoft.AspNet.Mvc; using Microsoft.Framework.ConfigurationModel; namespace TesteVS2015MVC.Controllers { public class HomeController : Controller { [Activate] public IConfiguration Configuration { get; set; } public IActionResult Index() { ViewBag.Cidade1 = Configuration.Get("Teste:Cidade1"); ViewBag.Cidade2 = Configuration.Get("Teste:Cidade2"); return View(); } ... } }

Por fim, na Listagem 12 está a implementação da View Index. Além de consumir os valores atribuídos ao objeto ViewBag em HomeController, este arquivo ainda faz uso de um Html Helper e de uma Tag View para a geração dos links de visualização do clima nas cidades de Seattle e Paris.

Listagem 12. View Index.cshtml (Controller HomeController)
@{ string cidade1 = ViewBag.Cidade1; } <div class="jumbotron"> <h1>ASP.NET 5</h1> <p class="lead"> Exemplo de aplicação construída com o framework ASP.NET MVC 6. </p> </div> <div > Consulta a informações climáticas - selecione uma cidade: <ul> <li> @Html.ActionLink(cidade1, "Cidade1", "Cidade") </li> <li> <a asp-controller="Cidade" asp-action="Cidade2"> @ViewBag.Cidade2 </a> </li> </ul> </div>

Teste da aplicação criada

Na Figura 15 é apresentada a tela inicial da aplicação TesteVS2015MVC.

Figura 15. Tela inicial da aplicação TesteASPNETvNext

Ao acionar o link “Seattle, US” serão exibidas as condições climáticas para esta cidade como indicado na Figura 16. Já a visualização das informações sobre Paris está na Figura 17.

Figura 16. Informações climáticas da cidade de Seattle<
Figura 17. Informações climáticas da cidade de Paris

A intenção deste artigo foi demonstrar os novos recursos para a implementação de aplicações MVC no ASP.NET 5 a partir de um exemplo simples, mas que contemplasse as principais novidades desta plataforma Web.

Embora tenham ocorrido grandes mudanças, é inegável que o conhecimento adquirido em versões anteriores do ASP.NET MVC ainda continuará válido. Há mais de um ano a Microsoft vem trabalhando neste processo de reformulação, sendo possível pressupor que ainda em 2015 acontecerá o lançamento das novas versões já estabilizadas do Visual Studio e da plataforma ASP.NET.

Artigos relacionados