NET-MAGAZINE_115_novidades do visual studio 2013

68 Pages • 36,491 Words • PDF • 12.3 MB
Uploaded at 2021-09-24 07:34

This document was submitted by our user and they confirm that they have the consent to share it. Assuming that you are writer or own the copyright of this document, report to us by using this DMCA report button.


115ª Edição 2014 - ISSN 1980-3931 - Impresso no Brasil

Fale com a Editora!

Corpo Editorial

Atendimento ao Leitor

Edição Geral

A DevMedia conta com um departamento exclusivo para

Daniella Costa ([email protected])

o atendimento ao leitor. Se você tiver algum problema

Revisor Técnico Luís Gabriel N. Simas ([email protected])

no recebimento do seu exemplar ou precisar de algum esclarecimento sobre assinaturas, exemplares anteriores, endereço de bancas de jornal, entre outros, entre em

Jornalista Responsável

contato com:

Kaline Dolabella - JP24185

www.devmedia.com.br/central (21) 3382-5038

É muito importante para a equipe saber o que você está achando da revista: que tipo de artigo você gostaria de ler, que artigo você mais gostou e qual artigo você menos gostou. Fique a vontade para entrar em contato com os editores e dar a sua sugestão! Se você estiver interessado em publicar um artigo na revista ou no site .NET Magazine, entre em contato com os editores, informando o título e mini-resumo do tema que você gostaria de publicar: Daniella Costa - Editora da Revista [email protected]

Capa Romulo Araujo

Diagramação Janete Feitosa

Publicidade revista ou no site e para fechar parcerias ou ações específicas de marketing com a DevMedia, entre em

Na Web ww.devmedia.com.br/dotnet

Distribuição FC Comercial e Distribuidora S.A Rua Teodoro da Silva, 907 | Grajaú - RJ - 206563-900

Daniella Costa

Para informações sobre veiculação de anúncio na

contato com:

Editora da .net Magazine e da easy .net Magazine

Cristiany Queiroz [email protected]

Assine agora e tenha acesso a todo o conteúdo da DevMedia: www.devmedia.com.br/mvp

Sumário Conteúdo sobre Novidades

06 – Novidades do Microsoft Visual Studio 2013 [ Henrique Machado Gasparotto ]

Conteúdo sobre Boas Práticas, Artigo no estilo Curso

18 – ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

Conteúdo sobre Boas Práticas

Feedback eu

[ Renato Groffe ]

edição ta

50 – Google Maps ASP.NET: obtendo chaves de acesso com ASP.NET

sobre e s

32 – Entity Framework Code First

Dê s

[ Luís Gabriel Nascimento Simas ]

Dê seu feedback sobre esta edição!

[ Henrique Machado Gasparotto ] A .NET Magazine tem que ser feita ao seu gosto. Para isso, precisamos saber o que você, leitor, acha da revista! Conteúdo sobre Boas Práticas, Artigo no estilo Curso

60 – Integração Contínua em .NET – Parte 1 [ Luís Gabriel Nascimento Simas ]

Dê seu voto sobre esta edição, artigo por artigo, através do link: www.devmedia.com.br/netmagazine/feedback

Novidades do Microsoft Visual Studio 2013

Novidades do Microsoft Visual Studio 2013 Conheça as principais novidades do Visual Studio 2013, bem como o Visual Studio Online, antigo Team Foundation Service

O

Microsoft Visual Studio pode ser considerado como a melhor IDE de todos os tempos. Desde a sua primeira versão, em 1997, vem trazendo novidades todos os anos, com grandes melhorias para o desenvolvimento de software. Hoje em dia, o Visual Studio é uma suíte de ferramentas de desenvolvimento integradas, capazes de facilitar a vida do desenvolvedor das tecnologias .NET. Com grandes vantagens no desenvolvimento de aplicações para o Windows Phone 8, Windows Store e Web, o Visual Studio é um dos grandes trunfos da Microsoft para atrair ainda mais desenvolvedores e criar o maior número possível de aplicações para popular a Windows Store, que ainda está muito atrás de outras lojas de aplicações, como a App Store, da Apple, e o Google Play, do Google Android.

Microsoft Visual Studio 2013 Visual Studio 2013 teve um aguardado lançamento O no mercado, e está sendo muito elogiado por inúmeras evoluções com relação a seu antecessor. As ferramentas para desenvolvimento em equipes, sempre as mais interessantes para os usuários do Visual Studio, passaram por várias mudanças, que podem trazer uma série de benefícios para as empresas de desenvolvimento. Algumas mudanças importantes no Visual C++ merecem destaque, bem como mudanças na depuração de código, no diagnóstico da aplicação e no gerenciamento de ciclo de vida, que mereceram tópicos a parte. A criação de aplicações para a Windows Store, um dos pilares da Microsoft nos dias atuais, também mereceu uma atenção especial nessa nova versão da ferramenta. A versão 2013 do Visual Studio trouxe algumas mudanças nas ferramentas para algumas linguagens. Enquanto o C# vem crescendo no gosto dos desenvolvedores e está próximo de se tornar a principal linguagem de progra-

6 .net Magazine • Edição 115

Fique por dentro Atualmente, o Microsoft Visual Studio é a principal ferramenta de desenvolvimento integrado disponível no mercado. Além de ser uma ferramenta excelente, ele é a base para uma das principais linguagens de programação do momento, o C#, juntamente com o .NET Framework. Desenvolvedores .NET dificilmente utilizam outra ferramenta, portanto é preciso conhecer as novidades que podem nos auxiliar no desenvolvimento de aplicações melhores. Esse artigo traz detalhes sobre as novidades do Visual Studio 2013, com destaque para as novidades do depurador e no gerenciamento do ciclo de vida da aplicação, além de apresentar o Visual Studio Online, e todas as vantagens e desvantagens que o desenvolvimento de software na nuvem pode oferecer.

mação do mercado, o C++ com certeza não está morto. Pensando nisso, a Microsoft trouxe algumas melhorias, adaptando o Visual C++ aos recursos do ISO C++ 11, a última versão da linguagem. Uma série de alterações foram realizadas, como suporte à bibliotecas C99, bibliotecas padrão de templates (o equivalente em C++ aos Generics do C#), contando ainda com suporte para criação de aplicações Windows Store com C++. Além disso, o Visual C++ traz suporte a aplicações DirectX, podendo ou não utilizar o XAML para criação de aplicações gráficas. Essas aplicações não são suportadas pelo Visual C#, e são uma das grandes vantagens para a utilização do C++ com o Visual Studio. A Figura 1 mostra os principais tipos de projetos do Visual C++ no VS 2013. Em termos de linguagens, o Visual Studio 2013 também traz melhorias nas ferramentas para JavaScript e F#. O principal ponto diz respeito ao JavaScript, que traz notas de deprecação no IntelliSense, que é responsável por completar de maneira inteligente o que o desenvolvedor está digitando. As mudanças basicamente dizem respeito ao editor da ferramenta, e trazem algum auxílio ao desenvolvedor ao escrever código.

O utro ponto que merece destaque no Visual Studio 2013 é a possibilidade da criação dos chamados Hub-style apps. Essas são aplicações Windows Store que permitem ao desenvolvedor a criação de uma experiência com o usuário através dos dados que o estão sendo mostrados na tela. A criação de aplicações desse tipo era possível anteriormente, mas com a adição do template, ficou muito mais fácil. Além disso, é possível também diminuir o espaço que a aplicação irá ocupar em disco, utilizando os chamados bundles. Esses bundles podem ser criados através do menu Project->Store->Create App Packages, e uma janela irá abrir. Esse menu funciona para criação de pacotes para a aplicação poder ser comercializada na Windows Store, e em uma etapa posterior do processo, a criação ou não do App Bundle pode ser realizada. Essa criação é recomendada em aplicações que utilizam muitas imagens ou outros recursos caros graficamente. A tela inicial da IDE também foi modificada, criando uma ligação muito maior com a conta Microsoft, permitindo que o desenvolvedor esteja logado em sua conta durante todo o processo de desenvolvimento. Tal iniciativa foi para facilitar para os desenvolvedores o acesso a áreas sensíveis, como na hora de enviar uma aplicação para a Windows Store. Os editores de código também trazem novos recursos, como o recurso de navegação dentro do código através das teclas CTRL + ,. A partir do login à conta Microsoft, o desenvolvedor também tem acesso aos serviços na nuvem do Windows Azure. Os chamados Windows Azure Mobile Services (BOX 1) foram incorporados à IDE nessa versão, trazendo uma maior facilidade para o desenvolvedor na hora de conectar clientes em aplicações Windows Store. Além disso, é possível trabalhar com esses serviços diretamente da IDE, não havendo necessidade de ir ao browser e navegar pela plataforma do Azure para tanto. A criação de aplicações para o Office e o SharePoint também recebeu alguma atenção por parte da Microsoft. Agora, é possível utilizarmos o padrão MVC para criação de aplicações desse tipo, além de

Figura 1. Projetos Visual C++ no VS 2013 também criar aplicações utilizando a nuvem. Além disso, as aplicações SharePoint também ganharam algumas capacidades de busca. O Visual Studio LightSwitch também sofreu algumas melhorias importantes, principalmente no suporte para desenvolvimento em equipe. Como sabemos, anteriormente o desenvolvimento LightSwitch ficava muito concentrado em apenas uma pessoa, não sendo muito simples dividir tarefas. Agora, com o modelo de projeto em segmentos, a divisão de tarefas ficou muito mais simples, facilitando o desenvolvimento de aplicações LightSwitch em equipe. Como podemos notar, o Visual Studio passou por algumas mudanças da versão 2012 para a 2013. A grande maioria delas diz respeito a serviços da nuvem, e isso tem uma explicação bastante simples: a Microsoft entrou com tudo na nuvem e está trazendo todo tipo de serviço para ser utilizado juntamente com o Azure. Além disso, a empresa entendeu que não adianta criar soluções apenas para o Windows Phone 8, no mundo mobile, enquanto o Android e o iOS possuem uma fatia maior de mercado. O mercado móvel, principalmente com serviços conectados à internet e à nuvem, são um dos principais focos dessa nova versão do Visual Studio.

BOX 1. Windows Azure Mobile Services Os serviços móveis do Windows Azure permitem ao desenvolvedor a utilização de serviços da nuvem em aplicações móveis. Os serviços que o Azure fornece são muitos, e estão disponíveis para as principais plataformas móveis do mercado. Com praticamente todo dispositivo do mundo conectado à internet, a Microsoft enxergou um nicho e utilizou esses serviços do Windows Azure para entrar com tudo no mercado móvel e da nuvem. É possível inclusive a criação de aplicações móveis multiplataforma. Esses serviços do Azure envolvem o armazenamento de dados e autenticação via redes sociais, além de outras possibilidades.

Depuração de Código e Ferramentas de Diagnóstico no VS 2013 No que diz respeito à depuração, não há muitas alterações. Como sabemos, o Visual Studio possui uma ferramenta excelente de depuração de código C# e VB.NET, e no que diz respeito à essas duas linguagens não há qualquer mudança. Porém, como comentado anteriormente, o VS 2013 traz uma evolução bastante grande nos editores de código C++ e JavaScript, e o depurador dessas duas linguagens não ficou para trás no que diz respeito a melhorias. A principal delas foi a adição do conceito conhecido como Just my Code, já presente no C# e no VB.NET. Trata-se de um recurso que permite ao desenvolvedor trabalhar por cima do sistema e do .NET Framework,

Edição 115 .net Magazine

7

Novidades do Microsoft Visual Studio 2013

permitindo que chamadas que não são do usuário atual do computador sejam empilhadas na pilha do Windows, aguardando a sua vez. Isso faz com que a execução do depurador seja, obviamente, muito mais rápida, garantindo máxima produtividade durante a depuração de código. Esse recurso pode ser habilitado ou desabilitado, de acordo com a vontade do desenvolvedor, conforme a Figura 2. Essa figura é referente à opção “Options and Settings”, sob o menu Debug do Visual Studio 2013. Porém, para os desenvolvedores que já tem algum conhecimento sobre esse recurso, é interessante notar que ele é diferente para o C++ e para o JavaScript do que para as

Figura 2. Habilitando a opção Just my Code

linguagens do .NET Framework. No que diz respeito ao C++, os conceitos de Step Into e Step Out (BOX 2) são completamente independentes da pilha de chamadas. Isso faz com que haja uma diferença na relação entre código do usuário e código que não é do usuário (código user e non-user), porque o depurador só irá considerar que o código não é do usuário em algumas questões específicas, como quando não há um arquivo-fonte correspondente à chamada na pilha. Essa distinção entre tipos de códigos é importante para o depurador devido ao comportamento passo a passo, que geralmente não permite que o usuário tenha acesso à códigos que não pertencem a ele.

O JavaScript, por sua vez, realiza uma categorização entre os códigos do usuário e os que não são. O chamado MyCode corresponde ao código que o usuário possui e controla; o LibraryCode corresponde a códigos que não são do usuário, mas a aplicação confia no funcionamento; e o UnrelatedCode, que corresponde ao restante dos códigos. O comportamento do depurador é essencialmente o mesmo, evitando os códigos que não pertencem ao usuário (LibraryCode e UnrelatedCode) e realizando o passo a passo apenas no código do usuário, salvo exceções. Outras adições ao depurador dizem respeito à chamadas assíncronas – agora, é possível ter um controle maior para saber qual o método que realizou a chamada – e valores de retorno de chamadas aninhadas. Além disso, a opção “Edit and Continue” foi estendida para funcionar em 64 bits (apenas para código .NET). As ferramentas de diagnóstico são outra conversa. As mudanças foram muito maiores nesse departamento, permitindo que o desenvolvedor faça uma análise da memória que a aplicação está utilizando. Vale ressaltar que essa opção só está disponível para aplicações que tem como plataforma alvo o .NET Framework 4.5 ou superior. Essa análise é muito importante em aplicações modernas, principalmente em aplicações móveis. Essa necessidade se dá pelo fato de que, embora os dispositivos possuam muito mais memória que antigamente, a maior parte deles hoje em dia funciona com baterias, e a utilização da memória pode drenar essa bateria muito rapidamente. Além disso, o desempenho BOX 2. Step Into e Step Out

Figura 3. Criando Dump Files

8 .net Magazine • Edição 115

Esses dois comportamentos dizem respeito ao depurador de código do Microsoft Visual Studio (e qualquer depurador). Eles permitem que o desenvolvedor tenha controle sobre a execução do código, e possa realiza-la passo a passo. O comportamento do Step Into diz respeito à passar para dentro de uma função ou chamada (o atalho do teclado é F11). O Step Out é o inverso (atalho: Shift + F11). Com o recurso Just My Code ativado, essas duas operações possuem comportamentos distintos para códigos do usuário e códigos que não são do usuário, sempre realizando as operações entre as linhas de código do usuário e ignorando o código que não pertence a ele.

da aplicação irá crescer bastante com o controle dos acessos à memória. Para utilizar essa opção, é preciso entender um pouco melhor como funciona a ferramenta de análise. Essa ferramenta analisa os chamados dump files. Esses arquivos contém informações sobre o heap em um determinado momento dentro da execução da aplicação. Para criar um arquivo desse tipo, durante um breakpoint da aplicação, basta selecionar “Debug->Save Dump As...”, como mostra a Figura 3. Uma vez que o arquivo foi criado, a parte da análise dos dados começa. Para realizar essa análise, o Visual Studio 2013 permite que o arquivo seja aberto. Quando esse arquivo é aberto, temos uma página como a da Figura 4. Como podemos perceber, existem várias opções e informações dentro desse arquivo. Além disso, existem várias opções à direita do arquivo, com várias ações que podem ser tomadas. A opção “Debug Managed Memory” permite que o desenvolvedor trabalhe em cima da memória que foi gerenciada naquele determinado momento na aplicação. Além disso, como podemos observar na Figura 5, essa opção traz diversas informações sobre o estado da memória durante determinado momento dentro da aplicação. Como é possível notarmos, a figura traz informações sobre todos os objetos armazenados em memória naquele momento da execução. A análise, então, pode ser realizada de forma bastante simples, analisando as informações a respeito dos bytes utilizados e do número de objetos, por exemplo. A melhor forma de analisar esses dados, no entanto, é por meio da comparação entre os dados em determinados pontos da execução da aplicação. Isso faz com que o desenvolvedor tenha uma ideia maior do todo, e não apenas do que está acontecendo em um momento da execução, apenas. O diagnóstico em cima dos gráficos de uma aplicação também foram melhorados para essa versão do Visual Studio. A principal adição é a possibilidade de trabalhar com esse tipo de diagnóstico em aplicações Windows Store também no Visual Studio 2013 Express para Windows. Esse diagnóstico permite um auxílio ao desenvolvedor

Figura 4. Arquivo Dump

Figura 5. Analisando o arquivo Dump na hora de depurar aplicações gráficas, como jogos com DirectX e aplicações que utilizem essa tecnologia para alguma renderização complexa. Esse diagnóstico é importante, uma vez que, com o avanço da tecnologia, as aplicações gráficas vem crescendo no gosto, e o desenvolvedor precisa entender como e porque alguns erros de renderização acontecem. As aplicações Windows Store receberam bastante atenção nessa versão do Visual Studio. Isso acontece porque, como se trata de uma nova tecnologia, ainda faltam alguns passos para ela estar totalmente consolidada. Isso faz com que ferramentas

de desenvolvimento tenham que estar em constante evolução para acompanhar essa consolidação. Algumas ferramentas foram adicionadas, como o DOM Explorer, que suporta busca, edição, IntelliSense e trabalhar com as pilhas no editor de CSS do VS 2013. Além disso, o JavaScript também recebeu alguma atenção, com melhorias no console e no Memory Profiler. Essas alterações passam muito pelo fato de que o JavaScript, juntamente com o CSS e o HTML5 são parte essencial em muitas aplicações Windows Store, e têm sido uma das grandes ferramentas dos desenvolvedores da loja nos últimos tempos.

Edição 115 .net Magazine

9

Novidades do Microsoft Visual Studio 2013

Por fim, a Microsoft também realizou a inserção de uma ferramenta para controle de consumo de energia e potência. Essa ferramenta funciona em tablets ARM com Windows RT, e permite que o desenvolvedor analise o consumo de energia e potência da aplicação. Isso acontece porque, como a maioria dos tablets, o controle desse consumo é essencial para garantir uma boa utilização da bateria do dispositivo. Esse recurso captura as atividades do display, da CPU e das conexões de rede do dispositivo durante a execução da aplicação. Então, ele estima a potência utilizada para essas atividades e calcula a energia total. Para a utilização desse recurso, é preciso realizar algumas configurações no Visual Studio 2013, bem como ter uma conta da Windows Store. Para mais informações, cheque a seção Links.

cando a execução da aplicação. O CodeMap é um recurso que é criado automaticamente pelo Visual Studio, como podemos ver na Figura 6. Para isso, basta clicar em algum código dentro do projeto e então em “Show Code Map”, que o mapa de código irá aparecer conforme a figura.

Gerenciamento do Ciclo de Vida da Aplicação O Gerenciamento do Ciclo de Vida da Aplicação é uma responsabilidade importante do desenvolvedor. Principalmente nos dias atuais, a simples criação de uma aplicação não é suficiente: é preciso que haja um controle sobre ela por tempo indeterminado, sempre prevendo falhas. Por isso, é interessante termos uma ferramenta que nos auxilie nesse controle, pois a cada alteração que fazemos na aplicação, a versão da mesma irá ser alterada. Além disso, esse tipo de controle permite que aumentemos a eficiência do processo (e da aplicação), bem como uma redução de riscos. Sem contar o fato de que o trabalho em equipe fica muito mais simples. Como tal, em praticamente todas as versões do Visual Studio, há melhorias nessa parte, e o Visual Studio 2013 não é diferente. O controle de versões, por exemplo, pode ser realizado através do Git ou do TFVC. Essas duas ferramentas são destinadas a trabalhos em equipe, onde o controle sobre as versões e sobre as alterações realizadas precisa ser muito maior. No Visual Studio 2013, é possível criar e desenvolver a aplicação utilizando um projeto em equipe Git. Os dados do projeto podem (e devem) estar hospedados na rede, utilizando um serviço de hospedagem Git, como o GitHub ou o CodePlex, e o projeto pode ser acessado diretamente do Visual Studio 2013. Alguns detalhes de implementação podem ser visualizado no link exposto na seção Links. O desenvolvimento de aplicações utilizando metodologias ágeis tem crescido muito nos últimos tempos. Pensando nisso, o VS 2013 traz algumas alterações para facilitar o desenvolvimento de aplicações com esse paradigma. A presença de salas de bate-papo entre os desenvolvedores da equipe, bem como a utilização de backlogs, são algumas das possibilidades em aplicações desenvolvidas utilizando métodos ágeis. As ferramentas de modelagem nunca foram o forte do Visual Studio, mas a versão 2013 da ferramenta está tentando alterar esse paradigma. Com a criação de mapas de código, é possível para o desenvolvedor ter uma ideia do que está acontecendo dentro da aplicação como um todo, podendo acessar determinados pedaços com alguns cliques, além de ter uma ideia da relação de dependência entre os elementos. Além disso, esses mapas de código podem ser utilizados em modo de depuração, permitindo um controle maior sobre os detalhes que podem estar prejudi-

10 .net Magazine • Edição 115

Figura 6. Code Map As novidades em termos de depuração e diagnóstico já foram apresentadas anteriormente. Entretanto, o Visual Studio 2013 traz alguns recursos interessantes com relação ao teste de aplicações. O Visual Studio Online, que vermos posteriormente, traz a possibilidade de realização de testes na nuvem. Essa utilização permite que o desenvolvedor utilize os recursos conforme sua necessidade, sem precisar instalá-los em sua máquina local. Além disso, o gerenciamento dos testes podem ser realizados diretamente no navegador. Por fim, o Visual Studio 2013 também traz a presença de testes unitários em aplicações Windows Store, permitindo um controle sobre os métodos dessas aplicações como um todo.

Visual Studio Online O Visual Studio Online é uma novidade da Microsoft no que diz respeito ao desenvolvimento de aplicações na nuvem. A infraestrutura para desenvolvimento já está toda pronta, e tudo o que o desenvolvedor precisa é de uma conta para acesso à essa infraestrutura. Existem algumas opções, com diferentes níveis de acesso e ferramentas disponíveis, que se encaixam na maior parte dos projetos de aplicações vistos atualmente no mercado. Trata-se de uma ferramenta que pode ser extremamente útil para empresas e desenvolvedores autônomos, e tende a evoluir muito nos próximos anos com o aumento e a melhoria dos serviços da nuvem. Esse serviço na nuvem, que agora é chamado de Visual Studio Online, nada mais é que o antigo Team Foundation Service. O grande foco do Visual Studio Online é o desenvolvimento em equipe, e existem diversas ferramentas para isso. Ele possui ferramentas de desenvolvimento .NET (C# e VB.NET), C++, HTML, JavaScript; todas as principais tecnologias que a versão desktop do Visual Studio possui. Um dos grandes pontos do Visual Studio Online é o que controle de versões da aplicação, uma questão que

é, muitas vezes, deixada de lado pelos desenvolvedores, principalmente os menos experientes. Outro ponto que foi pensado no desenvolvimento do Visual Studio Online é a disponibilidade do serviço. Antigamente, os desenvolvedores que não trabalhavam com Windows não poderiam instalar a ferramenta em seus computadores e, consequentemente, trabalhar em aplicações .NET. Com o Visual Studio Online, isso não existe mais. O desenvolvedor pode acessar seus projetos de qualquer lugar, a qualquer momento, a partir de qualquer sistema operacional. O Visual Studio Online, como podemos ver na Tabela 1, retirada do site do Visual Studio Online, possui diversas versões, dependendo da necessidade da equipe de desenvolvimento. Um conceito interessante aqui: mesmo que a equipe de desenvolvimento seja composta somente por você, ainda assim é uma equipe de desenvolvimento e pode utilizar as vantagens que o VS Online traz. A primeira, e mais básica, dessas versões é o chamado Visual Studio Online Basic. Basicamente, essa opção fornece uma oportunidade para compartilhamento de código, backlogs e outros dados relevantes do projeto. O desenvolvimento em si é realizado na máquina do desenvolvedor, podendo utilizar as Categories and capabilities Maximum number of users with this plan on an account

ferramentas da série Express do Visual Studio. Já o Visual Studio Online Professional contém todos os benefícios do Basic com o acréscimo da IDE do Visual Studio diretamente da nuvem. Por fim, o Visual Studio Advanced fornece uma maneira de trabalhar em equipes maiores, em projetos multiplataformas. Ele permite a integração com outras IDEs, como Eclipse e XCode, além de fornecer possibilidades de planejamento dos projetos, utilizando as últimas tecnologias ágeis. A criação de uma conta do Visual Studio Online é extremamente simples. A Microsoft permite a realização de trial totalmente de graça, permitindo ao desenvolvedor uma olhada em cima do que a ferramenta fornece, verificando se está adaptada realmente às necessidades do projeto. Como podemos ver na Figura 7, a página inicial do Visual Studio Online traz diversas possibilidades, desde a criação de um novo projeto, utilizando ou não o Git para controle de versão, com um template de processos que pode ser o Scrum, Agile ou CMMI. Uma das ferramentas mais interessantes que o Visual Studio Online proporciona é a presença de salas de bate-papo entre os integrantes do time de desenvolvimento. Isso pode ser muito útil em projetos que envolvam a presença de vários desenvolvedores

Visual Studio Online Advanced Visual Studio Online Professional Unlimited

10 users

Visual Studio Online Basic

Visual Studio Premium with MSDN

Unlimited

Unlimited

Unlimited team projects and private, hosted code repos using TFVC or Git Project planning and bug tracking tools, including Kanban boards and team velocity forecasts Integration with popular development tools, including Visual Studio, Eclipse, and Xcode

 

Work in one IDE to create solutions for the web, desktop, cloud, server, and phone Support for Office 365 business apps Track complex projects with hierarchical portfolio backlogs Visualize project data with work item chart authoring Discuss projects with teammates and monitor project events in Team Rooms Send feedback requests to users and stakeholders Manage and run tests and test plans Host team projects on-premises as well as in the cloud

Tabela 1. Comparação entre as versões do VS Online Edição 115 .net Magazine

11

Novidades do Microsoft Visual Studio 2013

Figura 7. Página inicial do Visual Studio Online

Figura 8. Gerenciamento de usuários no VS Online

Figura 9. Página inicial do projeto

Figura 10. Backlogs no VS Online

12 .net Magazine • Edição 115

em vários lugares, o que tem se tornado muito comum nos últimos anos. Essa presença facilita, e muito, o contato entre os integrantes da equipe, possibilitando que uma dúvida, por exemplo, seja respondida muito rapidamente por algum outro integrante. Além disso, é um excelente meio de fazer com que a equipe interaja e não fique somente focada na sua parte do projeto, entendendo o mesmo com um todo. É importante notar que essa função somente está disponível na versão Advanced do Visual Studio Online. O Visual Studio Online também, normalmente ao líder da equipe de desenvolvimento, a adição e remoção de usuários. Conforme foi conversado, a versão básica do VS Online permite até cinco usuários gratuitamente, e essas licenças podem ser definidas para alguns desenvolvedores, conforme a necessidade e vontade do desenvolvedor chefe. Podemos observar esses detalhes na Figura 8. Por fim, existem outras vantagens que o Visual Studio Online oferece, que pudemos ter uma ideia na Figura 7. Utilização de recursos, otimização de performance da aplicação, entre outras ferramentas interessantes, podem ser utilizados pelo desenvolvedor, sempre buscando criar a melhor experiência possível para o usuário. Um desses recursos é a controle de versão, brevemente citado anteriormente. Para esse exemplo, foi criado um projeto com Team Foundation Version Control, com template de processo Scrum. Repare na Figura 9 que a criação de um projeto abre uma tela totalmente diferente, com vários recursos referentes ao desenvolvimento. Como se trata de uma tecnologia nova, a Microsoft focou bastante nos recursos de aprendizagem, como o How To, ensinando ao desenvolvedor a melhor forma de extrair todos os recursos da plataforma. É interessante observarmos que, no caso da versão Basic, o Visual Studio Online permite uma rápida conexão com o Visual Studio 2013, instalado em sua máquina local, necessária para o desenvolvimento de código. Além disso, vale notar que as ferramentas de código, trabalho, construção e teste estão disponíveis através de um clique. Os Backlogs, por exemplo,

estão disponíveis muito facilmente, como mostra a Figura 10. Como podemos notar, esses elementos são muito importantes no desenvolvimento, informando à equipe o que e como foram realizadas as últimas adições ao projeto. Além do mais, permitem à todos os membros da equipe uma noção melhor do que deve ser feito posteriormente. O utro elemento importante que diz respeito aos Backlogs é a chance de criar gráficos das etapas do projeto, separandoos em etapas concluídas, em desenvolvimento ou novas, por exemplo. Isso fornece uma oportunidade de visualizar aonde a equipe está em termos de desenvolvimento do projeto. Todos esses elementos visuais do projeto podem ser anexados à tela inicial do projeto, na seção Pinned Items, que pode ser customizada de qualquer forma que o desenvolvedor desejar. Essa customização funciona como uma forma de permitir aos componentes do time de desenvolvimento analisar determinados dados rapidamente. Esses recursos estão disponíveis na versão avançada do Visual Studio Online.

Colaboração entre times no Visual Studio Online onforme já foi comentado, o Visual C Studio Online tem como grande foco a noção do trabalho realmente em equipe. As funcionalidades da ferramenta funcionam com muita facilidade, aliando noções de controle de versão da aplicação, bem como definição de escopo e mesmo o planejamento do projeto utilizando as mais recentes tecnologias ágeis do mercado. Além disso, a possibilidade de os membros da equipe interagirem enquanto trabalham é uma das vantagens da plataforma. Muitas pessoas podem rebater que a utilização de um bate-papo não é de todo necessária dentro do Visual Studio Online. Grande parte das empresas possui uma linha de bate-papo interna, dentro da intranet, por exemplo, sem contar as redes sociais e aplicações que são feitas justamente para conversas pela internet. Porém, o Visual Studio Online focou nessa parte justamente para evitar que os desenvolvedores precisem de outras

Figura 11. Comunicação entre os membros da equipe

Figura 12. Criando um backlog ferramentas, ou formas de contato entre os membros da equipe. Tal atitude visa valorizar o tempo dos programadores e analistas, evitando que um tempo que pode ser usado em prol do projeto seja perdido em estabelecer uma comunicação. Pelo VS Online, é possível saber exatamente quais membros da equipe estão presentes e trocar ideias. A utilização das salas de bate-papo do Visual Studio Online é muito simples, como mostra a Figura 11. Como podemos observar, todos os membros da equipe de desenvolvimento tem acesso à sala, e todas as ideias que são trocadas entre os desenvolvedores são compartilhadas entre todos eles. Repare que o sistema é bastante simples, mostrando os desenvolvedores que estão online no momento e os que não estão. Além disso, cada conta do Visual Studio Online possui diversas salas de bate-papo, uma para cada projeto em

andamento. No caso mostrado nessa figura, trata-se de uma equipe de desenvolvimento composta por somente uma pessoa, e uma conta com somente um projeto. As salas de bate-papo também contém informações a respeito de alterações realizadas dentro do projeto. Os demais elementos estão disponíveis internamente dentro do projeto, e podem ser utilizados também como um meio de comunicação entre os membros. A seção Work contém, além dos detalhes das Backlogs, outras informações relevantes do projeto, como queries que contém informações sobre as alterações realizadas no mesmo. Como podemos notar na Figura 12, a criação de Backlogs é bastante simples, e é preciso informações relevantes a respeito de quem irá realizar o trabalho, por exemplo, bem como outras a respeito de horas de trabalho e alguns detalhes descritivos. Esses detalhes auxiliam no controle do

Edição 115 .net Magazine

13

Novidades do Microsoft Visual Studio 2013

projeto, e estão disponíveis para todos os membros da equipe de desenvolvimento. Um detalhe muito interessante a respeito dos backlogs no Visual Studio Online é a presença da chamada Board, ou quadro. Como sabemos, muitas empresas utilizam esses quadros espalhados pelas salas de desenvolvimento, contendo detalhes a respeito dos projetos, para que todos os membros da equipe tenham acesso às informações e estejam atualizados sobre o que os outros estão fazendo. O conceito aqui é o mesmo. As backlogs são mostradas de uma forma diferente, para que todos possam analisar o que está acontecendo da maneira como estão acostumados: com as informações dispostas em um quadro. Como podemos ver na Figura 13, tal exibição é dividida em colunas, e essas colunas podem ser customizadas da forma que a equipe achar melhor. No caso desse exemplo, apenas a backlog que acabamos de criar está presente, marcada como “New”. Esse estado poderia ter

sido alterado na criação da backlog, como vimos na Figura 12, e pode ser alterado a qualquer momento, assim que a tarefa esteja finalizada. O utra forma de mostrar as tarefas a serem desenvolvidas é a utilização de gráficos. Primeiramente, é importante entendermos que os gráficos, no Visual Studio Online, estão diretamente conectados às queries. Isso é fácil de ser assimilado, uma vez que eles precisam de dados para funcionarem corretamente. Como podemos ver na Figura 14, os dados podem ser agrupados de várias formas, assim como o gráfico pode ser de vários tipos. A ordenação é bastante simples, e a ferramenta faz todo o trabalho de mostrar o gráfico da forma como o desenvolvedor o criou. Os gráficos são uma forma simples e fácil de mostrar a todos os membros da equipe aonde eles estão dentro do projeto. Uma boa prática é colocá-los na página inicial, que permite que itens sejam fixados pelos membros do time.

Desenvolvimento e testes no Visual Studio Online Conforme foi comentado, o desenvolvimento da aplicação em si (criação de código) é realizada localmente por cada membro da equipe nas assinaturas mais simples do VS Online. Apenas na versão Advanced que os desenvolvedores possuem todas as ferramentas de desenvolvimento, depuração e testes na plataforma, diretamente pela internet. Portanto, é importante notarmos que o desenvolvimento segue as etapas que normalmente vemos em nossas ferramentas. A grande questão nesse ponto é que o Visual Studio Online é totalmente independente de IDE. Isso permite uma liberdade para o desenvolvedor, que pode desenvolver para iOS utilizando o XCode ou para Android utilizando o Eclipse e utilizar o Visual Studio Online para trabalhar entre equipes. Porém, caso a equipe esteja trabalhando com o Visual Studio, a integração é muito mais simples.

Figura 13. Quadro de backlogs

Figura 14. Criação de gráficos no Visual Studio Online

14 .net Magazine • Edição 115

Figura 15. Acesso ao projeto pelo Team Explorer

É possível trabalhar com o projeto diretamente do Team Explorer dentro do Visual Studio. Isso pode ser visto diretamente na Figura 15. Note a simplicidade da importação do projeto para o Visual Studio. Para isso, basta adicionar o sítio do projeto (nomedaconta.visualstudio.com) ao Team Explorer e o projeto estará disponível para acesso. O Visual Studio Online fornece algumas ferramentas para os desenvolvedores organizarem o código mais corretamente dentro da plataforma. Ainda que normalmente o desenvolvimento não ocorra dentro da plataforma, fica mais fácil trabalharmos quando as coisas estão organizadas corretamente, mesmo em desenvolvimentos solo. Para essa organização, o VS Online fornece as mesmas ferramentas de arquivos que o Visual Studio convencional. Além disso, é possível para os membros da equipe definirem favoritos, o que pode aumentar a produtividade em um projeto com muitos arquivos, permitindo que os membros definam como seu favorito a parte da aplicação em que estão trabalhando, por exemplo. Além disso, como podemos notar na Figura 16, o Visual Studio Online mantém detalhes de cada uma das operações que os desenvolvedores realizaram dentro do projeto. Os chamados Changesets (ou conjuntos de mudanças) são responsáveis por mostrar cada uma das alterações realizadas dentro do projeto de acordo com o tempo.

Figura 17. Definições de Build A criação de uma definição de construção do projeto traz diversas propriedades que podem, e normalmente devem, ser modificadas para cada projeto. Como podemos ver na Figura 18, a construção do projeto é baseada em um controlador hospedado na nuvem, no Visual Studio Online. Além disso, o desenvolvedor pode definir o local que ele deseja para o resultado dessa construção, que será a aplicação em si. Normalmente, esse local será no próprio servidor do VS Online.

Figura 16. Alterações do projeto ao longo do tempo Para a construção do projeto (bem como compilação e depuração), o VS Online traz alguns elementos interessantes. É possível, por exemplo, definir permissões para construção de código para cada um dos integrantes do time. Algumas partes do código, por exemplo, podem ser confidenciais, e apenas alguns membros da equipe podem ter acesso a eles. Com isso, é possível separar as partes do código de acordo com suas permissões. Os Builds do projeto podem ser realizados diretamente pela versão local do Visual Studio 2013, com o auxílio do Team Explorer. Como vimos na Figura 15, há um elemento chamado “Builds”. Quando abrimos essa parte do código, como podemos observar na Figura 17, temos acesso às definições de construção da aplicação, que podem ser modificadas ou criadas naturalmente de acordo com a vontade do desenvolvedor. Como exemplo, vamos criar uma definição de Build para nosso projeto na nuvem.

Edição 115 .net Magazine

15

Novidades do Microsoft Visual Studio 2013

Porém, a aplicação também pode ser hospedada localmente, para alguns detalhes específicos que precisem ser testados. Por fim, mas não menos importante, é preciso definir alguns detalhes dos processos dentro do projeto. Como vemos na Figura 19, esses detalhes contém informações a respeito de testes automatizados, itens para serem construídos a qualquer momento, entre outros. Aqui, também, entram as permissões de construção, onde o chefe da equipe pode definir uma definição de Build para cada um dos membros, de acordo com suas permissões. Além disso, é possível criar alguns elementos que

Figura 18. Criando uma definição de Build

Figura 19. Definições do processo de construção

Figura 20. Adicionando comentários ao código

16 .net Magazine • Edição 115

irão garantir que cada construção será única. Como podemos ver na figura, o Visual Studio já cuida disso para nós, utilizando a data e a hora de cada construção, uma vez que é praticamente impossível que dois builds sejam realizados exatamente ao mesmo tempo por membros diferentes da equipe de desenvolvimento. O Visual Studio Online, conforme mostra a Figura 20, também permite a adição de blocos de comentários ao código, no melhor estilo Microsoft Word. Além disso, também como mostra a figura, é possível separarmos o código antigo do novo, para termos uma noção do que estamos alteran-

do e porquê. Além, é claro, de podermos voltar a utilizar o código antigo caso seja necessário. A adição de comentários é bastante simples, e o desenvolvedor pode adicionar o que quiser ao código. Todos os comentários estão disponíveis para os membros da equipe de desenvolvimento. Isso significa que a comunicação entre os membros pode ser realizada através desses comentários, com os membros informando uns aos outros de problemas ou soluções encontrados durante o trabalho naquele determinado código. Repare que o comentário está vinculado à linha de código. O Visual Studio Online, em sua versão Advanced, também permite a realização de testes no código diretamente na nuvem. Porém, para a criação de testes, é necessário algum planejamento, como sabemos, e o VS Online não permite que você crie um teste sem um plano de testes. A ferramenta permite vários test cases, que podem ser utilizados para entender o que está acontecendo dentro do código. Além disso, é possível utilizar testes já criados em outras ferramentas, adicionando-os ao projeto em questão. Como podemos ver na Figura 21, o Test Case é bastante complexo, e contém todas as informações que são necessárias para a criação de um bom teste. O Visual Studio Online também algumas ferramentas de depuração de código. Como sabemos, a depuração de código é uma parte essencial em qualquer projeto de software, e o VS Online não poderia deixar por menos. O Visual Studio Online fornece uma ligação bastante simples com o Windows Azure e o serviço que o mesmo possui para depuração de aplicações. Com a utilização do VS Online, não há necessidade de uma conta do Windows Azure para a depuração de aplicações, uma vez que o VS Online já possui o acesso ao Azure juntamente com a sua conta. Como podemos notar, o Visual Studio trouxe diversas melhorias com relação à sua última versão. Na versão desktop da IDE, podemos notar algumas alterações muito relevantes, principalmente no que diz respeito a aplicações para Windows Store. Essas alterações eram esperadas, uma vez que a plataforma está se desenvolvendo, ainda não tendo atingido a

Figura 21. Criação de test cases no VS Online maturidade necessária. Isso faz com que ainda sejam esperados algumas outras melhorias no Visual Studio no que diz respeito ao desenvolvimento de aplicações para a Windows Store para as próximas versões da IDE. Um dos pontos que a Microsoft resolveu focar nessa última versão do Visual Studio foi a conexão com projetos remotos. Como pudemos ver ao longo do artigo, o Visual Studio Online foi criado como a solução para projetos em equipes, com uma rápida e fácil conexão com a versão local da IDE através do Team Explorer. Outras IDEs também podem ser utilizadas, uma vez que o Visual Studio Online não é uma ferramenta totalmente voltada para as tecnologias Microsoft, fazendo com que seja possível utilizar a plataforma para a criação de aplicações para iOS, Android, Blackberry ou qualquer outro sistema operacional que se desejar. Além disso, o Visual Studio Online contém ferramentas que tornam possível todas as etapas de desenvolvimento, e, com isso, se torna diferente de outras plataformas similares. É possível criar software utilizando as principais tecnologias de planejamento, construção, depuração e testes, aumentando a produtividade sem a necessidade da compra de softwares caros. A grande sacada da Microsoft no que diz respeito ao Visual Studio Online é a capacidade de trabalhar em equipes utilizando a ferramenta. Várias funcionalidades foram adicionadas pensando exclusivamente em projetos globais, em que os membros do time não estão em contato no dia a dia. Uma delas é a sala de bate-papo interna, porém não é a única. O mais interessante nessa ferramenta é a capacidade de planejar a aplicação, e não apenas desenvolvê-la como um time. Cada membro pode colaborar como puder e desejar no intuito de criar um produto final muito mais satisfatório.

Autor Henrique Machado Gasparotto [email protected] Estudante de Engenharia de Computação na Universidade Federal de Santa Maria – UFSM e Técnico em Informática pelo SENAC Santa Maria. Experiência em programação C# .NET e Java, além de aplicações mobile e computação de alto desempenho. Atualmente, é bolsista do Programa Ciência sem Fronteiras, sendo aluno de Engenharia de Computação na Concordia University, em Montreal, Canadá.

Links: Novidades do VS 2013 http://msdn.microsoft.com/en-us/library/bb386063.aspx Consumo de energia em aplicações Windows Store http://msdn.microsoft.com/en-us/library/windows/apps/dn263062(v=vs.120).aspx Visual Studio com Git http://msdn.microsoft.com/en-us/library/hh850437.aspx Visual Studio Online http://www.visualstudio.com/en-us/products/visual-studio-online-overview-vs.aspx

Você gostou deste artigo? Dê seu voto em www.devmedia.com.br/netmagazine/feedback Ajude-nos a manter a qualidade da revista!

Edição 115 .net Magazine

17

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1 Este artigo faz parte de um curso

Fique por dentro Neste artigo vamos criar um sistema de exemplo totalmente ade-

N

ão podemos imaginar um site hoje em dia sem segurança e podemos começar diminuindo os riscos de invasão em um site criptografando todos os seus dados sensíveis já desde a interação dos usuários, para isso, utilizamos os certificados SSL. Qualquer site sério de compras ou que se preocupe com a garantia dos dados de seus usuários necessita utilizar ao menos um certificado, posto que nem todo o site tem a necessidade de ter seus dados criptografados. Por exemplo, podemos apenas colocar o site seguro no momento do login do usuário e o acompanhar em toda a sua navegação pelo site saindo da parte segura após o seu logoff da aplicação. Normalmente, pode-se adquirir um certificado de autoridades certificadoras conhecidas mundialmente e o valor não é muito alto, porém, ao longo do tempo e da complexidade do projeto, este valor pode aumentar e mesmo assim, é um valor irrisório em comparação ao prejuízo que a sua falta acarreta nas partes mais sensíveis de seu Sistema. Vamos criar uma Autoridade Certificadora, gerar um Certificado Mestre, assinar este certificado, registrar o certificado no Windows e configurar o IIS para tal. Para tal, vamos precisar do Visual Studio 2010 ou superior, do IIS 7.0 ou superior. Vamos também utilizar o OpenSSL e outras ferramentas que demonstraremos a seguir existentes no próprio .NET Framework.

Criando um domínio fake para simular um site do mundo real O nosso site se responderá no endereço fictício http:// www.projetoowasp01.com.br. Para que este domínio possa responder, vamos atrelá-lo ao IP de nossa estação de trabalho e para isto, devemos editar o arquivo Hosts.

18 .net Magazine • Edição 115

rente às melhores práticas de projeto, implementação e testes de sistemas web também pela ótica da segurança recomendados por dois órgãos muito influentes no que tange à segurança de aplicações Web: OWASP e NIST. Vamos também criar um site fictício para testes utilizando certificados gerados pelo OpenSSL e como mesmo criar certificados para assinar nossos assemblies e com isso poder registrar as versões estáveis na GAC. Com relação aos Testes Unitários, vamos gerar testes de todos os módulos e frameworks pertencentes ao Projeto. Vamos utilizar o TDD como principal forma de trabalho, assim como controlaremos nossa tarefa via Kanban mostrando ao nosso leitor como controlar o cronograma do artigo através das metodologias ágeis.

O arquivo Hosts é como, à grosso modo, um arquivo de resolução de nomes – DNS - embarcado no próprio Windows - c:\windows\ system32\etc\drivers\Hosts. Dentro deste arquivo replique o que está na Listagem 1. Caso o arquivo Hosts não exista, este deve ser criado. Uma dica muito importante é que este arquivo, assim como foi editado facilmente pelo leitor, também pode ser acessado por aplicações espiãs ou vírus. Diante disto, devemos mantê-lo como Somente Leitura após as alterações. Listagem 1. Configuração de Host Fake no IIS 192.168.0.3 www.projetoowasp01.com.br #Servidor IIS Fake

No caso de nossa máquina de testes, que é uma máquina virtual, colocamos o IP da máquina servidora, que é a máquina hospedeira desta máquina virtual, porém, no caso do leitor não ter a mesma estrutura, pode-se substituir o IP 192.168.0.3 para 127.0.0.1 ou o IP de sua estação de trabalho sem quaisquer ônus. Após isso, salve e feche o arquivo. Vamos testar se nosso domínio fake responde, para isso vamos abrir o prompt do DOS e digitar o mesmo descrito na Listagem 2.

Se tudo der certo com o que foi digitado na listagem anterior, então teremos a saída mostrada na Listagem 3.

Listagem 2. Testando o domínio Fake cd \ ping www.projetoowasp01.com.br

Instalando o OpenSSL Baixe o OpenSSL do site do fabricante (vide seção Links). A versão estável existente durante a escrita deste artigo é a versão 1.0.1f. Descompacte o OpenSSL na raiz de seu Sistema Operacional e crie alguns diretórios dentro do diretório do OpenSSL: chaves, CSRs e certificados.

Listagem 3. Resposta do ping para o domínio fake

Criando uma Autoridade Certificadora (CA)

Disparando contra www.projetoowasp01.com.br [192.168.0.3] com 32 bytes de dados:

Vamos criar inicialmente uma chave privada de 2048 bits, mas normalmente são criadas chaves de 1024. Podemos criar de vários tamanhos como múltiplos de 64 bits para que possamos usar em nosso CA. Vamos adicionar o caminho dos executáveis do OpenSSL ao Path do Windows com o comando da Listagem 4. O intuito deste comando é poder executar o arquivo openssl .exe de qualquer lugar dentro do console, sem a necessidade de navegarmos até o diretório onde está o openssl.exe. Vamos navegar até o diretório do openSSL e executar o comando mostrado na Listagem 5. Na linha 03 é executamos o comando para a nossa chave privada de onde se origina a Autoridade Certificadora. Demos o nome a ela de CA_IIS.key. Note que os diretórios que criamos facilitam e muito a organização de nosso CA. Este comando terá uma saída muito parecida com a Listagem 6.

Resposta de 192.168.0.3: bytes=32 tempo=2ms TTL=128 Resposta de 192.168.0.3: bytes=32 tempo=1ms TTL=128 Resposta de 192.168.0.3: bytes=32 tempo=2ms TTL=128 Resposta de 192.168.0.3: bytes=32 tempo=1ms TTL=128 Estatísticas do Ping para 192.168.0.3: Pacotes: Enviados = 4, Recebidos = 4, Perdidos = 0 (0% de perda), Aproximar um número redondo de vezes em milissegundos: Mínimo = 1ms, Máximo = 2ms, Média = 1ms

O tempo em milissegundos (ms) pode variar dependendo do processamento da máquina, mas o mais importante a ser destacado é justamente que o IP e o nome do domínio respondem à contento do que colocamos no arquivo Hosts e também que as estatísticas, temos 0% de perda, ou seja,100% de resposta para o nosso domínio fake. De posse de nosso domínio já funcional, vamos gerar o certificado.

Recomendações importantes sobre Certificados válidos De acordo com a OWASP (Open Web Application Security Project), para que tal site seja reconhecido como “Seguro”, faz-se necessária a compra de um certificado reconhecido internacionalmente. De posse de tal certificado, irá aparecerá o ícone de um cadeado próximo a barra de endereços do navegador, o que faz com que este cadeado apareça é justamente o certificado ser gerado com o padrão SSL v2 e seu reconhecimento quanto a qualidade deste certificado. Criar e registrar uma Autoridade Certificadora para ser reconhecida nacional ou internacionalmente não é uma tarefa fácil e as taxas são tão altas e o esforço administrativo é tão grande que sai muito mais barato se comprar um. Recomendamos fortemente que o leitor compre um certificado de uma Autoridade Certificadora Oficial. Na seção Links, no final deste artigo, temos algumas sugestões. Deixamos bem claro que o que faremos nesta primeira seção é apenas para questões de testes, posto que não é necessária a compra de um certificado para que se use em nosso teste. Um outro lembrete é que, para que funcione corretamente o certificado, faz-se muito importante colocar o FQDN (Full Qualified Domain Name) do servidor onde o IIS está hospedado, dentro do campo FQDN “common Name” que o programa gerador certificado solicita.

Listagem 4. Registrando o caminho do OpenSSL no path do Sistema Operacional Windows SET PATH=%PATH%;C:\OpenSSL-Win32\bin Listagem 5. Navegando via console e criando o Certificado 01 cd \ 02 cd OpenSSL ou cd OpenSSL-Win32 ou outro diretório escolhido 03 openssl genrsa -des3 -out chaves/CA_IIS.key 2048 Listagem 6. Geração do CA com saída do Sistema 01 Loading ‘screen’ into random state - done 02 Generating RSA private key, 2048 bit long modulus 03 .....+++ 04 ..............+++ 05 e is 65537 (0x10001) 06 Enter pass phrase for chaves/CA_IIS.key: openssl req -new -x509 -days 365 -key chaves\CA_IIS.key -out certificados\certMasterCA_IIS.cer Listagem 9. Informações para a geração do certificado 01 Enter pass phrase for chaves\CA_IIS.key: 02 Loading ‘screen’ into random state - done 03 You are about to be asked to enter information that will be incorporated 04 into your certificate request. 05 What you are about to enter is what is called a Distinguished Name or a DN. 06 There are quite a few fields but you can leave some blank 07 For some fields there will be a default value, 08 If you enter ‘.’, the field will be left blank. 09 ----10 Country Name (2 letter code) [AU]:BR 11 State or Province Name (full name) [Some-State]:Rio de Janeiro 12 Locality Name (eg, city) []:Rio de Janeiro 13 Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevMedia 14 Organizational Unit Name (eg, section) []:Revista .NET Magazine 15 Common Name (e.g. server FQDN or YOUR name) []:www.projetoowasp01.com.br 16 Email Address []:[email protected]

A primeira pergunta que foi feita ao executar este comando foi justamente a inserção da senha do CA. Já na linha 08 o OpenSSL informa ao leitor que basta colocar o “.”, sem as aspas, para que a resposta seja a padrão, porém, é obrigatória a inserção do FQDN, senão receberemos erros tais como: “A Autoridade certificadora não é reconhecida”, dentre outros durante o uso dos certificados. Na Listagem 10 temos o conteúdo gerado deste nosso certificado Mestre. Agora, faremos um passo opcional, pois caso queira exportar seus certificados para que o Windows reconheça como válido, precisamos gerar nossos certificados no formato PKCS12. Este formato permite aos usuários do Windows tornarem seus Certificados Confiáveis, sem a necessidade de receber um erro de certificado inseguro a cada vez que o site, para o qual o certificado foi gerado, for acessado. Este arquivo contém apenas a chave pública e não está atrelada a chave privada. Diante disso, ela pode ser compartilhada e não precisa ser protegida por senha. Criamos um CSR – Certificate Sign Request ou Solicitação de Certificado Assinado - que emula como um pedido do usuário. Em seguida, geramos um outro certificado só que assinado corretamente e ai sim convertemos este certificado, que é em formato pkcs12, para um de formato DER. Na Listagem 11 criaremos um CSR para o Windows. Nessa listagem vemos que o processo é idêntico ao processo da Listagem 9, porém, precisamos informar que este certificado é

para um “usuário”, posto que um CSR é um pedido de certificado ou seja, deve ser gerado e depois assinado e entregue ao usuário. Diante disto, precisamos passar os dados corretamente. Na linha 16, por exemplo, devemos passar o nome da máquina onde o certificado será instalado. Na linha 17 devemos passar o e-mail do usuário no qual o certificado está sendo gerado. Após gerado o CSR, o caminho natural é enviar o CSR para a autoridade certificadora, que tem a posse do arquivo .key e sua senha, assinar o certificado e devolvê-lo corretamente validado. Listagem 10. Conteúdo do arquivo C:\OpenSSL-in32\certificados\certMasterCA_IIS.cer -----BEGIN CERTIFICATE----MIIEWTCCA0GgAwIBAgIJAKOk0J7vLeXjMA0GCSqGSIb3DQEBBQUAMIHCMQswCQYD VQQGEwJCUjEXMBUGA1UECAwOUmlvIGRlIEphbmVpcm8xFzAVBgNVBAcMDlJpbyBk ZSBKYW5laXJvMREwDwYDVQQKDAhEZXZNZWRpYTEeMBwGA1UECwwVUmV2aXN0YSAu TkVUIE1hZ2F6aW5lMSIwIAYDVQQDDBl3d3cucHJvamV0b293YXNwMDEuY29tLmJy MSowKAYJKoZIhvcNAQkBFhthdXRvcmdhYnJpZWxzaW1hc0BnbWFpbC5jb20wHhcN MTQwMzIyMDIzMDI0WhcNMTUwMzIyMDIzMDI0WjCBwjELMAkGA1UEBhMCQlIxFzAV BgNVBAgMDlJpbyBkZSBKYW5laXJvMRcwFQYDVQQHDA5SaW8gZGUgSmFuZWlybzER MA8GA1UECgwIRGV2TWVkaWExHjAcBgNVBAsMFVJldmlzdGEgLk5FVCBNYWdhemlu ZTEiMCAGA1UEAwwZd3d3LnByb2pldG9vd2FzcDAxLmNvbS5icjEqMCgGCSqGSIb3 DQEJARYbYXV0b3JnYWJyaWVsc2ltYXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAtvs1SsSKjcNv+t89nKe/qcETYsVisWLnpPLTfnZn DodIffysXV4RfdFkyvYQXgdkULYFz8gsXpD4YpyLU3hLTDVrW+LLvqwrS/8FhbGB vPUJ9FQpTdJwz3jV/TxY5r/j7rcKKmH2f14cka+IqEFC2K1PMmSIipPiKQ7DBsnR NUZ8ZF98+7PKo/lPu9eMhjooemICUVZVHFW4CtsmbmXxWutCmoMnj7JDLuVJdx3T 7MWYePcSYCAvNI3ylSwzFD3M/L87XbhzXTH/iyXHKZ5nlzlY3gzhrId6mM0++twK ftSKtcMqsCa1i+B79ReO7IfflIgrLSvRUaz5/Go+ytY37wIDAQABo1AwTjAdBgNV HQ4EFgQULxe5pTPBCjTH74qoR9gTj4dKrOowHwYDVR0jBBgwFoAULxe5pTPBCjTH 74qoR9gTj4dKrOowDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAXD57 hJNB+vtwGNsE2Eyrhuvl1YcmoqRMi5Q3M7NjTtXOTaq45r2OIH74aL8YX/qRZj+Z WeQCAa52B1WDiO8BA1dZkM4alllr9YoCjPW7D9H1p+qAZGEzcrFR96vm8PkAxcad 5ZpFXkx3PF1O+PFUkDhzr31FOSsaZEGYuMpg93Bf4Bi39IZkA9u5FfR/tTgo9LoY D+6+voE+2yzfnLqMy22CG/PedYuL6J4RoGZah5LIRlKzq4o2FaIWxz7SgFeaIWI+ +gvtwUtJx6bEPAIvFkBG9Y4jr2GNnh5jlmVB2MmtuljcdsRW9SLTr3RpWNVRIeQj +s1JGIIPGIJ3wUKwTA== -----END CERTIFICATE----Listagem 11. Criando um CSR 01 C:\OpenSSL-Win32>openssl req -new -key chaves\CA_IIS.key -out CSRs\WindowsCert.csr 02 Enter pass phrase for chaves\CA_IIS.key: 03 Loading ‘screen’ into random state - done 04 You are about to be asked to enter information that will be incorporated into your certificate request. 06 What you are about to enter is what is called a Distinguished Name or a DN. 07 There are quite a few fields but you can leave some blank 08 For some fields there will be a default value, 09 If you enter ‘.’, the field will be left blank. 10 ----11 Country Name (2 letter code) [AU]:BR 12 State or Province Name (full name) [Some-State]:Rio de Janeiro 13 Locality Name (eg, city) []:Rio de Janeiro 14 Organization Name (eg, company) [Internet Widgits Pty Ltd]:DevMedia 15 Organizational Unit Name (eg, section) []:Revista .NET Magazine 16 Common Name (e.g. server FQDN or YOUR name) []:www.projetoowasp01.com.br 17 Email Address []:[email protected] 18 19 Please enter the following ‘extra’ attributes 20 to be sent with your certificate request 21 A challenge password []: 22 An optional company name []:

Para verificar a veracidade do certificado devolvido pelo CA, vamos validar o mesmo. A Listagem 12 mostra qual comando deve ser executado para verificar sua autenticidade, lembrando que o comando executado só terá efeito caso um certificado seja do tipo CSR, ou seja, x.509 que é o padrão, caso nenhum tipo de algoritmo seja selecionado no OpenSSL, como no caso da Listagem 11. Listagem 12. Validação do CSR gerado C:\OpenSSL-Win32>openssl req -noout -text -in CSRs\WindowsCert.csr Certificate Request: Data: Version: 0 (0x0) Subject: C=BR, ST=Rio de Janeiro, L=Rio de Janeiro, O=DevMedia, OU=Revista .NET Magazine, CN=www.projetoowasp01.com.br/ [email protected] Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:b6:fb:35:4a:c4:8a:8d:c3:6f:fa:df:3d:9c:a7: bf:a9:c1:13:62:c5:62:b1:62:e7:a4:f2:d3:7e:76: 67:0e:87:48:7d:fc:ac:5d:5e:11:7d:d1:64:ca:f6: 10:5e:07:64:50:b6:05:cf:c8:2c:5e:90:f8:62:9c: 8b:53:78:4b:4c:35:6b:5b:e2:cb:be:ac:2b:4b:ff: 05:85:b1:81:bc:f5:09:f4:54:29:4d:d2:70:cf:78: d5:fd:3c:58:e6:bf:e3:ee:b7:0a:2a:61:f6:7f:5e: 1c:91:af:88:a8:41:42:d8:ad:4f:32:64:88:8a:93: e2:29:0e:c3:06:c9:d1:35:46:7c:64:5f:7c:fb:b3: ca:a3:f9:4f:bb:d7:8c:86:3a:28:7a:62:02:51:56: 55:1c:55:b8:0a:db:26:6e:65:f1:5a:eb:42:9a:83: 27:8f:b2:43:2e:e5:49:77:1d:d3:ec:c5:98:78:f7: 12:60:20:2f:34:8d:f2:95:2c:33:14:3d:cc:fc:bf: 3b:5d:b8:73:5d:31:ff:8b:25:c7:29:9e:67:97:39: 58:de:0c:e1:ac:87:7a:98:cd:3e:fa:dc:0a:7e:d4: 8a:b5:c3:2a:b0:26:b5:8b:e0:7b:f5:17:8e:ec:87: df:94:88:2b:2d:2b:d1:51:ac:f9:fc:6a:3e:ca:d6: 37:ef Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha1WithRSAEncryption a6:1f:af:9c:c1:cd:d4:68:7d:7c:af:94:b5:cf:7a:ab:4c:8a: 76:36:2b:e3:6d:97:e8:e1:a4:17:8c:ca:c1:b7:17:7f:a6:c7: 96:cf:0b:9c:3d:09:9f:64:30:35:8a:87:90:1f:5d:73:60:60: 8c:95:d3:b9:a5:0e:56:07:73:fd:d8:cc:5b:13:91:af:ba:47: b8:58:5a:3c:59:b8:e7:98:bf:3c:4b:c7:94:b2:0b:02:c4:fd: cb:48:36:60:19:6c:c7:ed:1f:32:10:89:6d:b6:28:78:d4:5e: 69:69:55:6d:db:8f:1f:17:b3:19:8c:aa:8b:51:58:29:f5:9e: e3:28:17:16:04:ad:47:f4:84:d5:25:02:c2:fc:56:69:48:9f: 79:c0:51:2f:3a:be:dd:5d:41:e1:68:c3:e2:23:9c:8d:4e:43: 07:b0:5a:14:02:18:bd:97:f6:44:ba:d3:a9:7c:c2:e8:24:59: 81:4a:ef:a0:d6:75:9b:d6:37:29:b9:03:ff:64:44:8e:ae:c8: d2:9e:6b:63:f1:a8:fc:a4:7b:95:1b:b2:c4:45:34:de:c3:7b: b4:7a:08:77:55:85:02:3d:4a:6c:94:fe:8e:89:17:3a:b9:d4: e2:c1:30:bf:d5:7a:c0:1e:1c:9e:61:87:62:2a:fd:5e:b2:ad: 32:25:c8:a3

Pela listagem podemos ver que nosso certificado é válido. Vamos assinar o certificado gerado para o Servidor e em seguida, vamos criar o DER para distribuição. Na Listagem 13 temos a linha de comandos para tal execução. A operação de “commit” significa que um arquivo que controla as gerações será atualizado com mais um certificado gerado.

Edição 115 .net Magazine

21

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

Vamos gerar o certificado DER para instalar no Windows e distribuir caso precise. Veja a Listagem 14. Podemos validá-lo, se quisermos, como mostrado na Listagem 12. Agora, copie os dois certificados gerados para o servidor e os instale por lá. Ainda não é o certificado para o IIS, é apenas para o Windows. Após a instalação ser bem sucedida, vamos gerar através do IIS o nosso CSR para que possamos efetuar todo o processo que foi feito anteriormente. Listagem 13. Geração de certificado assinado via CSR C:\OpenSSL-Win32\certificados>openssl ca -policy policy_anything -cert certificados\ certMasterCA_IIS.cer -in CSRs\WindowsCert.csr -keyfile chaves\CA_IIS.key -days 365 -out certificados\windowsCert.cer -verbose Listagem 14. Geração de certificado DER

Figura 1. Certificados do Servidor

C:\OpenSSL-Win32>openssl x509 -in certificados\windowsCert.cer -outform DER -out certificados\windowsDER.der

Nota Antes de prosseguirmos, faz-se necessária uma explicação sobre uma atitude muito difundida, e não recomendável, na internet com relação a geração de certificados com a CA sem senha, como mostrado na Listagem 15. Pedimos que o leitor não faça isso, pois este comando irá destruir toda a teoria das chaves privadas e isso reduzirá a sua segurança para zero, pois permitirá a qualquer um gerar certificados à vontade. Listagem 15. Gerando certificados mestres de certificados sem senhas openssl pkcs12 -export -out cacert.p12 -in cacert.pem -inkey cakey.pem

Figura 2. Solicitação de Certificado

Gerando um pedido de Certificado via IIS 7.0 ou superior. Nós também podemos gerar um CSR diretamente do ISS. E como fazer isso é muito simples e será mostrado logo adiante. Primeiramente, vamos abrir o IIS através do Console do Gerenciador de Serviços de Informações da Internet. Dentro dele abra o item Certificados do Servidor, como mostra a Figura 1. Na tela que se abre, selecione Criar Solicitação de Certificado, como nos mostra a Figura 2. Aqui, os dados já são conhecidos, porém, para evitar qualquer tipo de imbróglio, na Figura 3 temos o formulário preenchido. Note que os campos a serem preenchidos são os mesmos preenchidos outrora via Console para o OpenSSL. Tal padronização facilita muito a compreensão. Salve o certificado em algum local onde seja fácil copiar e colar no diretório de CSRs que criamos anteriormente no OpenSSL. Salve-o com um nome fácil de identificar, em nosso caso salvamos com o nome de IIScsr.txt. Agora, vamos assinar nosso CSR para gerar um certificado real via CA para o ISS. Na Listagem 16 temos o comando completo que gera o certificado. Geramos um certificado válido por um ano, onde a política de validação dos dados é verificar se todos os dados digitados na criação do mesmo são os mesmos digitados na criação de outros

22 .net Magazine • Edição 115

Figura 3. Formulário de geração de Solicitação de Certificado Listagem 16. Assinatura do Certificado via CA C:\OpenSSL-Win32>openssl ca -policy policy_match -cert certificados\certMasterCA_IIS.cer -in CSRs\IIScsr.txt -keyfile chaves\CA_IIS.key -days 365 -out certificados\ iishttps.cer

certificados “filhos”. Novamente, respondemos sempre com “y”. Pronto, nosso certificado para o servidor já está criado com sucesso. Vamos finalizar importando o certificado público que faz com que o ícone do cadeado apareça no navegador quando a negociação com o protocolo HTTPS faz-se visível, posto que é o nosso objetivo inicial.

Criando o certificado para negociação SSL para o ISS Vamos criar um arquivo de exportação de chaves (arquivo .pfx) para que possamos registrar o SSL para uso do HTTPs pelo IIS. Mas antes,vamos instalar o certificado gerado para o servidor e logo após gerar o arquivo .pfx com senha. Figura 4. Importando certificados para o Windows Não devemos fazer confusão, pois este certificado é o que será inserido em nossa configuração de hosNa lista, selecione a opção Certificados e clique na tela de forma pedagem do website do IIS,ou seja, a configuração do site http:// que adicione o mesmo e clique em OK ao finalizar a operação. www.projetoowasp01.com.br. Temos agora acesso ao Gerenciador de Certificados do Windows. Crie um site com o nome de projetoowasp01 que contenha o Slecione a pasta Autoridades de Certificação Raiz Confiáveis e domínio www.projetoowasp01.com.br. vamos importar como demonstrado na Figura 4. Esta tarefa é extremamente fácil, basta importar e responder a Validando nosso certificado no cliente todas as perguntas positivamente. FairCom121212BRhalffinal.pdf 1 1/3/13 2:16 PM Abra o Microsoft Management console. Na tela que se abre, Na Listagem 17 vemos os comandos e saída da geração da chave clicamos em Arquivo e depois em Adicionar/Remover Snap-in. para exportação.

Estas soluções são monitoradas pela tecnologia FairCom todos os dias!

tecnologia de banco de dados ÜÜÜ°v>ˆÀVœ“°Vœ“ÊUÊ££‡ÎnÇӇ™näÓ

© 2013 FairCom Corporation

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

Figura 5. Resultado da importação do certificado no IIS Listagem 17. Chave para uso do IIS para negociação SSL 01 C:\OpenSSL-Win32>openssl pkcs12 -export -in certificados\certMasterCA_IIS.cer -inkey chaves\CA_IIS.key -out httpsiis.pfx -name “Certificado para o HTTPS do IIS” 02 03 Loading ‘screen’ into random state - done 04 Enter pass phrase for chaves\CA_IIS.key: 05 Enter Export Password: 06 Verifying - Enter Export Password:

Nas linhas 05 e 06 nos é solicitada uma senha par este certificado gerado. De posse deste, importamos para o IIS todos os nossos certificados gerados anteriormente: Servidor Windows e o pfx (mostrado na Listagem 17). Agora que já temos o nosso site configurado e nossos certificados confiáveis, agora, vamos instalá-los no IIS.

Configurando o IIS para receber nossos certificados confiáveis

Figura 6. Editar Ligações para habilitar o HTTPS

Figura 7. Configuração do HTTPS

24 .net Magazine • Edição 115

Vamos abrir o console do IIS e selecionar novamente o item de Certificados. Neste ponto, vamos selecionar os nossos certificados gerados para o servidor, incluindo o .pfx. Os certificados devem ser listados em Certificados do Servidor, como nos mostra a Figura 5. Agora, configuraremos o nosso site para que o mesmo possa acessar dispor do HTTPS. A Figura 6 mostra o caminho correto. Ao adicionar o protocolo HTTPS, o nome do domínio e selecionar o certificado, devemos selecionar o .pfx, como mostra a Figura 7. Vamos à configuração de como os clientes vão interagir com o nosso site. Para tal, basta selecionar a opção Configurações de SSL. Na janela que se abre, marque a caixa exigir SSL e depois clique em Aceitar. A Figura 8 mostra o resultado de nossa configuração. Para que o certificado seja reconhecido por seu navegador, basta clicar no ícone do site seguro, normalmente um cadeado, e solicitar

a instalação do certificado dentro de “Autoridade de certificação raiz confiável”.

Estrutura de nosso Exemplo prático Na Figura 9 temos a estrutura de nosso projeto e na Tabela 1 temos a especificação de cada uma destas camadas. Nossa arquitetura está bem organizada, de forma que será orientada a interfaces. Para isto, vamos utilizar o Spring.NET para persistência e container de IoC e DI. Porém, também mostraremos uma parte de persistência do sistema utilizando NHibernate apenas caso Figura 8. Resultado da Operação o leitor não utilize o Spring. NET em seus projetos e não tenha uma previsão para tal.

Organização e distribuição dos componentes Pela arquitetura ser multicamada, temos a facilidade de armazenar os assemblies em locais diferentes, mas isto deve ser feito após o projeto ser finalizado. Porém, pensando sempre no princípio da economicidade de recursos e também facilidade de acesso aos assemblies da aplicação, temos de centralizá-los em um diretório Camada

Descrição

DAL

Camada de Acesso a Dados

DTO

Camada de Data Transfer Object responsável por fazer a interação entre a DAL e a Camada de Negócios para evitar que a tal camada acesse diretamente a Camada de Acesso a Dados.

Entidade

Camada onde teremos todas as Entidades responsáveis por representar as tabelas do Banco de Dados e Entidades presentes na Modelagem da aplicação

Seguranca

Camada que cuida especificamente da segurança do Projeto. Contém as classes de tratamento de criptografia, Membership e Role Providers. Foi concebida para ser tratada como um módulo que poderia ser acoplado a qualquer outra aplicação ou facilitar a portabilidade para tal.

SiteSeguro

É a nossa Camada de Apresentação e consiste em um WebSite ASP.MVC 4 empty contendo Razor.

Teste

É a nossa Camada de Testes e será bastante utilizada, posto que todas as funcionalidades serão criadas primeiramente aqui e depois replicada para sua camada respectiva. Utilizaremos o NUnit para os testes unitários.

Negocio

Camada responsável por receber as necessidades do cliente quanto ao seu negócio e interação deste com os demais usuários. Esta camada também é responsável por ser a intermediária entre a camada de apresentação e as outras camadas. na camada de negócio, teremos o acoplamento e todas as operações de entidades feitas através da camada de DTO.

Tabela 1. Estrutura de Camadas do Projeto

Figura 9. Estrutura do Projeto Edição 115 .net Magazine

25

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

que seja padrão para ser usado como repositório de referência para todos os projetos envolvidos na solução. Tal centralização é importante, pois mantém as referências sempre atualizadas. Dentro da estrutura da solução criamos uma árvore específica para tal armazenagem, mostrada em destaque na Figura 10. Esta estrutura fica invisível para o Visual Studio.

Figura 11. Build Events Listagem 18. Comandos para o Evento de Build após o sucesso do mesmo.

Figura 10. Estrutura de Centralização de Assemblies

01 del /q “$(OutDir)*.*” 02 %WINDIR%\Microsoft.Net\Framework\v4.0.30319\ngen.exe install “$(TargetPath)”

Temos dois subdiretórios: Desenvolvimento, que recebe os assemblies de nosso artigo no momento de sua compilação quando a mesma resulta em sucesso - os arquivos .dll dos assemblies gerados por esta compilação são copiados para este diretório; já o subdiretório Produção serve para que coloquemos os mesmos assemblies,mas que serão distribuídos para o Sistema em produção, ou seja, após desenvolvimento pela equipe e validação pelo usuário para ser utilizado pela empresa do cliente como produto final. Este diretório é bastante útil para manobras de Integração Contínua ou Entrega Contínua. Devemos sempre apontar as referências de nossos projetos para Produção ou Desenvolvimento, pois estes dois diretórios justamente são de fácil localização e são comuns a todo o Projeto. Como é uma regra o uso destes dois subdiretórios quanto ao Controle do Projeto, precisamos automatizar o processo para evitar que cada membro da equipe guarde seus assemblies em locais da aplicação diferentes do proposto. E já que falamos sobre estratégias de compilação, mostraremos na Listagem 18 uma forma de efetuar a compilação e execução de comandos específicos no momento da compilação da solução. Os assemblies são gerados por projeto, então nossa diretriz de compilação deve ser executada também dentro de cada projeto que, durante a compilação da solution, a estratégia de automação de cada projeto é iniciada sem intervenção do desenvolvedor. O Visual Studio trata desta parte, na seção Propriedades do Projeto chamada Eventos de Build ou Build Events. Para que tenhamos êxito na centralização dos assemblies, precisamos copiá-los ao repositório assim que uma compilação bem sucedida é finalizada. Diante desta assertiva precisamos executar estes comandos ao final do Build. Na Figura 11 vemos a localização dos Build Events e o evento de pós build. Estando dentro dos Build Events, vamos adicionar as seguintes linhas para o post-build event command line, conforme a Listagem 18.

26 .net Magazine • Edição 115

03 Copy “$(TargetPath)” “$(SolutionDir)InfraEstrutura\ProjetoDLL\ Desenvolvimento” /y

Quando o assembly é compilado, o mesmo pode ser armazenado no diretório Bin/Debug ou Bin/Release, dependendo da estratégia de build. Então, na linha 01 eliminamos todos os assemblies com o mesmo nome do projeto, caso tenhamos algum problema em sobrescrever o assembly antigo. Logo após utilizamos o ngen.exe, que é um aplicativo criado para executar o assembly em runtime, ou seja, ele não é carregado totalmente na memória para ser utilizado quando carregado como o que ocorre normalmente, mas sim, gravado em uma espécie de cache de segundo nível na máquina. Então os trechos que são mais executados já ficam na memória aguardando execução sem a necessidade do assembly estar montado totalmente na memória. Após o registro do ngen, já temos o nosso assembly registrado no cache já compilado para o diretório centralizado de nossa aplicação, como mostrado na linha 03. Uma outra operação também muito importante que nos dá uma certa confiabilidade em nosso projeto é assinar nossos assemblies através de certificados. Se notarmos, todos os assemblies que fazem parte do .NET Framework são assinados e registrados no Global Assembly Cache, ou GAC.

Assinando os nossos asssemblies com Strong names gerados pelo OpenSSL Primeiramente, vamos gerar um certificado no formato PKCS12 utilizando a nossa chave privada, ou nosso CA, como informado anteriormente. Na Listagem 19 vemos como a criação do mesmo é efetuada via linha de comando.

Devemos entrar com a nossa senha do CA e depois devemos criar uma senha para o certificado criado. A saída deste comando é mostrada na Listagem 20. Agora, caso façamos a assinatura do assembly no Visual Studio e compilamos a aplicação, receberemos um erro parecido com o da Listagem 21. Para tal, vamos precisar extrair a chave privada sem a senha e com esta chave criar um novo certificado e, logo em seguida, devemos apagar a chave privada. Na Listagem 22 temos tal comando a ser executado e sua posterior saída. É a única forma do mesmo ser aceito pelo Visual Studio. De acordo com o comando na linha 1, pode-se notar que extraímos de nosso certificado inicial um arquivo contendo uma chave privada com extensão .key (lembrando que esta extensão não é obrigatória, mas foi mantida a quesito de informação). Na linha 2 devemos entrar com a senha que criamos quando geramos este certificado, que naquela ocasião seria o “Export Password”. Na linha 4 o OpenSSL nos pede que criemos uma senha também para acesso a esta chave Privada, impedindo que outros tentem extraíla em caso de roubo (sempre é uma boa prática criar uma senha). A senha em questão é para os certificados gerados pela chave privada e o problema gerado na Listagem 21 é justamente pelo compilador não acessar a chave privada para validar com a chave pública.

Listagem 19. Gerando o certificado para um Assembly C:\OpenSSL-Win32>openssl pkcs12 -export -in certificados\certMasterCA_IIS. cer -inkey chaves\CA_IIS.key -out certificados\StrongNameSeguranca.pfx -name “Certificado para Strong Name do Assembly Seguranca.dll” Listagem 20. Assinando o Certificado gerado 01 C:\OpenSSL-Win32>openssl pkcs12 -export -in certificados\certMasterCA_IIS. cer -inkey chaves\CA_IIS.key -out certificados\StrongNameSeguranca.pfx -name “Certificado para Strong Name do Assembly Seguranca.dll” 02 Loading ‘screen’ into random state - done 03 Enter pass phrase for chaves\CA_IIS.key: 04 Enter Export Password: 05 Verifying - Enter Export Password: Listagem 21. Erro ao tentar compilar um certificado assinado com o OpenSSL error MSB3325: Cannot import the following key file: StrongSeguranca.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_3523EF3C7BF9F6ED C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common. targets(1970,9): error MSB3321: Importing key file “StrongNameSeguranca.pfx” was canceled.

Edição 115 .net Magazine

27

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

Desta forma, criamos um certificado com ambas concatenadas, por isso a necessidade da senha no certificado novo. Agora que estamos de posse de nossa chave privada, vamos criar o certificado assinado propriamente dito, de forma que o Visual Studio o reconheça como Strong Name válido. Veremos a linha de comandos e posterior saída do mesmo na Listagem 23. Listagem 22. Criação de um certificado assinado através de extração de chave privada 01 C:\114\Código Fonte\Artigo114\packages\SHA3.0.9.2\lib\net40> openssl pkcs12 -in StrongNomeSeguranca.pfx -out bkpStrongSeguranca.key 02 Enter Import Password: 03 MAC verified OK 04 Enter PEM pass phrase: 05 Verifying - Enter PEM pass phrase: Listagem 23. Criação de certificado assinado aceito pelo Visual Studio 01 C:\114\Código Fonte\Artigo114\packages\SHA3.0.9.2\lib\net40> openssl pkcs12 -export -out StringSegurancaAssinado.pfx -keysig -in bkpStrongSeguranca.key 02 03 Loading ‘screen’ into random state - done 04 Enter pass phrase for bkpStrongSeguranca.key: 05 Enter Export Password: 06 Verifying - Enter Export Password:

Diante disto, acabamos de criar o nosso certificado assinado para ser utilizado pelo nosso projeto no Visual Studio. Podemos utilizar esta chave privada para criar outros certificados dentro da nossa Solução ao invés de extrair uma chave privada a cada projeto que formos criar. Já podemos copiar a chave privada diretamente para a raiz da solução. Para inserir um certificado a um projeto, basta entrarmos nas propriedades deste projeto e selecionar a opção “Signing”, marcar a opção “sign the assembly” e em “Choose a strong name key file”,clicamos em “Browse”, selecionando o arquivo “StringSegurancaAssinado.pfx”. Após isso, vamos efetuar o build de nossa aplicação, porém, nos deparamos com um erro informando que algumas referências utilizadas em nosso projeto não estão assinadas. Para que possamos assinar os assemblies que usamos e não estejam assinados, primeiro precisamos criar um certificado para o nosso assembly não assinado (normalmente é de um vendor e não faz parte da nossa equipe de projetos). Para criar um Certificado assinado e sem senha, basta utilizar o comando “sn.exe” do próprio .NET Framework. No nosso caso, o SH3 que baixamos do NuGet não está assinado e, com isto,precisamos entrar diretamente no diretório de pacotes da nossa solução (..\packages\SHA3.0.9.2\lib\net40) e navegar até este diretório via console. Já dentro deste diretório, vamos executar o seguinte comando mostrado na Listagem 24. Receberemos uma resposta positiva para a criação do mesmo. Como não temos com abrir o assembly, precisamos então desmontá-lo com o comando ILDASM. Caso o o leitor não o tenha instalado,faz-se necessário instalar o .NET Framework 2.0.

28 .net Magazine • Edição 115

A Listagem 25 nos mostra o que devemos inserir na linha de comandos. Criamos um arquivo com a extensão .il apenas para diferenciar o arquivo do assembly. Agora vamos gerar um novo assembly assinado de SHA3.dll, conforme a Listagem 26. Nela vemos como criar o SHA3Novo.dll. Repare que para isso vamos utilizar o comando ILASM.exe, não o ILDASM, pois o comando ILDASM faz o desassembly, enquanto que o ILASM faz a montagem. Listagem 24. Criado Strong Name para o Assembly de terceiros sn -k SHA3.snk Listagem 25. Desmontagem do Assembly C:\114\Código Fonte\Artigo114\packages\SHA3.0.9.2\lib\net40>ildasm /all / out=SHA 3Novo.il SHA3.dll

Métodos de autenticação que serão utilizados Já protegemos a infraestrutura de nosso projeto com esta parte solucionada. Agora precisamos pensar na forma como a segurança interna (que é a mais importante), no que tange à aplicação, será feita e principalmente no domínio da autorização e autenticação. Para a autenticação vamos utilizar uma classe já bem conhecida do .NET Framework: MembershipProvider. Esta classe contém muitos métodos válidos e já prontos para o uso da autenticação, porém, esta classe pode ser estendida e será isso que faremos posteriormente. Para a autorização utilizaremos a classe RoleProvider que provê um controle de acesso direto aos métodos com um nível de abstração feito por papéis, ou seja, se o usuário é administrador pode acessar o método tal, se o papel é usuário, o método x. Tal classe também pode ser estendida e customizada de acordo com o nosso projeto e será o que demonstraremos adiante.

Criando um Custom MembershipProvider Para criarmos uma classe personalizada de autenticação precisamos derivar a classe MembershipProvider que surgiu como uma solução na qual o desenvolvedor pode acoplar a sua própria solução de autenticação e autorização ao invés de utilizar o MembershipProvider gerado via assistente do Visual Studio que contêm muitas tabelas e seria um grande imbróglio no projeto de software por inserir muitas tabelas e outros objetos. Com o MembershipProvider já temos a Regra de Negócios bem definida e métodos como UpdateUser, ResetPassword, dentre outros aderentes a qualquer negócio de autenticação. Para que possamos utilizar o MembershipProvider precisamos adicionar como referência o assembly System.Web.ApplicationServices e System.Configuration, pois não estão na GAC. Na Listagem 27 demonstramos a nossa classe presente na Camada de Seguranca.

Listagem 26. Montagem do novo assembly assinado com sua saída do console C:\114\Código Fonte\Artigo114\packages\SHA3.0.9.2\lib\net40>ilasm /dll /OPTIMIZE /key=SHA3.snk SHA3ManagedNovo.il Microsoft (R) .NET Framework IL Assembler. Version 4.0.30319.1 Copyright (c) Microsoft Corporation. All rights reserved. Assembling ‘SHA3ManagedNovo.il’ to DLL --> ‘SHA3ManagedNovo.dll’ Source file is ANSI Assembled method SHA3.SHA3::.cctor Assembled method SHA3.SHA3::Create Assembled method SHA3.SHA3::Create Assembled method SHA3.SHA3::get_KeccakR Assembled method SHA3.SHA3::set_KeccakR Assembled method SHA3.SHA3::get_SizeInBytes Assembled method SHA3.SHA3::get_HashByteLength Assembled method SHA3.SHA3::get_CanReuseTransform Assembled method SHA3.SHA3::.ctor Assembled method SHA3.SHA3::ROL Assembled method SHA3.SHA3::AddToBuffer Assembled method SHA3.SHA3::get_Hash Assembled method SHA3.SHA3::get_HashSize Assembled method SHA3.SHA3::Initialize Assembled method SHA3.SHA3::HashCore Assembled method SHA3.SHA3Managed::.ctor Assembled method SHA3.SHA3Managed::HashCore Assembled method SHA3.SHA3Managed::HashFinal Assembled method SHA3.SHA3Managed::KeccakF

Creating PE file Emitting classes: Class 1: SHA3.SHA3 Class 2: {039ABB91-33B3-44B3-A515-71F657BAA F35} Class 3: {039ABB91-33B3-44B3-A515-71F657BAA F35}°__StaticArrayInitTypeSize=192 Class 4: SHA3.SHA3Managed Emitting fields and methods: Global Class 1 Fields: 10; Methods: 15; Class 2 Fields: 1; Class 3 Class 4 Methods: 4; Resolving local member refs: 171 -> 171 defs, 0 refs, 0 unresolved Emitting events and properties: Global Class 1 Props: 6; Class 2 Class 3 Class 4 Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved Writing PE file Signing file with strong name Operation completed successfully

Listagem 27. Classe CustomMembershipProvider 01    public class CustomMembershipProvider : MembershipProvider 02    { 03        public override string ApplicationName 04        { 05            get 06            { 07                throw new NotImplementedException(); 08            } 09            set 10            { 11                throw new NotImplementedException(); 12            } 13        } 14 15        public override bool ChangePassword(string username,  string oldPassword, string n16 ewPassword) 17        { 18            throw new NotImplementedException(); 19        } 20 21        public override bool ChangePasswordQuestionAndAnswer (string username, string password, string newPasswordQuestion,  string newPasswordAnswer) 22        { 23            throw new NotImplementedException(); 24        } 25 26        public override MembershipUser CreateUser(string username,  string password, string email, string passwordQuestion,  string passwordAnswer, bool isApproved, object providerUserKey,  out MembershipCreateStatus status) 27        { 28            throw new NotImplementedException(); 29        } 30 31        public override bool DeleteUser(string username, bool deleteAllRelatedData)

32        { 33            throw new NotImplementedException(); 34        } 35 36        public override bool EnablePasswordReset 37        { 38            get { throw new NotImplementedException(); } 39        } 40 41       public override bool EnablePasswordRetrieval 42        { 43            get { throw new NotImplementedException(); } 44        } 45 46        public override MembershipUserCollection FindUsersByEmail (string emailToMatch, int pageIndex, int pageSize, out int totalRecords) 47        { 48            throw new NotImplementedException(); 49        } 50 51        public override MembershipUserCollection FindUsersByName (string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) 52        { 53            throw new NotImplementedException(); 54        } 55 56        public override MembershipUserCollection GetAllUsers (int pageIndex, int pageSize, out int totalRecords) 57        { 58            throw new NotImplementedException(); 59        } 60 61        public override int GetNumberOfUsersOnline() 62        { 63            throw new NotImplementedException(); 64        }

Edição 115 .net Magazine

29

ASP.NET MVC 4: Criando sistemas web seguros– Parte 1

Continuação: Listagem 27. Classe CustomMembershipProvider 65 66        public override string GetPassword(string username, string answer) 67        { 68            throw new NotImplementedException(); 69        } 70 71        public override MembershipUser GetUser(string username, bool userIsOnline) 72        { 73            throw new NotImplementedException(); 74        } 75 76        public override MembershipUser GetUser(object providerUserKey,  bool userIsOnline) 77        { 78            throw new NotImplementedException(); 79        } 80 81        public override string GetUserNameByEmail(string email) 82        { 83             84            throw new NotImplementedException(); 85        } 86 87        public override int MaxInvalidPasswordAttempts 88        { 89            get { throw new NotImplementedException(); } 90        } 91 92        public override int MinRequiredNonAlphanumericCharacters 93        { 94            get { throw new NotImplementedException(); } 95        } 96 97        public override int MinRequiredPasswordLength 98        { 99            get { throw new NotImplementedException(); } 100        } 101 102        public override int PasswordAttemptWindow 103        { 104            get { throw new NotImplementedException(); } 105        }

Diante do que vimos nesta primeira parte, já estamos prontos para verificar as necessidades de nossos clientes e podemos já separar o backlog de produtos e começar os testes unitários e posterior programação dos módulos.

Autor Luís Gabriel Nascimento Simas [email protected] Atua como Desenvolvedor de Software desde 1996. É Coordenador das Revistas Infra Magazine e Delphi Magazine na Devmedia e Programador na Fundação Getúlio Vargas (FGV) na TIC - Tecnologia da Informação e Comunicação. Também é aluno de Análise e Desenvolvimento de Sistemas na Universidade Estácio de Sá no Campus Praça XI. Lida com Metodologias e Processos Ágeis e é proficiente nas Linguagens Java e C#.

106 107        public override MembershipPasswordFormat PasswordFormat 108        { 109            get { throw new NotImplementedException(); } 110        } 111 112        public override string PasswordStrengthRegularExpression 113        { 114            get { throw new NotImplementedException(); } 115        } 116 117        public override bool RequiresQuestionAndAnswer 118        { 119            get { throw new NotImplementedException(); } 120        } 121 122        public override bool RequiresUniqueEmail 123        { 124            get { throw new NotImplementedException(); } 125        } 126 127        public override string ResetPassword(string username, string answer) 128        { 129            throw new NotImplementedException(); 130        } 131 132        public override bool UnlockUser(string userName) 133        { 134            throw new NotImplementedException(); 135        } 136 137        public override void UpdateUser(MembershipUser user) 138        { 139            throw new NotImplementedException(); 140        } 141 142        public override bool ValidateUser(string username, string password) 143        { 144            throw new NotImplementedException(); 145        } 146    }

Links: ICP Brasil - Autoridade Certificadora http://www.iti.gov.br/icp-brasil/o-que-e Verisign Certificados http://www.verisigninc.com/?loc=pt_BR&cmp=SEMG02:01 GeoCert - Certificados Digitais http://www.rapidssl.com.br/ Site OpenSSL https://www.openssl.org/

Você gostou deste artigo? Dê seu voto em www.devmedia.com.br/netmagazine/feedback Ajude-nos a manter a qualidade da revista!

30 .net Magazine • Edição 115

Edição 115 .net Magazine

31

Entity Framework Code First

Entity Framework Code First Uma alternativa para o uso de técnicas de ORM em .NET

É

inegável a importância que os bancos de dados relacionais adquiriram dentro das mais diversas organizações. Oferecendo meios para o armazenamento de um volume crescente de informações num formato estruturado, estes repositórios são utilizados como recursos na automação de processos cotidianos por empresas e órgãos governamentais dos mais variados portes. Importante destacar ainda a existência de inúmeras opções baseadas neste tipo tecnologia, desde produtos comercializados por gigantes da área de software (como o SQL Server da Microsoft, o DB2 da IBM e o Oracle), passando ainda por soluções livres mantidas por comunidades de desenvolvedores (como o Firebird e o PostgreSQL). Como não é difícil de imaginar, as principais plataformas de desenvolvimento da atualidade oferecem total suporte ao uso de bancos de dados relacionais na construção de novos sistemas. Com o .NET Framework isto não é diferente: a tecnologia conhecida como ADO .NET (ActiveX Data Object for .NET) existe desde os primórdios desta plataforma, representando a base para que aplicações em .NET consigam interagir com serviços de bancos de dados como o SQL Server. Por mais que o ADO.NET conte com recursos capazes de atender às mais diversas demandas decorrentes da implementação de projetos em .NET, este mecanismo apresenta algumas limitações. Por não dispor de um recurso nativo capaz de converter as informações de uma base relacional em construções típicas da orientação a objetos, é bastante comum que desenvolvedores façam uso de algum dispositivo responsável por realizar estas transformações. O processo de mapeamento das estruturas relacionais em objetos compatíveis com uma linguagem/plataforma é conhecido como ORM, com o uso de frameworks que definem este tipo de comportamento estando normalmente associado à implementação de funcionalidades de CRUD.

32 .net Magazine • Edição 115

Fique por dentro A necessidade de transformar informações oriundas de bases relacionais em objetos corresponde, sem sombra de dúvidas, a um tipo de ocorrência extremamente comum no desenvolvimento de aplicações. Diversos frameworks foram criados levando em consideração tal aspecto, sendo o Entity Framework uma das soluções oferecidas pela Microsoft para atender a demandas deste gênero. Este artigo tem por meta apresentar o Entity Framework Code First (uma das alternativas para uso do Entity Framework), demonstrando como este recurso pode ser útil na implementação de soluções dentro da plataforma .NET. Para isto, será criada uma aplicação de testes que fará uso de um mecanismo de CRUD genérico e reutilizável baseado no Entity Framework.

Introduzido a com a versão 3.5 da plataforma .NET, o Entity Framework é uma solução ORM criada pela Microsoft com o intuito de simplificar a construção de aplicações que façam uso de bancos de dados relacionais. Um dos grandes diferenciais do Entity Framework foi permitir a criação de modelos de bancos de dados por meio de uma ferramenta gráfica, dispensando os desenvolvedores da necessidade de codificar uma ou mais classes representando as estruturas de uma base específica. Muito embora esta técnica apresente vantagens (como a geração de um diagrama com todas as classes que efetuam o mapeamento objeto-relacional), com o release da versão 4.1 do Entity Framework (voltado ao .NET Framework 4.0) uma nova alternativa de desenvolvimento foi disponibilizada. Trata-se do Entity Framework Code First, em que classes são codificadas de forma a representar estruturas pertencentes a um banco de dados utilizado pela aplicação construída. O objetivo deste artigo é discutir as principais características do Code First. A partir disto será apresentado um exemplo de uso deste recurso em uma aplicação MVC, empregando neste caso um mecanismo genérico baseado no do Entity Framework Code First para a implementação de funções de CRUD.

Entity Framework Code First: uma visão geral Na primeira versão do Entity Framework a manipulação de informações provenientes de bases relacionais acontecia a partir de um modelo gráfico gerado por meio do Visual Studio. Em termos práticos, tal modelo nada mais é do que um arquivo XML com a extensão .edmx, em que Views, tabelas e os relacionamentos entre essas estruturas são mapeados para classes que poderão ser utilizadas em aplicações .NET. Quanto à codificação de instruções acessando e manipulando as entidades de um modelo, será a classe ObjectContext (namespace System.Data.Objects) a estrutura responsável por prover as funcionalidades que tornam possíveis estas ações. Ao criar um modelo baseado em um arquivo .edmx, duas abordagens de desenvolvimento empregando o Entity Framework são possíveis: • Database First: através de uma ferramenta de engenharia reversa um modelo é gerado, tomando-se como referência as informações de metadados de um banco relacional pré-existente; • Model First: as diferentes classes representando estruturas de uma base relacional são modeladas antes mesmo que tais construções tenham sido implementadas. O Entity Framework disponibiliza recursos para a criação dos elementos gerados em um banco de dados de destino. Na Figura 1 está um exemplo de arquivo .edmx do Entity Framework. É possível observar neste modelo a presença de entidades representando as tabelas de regiões e estados de uma base de dados hipotética. Independentemente da escolha que for feita, algumas questões devem ser ponderadas quanto ao uso do Entity Framework via arquivos .edmx: • A criação de um modelo baseado em um arquivo .edmx é recomendável para sistemas novos, em que classes representando diferentes itens de negócio sequer foram implementadas; • Embora represente uma alternativa que pode conduzir a uma maior produtividade, este processo de modelagem gráfica baseado em um arquivo XML pode revelar-se como inviável em algumas situações. Um destes casos seria o de projetos com grandes equipes, nos quais diversos programadores podem estar editando um mesmo arquivo .edmx e adicionando/modificando estruturas dentro deste último. A unificação de tais modificações (atividade esta popularmente conhecida como “merge”) poderá resultar na perda de alguns ajustes ou, até mesmo, na danificação do modelo .edmx (algo que obrigaria a um retrabalho a fim de regerar e configurar manualmente esta estrutura); • Modificações na base de dados podem também invalidar as representações definidas em um arquivo .edmx. Como também constam neste último informações de metadados (como o tamanho e o tipo de campos, o relacionamento entre diferentes tabelas etc.), alterações na estrutura de um banco de dados exigirão muitas vezes a atualização do modelo correspondente; • Cada uma das classes pertencentes a um modelo gerado pelo Visual Studio herdará do tipo EntityObject (namespace System

.Data.Objects.DataClasses). Essa estrutura encapsula todo um mecanismo para detecção a de mudanças nos valores de uma entidade/objeto, sendo que muitos desenvolvedores não vêm com bons olhos (já que em muitos cenários um objeto comum com propriedades e, eventualmente, alguns métodos simples resolveriam as demandas envolvendo a manipulação de valores referentes a um ou mais ou registros de uma base).

Figura 1. Exemplo de modelo do Entity Framework gerado através do Visual Studio Por mais que as primeiras versões do Entity Framework contassem com todos os recursos normalmente esperados de um mecanismo de ORM, muitos desenvolvedores ainda preferiam o uso de soluções que dispensassem a modelagem gráfica de classes representando entidades de negócio. A disponibilização da abordagem Code First a partir do release 4.1 do Entity Framework (voltada ao .NET Framework 4.0) procurou atender a esta demanda, contemplando ainda todas as funcionalidades de manipulação de dados suportadas pelos métodos Model e Database First. Conforme mencionado anteriormente, dentro do padrão Code First a representação de estruturas como tabelas e views é feita por meio de classes que não possuem nenhuma dependência direta para com o Entity Framework (logo, não há herança a partir de ObjectEntity). Estes tipos seguem um pattern conhecido como POCO (BOX 1), sendo que esta característica permite inclusive a utilização da abordagem Code First com classes já implementadas anteriormente em um projeto. BOX 1. POCO POCO (sigla do inglês “Plain Old CRL Objects”) é um padrão em que classes são definidas com uma estrutura simples, codificadas de forma a não possuir uma ligação direta com qualquer tipo de framework ORM. Devido a esta independência para com mecanismos de acesso a dados, tipos que seguem este padrão podem ser reutilizados com diferentes bibliotecas na manipulação de informações provenientes de bases relacionais.

Na Listagem 1 é possível observar exemplos de classes que podem ser utilizadas em conjunto com o Entity Framework Code First. Neste caso específico, as classes Regiao e Estado contam com propriedades cujos nomes e tipos coincidem com as definições

Edição 115 .net Magazine

33

Entity Framework Code First

da base de dados. Além disso, nota-se a existência de um relacionamento entre Estado e Regiao (a propriedade Regiao, que está declarada na linha 17). Listagem 1. As classes Regiao e Estado 01 using System; 02 03 namespace Exemplo 04 { 05 public class Regiao 06 { 07 public string CdRegiao { get; set; } 08 public string NmRegiao { get; set; } 09 } 10 11 public class Estado 12 { 13 public string CdEstado { get; set; } 14 public string NmEstado { get; set; } 15 public string CdRegiao { get; set; } 16 public virtual Regiao Regiao { get; set; } 17 } 18 }

Ao desenvolver tomando como base o padrão Code First, a Microsoft recomenda o uso da classe DbContext (namespace System.Data.Entity) ao invés do tipo ObjectContext. Esta estrutura foi também introduzida a partir do Entity Framework 4.1, sendo uma versão simplificada que encapsula as funcionalidades de ObjectContext. Será a partir de uma instância da classe DbContext que acontecerá o acesso a uma base de dados para a realização de operações de consulta, inclusão, alteração e exclusão de informações. Estas ações serão sempre executadas sobre um conjunto de entidades, as quais são representadas através de propriedades do tipo genérico DbSet (namespace System.Data.Entity) declaradas em classes que derivam de DbContext. Em tempo de execução o Entity Framework Code First irá analisar classes que representem entidades, sendo capaz de inferir relacionamentos e os tipos de dados utilizados por estas construções. Contudo, haverá casos em que os desenvolvedores precisarão especificar maiores detalhes envolvendo a configuração destes tipos, a fim de possibilitar que as funcionalidades de ORM do Code First façam o correto mapeamento entre tais elementos e as estruturas de um banco de dados. Existem duas opções para realizar estas configurações: • Através da utilização de atributos conhecidos como Data Annotations. Estes itens encontram-se definidos no namespace System .ComponentModel.DataAnnotations, podendo ser aplicados às declarações de classes e propriedades utilizadas em conjunto com o padrão Code First. Isto não significa, no entanto, que o uso de Data Annotations seja uma característica específica do Entity Framework; o ASP.NET MVC representa um bom exemplo de framework que faz uso deste mecanismo, valendo-se de tais atributos como base para a validação de dados em telas de cadastros;

34 .net Magazine • Edição 115

• Empregando o mecanismo do Entity Framework Code First conhecido como Fluent API. Este recurso faz uso da classe genérica EntityTypeConfiguration (namespace System.Data .Entity.ModelConfiguration), a qual disponibiliza vários métodos de configuração que se baseiam em um padrão conhecido como interface fluente. A chamada aos métodos da Fluent API deve acontecer a partir de uma versão sobrecarregada do método OnModelCreating, em uma classe derivada do tipo DbContext. Na Listagem 2 é apresentado um exemplo de implementação do tipo DbContext, com a configuração das classes Regiao e Estado sendo feita por meio do uso da Fluent API. Observando a forma como o tipo TesteDbContext foi estruturado, é possível observar: • As propriedades Regioes e Estados (linhas 9 e 10). Estes elementos armazenarão instâncias do tipo genérico DbSet, representando conjunto de entidades dos tipos Regiao e Estado. O preenchimento destas propriedades acontecerá de forma automática, com o pré-requisito para isto sendo a existência de uma string de conexão com o mesmo nome da classe TesteDbContext declarada no arquivo de configuração da aplicação; • Uma versão sobrecarregada do método OnModelCreating (linha 12). Esta operação recebe como parâmetro uma instância do tipo DbModelBuilder (namespace System.Data.Entity); a partir deste objeto será acessado o método genérico Entity, o qual retornará uma referência do tipo EntityTypeConfiguration . Será por meio de instâncias da classe EntityTypeConfiguration que métodos como ToTable e HasKey serão acionados, a fim de gerar as configurações que permitirão o correto mapeamento entre tipos e estruturas de bancos de dados manipuladas pelo tipo derivado derivado de DbContext. Listagem 2. Exemplo de uso do tipo DbContext 01 using System; 02 using System.Data.Entity; 03 using System.Data.Entity.ModelConfiguration.Configuration; 04 05 namespace Exemplo 06 { 07 public class TesteDbContext : DbContext 08 { 09 public DbSet Regioes { get; set; } 10 public DbSet Estados { get; set; } 11 12 protected override void OnModelCreating( 13 DbModelBuilder modelBuilder) 14 { 15 modelBuilder.Entity() 16 .ToTable(“TB_REGIAO”) 17 .HasKey(r => r.CdRegiao); 18 modelBuilder.Entity() 19 .ToTable(“TB_ESTADO”) 20 .HasKey(r => r.CdEstado); 21 } 22 } 23 }

Um último ponto que merece ser destacado diz respeito às formas possíveis de interação do Entity Framework Code First com bancos de dados do SQL Server. Além do acesso para a execução de comandos que envolvam consultas, inclusão, alteração e/ou exclusão de dados, o Code First oferece ainda funcionalidades para a criação de um banco de dados a partir das classes (e respectivas configurações) que representam diferentes entidades dentro de um sistema. Este recurso pode ser extremamente útil em aplicações que funcionem como provas de conceito, em que as diferentes funcionalidades foram concebidas com o objetivo de demonstrar uma arquitetura elaborada com um fim específico.

Exemplo de utilização de Entity Framework Code First Para implementar a solução demonstrada foram utilizados os seguintes recursos: • O Microsoft Visual Studio Professional 2013 Update 1 como IDE de desenvolvimento; • O .NET Framework 4.5.1; • O SQL Server 2012 como SGBD; • O framework ASP.NET MVC 5.1 como base para a criação das interfaces gráficas de testes; • A versão 6.0.2 do Entity Framework; • A biblioteca jQuery, além de plug-ins baseados nesta última (autoNumeric e jQuery.MaskedInput); • O Unity Application Block 3.0 como mecanismo de injeção de dependências, bem como a extensão Unity bootstrapper for ASP .NET MVC. Será através do utilitário NuGet que as bibliotecas do Entity Framework, do Unity Application Block, da extensão Unity bootstrapper for ASP.NET MVC, assim como os plugins autoNumeric e jQuery.MaskedInput serão adicionados aos projetos que farão uso dos mesmos. O exemplo apresentado a seguir tem por objetivo abordar a construção de uma aplicação para o gerenciamento de consultores vinculados a uma consultoria de tecnologia. Para isto serão implementadas funcionalidades de visualização, inclusão, alteração e exclusão de registros contendo dados de profissionais que possuam contrato junto à companhia em questão. Importante destacar, antes de prosseguir com a implementação da solução de exemplo, que um dos projetos que fará parte desta última é uma Class Library com funcionalidades básicas de CRUD. Esta biblioteca demonstrará como os recursos do Entity Framework Code First podem ser utilizados na criação de um mecanismo genérico, o qual possibilitará a manipulação de informações oriundas de bancos relacionais de uma forma simplificada.

Geração da Base de Dados A solução que estará sendo detalhada a partir da próxima seção fará uso de um banco de dados chamado TesteCodeFirst. No link para download do material deste artigo encontra-se o script SQL

para criação de tal base. O banco de dados TesteCodeFirst será formada pelas tabelas: • TB_OCUPACAO: nesta estrutura constarão as ocupações/cargos possíveis dentro de uma consultoria hipotética; • TB_PROFISSIONAL: tabela que conterá informações de profissionais que possuam contrato junto à empresa de tecnologia (além de suas respectivas ocupações).

Criando a solução de exemplo A fim de iniciar a construção da aplicação de testes proposta por este artigo, será necessário criar primeiramente uma Solution no Visual Studio chamada TesteCodeFirst. A solução mencionada será formada pelos seguintes projetos: • TesteCodeFirst.Utils.ORM: biblioteca em que estão definidas funcionalidades básicas de CRUD, utilizando para isto recursos do Entity Framework Code First; • TesteCodeFirst.Entities: nesta Class Library constarão as classes que representam entidades de negócio manipuladas pela solução de exemplo; • TesteCodeFirst.DAL: projeto no qual serão implementadas as classes de acesso a dados, empregando para isto o mecanismo de mapeamento objeto-relacional definido na biblioteca TesteCodeFirst.Utils.ORM; • TesteCodeFirst.BLL: Class Library em que estarão classes responsáveis por invocar a camada de acesso a dados, assim como as regras de negócio da solução; • TesteCodeFirst.MVC: aplicação MVC através na qual serão implementadas as funcionalidades que envolvem a manipulação de dados cadastrais de profissionais de TI.

Implementando as classes básicas de acesso a dados TesteCodeFirst.Utils.ORM é um projeto do tipo Class Library em que irão constar as classes básicas de acesso a dados utilizadas pela Solution TesteCodeFirst. Tais tipos estarão sendo criados com o intuito de simplificar a interação com a base de dados de testes, através da construção de um mecanismo de CRUD genérico. A implementação destas funcionalidades de uso geral empregará, por sua vez, recursos do Entity Framework Code First. Com o projeto TesteCodeFirst.Utils.ORM já criado, o primeiro ajuste a ser efetuado nesta Class Library consistirá na inclusão via NuGet dos assemblies do Entity Framework e do Unity Application Block (conforme indicado na Figura 2). Quanto aos tipos que farão parte da Class Library TesteCodeFirst.Utils.ORM, serão implementadas nesta seção as seguintes estruturas: • A interface IUnitOfWork; • A classe abstrata BaseRepository. Na Listagem 3 está a definição do tipo IUnitOfWork. Esta interface está baseada em um padrão chamado Unit of Work (BOX 2), sendo utilizada no acesso e manipulação de informações provenientes de bancos relacionais. Analisando a interface de IUnitOfWork, é possível observar:

Edição 115 .net Magazine

35

Entity Framework Code First

• A existência da propriedade DefaultContext (linha 8), à qual estará associada uma instância do tipo DbContext. Será através desta referência que o mecanismo genérico de CRUD (a partir da classe BaseRepository) irá realizar operações de consulta, inclusão, alteração e/ou exclusão em uma base de dados; • O método Commit (linha 9), no qual deverão constar instruções que confirmem (persistam) um conjunto de alterações na base de dados vinculada à propriedade DefaultContext; • O tipo IUnitOfWork está derivando da interface IDisposable (namespace System). Classes baseadas nesta estrutura (IDisposable) deverão implementar um método chamado Dispose, o qual será acionado automaticamente pelo Garbage Collector a fim de liberar recursos alocados em memória. Já na Listagem 4 é apresentada a implementação da classe abstrata BaseRepository. Nessa estrutura estarão centralizadas todas as funcionalidades básicas de CRUD, sendo que este tipo deverá BOX 2. O padrão Unit of Work O pattern Unit of Work tem por objetivo manter o registro de tudo o que é alterado numa base de dados durante o processamento de um grupo de operações. Para isto, utiliza-se uma mesma transação durante uma série de interações, podendo-se ao final confirmar a mesma a fim de persistir as informações na base de dados (através do método Commit no exemplo aqui descrito).

Listagem 3. Interface IUnitOfWork 01 using System; 02 using System.Data.Entity; 03 04 namespace TesteCodeFirst.Utils.ORM 05 { 06 public interface IUnitOfWork : IDisposable 07 { 08 DbContext DefaultContext { get; } 09 void Commit(); 10 } 11 }

Figura 2. Configurando as dependências do projeto TesteCodeFirst.Utils.ORM

36 .net Magazine • Edição 115

ser implementado por classes concretas que representem objetos de acesso a dados. Quanto à estrutura do tipo BaseRepository, é necessário destacar: • A presença de uma restrição (“where T : class” – linha 13) utilizada para definir que somente classes que possuam um construtor sem parâmetros (implementado explicitamente ou não) poderão ser indicadas no lugar do placeholder (linha 12). Essa instrução nada mais é do que um recurso de Generics conhecido como constraint, sendo que através do mesmo é possível estipular condições que devam ser atendidas pelo tipo T; • A propriedade UnitOfWork, que armazenará uma referência de um objeto cuja classe correspondente implementa a interface IUnitOfWork (linha 16). Esta propriedade foi marcada com o atributo DependencyAttribute (namespace Microsoft.Practices. Unity) para que seja preenchida automaticamente em tempo de execução, fazendo-se uso para isto do mecanismo de injeção de dependências disponibilizado pelo Unity Application Block. O objetivo deste procedimento é garantir que todos o tipos derivados de BaseRepository apontem para uma única instância de IUnitOfWork (no caso específico desta solução de exemplo, durante uma requisição HTTP), garantindo assim que diversas ações envolvendo modificações numa base permaneçam dentro de uma única transação; • O método privado GetKeyNames (linha 20). Esta operação irá retornar os nomes dos campos que fazem parte da chave primária de uma entidade representada pelo tipo T, sob a forma de um array de strings associado ao atributo privado “_keyNames” (declarado na linha 18). Caso o conteúdo da referência “_keyNames” seja nulo, uma nova instância do tipo genérico ObjectSet é gerada (linha 24), acessando-se para isto o objeto ObjectContext (este último uma referência de IObjectContextAdapter, interface que pertence ao namespace System.Data.Entity.Infrastructure) por meio da propriedade DefaultContext definida em IUnitOfWork e, na sequência, o método genérico CreateObjectSet. Através da instância do tipo ObjectSet serão acessadas as propriedades EntitySet, ElementType e KeyMembers; a partir deste último elemento e do método Select será criado um novo array com os identificadores dos campos que fazem parte de uma chave primária, com o resultado disto sendo então associado ao atributo “_keyNames”; • A operação privada GetPrimaryKeyValues (linha 34). Recebendo como parâmetro uma instância de um tipo representado por T, este método produzirá como resultado de sua execução um array de objetos com os valores dos

campos de chave-primária para a referência informada durante a sua invocação. O funcionamento desta operação envolve num primeiro momento uma chamada ao método GetKeyNames (descrito anteriormente), com o intuito de obter o nome dos campos que formam a chave primária (linha 36). Além disso, uma instância da classe Type (namespace System) é gerada, de forma a possibilitar o acesso a informações de metadata do tipo T (linha 37). Um novo array de objetos é então criado (linha 39), preenchido com os valores dos campos de chave primária (dentro de um loop que se inicia na linha 40, no qual são acessadas as duas referências geradas no início da execução de GetPrimaryKeyValues) e finalmente devolvido como resultado (linha 46); • O método público FindByPrimaryKey (linha 49). Esta operação recebe como parâmetro um array com os valores que identificam um determinado registro. Partindo do objeto associado à propriedade DefaultContext de IUnitOfWork, é acionado o método

genérico Set e, em seguida, a operação Find (repassando a esta última o parâmetro informado ao acionar FindByPrimaryKey). A instância do tipo T devolvida pelo método Find será retornada então como resultado, correspondendo a um registro que está em conformidade com os valores de chave primária fornecidos à operação FindByPrimaryKey; • A operação pública GetQueryable (linha 55). Ao ser invocado, este método acionará a operação Set a partir da propriedade DefaultContext de um objeto do tipo IUnitOfWork, produzindo como resultado uma instância baseada na interface genérica IQueryable (namespace System.Linq). Objetos cuja classe deriva de IQueryable servem de base para a execução de consultas em um banco de dados, empregando para tanto recursos do Entity Framework e da extensão LINQ; • Os métodos públicos Insert (linha 60) e Delete (linha 65). Estas operações possuem um comportamento bastante similar,

Listagem 4. Classe BaseRepository 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; 04 using System.Data.Entity; 05 using System.Data.Entity.Infrastructure; 06 using System.Data.Entity.Core.Objects; 07 using System.ComponentModel.DataAnnotations; 08 using Microsoft.Practices.Unity; 09 10 namespace TesteCodeFirst.Utils.ORM 11 { 12 public abstract class BaseRepository 13 where T : class 14 { 15 [Dependency] 16 public IUnitOfWork UnitOfWork { get; set; } 17 18 private string[] _keyNames; 19 20 private string[] GetKeyNames() 21 { 22 if (_keyNames == null) 23 { 24 ObjectSet objectSet = 25 ((IObjectContextAdapter)UnitOfWork.DefaultContext) 26 .ObjectContext.CreateObjectSet(); 27 _keyNames = objectSet.EntitySet.ElementType. 28 KeyMembers.Select(k => k.Name).ToArray(); 29 } 30 31 return _keyNames; 32 } 33 34 private object[] GetPrimaryKeyValues(T item) 35 { 36 var keyNames = GetKeyNames(); 37 Type type = typeof(T); 38 39 object[] keys = new object[keyNames.Length]; 40 for (int i = 0; i < keyNames.Length; i++) 41 { 42 keys[i] = type.GetProperty(keyNames[i]) 43 .GetValue(item, null); 44 } 45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 } 89 }

return keys; } public T FindByPrimaryKey(params object[] keyValues) { return UnitOfWork.DefaultContext.Set() .Find(keyValues); } public IQueryable GetQueryable() { return UnitOfWork.DefaultContext.Set(); } public void Insert(T entity) { UnitOfWork.DefaultContext.Set().Add(entity); } public void Delete(T entity) { UnitOfWork.DefaultContext.Set().Remove(entity); } public void Update(T entity) { object[] keyValues = this.GetPrimaryKeyValues(entity); T currentEntity = this.FindByPrimaryKey(keyValues); if (currentEntity == null) { throw new Exception(String.Format( “Erro durante a atualização de uma instância “ + “do tipo {0}. Verifique se o registro “ + “correspondente existe na base de dados.”, typeof(T).Name)); } var entry = UnitOfWork.DefaultContext .Entry(currentEntity); entry.CurrentValues.SetValues(entity); entry.State = EntityState.Modified; }

Edição 115 .net Magazine

37

Entity Framework Code First

acessando o método Set por meio do objeto associado à propriedade DefaultContext de IUnitOfWork. A partir de chamadas às operações Add e Remove da instância retornada pelo método Set acontecerá, respectivamente, a inclusão e a exclusão de registros representados pelo tipo T; • A operação pública Update (linha 70). Utilizado na atualização de um registro que corresponda ao tipo T, o método Update aciona primeiramente as operações GetPrimaryKeyValues (linha 72) e FindByPrimaryKey (linha 73). Se não for encontrado um registro válido na base, uma exceção será lançada descrevendo este problema (linha 76). Caso o objeto em questão conte com um registro equivalente no banco de dados, o método Entry é acionado a partir do objeto vinculado à propriedade DefaultContext (linha 83); esta ação retornará um referência do tipo genérico DbEntityEntry (namespace System.Data.Entity.Infrastructure .DbEntityEntry). Partindo desta última instância, será acionado o método SetValues a partir da propriedade CurrentValues (linha 85), fornecendo como parâmetro a instância informada inicialmente à operação Update; este procedimento tem por objetivo atualizar os diferentes campos que formam um registro. Por fim, a propriedade State da instância do tipo DbEntityEntry é atualizada com o valor de enumeration EntityState.Modified, a fim de marcar o registro da classe T como alterado para posterior persistência das modificações.

Implementando as entidades No projeto TesteCodeFirst.Entities serão definidas as representações das diferentes entidades manipuladas pela aplicação de testes. Estas classes servirão de base para a transferência de dados entre as diferentes camadas da solução aqui apresentada, assim como farão parte do modelo baseado no Entity Framework Code First descrito mais adiante. Constarão nesta Class Library os seguintes tipos: • Ocupacao; • ResumoDadosProfissional; • Profissional. Na Listagem 5 está a definição da classe Ocupacao, a qual será utilizada na exibição das diferentes funções possíveis de se atribuir a um profissional. Analisando a forma como este tipo foi implementado, é possível observar: • O uso do Data Annotation TableAttribute (namespace System .ComponentModel.DataAnnotations.Schema) na linha 7. Quando associado a uma classe, este atributo indica a tabela à qual tal construção estará vinculada (para o caso específico do tipo Ocupacao, o mesmo corresponde a uma representação da tabela TB_OCUPACAO); • A propriedade Id (linha 11), que foi marcada com o atributo KeyAttribute (namespace System.ComponentModel.DataAnnotations). Este Data Annotation deverá ser vinculado a propriedade que correspondam aos campos de chave-primária em uma tabela (que neste exemplo seria a propriedade Id); • A propriedade NomeOcupacao (linha 13).

38 .net Magazine • Edição 115

Listagem 5. Classe Ocupacao 01 using System; 02 using System.ComponentModel.DataAnnotations; 03 using System.ComponentModel.DataAnnotations.Schema; 04 05 namespace TesteCodeFirst.Entities 06 { 07 [Table(“TB_OCUPACAO”)] 08 public class Ocupacao 09 { 10 [Key] 11 public int? Id { get; set; } 12 13 public string NomeOcupacao { get; set; } 14 } 15 }

Nota Será necessário adicionar uma referência à biblioteca System.ComponentModel.DataAnnotations dentro do projeto TesteCodeFirst.Entities, possibilitando o uso de Data Annotations pelas classes que farão parte desta Class Library.

Já o código referente à classe ResumoDadosProfissional é apresentado na Listagem 6. Embora não possua uma relação direta com o modelo do Entity Framework a ser implementado na próxima seção, este tipo será empregado na exibição de informações relativas aos diferentes profissionais cadastrados na base de dados. Fazem parte da classe ResumoDadosProfissional os seguintes campos: • Id/Código do profissional (linha 7); • CPF (linha 8); • Nome do profissional (linha 9); • Descrição da ocupação (linha 10); • Valor recebido por hora (linha 11); • O valor mensal recebido por um profissional (linha 13) com base em uma média de 168 horas trabalhadas. Listagem 6. Classe ResumoDadosProfissional 01 using System; 02 03 namespace TesteCodeFirst.Entities 04 { 05 public class ResumoDadosProfissional 06 { 07 public int Id { get; set; } 08 public string CPF { get; set; } 09 public string NmProfissional { get; set; } 10 public string DsOcupacao { get; set; } 11 public decimal VlHora { get; set; } 12 13 public decimal VlBase168Horas 14 { 15 get 16 { 17 return VlHora * 168; 18 } 19 } 20 } 21 }

Na Listagem 7 está a definição da classe Profissional. Este tipo conta com dados pessoais de um consultor, sua ocupação, o valor recebido por hora trabalhada e informações para contato. A fim de possibilitar o mapeamento entre propriedades da classe Profissional e campos da tabela TB_PROFISSIONAL, foram realizados os seguintes: • O tipo Profissional foi marcado com atributo TableAttribute (linha 8), indicando a estrutura correspondente na base de testes; • À propriedade Id (linha 12) foi associado o atributo KeyAttribute, já que este elemento corresponde ao campo de chave-primária na tabela TB_PROFISSIONAL; • Já o Data Annotation ForeignKeyAttribute (namespace System .ComponentModel.DataAnnotations.Schema) está vinculado à propriedade CdOcupacao. Este atributo recebe como parâmetro o nome da propriedade que conterá dados de uma ocupação (o elemento Ocupacao, definido na linha 27), indicando assim que o campo CdOcupacao possui uma chave primária. Conforme pode observar, diversos outros tipos de Data Annotations foram associados às propriedades da classe Profissional. No caso das propriedades CPF (linha 16), NmProfissional (linha 20), CdOcupacao (linha 25), Email (linha 34), Telefone (linha 38) e VlHora (linha 47), nota-se que a declaração de cada um destes elementos está associada a um atributo RequiredAttribute (namespace System.ComponentModel.DataAnnotations). Ao efetuar este tipo de ajuste, o ASP.NET MVC irá considerar como obrigatório o preenchimento em tela de campos que foram marcados com o item RequiredAttribute, exibindo ainda uma mensagem (definida na propriedade ErrorMessage) se esta condição não for atendida.

Outro ponto a ser destacado é o uso do atributo DisplayNameAttribute (namespace System.ComponentModel). Além dos campos já mencionados, este tipo também foi vinculado à propriedade DsObservacao (linha 50). Quando empregado em conjunto com o framework MVC, a classe DisplayNameAttribute permite a geração automática de legendas para os diversos campos que farão parte de uma tela de inclusão ou exclusão de registros (valores informados como parâmetro no construtor de DisplayNameAttribute correspondem ao texto de tais legendas). A propriedade Email foi marcada também com o atributo RegularExpressionAttribute (namespace System.ComponentModel.DataAnnotations), com o intuito de verificar se um e-mail informado em tal campo é aceitável. Procurando determinar se o conteúdo de um campo é realmente válido, o tipo RegularExpressionAttribute faz uso de sequências padronizadas de texto conhecidas expressões regulares. No que se refere à propriedade VlHora, observa-se também a utilização do tipo RangeAttribute (namespace System.ComponentModel.DataAnnotations). Este tipo é empregado para definir os limites mínimo e máximo de um campo, apresentando ainda uma mensagem de erro caso os valores informados por um usuário não estejam em tal faixa. O atributo DataTypeAttribute (namespace System.ComponentModel.DataAnnotations) também foi associado à propriedade VlHora, indicando que este campo aceitará apenas valores monetários no seu preenchimento. Dentro de aplicações ASP.NET MVC, o tipo DataTypeAttribute costuma ser utilizado para validar o tipo de dado que poderá ser informado em um campo editável.

Listagem 7. Classe Profissional 01 using System; 02 using System.ComponentModel; 03 using System.ComponentModel.DataAnnotations; 04 using System.ComponentModel.DataAnnotations.Schema; 05 06 namespace TesteCodeFirst.Entities 07 { 08 [Table(“TB_PROFISSIONAL”)] 09 public class Profissional 10 { 11 [Key] 12 public int? Id { get; set; } 13 14 [Required(ErrorMessage = “Campo obrigatório.”)] 15 [DisplayName(“CPF”)] 16 public string CPF { get; set; } 17 18 [Required(ErrorMessage = “Campo obrigatório.”)] 19 [DisplayName(“Nome do Profissional”)] 20 public string NmProfissional { get; set; } 21 22 [Required(ErrorMessage = “Campo obrigatório.”)] 23 [ForeignKey(“Ocupacao”)] 24 [DisplayName(“Ocupação”)] 25 public int? CdOcupacao { get; set; } 26

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 } 52 }

public Ocupacao Ocupacao { get; set; } [Required(ErrorMessage = “Campo obrigatório.”)] [RegularExpression(@”^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*” + @”@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$”, ErrorMessage = “Formato de E-mail inválido.”)] [DisplayName(“E-mail para Contato”)] public string Email { get; set; } [Required(ErrorMessage = “Campo obrigatório.”)] [DisplayName(“Telefone para Contato”)] public string Telefone { get; set; } [Required(ErrorMessage = “Campo obrigatório.”)] [Range(10, 9999.99, ErrorMessage = “O Valor Hora deve estar entre “ + “10,00 e 9999,99.”)] [DataType(DataType.Currency, ErrorMessage = “Valor inválido.”)] [DisplayName(“Valor Hora”)] public decimal? VlHora { get; set; } [DisplayName(“Observação”)] public string DsObservacao { get; set; }

Edição 115 .net Magazine

39

Entity Framework Code First

Implementando as classes de acesso a dados TesteCodeFirst.DAL é um projeto do tipo Class Library no qual estão definidas as seguintes classes (o sufixo “DAO” é uma abreviação de “Data Access Object”, termo em inglês que designa uma classe empregada na geração de objetos de acesso a dados): • DefaultContext; • UnitOfWork; • OcupacaoDAO; • ProfissionalDAO. Nota O projeto TesteCodeFirst.DAL também irá utilizar o Entity Framework. Tal referência poderá ser adicionada por meio do utilitário NuGet.

O tipo DefaultContext (Listagem 8) deriva da classe DbContext, representando o modelo a partir do qual ocorrerá a interação entre a aplicação de exemplo e o banco de dados de testes. Foram definidas nesta estrutura duas propriedades que fazem uso no tipo genérico DbSet, servindo de base para a manipulação de entidades/registros: • Ocupacoes (linha 9): permite o acesso a dados do cadastro de ocupações disponíveis; • Profissionais (linha 10): utilizada na manipulação de registros envolvendo informações de profissionais vinculados à consultoria hipotética. Listagem 8. Classe DefaultContext 01 using System; 02 using System.Data.Entity; 03 using TesteCodeFirst.Entities; 04 05 namespace TesteCodeFirst.DAL.Base 06 { 07 public class DefaultContext : DbContext 08 { 09 public DbSet Ocupacoes { get; set; } 10 public DbSet Profissionais { get; set; } 11 } 12 }

Como aconteceu no caso do tipo TesteDbContext (descrito ainda na seção teórica), as propriedades declaradas em DefaultContext serão preenchidas automaticamente ao gerar uma nova instância desta classe. Além disso, o uso de Data Annotations na codificação das entidades fez com que não fosse mais necessário sobrecarregar o método OnModelCreating. Já a Listagem 9 apresenta o código que define a classe UnitOfWork. Este tipo implementa a interface IUnitOfWork (pertencente ao projeto TesteCodeFirst.DAL), sendo um objeto que centralizará todas as operações de acesso a dados provenientes da base de testes. Analisando a estrutura da classe UnitOfWork, é possível observar: • A existência da propriedade DefaultContext (linha 11), a qual representa o modelo do Entity Framework que possibilitará o acesso

40 .net Magazine • Edição 115

às informações da base de exemplo. A instância associada a esta propriedade é armazenada no atributo “_defaultContext”, com o preenchimento deste último acontecendo dentro do construtor da classe UnitOfWork (linha 21); • O método Commit (linha 24). Esta operação utiliza a instância vinculada à propriedade DefaultContext para acionar o método SaveChanges (implementado na classe básica DbContext), a fim de persistir/confirmar um conjunto de modificações no banco de teste; • O método Dispose (linha 29). Este método foi criado para implementar a interface IDisposable, tendo por função liberar recursos alocados pela referência associada à propriedade DefaultContext. Listagem 9. Classe UnitOfWork 01 using System; 02 using System.Data.Entity; 03 using TesteCodeFirst.Utils.ORM; 04 05 namespace TesteCodeFirst.DAL.Base 06 { 07 public class UnitOfWork : IUnitOfWork 08 { 09 private DbContext _defaultContext; 10 11 public DbContext DefaultContext 12 { 13 get 14 { 15 return _defaultContext; 16 } 17 } 18 19 public UnitOfWork() 20 { 21 this._defaultContext = new DefaultContext(); 22 } 23 24 public void Commit() 25 { 26 DefaultContext.SaveChanges(); 27 } 28 29 public void Dispose() 30 { 31 DefaultContext.Dispose(); 32 } 33 } 34 }

A definição do tipo OcupacaoDAO está na Listagem 10. Essa estrutura deriva da classe abstrata BaseRepository (criada através do projeto TesteCodeFirst.Utils.ORM), sendo que para o placeholder “” foi informado como parâmetro a entidade Ocupacao (de forma que instâncias de OcupacaoDAO sejam utilizadas exclusivamente na manipulação de objetos baseados neste tipo). Além dos métodos públicos herdados de BaseRepository, a classe OcupacaoDAO conta ainda com o método ListarOcupacoes (linha 11). Esta operação será utilizada para retornar informações

sobre ocupações profissionais possíveis dentro de uma consultoria de TI, funcionando da seguinte maneira: • Inicialmente é invocado o método GetQueryable (definido BaseRepository), a fim de obter um objeto que permita a execução de instruções que serão convertidas para comandos SQL; • Na sequência a operação OrderBy (disponibilizada pela extensão LINQ) é acionada, com o intuito de ordenar os dados de ocupações de acordo com as descrições destas; • Por fim, o método ToList é acionado, gerando uma coleção de objetos do tipo Ocupacao a ser devolvida como resultado da execução de ListarOcupacoes. Listagem 10. Classe OcupacaoDAO 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; 04 using TesteCodeFirst.Entities; 05 using TesteCodeFirst.Utils.ORM; 06 07 namespace TesteCodeFirst.DAL 08 { 09 public class OcupacaoDAO : BaseRepository 10 { 11 public List ListarOcupacoes() 12 { 13 List ocupacoes = 14 this.GetQueryable().OrderBy( 15 o => o.NomeOcupacao).ToList(); 16 return ocupacoes; 17 } 18 } 19 }

Quanto ao método CPFJaExistente, é possível observar o uso das operações GetQueryable e Where (da linha 30 em dia) para a obtenção de uma coleção em que constem dados de um CPF já em uso por outros registros. A partir disto, o método Count (linha 34) é acionado, com o retorno desta ação indicando se o CPF em questão já foi utilizado no cadastro de outro profissional. Nota O projeto TesteCodeFirst.DAL também irá utilizar o Entity Framework. Tal referência poderá ser adicionada por meio do utilitário NuGet.

Listagem 11. Classe ProfissionalDAO 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; 04 using TesteCodeFirst.Entities; 05 using TesteCodeFirst.Utils.ORM; 06 07 namespace TesteCodeFirst.DAL 08 { 09 public class ProfissionalDAO : BaseRepository 10 { 11 public List ListarResumoProfissionais() 12 { 13 List profissionais = 14 this.GetQueryable() 15 .OrderBy(p => p.NmProfissional) 16 .Select(p => new ResumoDadosProfissional() 17 { 18 Id = p.Id.Value, 19 CPF = p.CPF, 20 NmProfissional = p.NmProfissional, 21 DsOcupacao = p.Ocupacao.NomeOcupacao, 22 VlHora = p.VlHora.Value 23 }) 24 .ToList(); 25 return profissionais; 26 } 27 28 public bool CPFJaExistente(int id, string cpf ) 29 { 30 var profissionaisEncontrados = 31 this.GetQueryable() 32 .Where(p => p.Id != id && 33 p.CPF == cpf ); 34 return (profissionaisEncontrados.Count() > 0); 35 } 36 } 37 }

A classe ProfissionalDAO (Listagem 11) corresponde à última estrutura a ser implementada dentro do projeto TesteCodeFirst. DAL. Este tipo será utilizado na manipulação de informações envolvendo o cadastro de profissionais de tecnologia dentro da aplicação de exemplo. Além dos métodos herdados da classe BaseRepository, foram definidos ainda em ProfissionalDAO os seguintes métodos: • ListarResumoProfissionais (linha 11): esta operação possibilita a consulta a informações de consultores cadastrados no banco de testes; • CPFJaExistente (linha 28): este método tem por finalidade verificar se um CPF já foi cadastrado anteriormente na base de dados (recebendo como parâmetros o Id do registro manipulado naquele instante, além do CPF).

Implementando os objetos de negócio

Conforme é possível observar, o retorno da operação ListarResumoProfissionais será uma coleção de instâncias do tipo ResumoDadosProfissional. Isto acontecerá a partir de chamadas aos métodos GetQueryable (declarado em BaseRepository), OrderBy, Select (estes dois últimos são parte integrante da extensão LINQ) e, finalmente, ToList (esta última ação irá gerar uma lista genérica contendo referências baseadas na classe ResumoDadosProfissional).

Na Class Library TesteCodeFirst.BLL encontram-se classes que enviam chamadas à camada de acesso a dados (projeto TesteCodeFirst.DAL). Nessas estruturas também foram declaradas as regras de negócio da aplicação. Estão definidos em TesteCodeFirst.BLL os tipos OcupacaoBO e ProfissionalBO. Na Listagem 12 está a implementação do tipo OcupacaoBO. Analisando a estrutura desta classe, é possível observar a existência da operação ListarOcupacoes (linha 14). Acionando um método de mesmo nome a partir de uma instância da classe

Edição 115 .net Magazine

41

Entity Framework Code First

OcupacaoDAO vinculada à propriedade “DAO” (linha 16), esta operação devolverá como resultado uma coleção de objetos do tipo Ocupacao. Quanto à propriedade “DAO” (linha 12), nota-se que a mesma foi marcada com o atributo DependencyAttribute. Conforme já descrito anteriormente, esta indicação fará com que o mecanismo de injeção do Unity Application Block associe em tempo de execução uma instância do tipo OcupacaoDAO a esta propriedade. Nota Por fazer uso do Unit Application Block, uma referência para este pacote deverá ser adicionada ao projeto TesteCodeFirst.BLL via utilitário NuGet.

Listagem 12. Classe OcupacaoBO 01 using System; 02 using System.Collections.Generic; 03 using Microsoft.Practices.Unity; 04 using TesteCodeFirst.Entities; 05 using TesteCodeFirst.DAL; 06 07 namespace TesteCodeFirst.BLL 08 { 09 public class OcupacaoBO 10 { 11 [Dependency] 12 public OcupacaoDAO DAO { get; set; } 13 14 public List ListarOcupacoes() 15 { 16 return DAO.ListarOcupacoes(); 17 } 18 } 19 }

Já na Listagem 13 é apresentado o código que implementa a classe ProfissionalBO. Uma propriedade baseada no tipo ProfissionalDAO foi declarada na linha 12, sendo resolvida por meio de técnicas de injeção de dependências a partir Unit Application Block (já que foi também marcada com o atributo DependencyAttribute). Importante destacar que tal referência servirá de base para que os diferentes métodos de ProfissionalDAO (descritos a seguir) invoquem a camada de acesso a dados. O método ListarResumoProfissionais (linha 14) ao ser invocado acionará uma operação de mesmo nome na classe ProfissionalDAO, retornando como resultado de sua execução uma coleção de objetos do tipo ResumoDadosProfissional. A operação ObterDadosProfissional (linha 19) recebe como parâmetro o Id de um profissional, acionando a camada de acesso a dados a fim de obter os dados cadastrais do mesmo. Se o registro correspondente for encontrado, será retornada uma instância do tipo Profissional; do contrário, uma exceção será gerada informando que o Id em questão é inválido. O retorno do método ValidarDadosProfissional (linha 31) será um valor do tipo bool, o qual indica se os dados associados a uma instância da classe Profissional são válidos ou não; se

42 .net Magazine • Edição 115

este não for o caso, os parâmetros CampoInconsistente e DescricaoInconsistencia serão preenchidos com informações que identificam o campo e o problema detectado. A operação ValidarDadosProfissional verifica primeiramente se o CPF associado a uma instância do tipo Profissional é realmente válido, com isto acontecendo por meio do método ValidarCPF (linha 39). Além disso, é efetuada outra checagem (linha 46) via método CPFJaExistente (o qual pertence à classe ProfissionalDAO), com o objetivo de determinar se o CPF em questão já se encontra cadastrado na base (partindo da premissa que apenas novos CPFs poderão ser informados). As operações IncluirDadosProfissional (linha 59), AtualizarDadosProfissional (linha 66) e ExcluirProfissional (linha 73) serão responsáveis pela persistência dos dados modificados a partir da aplicação de testes. A confirmação das mudanças realizadas acontecerá acessando o objeto UnitOfWork da propriedade e invocando na sequência o método Commit (como indicado nas linhas 63, 70 e 78). Contando com um comportamento bastante similar, as operações IncluirDadosProfissional e AtualizarDadosProfissional fazem uso da instância vinculada à propriedade DAO, invocando através desta última os métodos Insert e Update para a inclusão e atualização de registros, respectivamente. Já a operação ExcluirProfissional será utilizada na remoção de dados de um profissional da base, acionando para isto os métodos FindByPrimaryKey (a fim de obter uma instância do tipo Profissional) e Delete por meio da instância do tipo ProfissionalDAO. Nota Para efeitos de simplificação, a implementação do método ValidarCPF foi omitida deste artigo. No link para download do material desta edição será possível obter o código-fonte completo para a solução de exemplo aqui apresentada.

Implementando a aplicação MVC O último passo para a implementação do exemplo proposto por este artigo será a criação do projeto TesteCodeFirst.MVC. Esta aplicação será do tipo “ASP.NET Web Application”, fazendo uso do framework ASP.NET MVC 5.1. Serão definidas no projeto TesteCodeFirst.MVC as seguintes estruturas: • A classe MVCxUnityDependencyResolver, utilizada para ativar o mecanismo de injeção de dependências do Unity Application Block em conjunto com o framework ASP.NET MVC 5.1; • Um primeiro Controller (HomeController) responsável pela exibição da tela inicial da aplicação, além de outras duas páginas em que constam os objetivos do sistema, além de informações para contato; • Um segundo Controller em que serão definidas as funcionalidades do cadastro de profissionais de tecnologia (ProfissionaisController); • Views associadas às diferentes Actions dos Controllers já citados.

Listagem 13. Classe ProfissionalBO 01 using System; 02 using System.Collections.Generic; 03 using Microsoft.Practices.Unity; 04 using TesteCodeFirst.Entities; 05 using TesteCodeFirst.DAL; 06 07 namespace TesteCodeFirst.BLL 08 { 09 public class ProfissionalBO 10 { 11 [Dependency] 12 public ProfissionalDAO DAO { get; set; } 13 14 public List ListarResumoProfissionais() 15 { 16 return DAO.ListarResumoProfissionais(); 17 } 18 19 public Profissional ObterDadosProfissional(int id) 20 { 21 Profissional profissional = 22 DAO.FindByPrimaryKey(id); 23 if (profissional == null) 24 { 25 throw new Exception( 26 “Foi informado um Id de Profissional inválido.”); 27 } 28 return profissional; 29 } 30 31 public bool ValidarDadosProfissional( 32 Profissional profissional, 33 out string CampoInconsistente, 34 out string DescricaoInconsistencia) 35 { 36 CampoInconsistente = null; 37 DescricaoInconsistencia = null; 38 39 if (!ValidarCPF(profissional.CPF)) 40 { 41 CampoInconsistente = “CPF”; 42 DescricaoInconsistencia = “CPF inválido.”; 43 return false;

Deverão ser adicionadas a esta aplicação MVC (via NuGet): • Referências que apontem para os assemblies do Entity Framework, Unity Application Block e Unity bootstrapper for ASP .NET MVC (conforme é possível observar na Figura 3); • As bibliotecas de scripts autoNumeric (para máscaras em campos monetários) e jQuery.MaskedInput (usada para máscaras de CPF, Telefone, dentre outros tipos de dados com uma formatação especial). Tais plugins fazem uso de recursos de jQuery/JavaScript. O projeto TesteCodeFirst.MVC também irá referenciar as Class Libraries implementadas nas seções anteriores. O próximo passo será alterar o arquivo Web.config (Listagem 14) da aplicação TesteCodeFirst.MVC, especificando no mesmo: • Uma referência ao Unity Application Block dentro do elemento “configSections” (linha 4), a fim de permitir do mecanismo de injeção de dependências disponibilizado por esta biblioteca;

44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 } 86 }

} if (DAO.CPFJaExistente(profissional.Id.HasValue ? profissional.Id.Value : 0, profissional.CPF)) { CampoInconsistente = “CPF”; DescricaoInconsistencia = “CPF já cadastrado anteriormente.”; return false; } return true; } public void IncluirDadosProfissional( Profissional profissional) { DAO.Insert(profissional); DAO.UnitOfWork.Commit(); } public void AtualizarDadosProfissional( Profissional profissional) { DAO.Update(profissional); DAO.UnitOfWork.Commit(); } public void ExcluirProfissional(int id) { Profissional profissional = DAO.FindByPrimaryKey(id); DAO.Delete(profissional); DAO.UnitOfWork.Commit(); } private bool ValidarCPF(string vrCPF) { ... }

• A string de conexão no elemento connectionStrings” (linha 12), a qual apontará para a base de testes utilizada pela aplicação MVC e possuindo o mesmo nome da classe de contexto empregada no acesso a este repositório (“DefaultContext”); • A cultura utilizada no Brasil, a fim de evitar problemas com formatação e conversão de datas e valores monetários. Forma preenchidos para isto os atributos “culture” e “uiCulture” do elemento “globalization” com o valor “pt-BR” (linha 23); • Uma seção iniciada pelos elementos unity e container (linhas 28 e 29), em que estão indicadas as classes e interfaces a serem resolvidas pelo Unity Application Block em tempo de execução (através do uso do elemento “register”, além dos atributos “type” e “mapTo”). Importante destacar no mapeamento da interface IUnitOfWork a existência de uma declaração em que se faz uso do elemento “register” (linha 36); o tipo especificado dentro desta construção (PerRequestLifetimeManager, pertencente ao namespace Microsoft.Practices.Unity da extensão “Unity bootstrapper

Edição 115 .net Magazine

43

Entity Framework Code First

for ASP.NET MVC”) fará com o Unity Application Block gere uma única referência de classe que implementa IUnitOfWork durante a validade de uma requisição HTTP. A implementação da classe MVCxUnityDependencyResolver é demonstrada na Listagem 15. Este tipo implementa a interface IDependencyResolver (namespace System.Web.Mvc), sendo esta última utilizada pelo ASP.NET MVC para integrar uma aplicação a um framework de injeção de dependências. Analisando a forma como este tipo foi estruturado, é possível observar: • Um construtor (linha 12) que espera como parâmetro uma instância do tipo IUnityContainer (namespace Microsoft.Practices. Unity), com este objeto sendo utilizado posteriormente para resolver dependências durante a execução de uma aplicação baseada no ASP.NET MVC (a partir da instância armazenada na referência “_container”); • A operação GetService (linha 18) será utilizada pelo framework MVC para resolver uma dependência relacionada a um determino tipo. Esta operação irá retornar o valor “null” caso uma classe ou interface não esteja registrada (cabendo ao desenvolvedor gerar a instância correspondente nos pontos em que a mesma for necessária); caso o tipo em questão tenha sido registrado (o que é verificado na linha 20, ao invocar o método IsRegistered por meio da instância do tipo IUnityContainer), o método Resolve será acionado através da referência “_container”; Nota O código referente às Views da aplicação de testes também foi omitido, já que não constam nestas 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 no site da revista o link contendo o material deste artigo. Este mesmo procedimento também foi adotado com a classe HomeController.

Figura 3. Configurando as dependências do projeto TesteCodeFirst.MVC

44 .net Magazine • Edição 115

Listagem 14. Arquivo Web.config do projeto TesteCodeFirst.MVC 01 02 03 04 05 06 ... 07 08 09 ... 10 11 12 15 16 17 ... 18 19 20 21 ... 22 23 24 25 26 ... 27 28 29 30 31 32 33 34 36 37 38 39 40 41 ... 42 43

• O método GetServices (linha 30), o qual permite resolver múltiplas dependências para um mesmo tipo, contando com um comportamento bastante similar àquele apresentado pela operação GetService. Listagem 15. Classe MVCxUnityDependencyResolver 01 using System; 02 using System.Collections.Generic; 03 using System.Web.Mvc; 04 using Microsoft.Practices.Unity; 05 06 namespace TesteCodeFirst.MVC 07 { 08 public class MVCxUnityDependencyResolver : IDependencyResolver 09 { 10 private IUnityContainer _container; 11 12 public MVCxUnityDependencyResolver( 13 IUnityContainer container) 14 { 15 this._container = container; 16 } 17 18 public object GetService(Type serviceType) 19 { 20 if (!_container.IsRegistered(serviceType)) 21 { 22 if (serviceType.IsAbstract || serviceType.IsInterface) 23 { 24 return null; 25 } 26 } 27 return _container.Resolve(serviceType); 28 } 29 30 public IEnumerable GetServices(Type serviceType) 31 { 32 return _container.ResolveAll(serviceType); 33 } 34 } 35 }

Modificações também serão necessárias no arquivo Global .asax (Listagem 16), a fim de tornar possível o funcionamento do Unity Application Block em conjunto com a aplicação TesteCodeFirst.MVC: • Uma nova instância da classe UnityContainer (namespace Microsoft.Practices.Unity) deverá ser gerada (linha 20). Partindo desta referência, acionar então o método LoadConfiguration (linha 21) com o intuito de carregar as configurações com mapeamentos de tipos que foram declaradas no arquivo Web.config. A operação LoadConfiguration definida dentro do namespace Microsoft .Practices.Unity.Configuration; • Também será necessário gerar uma instância da classe MVCx UnityDependencyResolver (com o construtor recebendo como parâmetro a referência do tipo UnityContainer), para posterior registro deste objeto através de uma chamada ao método estático SetResolver (linha 22). Esta última operação é parte integrante da classe DependencyResolver (esta última estrutura encontra-se localizada namespace System.Web.Mvc).

Listagem 16. Ajustes a serem realizados no arquivo Global.asax 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; 04 using System.Web; 05 using System.Web.Mvc; 06 using System.Web.Optimization; 07 using System.Web.Routing; 08 using Microsoft.Practices.Unity; 09 using Microsoft.Practices.Unity.Configuration; 10 11 namespace TesteCodeFirst.MVC 12 { 13 public class MvcApplication : System.Web.HttpApplication 14 { 15 protected void Application_Start() 16 { 17 18 ... 19 20 UnityContainer container = new UnityContainer(); 21 container.LoadConfiguration(); 22 DependencyResolver.SetResolver( 23 new MVCxUnityDependencyResolver(container)); 24 } 25 } 26 }

A estrutura do Controller ProfissionaisController é apresentada na Listagem 17. Os métodos declarados neste tipo correspondem às diferentes Actions utilizadas no cadastro de profissionais. Estas operações foram marcadas com os atributos HttpGetAttribute e HttpPostAttribute, os quais determinam o tipo de requisição HTTP processada por uma Action (GET ou POST, respectivamente). O uso do atributo HttpGetAttribute é opcional (quando nenhum atributo estiver vinculado a uma Action, o framework MVC assumirá que a mesma deverá tratar requisições do tipo GET). As Actions responsáveis operações inclusão, alteração e/ou exclusão são implementadas por meio de dois métodos de mesmo nome. O primeiro equivale a uma requisição do tipo GET, tendo por função gerar a View para a montagem da página em que serão digitadas/exibidas informações. O segundo é do tipo POST, recebendo como parâmetro uma instância da classe que estará sendo manipulada (o tipo Profissional, no caso específico desta aplicação de exemplo). Importante destacar ainda que a classe ProfissionaisController também fará uso do mecanismo de injeção de dependências do Unity Application Block. Para isto, as propriedades Profissional_BO (linha 15) e Ocupacao_BO (linha 18) foram marcadas com o atributo DependencyAttribute. Estas referências serão utilizadas nas diferentes Actions que fazem parte do Controller ProfissionaisController, conforme será descrito mais adiante. A Action Index (Listagem 18) exibirá os consultores já cadastrados. Através de uma chamada ao método ListarResumoProfissionais (linha 4) no objeto associado à propriedade Profissional_BO, será retornada uma coleção de objetos do tipo ResumoDadosProfissional; tais referências serão então repassadas ao método View, gerando assim o resultado da Action Index no formato HTML.

Edição 115 .net Magazine

45

Entity Framework Code First

Listagem 17. Estrutura do Controller ProfissionaisController 01 using System; 02 using System.Collections.Generic; 03 using System.Linq; 04 using System.Web; 05 using System.Web.Mvc; 06 using Microsoft.Practices.Unity; 07 using TesteCodeFirst.BLL; 08 using TesteCodeFirst.Entities; 09 10 namespace TesteCodeFirst.MVC.Controllers 11 { 12 public class ProfissionaisController : Controller 13 { 14 [Dependency] 15 public ProfissionalBO Profissional_BO { get; set; } 16 17 [Dependency] 18 public OcupacaoBO Ocupacao_BO { get; set; } 19 20 [HttpGet] 21 public ActionResult Index() 22 { 23 ... 24 } 25 26 private ActionResult ProcessarGravacaoDadosProfissional( 27 Profissional profissional, bool inclusao) 28 { 29 ... 30 } 31 32 [HttpGet] 33 public ActionResult Inserir() 34 {

Listagem 18. Action Index (Controller ProfissionaisController) 01 [HttpGet] 02 public ActionResult Index() 03 { 04 return View(Profissional_BO.ListarResumoProfissionais()); 05 }

Para a Action Inserir (Listagem 19), responsável pela inclusão de um novo profissional na base de dados, é possível observar que foram definidas três operações. Um primeiro método chamado ProcessarGravacaoDadosProfissional (linha 1) tratará solicitações do tipo POST, recebendo como parâmetro uma instância do tipo Profissional com as informações relativas a um consultor, além de um flag que indica se acontecerá a inclusão ou alteração de um registro no banco de exemplo. Esta operação faz uso do método ValidarDadosProfissional definido na classe ProfissionalBO (linha 8); caso existam inconsistências nos dados a serem gravados na base, o método AddError é acionado a partir propriedade ModelState (linha 12), com o objetivo de gerar uma mensagem que descreva o problema que deverá ser corrigido. Outras inconsistências geradas a partir dos atributos vinculados às propriedades da classe Profissional também poderão ser

46 .net Magazine • Edição 115

35 36 37 38 39 40 41 42 43 44 45 46 47 48 48 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 } 68 }

... } [HttpPost] public ActionResult Inserir(Profissional profissional) { ... } [HttpGet] public ActionResult Editar(int id) { ... } [HttpPost] public ActionResult Editar(Profissional profissional) { ... } [HttpGet] public ActionResult Excluir(int id) { ... } [HttpPost] public ActionResult Excluir(Profissional profissional) { ... }

detectadas. Independente de onde tenham sido geradas mensagens descrevendo falhas durante uma tentativa de cadastro ou atualização, a propriedade IsValid (pertencente ao objeto ModelState) assumirá o valor “false”. Em tais situações o objeto ViewBag (BOX 3) será utilizado, associando-se ao mesmo dados relativos às ocupações disponíveis: estas informações servirão de base para a exibição das opções disponíveis em um controle do tipo DropDown. O método View é então acionado (linha 19), de forma que não prossiga com a gravação daquele registro. Se nenhum problema for diagnosticado com as informações preenchidas por um usuário, a propriedade Profissional_BO é utilizada novamente. Para inclusões, será acionada a operação IncluirDadosProfissional (linha 23); já na alteração de um registro invoca-se o método AtualizarDadosProfissional (linha 25). O método Inserir (linha 30) cuidará de requisições do tipo GET, preenchendo para isto a propriedade ViewBag com informações de ocupações possíveis (linha 40), além de uma instância sem informações da classe Profissional (linha 41). A finalidade destas ações é gerar um formulário para cadastro de profissionais, utilizando para isto o método View (linha 41). Já a segunda versão do método Inserir (linha 45) recebe como parâmetro uma instância da classe Profissional, acionando o método ProcessarGravacaoDadosProfissional (linha 47) para proceder com a inclusão das informações na base de dados.

Listagem 19. Método ProcessarGravacaoDadosProfissional e Action Inserir (Controller ProfissionaisController) 01 private ActionResult ProcessarGravacaoDadosProfissional( 02 Profissional profissional, bool inclusao) 03 { 04 string CampoInconsistente = null; 05 string DescricaoInconsistencia = null; 06 07 if (ModelState.IsValid && !Profissional_BO 08 .ValidarDadosProfissional(profissional, 09 out CampoInconsistente, 10 out DescricaoInconsistencia)) 11 { 12 ModelState.AddModelError(CampoInconsistente, 13 DescricaoInconsistencia); 14 } 15 16 if (!ModelState.IsValid) 17 { 18 ViewBag.Ocupacoes = Ocupacao_BO.ListarOcupacoes(); 19 return View(profissional); 20 } 21 22 if (inclusao) 23 Profissional_BO.IncluirDadosProfissional(profissional); 24 else 25 Profissional_BO.AtualizarDadosProfissional(profissional); 26 return RedirectToAction(“Index”); 27 } 28 29 [HttpGet] 30 public ActionResult Inserir() 31 { 32 var ocupacoes = Ocupacao_BO 33 .ListarOcupacoes().ToList(); 34 ocupacoes.Insert(0, 35 new Ocupacao() 36 { 37 Id = null, 38 NomeOcupacao = “Selecione uma Ocupação...” 39 }); 40 ViewBag.Ocupacoes = ocupacoes; 41 return View(new Profissional()); 42 } 43 44 [HttpPost] 45 public ActionResult Inserir(Profissional profissional) 46 { 47 return ProcessarGravacaoDadosProfissional( 48 profissional, true); 49 }

BOX 3. A propriedade ViewBag ViewBag é uma propriedade definida no tipo básico ControllerBase e que faz uso do recurso conhecido como Dynamics. Graças a esta característica é possível definir atributos a um objeto para utilização posterior, descartando com isto a necessidade de declarar um novo tipo para cumprir tal objetivo.

Na Listagem 20 está a implementação da Action Editar, a qual será formada por dois métodos: • O primeiro dos métodos (linha 2) está associado a requisições do tipo GET. Esta operação faz uso das instâncias vinculadas às propriedades Profissional_BO e Ocupacao_BO, invocando os métodos ObterDadosProfissional (linha 5) e ListarOcupacoes

(linha 6) a fim de retornar as informações para a alteração em tela do cadastro de um profissional contratado pela consultoria; • A segunda versão do método Editar (linha 11) aciona a operação ProcessarGravacaoDadosProfissional, sendo que a partir disto acontecerá a atualização dos dados relativos a um consultor (desde que não existam inconsistências nas informações preenchidas por um usuário). Listagem 20. Action Editar (Controller ProfissionaisController) 01 [HttpGet] 02 public ActionResult Editar(int id) 03 { 04 Profissional profissional = 05 Profissional_BO.ObterDadosProfissional(id); 06 ViewBag.Ocupacoes = Ocupacao_BO.ListarOcupacoes(); 07 return View(profissional); 08 } 09 10 [HttpPost] 11 public ActionResult Editar(Profissional profissional) 12 { 13 return ProcessarGravacaoDadosProfissional( 14 profissional, false); 15 }

Por fim, a Action Excluir (Listagem 21) estará encarregada da remoção do cadastro de um consultor da base de dados. Uma primeira implementação do método Excluir (linha 2) será utilizada para a exibição de informações sobre um profissional, solicitando ao usuário se o mesmo deseja realmente excluir o registro correspondente. Já a segunda versão da operação Excluir (linha 10) removerá da base de dados um determinado consultor. Em ambos os métodos que compõem a Action Excluir foram utilizadas operações definidas na classe ProfissionalBO. Listagem 21. Action Excluir (Controller ProfissionaisController) 01 [HttpGet] 02 public ActionResult Excluir(int id) 03 { 04 Profissional profissional = 05 Profissional_BO.ObterDadosProfissional(id); 06 return View(profissional); 07 } 08 09 [HttpPost] 10 public ActionResult Excluir(Profissional profissional) 11 { 12 Profissional_BO.ExcluirProfissional( 13 profissional.Id.Value); 14 return RedirectToAction(“Index”); 15 }

Teste da aplicação MVC criada Na Figura 4 é apresentada a tela inicial da aplicação TesteCodeFirst.MVC. Ao clicar no link para acesso ao cadastro (Figura 5), serão listados todos os consultores já registrados na base de dados, bem como

Edição 115 .net Magazine

47

Entity Framework Code First

Figura 4. Tela inicial da aplicação TesteCodeFirst.MVC

Figura 5. Consulta a Profissionais de TI

Figura 6. Inclusão de um novo Profissional

48 .net Magazine • Edição 115

disponibilizadas opções para a inclusão de um novo profissional, a alteração ou ainda a exclusão de dados pré-existentes. Quando for acionada a funcionalidade para inclusão de um novo profissional, será exibida ao usuário uma tela similar à apresentada na Figura 6. Já a Figura 7 corresponde ao procedimento de editar os dados de um consultor já cadastrado anteriormente. Finalmente, ao solicitar a exclusão do cadastro de um profissional, será mostrada ao usuário uma tela similar à da Figura 8. Frameworks ORM representam uma importante ferramenta para um desenvolvimento mais produtivo em aplicações que dependam de bancos de dados relacionais. Encapsulando rotinas para a execução de operações de consulta, inclusão, alteração e exclusão de informações a partir do uso de estruturas típicas da Orientação a Objetos, estes mecanismos procuram descomplicar o trabalho de codificação de funcionalidades CRUD. Os fornecedores deste tipo de recurso procuram incorporar padrões e práticas de uso consagrado em seus frameworks, buscando com isto fornecer um meio mais simplificado e seguro para a interação com bases relacionais.

O Entity Framework corresponde à solução ORM da Microsoft para a construção de aplicações voltadas à plataforma .NET. esta ferramenta permite desde a geração de um modelo com as classes que representam entidades de negócio a partir de uma ferramenta gráfica, passando ainda pela utilização de tipos com uma estrutura simples e totalmente baseados em código .NET. Esta última abordagem é conhecida como Code First e foi demonstrada ao longo deste artigo, possuindo como grande vantagem a possibilidade de reuso de classes já definidas anteriormente. Qualquer que seja o modo de trabalho escolhido (Model First, Database First, Code First), todas estas alternativas suportam os mesmos recursos, fato esse que contribui para que o Entity Framework se adapte mais facilmente a qualquer tipo de projeto. Conforme apresentado na solução de exemplo, o Entity Framework Code First pode inclusive ser utilizado na criação de um mecanismo genérico que suporte operações de CRUD. Combinado recursos como Generics e funcionalidades que permitem inferir a estrutura de uma base a partir de informações de metadata (como relacionamentos entre diferentes entidades), o modo Code First mostra com isto uma grande flexibilidade. Assim, é possível concluir que esta abordagem é capaz de atender, sem maiores percalços, às demandas de desenvolvedores preocupados com a obtenção de um código mais enxuto e que dispense o uso de arquivos .edmx.

Figura 7. Alteração de dados de um Profissional

Figura 8. Exclusão de um Profissional

Autor

Links:

Renato José Groffe [email protected] - http://www.devmedia.com.br/ renatogroffe Atua como consultor em atividades voltadas ao desenvolvimento de softwares há mais de 10 anos. Bacharel em Sistemas de Informação, com especialização em Engenharia de Software. Microsoft Certified Technology Specialist (Web, WCF, Distributed Applications, ADO.NET, Windows Forms), Microsoft Specialist (HTML5 with JavaScript and CSS3, Developing ASP.NET MVC 4 Web Applications), Oracle Certified Associate (PL/SQL), Sun Certified (SCJP, SCWCD), ITIL Foundation V2, Cobit 4.1 Foundation.

Configuring/Mapping Properties and Types with the Fluent API http://msdn.microsoft.com/en-us/data/jj591617.aspx

Você gostou deste artigo?

Unity 3 – April 2013 http://msdn.microsoft.com/en-us/library/dn170416.aspx Entity Framework Overview http://msdn.microsoft.com/en-us/library/bb399567(v=vs.110).aspx Entity Framework Code First Conventions http://msdn.microsoft.com/en-us/data/jj679962.aspx Unit of Work http://martinfowler.com/eaaCatalog/unitOfWork.html

Dê seu voto em www.devmedia.com.br/netmagazine/feedback Ajude-nos a manter a qualidade da revista!

Edição 115 .net Magazine

49

Google Maps: obtendo chaves de acesso com ASP.NET

Google Maps: obtendo chaves de acesso com ASP.NET Conheça as funções mais avançadas da API web do Google Maps e aprenda a utilizar as principais APIs relacionadas a este serviço

A

tualmente, aplicações web que utilizam, de alguma forma, mapas, estão na moda. Seja para simples amostragem, utilizando mapas estáticos ou para criar controles interativos, onde o usuário pode escolher como navegar através do controle, a opção fica por conta do desenvolvedor. As principais aplicações desse tipo de serviço na web é para localização de lugares ou amostragem de outros. Tudo depende da aplicação para a qual estamos desenvolvendo um site. O Google Maps é o principal serviço desse tipo no mercado. O Bing Maps, da Microsoft, vem crescendo, principalmente com o advento do Windows 8 e o crescimento do Windows Phone, mas ainda não está no mesmo patamar que a solução do Google. Muito disso se dá pela quantidade de serviços que o Google oferece que são diretamente relacionados à soluções de mapas. Além da API do Google Maps em si, que é oferecida para iOS, Android e Web, o Google oferece uma série de outros serviços que serão cobertos em detalhes por esse artigo, desde localização até serviços de direções e distâncias entre dois lugares. Além disso, com a utilização do serviço de Geocoding, fica muito mais fácil se localizar dentro de um determinado espaço. O objetivo desse artigo é a criação de um website ASP .NET com a utilização de controles de mapa do Google, bem como a utilização de alguns dos serviços que o mesmo disponibiliza. Através desse artigo, será possível entender como e porque customizar os mapas, além lidar com os serviços, entre os quais a API de lugares do Google (Google Places API), que contém mais de 95

50 .net Magazine • Edição 115

Fique por dentro O Google Maps é, hoje em dia, a principal solução para aplicações, web ou não, que lidam com mapas. O presente artigo busca apresentar a API web do Google Maps, juntamente com os vários Web Services que o Google fornece para criar grandes experiências para os usuários. Esse artigo traz ideias sobre customização dos mapas do Google, bem como Geocoding, distâncias e direções entre lugares, além de mapas estáticos em aplicações web.

milhões de locais de interesse ao redor do mundo, segundo dados do próprio Google.

Google Maps O Google Maps é, como já foi comentado, o principal serviço online de localização e mapas, apesar do crescimento do Bing Maps. O serviço contém inúmeras funções para o usuários, entre as quais as mais comuns é a localização, além de outras como direções e distâncias entre lugares. Além disso, o serviço também contém informações de tráfego em determinadas vias, avisando o usuário que o tempo de deslocamento entre dois lugares pode alterar dependendo da hora do dia e do dia em si. Outros serviços oferecidos incluem o tempo de deslocamento entre lugares utilizando alguns diferentes meios de transporte, como carros, transporte público ou as próprias pernas. Umas das principais adições ao serviço nos últimos anos foi o Street View. Esse serviço mostra para o usuário exatamente como é o endereço que ele deseja, baseado em uma visão da rua como se o usuário estivesse passeando pela calçada. As fotos não são atualizadas muito constantemente, e a maioria delas data de 2011.

Porém, como dificilmente uma rua vai mudar tanto assim em poucos anos, trata-se de uma boa opção para visitantes, que tem a oportunidade de “conhecer” os lugares antes mesmo de chegarem lá. Entretanto, embora o site do Google Maps seja muito utilizado, a maior parte dos usuários, principalmente com o aumento no número de smartphones, utiliza a versão móvel do Google Maps. Trata-se de uma aplicação disponível gratuitamente para smartphones, e se trata da aplicação móvel mais utilizada no mundo, segundo dados de agosto de 2013. Essa aplicação está disponível desde 2005, e teve inúmeras atualizações e melhorias desde então. O Google Maps não se destaca apenas pelas aplicações que o Google disponibiliza para os usuários comuns, como também pelas APIs que permitem que desenvolvedores reutilizem esses serviços dentro de suas aplicações. Como o Google Maps é codificado em JavaScript e XML, a criação das APIs é na realidade muito simples. O Google disponibiliza a API Web do Google Maps desde 2005, quando o serviço era totalmente gratuito. Hoje em dia, para um determinado número de acessos, o serviço ainda é gratuito. Porém, passando desse número de acessos, o serviço é pago. Isso significa que os desenvolvedores precisam ter uma noção do número de acessos que o seu website terá, para que o serviço não seja interrompido na metade do dia, por exemplo. Uma das grandes vantagens da API do Google Maps é o fato de ser baseada em JavaScript, o que significa que pode ser visualizada em qualquer navegador do mercado. Além disso, pode ser utilizada com qualquer linguagem de programação. A utilização da API com ASP.NET é muito simples, é apenas o acréscimo de alguns scripts ao código da aplicação web e o mapa será mostrado. Apesar dessa facilidade, a customização dos mapas, bem como a utilização de algumas APIs de localização, direções, entre outras, requerem um pouco mais de trabalho. A API JavaScript do Google Maps contém alguns detalhes importantes que podem ser levados em consideração pelos desenvolvedores, conforme mostra a Tabela 1. As classes que podemos utilizar em nossas aplicações web são divididas em categorias, de acordo com o que elas representam. Repare que a categoria Overlays, por exemplo, contém várias classes que são responsáveis por marcações nos mapas que estamos criando. Outras classes que utilizaremos nesse artigo são as classes da categoria Services, que contém classes de Geocoding, direções, detalhes de trânsito, entre outras. Repare também que o Street View possui uma categoria de classes separadas, bem como a API do Google Places. É importante notar que a utilização da Google Maps API está restrita a um determinado website através de uma chave de acesso. Essa chave é obtida através da conta Google do desenvolvedor e fornece uma chave de acesso única. É possível utilizar a mesma chave para vários websites, embora isso não seja recomendado, devido ao fato do controle de utilização. Se você possuir vários sites utilizando a mesma chave, isso significa que o número de acessos será dividido entre esses sites, o que não é desejável em nenhuma aplicação. Outra importante vantagem que o Google Maps oferece é a possibilidade de utilização de mapas estáticos.

Em algumas aplicações, é imprescindível a utilização de mapas estáticos, devido ao fato de eles serem muito mais leves em termos de carregamento. Para sites que não necessitem de mapas dinâmicos, onde não é necessário que o usuário tenha liberdade de buscar alguns detalhes no mapa, os mapas estáticos aparecem como uma alternativa interessante que deve ser levada em consideração. A API dos mapas estáticos é diferente da API dos mapas dinâmicos, e, como tal, necessita de uma nova chave de acesso, específica para esse serviço. Essa API está na versão 2, e permite que você coloque em sua página web uma imagem estática do Google Maps sem necessidade de JavaScript ou carregamento dinâmico de página, aumentando muito a velocidade de carregamento. Categoria (namespace) Descrição Map

Classes principais, responsáveis pela amostragem do mapa propriamente dito.

Controls

Definição dos controles dentro do mapa, como zoom e escala.

Overlays

Marcadores de lugares específicos no mapa.

Services

Serviços como Geocoding, direções e distâncias.

Map Types

Tipos de mapas (satélite, trânsito, etc.)

Layers

Camadas de visualização do mapa (tempo, trânsito, etc.)

Street View

Detalhes do serviço de Street View do Google Maps.

Events

Eventos que envolvem o mapa.

Weather Library

Detalhes meteorológicos no mapa.

Places Library

Biblioteca que contém classes da API do Google Places, com recursos como função autocomplete e buscas.

Outras

Classes de visualização do mapa, de definição de latitude e longitude, anúncios, entre outras não tão importantes dentro desse artigo.

Tabela 1. Categorias das classes na API JavaScript do Google Maps

Web Services da API Google Maps Todos os serviços de mapas precisam de serviços auxiliares que forneçam um maior nível de detalhe em termos de relacionamento com o usuário. O Google Maps não é diferente. Esse serviço utiliza uma série de serviços, Web Services (BOX 1), que funcionam de modo a adicionar aos mapas a possibilidade de localização, distâncias entre lugares, entre outros pontos importantes. O Google fornece seis APIs principais que são, na realidade, Web Services, responsáveis por criar uma interface com os serviços de dados geográficos dentro da aplicação que utiliza o Google Maps. Esses serviços não funcionam com off-line, o que não é um problema em aplicações ASP.NET, embora possa ser em aplicações móveis. Conforme foi comentado, os Web Services que o Google fornece para criar uma experiência superior para seus usuários são 6: • Directions API: É um serviço que calcula direções entre dois pontos do mapa através de uma requisição HTTP. Embora o Google faça parecer simples, trata-se de um tema bastante complexo, que envolve busca em grafos, sempre buscando a melhor direção. Além disso, podem ser utilizados dados de tráfego, o que complica ainda mais a busca pelas direções.

Edição 115 .net Magazine

51

Google Maps: obtendo chaves de acesso com ASP.NET

BOX 1. Web Services Web Services, atualmente, permeiam grande parte do que acontece em aplicações que utilizam a internet em qualquer forma. Trata-se de um serviço que, como o nome sugere, estabelece uma comunicação entre dois dispositivos através de uma rede, não necessariamente a internet. No caso dos Web Services que utilizaremos nesse artigo, eles nada mais são do que uma coleção de interfaces HTTP que fornecem dados geográficos para o controle do Google Maps que utilizamos em nossa aplicação.

• Distance Matrix API: É um serviço similar ao primeiro, embora não estabelece detalhes da rota entre a origem e o destino. Ele utiliza uma matriz de destinos, criando uma rota recomendada entre esses pontos, passando pelos demais pontos. • Elevation API: Retorna informações a respeito dos aspectos físicos do mapa, como depressões, planaltos e montanhas. Normalmente, é utilizado em simuladores de construção civil, e pode auxiliar muito também em outras áreas, como agricultura. • Geocoding API: É um serviço que converte endereços em coordenadas geográficas, ou vice-versa (Reverse Geocoding). Como veremos na sequência do artigo, esses valores podem ser utilizados para marcar pontos dentro do mapa. • Time Zone API: Fornece informações sobre o fuso horário em um determinado ponto (latitude, longitude). Retorna o nome do fuso, diferença para o fuso horário 0 (UTC), bem como diferenças durante o “horário de verão” naquele fuso, ou Daylight Savings. • Places API: A API do Google Places possui várias funções muito interessantes. Além dos mais de 95 milhões de lugares que ela traz ao redor do mundo, esse serviço também permite buscas por lugares, bem como eventos que podem ser tratados no determinado local. Esses eventos podem ser utilizados para criar uma caixa de comentários, por exemplo, dentro da aplicação, atrelada ao determinado local. Todos esses serviços fornecidos pelo Google podem ser acessados de forma segura via SSL (BOX 2). Além disso, todos eles necessitam de uma chave de acesso, que irá controlar o acesso a cada um dos serviços, de acordo com a licença que foi acordada. Assim como o Google Maps propriamente dito, cada serviço possui um número bem limitado de acessos com uma licença gratuita, e esse número é multiplicado com as chamadas licenças de negócios. BOX 2. SSL SSL ou Secure Sockets Layer é uma coleção de protocolos criados com a função específica de garantir segurança nas comunicações via internet. São protocolos criptografados, que servem para estabelecer a comunicação entre dois dispositivos através de chaves de comunicação. Além disso, esses protocolos também estabelecem códigos de autenticação de mensagem, para garantir a integridade dos dados que estão sendo transmitidos.

As respostas de todos esses serviços precisam ser lidas apropriadamente pela aplicação. Como podem haver diferentes respostas para diferentes buscas (devido a erros ou mesmo serviços diferentes), a aplicação precisa processar a resposta primeiramente,

52 .net Magazine • Edição 115

para então selecionar os valores apropriados via expressões. O valor retornado pode estar em XML ou JSON. Normalmente, com a API web do Google Maps, utilizaremos o retorno em JSON, que é muito mais facilmente processado via JavaScript.

Obtendo e organizando as chaves de acesso Antes de começarmos a discutir os detalhes da adição do controle de mapa à nossa aplicação, vamos criar uma aplicação web ASP .NET simples. O objetivo não é dar detalhes de como criar web sites com ASP.NET nesse artigo, então iremos criar uma simples aplicação web, um projeto praticamente pronto onde iremos fazer algumas alterações pontuais. Além, é claro, da adição dos mapas e serviços a ele relacionados. Conforme discutimos, praticamente todos os serviços do Google relacionados ao Google Maps tem seu acesso controlado por uma chave. Grande parte deles possui diferenças na obtenção dessa chave, bem como diferentes formas de uso, gratuitas ou pagas. A obtenção dessas chaves é, na realidade, bastante simples. A grande questão é como organizar essas muitas chaves de acesso dentro de nossa aplicação ASP.NET. Isso se dá pelo fato de estarmos lidando com várias chaves, e não é muito interessante colocarmos todas no código-fonte, para facilitar a reutilização das mesmas. Porém, antes de organizarmos as chaves, precisamos obtê-las. O Google fornece o chamado APIs Console, onde o desenvolvedor, através de sua conta do Google, possui acesso a todos os serviços fornecidos por eles (seção Links). Utilizando esse console, o desenvolvedor tem acesso a informações sobre os serviços do Google, ativos ou não. Essa informações incluem, além da obtenção das chaves de acesso, dados sobre pagamentos, utilização dos serviços, sem contar relatórios e outros dados importantes, como mostra a Figura 1. Atualmente, o Google está testando uma nova versão do Console, mais avançada e com uma configuração um pouco diferente da demonstrada na figura, embora todos os serviços ainda estejam presentes. Como podemos notar, o serviço do Google Maps já está ativo. A API Google Maps JavaScript v3 é a que utilizaremos nesse artigo. Como não se trata de uma aplicação web comercial, ou seja, nada que será utilizado constantemente, podemos utilizar a mesma chave de acesso sem problema nenhum. Vale ressaltar que cada chave de acesso está atrelada a uma conta do Google, e cada conta pode possuir várias chaves de acesso. Primeiramente, vamos analisar a chave de acesso principal, para a API do Google Maps em si. Todas as informações a respeito dessa chave estão na aba API Access, que controla o acesso das chaves específicas a cada uma das APIs. Como podemos observar na Figura 2, a chave de acesso não é restrita a apenas um domínio, o que significa que podemos utilizar essa chave para qualquer tipo de site que desejarmos. Em uma aplicação real, logicamente, queremos que a chave esteja atrelada a apenas nossa aplicação web. É interessante termos uma chave geral para utilizarmos em testes, e quando o site estiver pronto para o público, obter uma nova chave de acesso, atrelada ao domínio que estamos utilizando.

Agora que a chave de acesso para a API principal já está definida, precisamos obter as demais chaves de acesso. Utilizaremos vários serviços do Google ao longo do artigo, e precisamos de chave para todos eles. Todos os serviços usados estão presentes na aba Services no Console. Então, basta ativarmos os serviços que desejamos e a chave de acesso estará disponível na aba API Access. Os serviços que iremos ativar são: • Geocoding API: para geocodificação; • Distance Matrix API: distância e tempo de deslocamento entre lugares; • Directions API: direções entre lugares; • Static Maps API: mapas estáticos.

Figura 1. APIs Console

A obtenção da chave de acesso não é tão simples assim. É interessante ressaltar que cada um dos serviços utiliza Figura 2. Chave de acesso da API do Google Maps um tipo de chave de acesso, e o Google possui apenas quatro tipos: chave para aplicações em browser, para aplicações em servidor, para apli A criação de arquivos de recursos é facilitada pelo Visual Studio cações Android e iOS. O serviço de Geocoding, assim como os sobremaneira. Porém, é preciso ter noção de alguns conceitos. serviços de distância e direções entre lugares, utiliza a chave para Os arquivos de recursos dentro de uma aplicação ASP.NET podem aplicações em servidor (Key for server apps), enquanto o serviço ser locais ou globais, sendo que os locais são acessados apenas de mapas estáticos utiliza a chave para aplicações em browser. de uma determinada página e os globais, obviamente, por toda a Com isso, é possível notarmos que uma chave de acesso funciona aplicação. Os recursos locais estão localizados em qualquer nível para vários serviços, e cada um desses serviços está vinculado a dentro da aplicação, normalmente em um diretório chamado essa chave. App_LocalResources. A utilização do diretório não é obrigatória, embora altamente recomendada. O mesmo é válido para os recursos globais e seu diretório, App_GlobalResources. Esse diretório Nota se encontra na raiz do projeto. Assim como a chave de acesso para aplicações em browser, a chave de servidor também permite a O arquivo de recursos que vamos criar para esse exemplo será vinculação a um determinado domínio. Essa vinculação é realizada através de endereços IP, nesse global. Não há necessidade de criarmos também o diretório, mas caso. Porém, utilizaremos uma chave que permite qualquer IP, nesse caso, pelos motivos já discutidos. ele será criado para uma melhor organização do projeto. NormalAs chaves para Android e iOS são únicas para cada aplicação, utilizando certificados para garantir mente, é interessante criarmos a pasta quando temos mais de um essa unicidade. arquivo de recursos, como em casos que vamos criar um site para várias linguagens. A criação do arquivo é bastante simples, basta Agora que temos as chaves de acesso, precisamos salvá-las em que adicionemos um novo item ao projeto, do tipo “Resources algum lugar. Conforme comentado anteriormente, a utilização de File”, e posicioná-lo dentro do diretório criado. Aqui, iremos um arquivo de recursos é muito importante para a qualidade do adicionar as duas chaves de acesso, de browser e de servidor, que código que se está produzindo. Vamos assumir que a aplicação serão utilizadas pelos serviços do Google Maps. Os nomes dos web que estamos criando possui vários mapas, com diferentes recursos são Server_Key e Browser_Key. funções. Porém, todos eles irão utilizar a mesma chave de acesso básica. Caso seja necessária, futuramente, uma alteração na chave Criando e customizando um controle de mapa de acesso do mapa, será necessário alterar em todos eles. Com Para trabalhar com o controle de mapas do Google Maps é a utilização de um arquivo de recursos, isso não é necessário. bastante simples. Hoje em dia, todos os desenvolvedores web Todos os mapas irão acessar o mesmo recurso, e caso necessário, tem que ter algum tipo de familiaridade com JavaScript, prinbasta alterar diretamente nesse arquivo. Isso é muito importante cipalmente para criação de conteúdos dinâmicos. Como a API também em situações normais de trabalho no dia a dia, onde do Google Maps é totalmente baseada nessa linguagem, iremos utilizamos uma chave geral para testes e outra quando o site está trabalhar basicamente com scripts para criar e customizar um pronto e irá para a rede. controle de mapa.

Edição 115 .net Magazine

53

Google Maps: obtendo chaves de acesso com ASP.NET

Primeiramente, precisamos entender a API que estamos trabalhando. O mapa, dentro da API v3, é a classe google.maps.Map. Essa classe é responsável pela criação de um novo mapa dentro de um container HTML. Essa classe possui alguns métodos interessantes que iremos abordar a seguir, mas inicialmente vamos nos ater ao construtor dessa classe, que utilizaremos inicialmente. Essa classe possui um construtor, que recebe como parâmetros o container HTML que irá receber o mapa, bem como as opções desse mapa. Essas opções é que irão definir o nível de customização que será apresentado no nosso controle, bem como o local inicial, por exemplo. A assinatura do construtor da classe Map é Map(mapDiv:node, opts?:MapOptions). A classe MapOptions fornece várias opções de customização, desde botões de zoom até controles de rotação, entre outros elementos importantes para que o usuário possa lidar com o mapa. Abaixo, os mais importantes: • center: obrigatória, informa ao mapa o local central do mesmo. • rotateControl, panControl, scaleControl, overviewMapControl, zoomControl etc.: desabilita/habilita esses controles no mapa. Além disso, todos os controles opções que podem ser definidas, como a posição, na maioria dos casos. Essas opções são controladas por outras classes, como RotateControlOptions. Agora que temos uma ideia um pouco mais clara das possibilidades, é possível criarmos o nosso controle customizado. Primeiramente, precisamos definir uma div onde o mapa será posicionado dentro de nossa página. Iremos posicionar o mapa na página inicial de nossa aplicação, no div de id “localmapa”. Uma vez que temos a posição de nosso mapa, precisamos customizá-lo e iniciá-lo. Para começarmos, vamos carregar a API do Google Maps em nossa aplicação ASP.NET. Para tanto, chamamos um script remoto utilizando a chave de acesso que adquirimos anteriormente. Essa chamada possui, além da chave de acesso, outro parâmetro obrigatório: sensor. Esse parâmetro irá informar ao mapa se o GPS do dispositivo está habilitado para o site. Vamos definir essa propriedade como true, inicialmente, pois ela será importante mais para a frente. Como notamos na Listagem 1, a utilização de arquivos de recursos cria uma diferença nessa chamada. Normalmente, estaríamos utilizando uma simples URL com a chave passada diretamente como parâmetro. Nesse caso, estamos utilizando a função GetGlobalResourceObject (nomeDicionario, nomeChave) para acessarmos a chave de acesso e adicioná-la à URL. Caso estivéssemos utilizando um recurso local, a função seria GetLocalResourceObject(). Com a API já carregada, precisamos definir as opções e posicionar o mapa dentro de nosso site. Para isso, um script bastante simples, também mostrado na Listagem 1, faz o trabalho. É interessante notar que apenas duas opções são obrigatórias: center e zoom, que diz quantas vezes o zoom será aplicado ao mapa inicialmente. Repare que carregaremos um mapa aproximado oito vezes no meio do oceano Atlântico, que é onde ficam as coordenadas (0,0). Porém, como podemos notar, tal atitude não faz nada em nossa aplicação. Isso acontece porque precisamos rodar essa função em

54 .net Magazine • Edição 115

algum momento durante o carregamento de nosso site. Para isso, como estamos utilizando o conceito de Master Pages, podemos utilizar um método fictício no corpo de nossa página mestre e implementar esse método na página local. Esse método fictício será chamado no evento onload da Master Page. Essa atitude nos permite alguma liberdade futura, caso desejemos carregar outras coisas durante a inicialização da página. Como podemos ver na Listagem 2, o método está implementado de forma bastante simples, apenas realizando a chamada para o método GetMap() definido na Listagem 1. Listagem 1. Carregando o mapa inicial function GetMap() { var opt = { center: new google.maps.LatLng(0, 0), zoom: 8 }; var map = new google.maps.Map(document.getElementById(“localmapa”), opt); } Listagem 2. Definindo método Funcao() function Funcao() { GetMap(); }

Com isso, temos um mapa funcionando em nossa aplicação. Repare que seu ponto inicial é totalmente azul, representado o Oceano Atlântico. Porém, é possível mexermos nele como quisermos, navegando pelo mapa. Uma vez que o mapa em si já está pronto, vamos analisar as funções de customização do mesmo. O mapa possui, por padrão, controle de zoom, Street View, rotação e tipo de mapa, com posições definidas. Podemos adicionar outros tipos de controle, bem como retirar alguns deles se não servirem para nossos propósitos. Além disso, é possível modificarmos a posição de grande parte desses controles, através da opção position, disponível em quase todos eles. Inicialmente, vamos desabilitar o street view. Trata-se de uma operação muito cara em termos de processamento e não necessária nesse momento em nossa aplicação. Duas propriedades interessantes que podem ser utilizadas são max e minZoom. Elas definem um limite inferior e superior para o usuário aproximar ou afastar a visão dentro do mapa. Essas opções podem ser úteis em aplicações mais amplas, que irão perder muito em nível de detalhes caso estejam muito aproximadas ou afastadas. Nesse exemplo, vamos definir um máximo de zoom de 12. Como notamos na Listagem 3, a definição dos controles é um tanto simples.

O desenvolvedor possui muita liberdade no que fazer com os controles, se retirá-los do mapa ou posicioná-los em qualquer local dentro do mesmo. Porém, é preciso estar atento para utilizar o caminho completo da API, para evitar problemas. Podemos ver na Figura 3 o resultado de nossa customização. Listagem 3. Customização do controle de mapa var opt = { center: new google.maps.LatLng(0, 0), zoom: 8, maxZoom: 12, zoomControl: true, zoomControlOptions: { position: google.maps.ControlPosition.BOTTOM_LEFT, style: google.maps.ZoomControlStyle.SMALL }, mapTypeControl: true, mapTypeControlOptions: { position: google.maps.ControlPosition. TOP_CENTER, style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR }, panControl: true, panControlOptions: { position: google.maps.ControlPosition.TOP_LEFT }, streetViewControl: false };

Figura 3. Mapa Customizado

Trabalhando com Geocoding uando trabalhamos com Geocoding, o grande objetivo é que Q possamos fornecer um endereço e receber as coordenadas geográficas relativas a ele ou vice-versa. Quando trabalhamos com mapas, esse processo é necessário pois não podemos, por exemplo, marcar pontos no mapa utilizando o endereço do mesmo: para isso, precisamos das coordenadas geográficas do mesmo. A API do Google Maps possui uma classe para esse tipo de processo, permitindo que o desenvolvedor realize essas transformações baseado na entrada de dados que o usuário fornece. O Geocoding no Google Maps funciona através de uma chamada externa, o que significa que o serviço precisa ser assíncrono de modo a não travar o mapa durante uma chamada. Além disso, é preciso que tratemos o resultado que a chamada nos oferece para

que possamos utilizá-lo. A classe que trabalharemos é a google. maps.Geocoder, utilizando um método específico, geocode() para iniciar o serviço. Esse método recebe um GeocodeRequest com alguns campos que iremos discutir a seguir. Primeiramente, vamos preparar o terreno para trabalharmos com o serviço. Como esperaremos uma entrada de usuário, vamos criar uma caixa de texto onde o mesmo pode escrever o endereço desejado. Além disso, precisamos também de um controle Button para chamarmos o serviço quando acabarmos de escrever o endereço. Para adicionar esses dois controles, é bastante simples com ASP .NET. O código para esses elementos de UI está na Listagem 4.

Listagem 4. Elementos de UI

Agora que a interface de usuário já está definida, precisamos trabalhar no método GoAddress(), que irá realizar a operação de Geocoding. Primeiramente, vamos entender o método geocode(). Esse método recebe dois argumentos: um objeto GeocodeRequest, que contém quatro possíveis campos: address (o endereço, string), location (coordenadas geográficas, LatLng (para Geocoding reverso)), bounds (limites para as coordenadas, LatLngBounds) e region (código da região de busca, string); e um método que será executado quando do recebimento da chamada. O objeto precisa ter ou um campo address ou um campo location, dependendo da operação em questão, sendo que os demais campos são opcionais. Já o método é normalmente utilizado para lidar com os resultados, bem como verificar se a chamada funcionou corretamente. Para nosso exemplo, vamos definir uma requisição com dois parâmetros: o endereço, obtido através da caixa de texto que foi adicionada anteriormente, e a região, Brasil. É importante definirmos a região porque, do contrário, o foco da pesquisa será a região padrão, os Estados Unidos. Isso pode gerar problemas em endereços iguais, nos levando para um local que não é o que procuramos. Isso está demonstrado na Listagem 5. Listagem 5. Objeto GeocodeRequest { ‘address’: document.getElementById(“txtEndereco”).value, ‘region’: “br” }

Quanto a função que será chamada ao recebimento da resposta, precisamos entender o formato dessa resposta. O serviço de Geocoding do Google Maps fornece respostas com uma forma bastante específica, e precisamos lidar com esses resultados de forma a obter os dados que desejamos. Esses dados são representados na forma de um objeto GeocoderResults e é formatado como mostra a Figura 4.

Edição 115 .net Magazine

55

Google Maps: obtendo chaves de acesso com ASP.NET

Repare que o dado que estamos interessantes nesse momento é o campo location, que contém as coordenadas geográficas do endereço que foi passado. Além desses resultados, a requisição também retorna um código de status, do tipo GeocoderStatus, e pode retornar vários valores, sendo OK para o caso em que a requisição foi completada com sucesso.

Listagem 6. Função para lidar com os resultados do Geocoding Listagem 6. Função para lidar com os resultados do Geocoding function (results, status) { if (status == google.maps.GeocoderStatus.OK) { map.setCenter(results[0].geometry.location); } else alert(“Erro: “ + status); } Listagem 7. Geocoding Reverso function GoLatLng() { geocoder.geocode( { ‘location’: new google.maps.LatLng(document. getElementById(“txtEndereco”).value) }, function (results, status) { if (status == google.maps.GeocoderStatus.OK) { document.getElementById(“txtEndereco”). value = results[0].format­ted_address; } else alert(“Erro: “ + status); }); }

Figura 4. Formato das respostas do serviço de Geocoding Cada requisição normalmente irá retornar mais de um valor, em que o primeiro deles é o mais provável representante do endereço requisitado. Isso significa que, para acessar esse valor, iremos utilizar o índice 0 do array de resultados. O objetivo aqui é colocarmos o endereço que estamos obtendo no centro do mapa. Para isso, precisamos definir o mapa como variável global dentro do script, e não apenas dentro do método GetMap(), como anteriormente. Feito isso, podemos utilizar esse objeto mapa e trabalhar com ele como quisermos. Para colocarmos o endereço requisitado em evidência, vamos utilizar o método map.setCenter(), que recebe como parâmetro as coordenadas geográficas do ponto que desejamos colocar no centro do mapa. Esse ponto é o campo location do resultado que obtemos. Além disso, também é importante que lidemos com problemas, para casos em que o usuário digite dados inconsistentes e a pesquisa não retorne resultados, por exemplo. Para isso, podemos utilizar o código de status que é retornado. Tudo isso é mostrado na Listagem 6. Podemos ver a busca para a cidade de Santa Maria, RS na Figura 5. Para realizarmos o Geocoding reverso, precisamos de algumas modificações no script. Primeiramente, vamos definir um novo botão, “Vai Inverso!”, que irá chamar o método GoLatLng(). Esse método irá realizar o Geocoding reverso, a partir das coordenadas geográficas que iremos passar pela caixa de texto. Dessa vez, iremos escrever esse endereço na caixa de texto. No caso do geocoding reverso, não é necessário definirmos a região, uma vez que estamos lidando com valores de coordenadas absolutos. Temos um código como o mostrado na Listagem 7, que realiza essa função. Assim, podemos descobrir o endereço mais próximo de uma coordenada geográfica qualquer.

56 .net Magazine • Edição 115

Figura 5. Busca com sucesso para Santa Maria, RS

Distâncias e direções com o Google Maps Os serviços que cuidam dos cálculos de direções e distâncias são diferentes no Google Maps. Eles podem ser utilizados juntos, obviamente, mas é preciso levar em consideração que isso irá gerar uma sobrecarga de requisições que pode deixar a conexão mais lenta. Hoje em dia isso acaba não sendo um problema na maioria das conexões à internet. As requisições de direções são muito similares ao que vimos em termos de Geocoding. Esse cálculo é realizado através de um objeto DirectionsService, que irá se comunicar com o serviço apropriado através do método route(), que irá receber um objeto DirectionsRequest e um método que será executado quando a resposta chegar.

Embora a ideia seja a mesma, o objeto DirectionsRequest é bem diferente do que vimos do GeocoderResults. Ele possui uma série de campos que podem ser utilizados, sendo que os principais, obviamente, são a origem e o destino (origin e destination). Esses campos podem ser strings, que serão traduzidas em endereços e posteriormente em coordenadas geográficas, ou as próprias coordenadas. Outras opções, como travelMode e transitOptions também podem ser utilizadas para criar uma experiência mais elaborada. Além disso, através do campo waypoints[], é possível definir algumas direções que terão que ser cruzadas entre origem e destino. A forma de amostragem dos resultados depende do desenvolvedor. O Google fornece a classe DirectionsRenderer, que permite que você simplesmente mostre os resultados diretamente no mapa. Porém, há a liberdade de fazer o que quiser com esses resultados, permitindo que uma experiência customizada seja preparada para os usuários. Neste exemplo, iremos utilizar a classe DirectionsRenderer. Para realizarmos essa tarefa, vamos criar mais duas caixas de texto e um botão. As caixas de texto irão representar a origem e o destino, e o botão irá calcular a direção entre os dois pontos quando for clicado. Tal ação é bastante simples, e irá chamar o método CalculaDirecao(). Esse método é responsável por obter os valores das caixas de texto e transmiti-los via requisição. A função que será chamada quando da resposta à chamada irá simples setar as direções obtidas no mapa. Porém, para que isso funcione, o mapa precisa estar vinculado ao objeto DirectionsRenderer (dirRenderer), o que foi incluído no método GetMap(), que é o método inicial em nosso projeto. Como podemos ver na Listagem 8, a função está retornando os caminhos entre dois locais por carro. O carro foi escolhido (TravelMode.DRIVING) por ser o método mais comum de viagem, uma vez que o serviço do Google não fornece uma cobertura tão boa para transporte público. Como podemos notar na Figura 6, a rota entre Santa Maria e Porto Alegre, no Rio Grande do Sul, e bastante simples. Outra vantagem interessante desse serviço é as dicas, tal como no site do Google Maps. Como vire à esquerda na rua tal, atravesse a avenida tal, entre outras. Isso pode ser ativado através da função setPanel() do objeto DirectionsRenderer(). Além disso, o serviço fornece várias oportunidades, dependendo apenas da criatividade do desenvolvedor. É possível, por exemplo, utilizar um comboBox para escolher o modo de viagem entre as opções dadas, bem como outras opções disponíveis no mundo real. O serviço é bastante completo e permite muita liberdade aos desenvolvedores que assim desejarem. Por sua vez, o serviço de matriz de distâncias trabalha de forma muito parecida com o de direções. A diferença é que ele lida com uma matriz de origens e destinos, e calcula a distância entre cada par origem/destino para um determinado meio de transporte. Vale ressaltar, porém, que o serviço não aponta os lugares por onde o usuário deve ir para ter aquela distância. Por isso, o ideal é utilizar o serviço de distâncias juntamente com o serviço de direções, sempre buscando criar a melhor experiência possível para o usuário.

Figura 6. Rota entre Santa Maria e Porto Alegre Listagem 8. Método CalculaDirecao() function CalculaDirecao() { var origem = document.getElementById(“txtOrigem”).value; var destino = document.getElementById(“txtDestino”).value; var request = { origin: origem, destination: destino, travelMode: google.maps.TravelMode.DRIVING, region: “br” }; directions.route(request, function (response, status) { if (status == google.maps.DirectionsStatus.OK) { dirRenderer.setDirections(response); } else alert(“Erro: “ + status); }); }

O funcionamento desse serviço é muito parecido com o de direções, tendo inclusive os mesmos campos de requisição e a função de call-back. A diferença é que, ao invés de apenas uma origem e um destino, do tipo string ou LatLng, agora temos duas matrizes de valores que criarão distâncias entre duplas de lugares. Vale ressaltar que os valores não precisam ser do mesmo tipo, o que significa que podemos ter um local representado por um endereço, por exemplo, e outro pelas coordenadas geográficas. Para realizarmos esse exemplo, vamos acrescentar mais um botão à nossa UI, novamente com uma chamada de função no evento click. O método irá utilizar as duas caixas de texto utilizadas para as direções, bem como alguns valores fixos. A utilização de valores fixos é uma ideia interessante para um site comercial, por exemplo, onde os usuários podem querer saber as distâncias de suas casas até a loja física mais próxima.

Edição 115 .net Magazine

57

Google Maps: obtendo chaves de acesso com ASP.NET

Os resultados (distância e tempo) irão ser mostrados abaixo do mapa e dos controles que vimos até agora. Quanto aos resultados da chamada, para podermos trabalhar com eles, precisamos primeiro entende-los. A resposta que o serviço de Distance Matrix retorna contém os endereços de origem (origin_adresses), sempre uma string com o endereço real (mesmo que o usuário tenha passado as coordenadas), os endereços de destino (destination_adresses) e os resultados. Os resultados estão colocados em sequência em um array (rows) que contém elements. Cada elemento dentro da matriz de linhas corresponde a uma linha de resultados. A primeira linha contém as distâncias da primeira origem a todos os destinos e assim sucessivamente. Cada elemento salva o status da chamada, bem como a duração da “viagem” e a distância. Essa complexidade nos resultados torna o acesso aos itens um pouco mais complexo, embora o desenvolvedor só precise entender o formato dos dados para poder trata-los corretamente. O código utilizado para a matriz de distâncias está mostrado na Listagem 9. Repare estamos utilizando dois destinos e três origens, o que irá criar, obviamente, uma matriz de resultados 3 por 2. É importante notar que estamos passando na requisição o sistema de unidades que desejamos, o sistema métrico. Trata-se do padrão, porém preferi colocá-lo explicitamente para deixar mais claro essa parte. O outro sistema é o sistema imperial, que mostraria os resultados em milhas e pés. Quanto a função de retorno, estamos lendo os endereços de destino e origem que o resultado nos trouxe. É muito melhor lermos diretamente do resultado porque o serviço ajusta essas strings, além de transformar latitudes e longitudes em endereços escritos. Por fim, esses resultados estão sendo expostos em um div chamada results. Repare que a variável aux contém os elementos em cada linha que estamos acessando, e, para obtermos as distâncias e durações das viagens precisamos acessar o campo text de cada um dos elementos. A Figura 7 mostra o resultado no site.

Figura 7. Matriz de distâncias em ação

Mapas estáticos A utilização de mapas estáticos pode ser uma vantagem para sites que não precisem fornecer um controle dinâmico para seus usuários. A grande vantagem nesse caso é que o controle não precisa carregar scripts para sua execução, o que sempre atrasa o carregamento da página. A página fica mais leve e simples. Tudo o que precisamos fazer aqui é criar uma URL, adicionando parâmetros para a criação do mapa que desejarmos e colocá-lo dentro de uma tag . A API de mapas estáticos do Google é recomendada também para aplicações móveis, e não apenas sites.

58 .net Magazine • Edição 115

Nota Repare que os resultados do serviço de matriz de distâncias não estão diretamente vinculados ao mapa em si. Isso significa que eles podem ser utilizados sem que o mapa esteja carregado. Porém, a API precisa estar presente dentro da aplicação web para esse serviço funcionar.

Listagem 9. Método CalculaDistancias() function CalculaDistancias() { var results = document.getElementById(“resultDiv”); results.innerHTML = ‘Resultados: ’; var origem1 = document.getElementById(“txtOrigem”).value; var destino1 = document.getElementById(“txtDestino”).value; var service = new google.maps.DistanceMatrixService(); service.getDistanceMatrix( { origins: [origem1, ‘Brasilia, DF’, ‘Campo Grande, MS’], destinations: [destino1, ‘Rio de Janeiro, RJ’], travelMode: google.maps.TravelMode.DRIVING, unitSystem: google.maps.UnitSystem.METRIC }, function (response, status) { if (status == google.maps.DistanceMatrixStatus.OK) { var origens = response.originAddresses; var destinos = response.destinationAddresses; for (var i = 0; i < origens.length; i++) { var aux = response.rows[i].elements; for (var j = 0; j < aux.length; j++) { results.innerHTML += origens[i]; results.innerHTML += ‘ a ‘; results.innerHTML += destinos[j]; results.innerHTML += ‘ = ‘; results.innerHTML += aux[j].distance.text; results.innerHTML += ‘ em ‘; results.innerHTML += aux[j].duration.text; results.innerHTML += ‘’; } } } else { alert(“Erro: “ + status); } }); }

O grande foco dessa API são os parâmetros que iremos utilizar. Esses parâmetros vão dizer tudo para o serviço buscar a imagem estática que desejamos. Esses parâmetros contêm os que já vimos, key e sensor, também presentes na versão dinâmica da API, e mais uma série de outros, entre os quais: • center: define o centro do mapa, podendo ser representado por coordenadas geográficas ou um endereço. • zoom: nível de zoom aplicado. • size: tamanho do mapa. • markers: posiciona (ou não) marcadores na imagem. • path: cria um caminho dentro da imagem através de dois ou mais pontos. O serviço traz vários outros parâmetros que não são tão importantes quanto esses quatro. Em nosso exemplo, vamos criar uma imagem estática de um mapa com um marcador no Parque Farroupilha, em Porto Alegre. Repare na Listagem 10 a URL que foi criada. Trata-se de uma imagem dentro de um div com a fonte da imagem sendo essa

URL que irá retornar o mapa estático que desejamos. O centro do mapa está setado como “Parque Farroupilha ou A Redenção”, exatamente como expressado no Google Maps. Utilizar o nome exatamente como o Google o expressa é importante para garantir que não haverá erros. Outro meio é utilizar as coordenadas geográficas do local. Utilizaremos um zoom de 15 e um mapa do tipo satélite, como mostra a listagem. Listagem 10. Mapa estático sobre a Redenção

Outro detalhe importante diz respeito aos marcadores e ao caminho que criamos. Estamos posicionando um marcador exatamente sobre a Redenção e outro sobre um hotel nas proximidades. Iremos criar um caminho entre os dois locais, bem como marcá-los em nosso mapa estático. Pode ser um recurso que o site do próprio hotel utilize, uma vez que a proximidade a locais turísticos é um dos grandes atrativos em qualquer hotel. Além disso, fornecer caminhos para os principais pontos é uma obrigação da rede hoteleira, principalmente com a Copa do Mundo. O hotel está representado pelo marcador em cor azul e o parque pelo marcador em cor verde. Os marcadores podem apresentar rótulos (label, H e P, no caso). É possível utilizarmos ícones customizados para apresentar em nossos mapas estáticos, bem como estilizarmos os ícones padrão do Google. Por fim, a Listagem 10 também apresenta o parâmetro path, que cria um caminho entre os dois ícones que foram posicionados. Repare que, ao utilizarmos apenas dois pontos para o caminho, criamos uma linha reta entre os dois. Caso quiséssemos algo para acompanhar a rua, precisaríamos de mais pontos, para que o traçado seja mais realista. O formato do parâmetro path é o seguinte: path=estilos|ponto1|ponto2|...|pontoN. O estilos irão definir detalhes como cor e largura da linha que estamos traçando. A Figura 8 mostra o mapa finalizado. Através desse artigo foi possível apresentarmos o Google Maps e seus principais serviços de mapas. É interessante ressaltarmos que existem outros tantos, e que esses serviços apresentados ainda possuem muitos outros detalhes que podem ser explorados a fundo para criar as melhores experiências possíveis para o usuário. O Google criou esses vários serviços e cabe a nós explorá-los ao máximo para criar as melhores aplicações possíveis. Um serviço que é muito interessante e não foi apresentado nesse artigo é a API do Google Places. Conforme foi comentado brevemente no artigo, trata-se de uma API que possui cerca de 95 milhões de lugares ao redor do mundo. Em sites turísticos esse,

Figura 8. Mapa estático final sem sombra de dúvidas, é um acréscimo muito grande. Além disso, a API é, também, muito simples de trabalhar. Por fim, vale ressaltar que, durante esse artigo, apenas arranhamos a superfície. Todos os serviços do Google e a própria API JavaScript v3 do Google Maps possuem muito mais que podemos explorar. Por exemplo, marcadores nos mapas é um assunto que tem muito a render, pois além de marcar um lugar eles lidam com eventos, como o clique do mouse. Isso pode ajudar a criar experiências interessantes no futuro. Com a utilização de todos esses serviços, percebemos que o céu é o limite.

Autor Henrique Machado Gasparotto [email protected] Estudante de Engenharia de Computação na Universidade Federal de Santa Maria – UFSM e Técnico em Informática pelo SENAC Santa Maria. Experiência em programação C# .NET e Java, além de aplicações mobile e computação de alto desempenho. Atualmente, é bolsista do Programa Ciência sem Fronteiras, sendo aluno de Engenharia de Computação na Concordia University, em Montreal, Canadá. Links: Google Maps http://maps.google.com Bing Maps http://www.bing.com/maps/ APIs Console https://code.google.com/apis/console/

Você gostou deste artigo? Dê seu voto em www.devmedia.com.br/netmagazine/feedback Ajude-nos a manter a qualidade da revista!

Edição 115 .net Magazine

59

Integração Contínua em .NET – Parte 1

Integração Contínua em .NET – Parte 1 Automatizando a construção, documentação e entrega de seus sistemas Este artigo faz parte de um curso

Fique por dentro A Integração Contínua (CI) deixa o desenvolvedor livre para se pre-

U

ma das chaves para a melhoria da produtividade e, consequentemente das aplicações entregues, é a automatização da parte repetitiva do trabalho e a Integração Contínua é uma das melhores formas de se fazer isso. Não podemos crer que o processo de Integração Contínua seja a solução para todos os males, mas onde ela tem sido implementada tem-se tido grande sucesso com melhorias no processo de software para as equipes de desenvolvimento. A Integração Contínua, também conhecida como CI - Continuous Integration - é o ponto central do desenvolvimento de software atualmente. De fato, quando a CI é introduzida em uma empresa, torna-se o grande divisor de águas, pois ela altera radicalmente a forma como as equipes pensam sobre todo o processo de desenvolvimento. A CI tem o potencial de executar uma série de melhorias contínuas e incrementais nos processos, indo de um processo de simples agendamento de construção (build) até o processo de entrega contínua que culmina no processo de publicação nos demais ambientes para teste, homologação ou produção. Uma boa infraestrutura que possibilita a Integração Contínua pode simplificar o processo de desenvolvimento até a entrega do software ou de sua iteração, auxiliando a identificação e correção de falhas rapidamente, afinal de contas, precisa integrar toda a equipe e precisa armazenar todas as versões do software.Também facilita a disponibilização de uma dashboard muito útil no Projeto, tanto para desenvolvedores quanto para equipes, por agregar mais valores ao negócio e ao produto. Todo time de desenvolvimento, não importando se grande ou pequeno, deve implementar e pensar como Integração Contínua.

60 .net Magazine • Edição 115

ocupar com o que realmente importa: criar e desenvolver software. Não importa o tamanho do projeto, seja ele um pequeno sistema de cadastro de contatos ou um sistema especialista para simulações do clima terrestre ou da expansão do Universo: suas tarefas básicas consistem em compilar, testar, documentar, verificar qualidade e consistência do código e finalmente informar sobre erros. Nessa primeira parte do curso veremos uma introdução aos passos que a empresa precisa dar para implementar a CI em sua rotina de desenvolvimento.

O que é a Integração Contínua? Logo que uma alteração no código é identificada, o servidor automaticamente compila e testa o código de sua aplicação. Se algo dá errado, a ferramenta imediatamente notifica os desenvolvedores para que eles possam corrigir o problema imediatamente. Mas, a integração contínua pode fazer muito mais do que isso. A visibilidade das métricas de qualidade de código faz com que a equipe se preocupe mais com o desenvolvimento, pois o principal fundamento da Integração Contínua é facilitar a manutenção do código. Combinando testes de aceitação, a CI pode também funcionar como uma ferramenta de comunicação, mostrando um completo resumo do estado atual do projeto em andamento, dentro e fora da equipe. Pode simplificar e acelerar a entrega, auxiliando a automação do processo, deixando a publicação da última versão da aplicação totalmente automática ou permitindo a operação com apenas um aperto de botão. Em sua essência, a Integração Contínua age sempre na redução de riscos à aplicação e seu desenvolvimento nos dá uma resposta rápida. O uso da Entrega Contínua está ligado diretamente a Integração Contínua, pois o passo de compilação e testes é tarefa da Integração Contínua, enquanto que o Deploy da aplicação já fica sob o domínio da Entrega Contínua. Formalmente, a entrega contínua é definida como “um conjunto de práticas e princípios com

o objetivo de compilar, testar e liberar software de forma mais rápida e frequente”. Observe que a definição em si não menciona programas específicos, mas sim uma filosofia a ser seguida. O processo de Integração Contínua, e em particular a Entrega Contínua, é muito mais do que entregar produtos para os usuários de forma rápida. A CI ajuda a mensurar o tempo gasto por seu time em pequenas alterações de códigos antes de ir para produção. Podemos mensurar o custo do processo de solução em problemas legados que ofendem há muito tempo a equipe gerando grandes demandas de falha. Corrigir erros durante a compilação se torna uma prioridade e evita que o processo de desenvolvimento pare. Uma das definições de Integração Contínua reza que um processo automatizado deve construir, testar, analisar (Build) e implementar uma aplicação para garantir que o processo funcione (Deploy) corretamente seguindo as melhores práticas e as tornem entregáveis (Cobertura de Código). Este processo é executado em cada mudança de código fonte e permite resposta imediata para a equipe de desenvolvimento.

Processos de Desenvolvimento para Integração Contínua Seu processo de desenvolvimento é ágil? Em sua equipe é utilizada Extremme Programming - XP, Scrum ou algum outro? Sua companhia é profundamente enraizada em usar o método Cascata? Seu processo está em algum lugar entre Ágil e Cascata? A resposta a estas perguntas não importa, porque todas as equipes, sem exceção, devem seguir um processo parecido com o que é mostrado a seguir. 1. Baixa o código fonte, necessário para a programação, de seu SCM (Software Configuration Management - Sistema de Controle de Versões) 2. Faz alterações neste código. 3. No Visual Studio, clica em Build e espera que o código compile com sucesso. 4. Volta ao passo dois, caso o Visual Studio identifique erros. 5. Executa os testes unitários, e espera que tudo fique verde, ou seja, que passe em todos. 6. Volta ao passo dois, caso o teste unitário falhe, neste caso, o desenvolvedor vê um alerta vermelho e pode ver mais de um.

7. Refatora o código tornando-o mais compreensível e então volta ao passo cinco. 8. Efetua o envio do seu código alterado para o SCM, caracterizando o trabalho como commit. Vendo o processo demonstrado no parágrafo anterior e quando começamos a utilizar o CI, notamos que seguimos o mesmo processo. Porém, para o CI, o processo ainda vai mais além, posto que ele faz todos estes passos e ainda continua após o commit do código por parte do desenvolvedor, como veremos a continuação dos passos: 1. O Servidor de CI observa as alterações no SCM.Quando encontra qualquer nova alteração, ele efetua um download da última versão do código contendo o último commit. 2. O Servidor de CI efetua o build do código. 3. O Servidor de CI executa o teste unitário. 4. O Servidor de CI envia os resultados do build e o resultado dos testes para um sistema de comunicação (normalmente e-mail, mas também pode ser em SMS, Mensageiro instantâneo ou outro) para informar aos membros do time o estado do build.

Tipos de Construção para a Integração Contínua Existem alguns tipos de builds que dependem do ambiente e da natureza das aplicações. Alguns dos mais comuns são mostrados na Tabela 1. O build mais importante e que nos dá o resultado mais rápido é o build contínuo ou incremental. Tal build é automaticamente chamado quando o CI identifica uma alteração no código fonte comitado no SCM. Este build é executado muitas vezes durante o dia (um build pode ser executado logo após o término de outro), podendo ser executado a cada cinco ou dez minutos. Ocupando o segundo lugar em frequência, por ser executado em um período mais espaçado, é o build diário, também chamado de build noturno, posto que ele seja executado uma vez por dia e preferencialmente quando não se tem quase nenhuma atividade na infraestrutura, o que ocorre frequentemente a noite, mas pode ser um horário durante o dia também, por exemplo, quando todos devem ter ido almoçar. Tal tipo de build é agendado para que execute toda uma gama de testes

Tipo de Build

Descrição

Contínuo ou Incremental

É executado quando o código é comitado no SCM. Executa uma compilação rápida e um ou outro Teste Unitário.

Diário ou Noturno (Daily ou Nightly Builds)

Executa uma compilação e um gama maior de testes unitários e, em alguns casos, pode executar testes adicionais, como testes de aceitação e teste de Interface de usuário.

Semanal

Executa a compilação, testes de unidade completos e testes adicionais, como testes de aceitação, testes de fumaça e afins.

QA

Cria um build apenas para verificações do pessoal do Setor de Qualidade contendo as métricas para tal.

Staging ou Pré-Produção

Consiste em ser um servidor que age como uma réplica perfeita do ambiente de produção, também pode ser chamado de préprodução em alguns lugares. Nesta categoria, o build é executado e retornando com sucesso, deixa os assemblies disponíveis para testes em pré-produção.

Release

Cria um conjunto de instalação e então efetua os testes de instalação e todos os outros processos necessários ao funcionamento do sistema em produção e retorna o feedback.

Tabela 1. Tipos de Build Edição 115 .net Magazine

61

Integração Contínua em .NET – Parte 1

unitários em todo o código, sem exceção. Por isso que é muito importante ter um seu projeto uma estratégia bem definida de testes para os módulos, para que estes builds nos devolvam a informação verossímil e necessária. Assim, também verificamos a qualidade do software utilizando Cobertura de Códigos e Métricas de software. Outro tipo de build é o Build Semanal que executa automaticamente e de forma usual, sempre aos finais de semana. Uma vez por semana é o suficiente para medirmos a qualidade de nosso código e executar Testes adicionais com ferramentas para testes de fumaça como Selenium, FitNesse e NUnitForms. Além disso, podemos criar a documentação de nosso código utilizando SandCastle e fazer a Integração Contínua de nossa base de dados. Para um controle maior da data de liberação das novas versões do seu sistema, além do build semanal, também seria recomendado um build de release, que tem como propósito criar um conjunto de instalação e executá-lo. Este build normalmente é executado manualmente, mas, após este ser iniciado, todos os outros passos são executados automaticamente. No build de release o CI compila todo o código fonte, executa todos os testes criados, incrementa o número de versão e etc., então é criado o conjunto de artefatos para a implementação do mesmo e posterior teste desta implementação.

CI em alguns passos para a sua organização Para introduzir a CI dentro da empresa, é necessário percorrer um caminho através de ciclos distintos. Cada um destes ciclos envolve melhorias que são incrementais entre si para todo o corpo técnico (sejam eles servidores ou profissionais da equipe de desenvolvimento), bem como melhorias na cultura e estrutura de trabalho. Vamos mostrar nos parágrafos seguintes um pouco de cada ciclo organizado do mais elementar ao mais maduro. Para isso, vamos usar o estudo de caso de uma empresa fictícia que organizou seu processo de desenvolvimento e entrega utilizando a CI. A empresa inicialmente não dispunha de uma infraestrutura competitiva e, apesar de uma parte da equipe declarar oposição diante da implementação da Integração Contínua, foi dado um prazo de cinco meses (a contar da implementação) para mudar a filosofia de trabalho da organização. Veremos mais adiante como tal resistência fora combatida.

Primeiro Ciclo Nesse ciclo não existe um servidor de Build. Inicialmente, a equipe ainda não dispõe de nenhum tipo de servidor central de builds. O software é compilado e construído manualmente na máquina do desenvolvedor, mesmo que se use um Script NAnt (BOX 1) ou similar. O código fonte dos projetos é armazenado em servidores centralizados, mas os desenvolvedores nem sempre comitam suas alterações neste servidor. Antes que uma versão estável seja liberada, um desenvolvedor executa a integração das alterações no código fonte da aplicação de forma manual, mas isso pode gerar um grande prejuízo.

62 .net Magazine • Edição 115

BOX 1. Script NAnt Nant é uma ferramenta de scripting livre para automatizar a construção de processo de software. É semelhando ao Apache Ant, mas voltado para .NET.

Segundo Ciclo O time agora dispõe de um servidor para builds automatizados que são agendados em um período regular, sendo tipicamente à noite ou durante o dia quando o fluxo de trabalho é interrompido por algum período ou algo que cause a queda de utilização do link. Estes builds apenas compilam os códigos, pois ainda não existem os testes unitários sendo executados. Nota Testes Unitários, quando existem, não são parte integral ou obrigatória do processo de build.

Desenvolvedores comitam suas alterações de código fonte regularmente, mas se um membro da equipe de desenvolvimento efetua um commit de seus códigos e este conflita com o trabalho de outro membro da equipe, o servidor de builds alerta toda a equipe via e-mail na manhã seguinte. Porém, faz-se mister que o time ainda utilize o servidor de builds com o único propósito de informar as quebras e nada mais, logo a equipe acaba se sentindo desobrigada à corrigir toda a compilação interrompida para corrigir apenas aquele build em sua estação de trabalho, e o build pode ficar quebrado no servidor de por um tempo maior.

Terceiro Ciclo O time agora já está começando a tirar proveito da Integração Contínua com Testes automatizados mais seriamente. O servidor de build está configurado para dar início a um novo build assim que um novo código é comitado para o SCM e aos membros do time é permitida a livre visualização da alteração do código gerou a execução do Build e qual o impacto desta mudança. Além disso, o script que executa o build compila a aplicação e executa um conjunto de testes unitários ou testes de integração automatizados. Com relação ao envio de mensagens à equipe, o servidor de builds também envia um alerta aos membros do time sobre problemas na integração utilizando não só o e-mail, mas como outras formas mais proativas como mensageiros instantâneos. Builds que ficam quebrados agora são corrigidos mais rapidamente.

Quarto Ciclo Tem início a revolução das métricas, pois agora a equipe dispõe de verificação da qualidade de código automatizada e validação de métricas quanto à cobertura do código junto às melhores práticas, auxiliam muito na verificação para a eficiência dos nossos testes. Existe um build que incide apenas sobre a verificação da qualidade do código, ou seja, em um processo que é executado de forma distinta dos outros builds mostrados

anteriormente, este ocorre sempre, de forma separada, sobre a versão mais estável que está sendo executada, também gera uma documentação sobre a API utilizada para a criação da aplicação, facilitando assim a organização do código e escalabilidade da infraestrutura da aplicação ao longo do tempo o que facilita a chegada de novos membros à equipe e diminui o tempo de treinamento do novo recurso. Este tipo de implementação da CI ajuda a equipe a manter a qualidade do código sempre em alto nível, informando ao time quais métricas/práticas de testes estão sendo eficientes e úteis ao processo. O time também dispõe de um painel de acompanhamento de builds, que consiste em mostrar os resultados de todo o projeto em um monitor na sala ou no corredor da empresa de forma que todos tenham visibilidade de todos os processos de CI que estejam sendo executados e os status destes.

Quinto Ciclo Os benefícios da Integração Contínua são intimamente relacionados à práticas de testes bem consolidadas dentro da equipe. Agora, práticas como Desenvolvimento Orientado a Testes, TDD, são largamente utilizados resultando em um crescimento na confiança dos resultados dos builds automatizados. A aplicação não é mais simplesmente compilada e testada, mas se o teste tem sucesso, este

é automaticamente implementado para um servidor de aplicação para testes de outros tipos tais como testes de Aceitação e Testes de Desempenho e chegando a este ponto, já podemos começar o 6º e penúltimo ciclo, o dos Testes de Aceitação e Implementação que levará a empresa à filosofia da Entrega Contínua.

Sexto Ciclo O Desenvolvimento Orientado à Testes de Aceitação é praticado, guiando esforços de desenvolvimento e providenciando sempre relatórios de alto nível do estado atual do Projeto. Estes testes automatizados utilizam ferramentas para Desenvolvimento Orientado a Comportamentos, BDD, que agem como agentes para comunicação e documentação assim como as ferramentas de testes que publicam relatórios sobre os resultados de testes nos termos de negócio que profissionais que não sejam de desenvolvimento possam entender. Uma vez que testes de alto nível sejam automatizados dentro do projeto o mais cedo possível no processo de desenvolvimento, eles também dão a ideia de que melhorias foram implementadas e o quanto falta para a entrega da iteração ou do Projeto como um todo. A aplicação é automaticamente implementada no ambiente especifico para testes junto ao pessoal da Qualidade, ou QA, tão logo as alterações sejam comitada no SCM ou em uma base de build noturno.

Edição 115 .net Magazine

63

Integração Contínua em .NET – Parte 1

Uma versão estável do software projetado poder ser implementada em ambiente controlado, como pré-produção por exemplo, utilizando um build executado manualmente, caso a Equipe de Testes julgar estável. A equipe de desenvolvimento também será capaz de utilizar o servidor de build para proteger a versão estável gerando um rollback para uma versão anterior, se algum erro brusco e crítico ocorrer.

Sétimo Ciclo Existe um confiança colocada nos testes automatizados de Unidade, de Integração e de Aceitação de tal forma que as equipes podem aplicar as técnicas de implementação automatizada no Ciclo 6, porém, caso tudo corra bem, podem permitir que o CI implemente-as diretamente em produção em caso positivo dos builds. É este tipo de procedimento que configura a Entrega Continua e pelo que pudemos ver no decorrer deste processo,a única intervenção humana neste processo foi executada no sexto ciclo para testes de implementação. Será dentro destes ciclos que nossa série de artigo irá funcionar, utilizaremos estes sete ciclos para mostrar de forma prática ao leitor como que o CI vai evoluindo dentro da organização e como o nosso script de build vai sendo incrementado durante a implementação das melhorias.

Lidando com a resistência às mudanças Com todos estes builds acontecendo e membros da equipe tendo que modificar a sua rotina e efetuar atualizações em seus códigos, motivados por um servidor de SCM , com os códigos mais atuais para se manterem atualizados de forma frequente, ou seja, quase que diariamente, podemos encontrar certas objeções dos membros do time e as mais comuns veremos a seguir. CI aumenta a manutenção. Algum membro terá de manter o Sistema de CI. Tal procedimento fará com que este membro saia de seu escopo de ser apenas um desenvolvedor. No início, existirá um tempo maior que gerará um excesso de trabalho ao membro da equipe, porém, o time terá uma grande economia de tempo posto que o grande gargalo conhecido, que era o da Integração manual, não irá ocorrer e tornará o teste da aplicação mais simples. Muitas equipes informam, e isso é facilmente encontrado na grande rede, que após o processo de CI ser implantado, as rotinas de manutenção demoram menos que uma hora por semana na média. Estas mudanças são rápidas demais e são muitas. É difícil se adaptar a uma nova forma de se fazer algo. Não implementar tudo de uma só vez. Começar com um build simples executado uma vez ao dia e então adicionar um teste unitário. Após o time se sentir mais confortável e se acostumar com esta rotina podem adicionar um ou mais builds por dia ou começar a executar uma análise de código. Por implementar o processo em pequenos passos e mostrar que estes pequenos passos nos retornam grandes resultados - principalmente em tempo e facilidade, teremos mais aceitação dentro deste novo processo.

64 .net Magazine • Edição 115

CI implica em uma custo adicional de hardware e de software. Comece com um PC antigo como seu servidor de CI se conseguir. Eventualmente, vamos precisar melhorar o hardware para que possamos executar builds de forma mais veloz (devemos nos lembrar de que um build de integração, demora no mínimo, cinco minutos), mas para builds executados de duas à três vezes ao dia, máquinas antigas também vão nos atender. Se as ferramentas que informarmos nesta série forem utilizadas como recomendamos, o seu custo com software será mínimo. Desenvolvedores devem compilar e testar. Não estamos tirando estas responsabilidades dos desenvolvedores. Estamos apenas movendo boa parte do trabalho mais demorado e oneroso para um Sistema automatizado. Tal medida fará com que os membros da equipe possam produzir mais e resolver melhor os problemas de Regras de Negócios que existam na aplicação, logo esta medida fará com que os desenvolvedores fiquem mais produtivos aonde importa: Escrever e identificar erros no código. O projeto é longo demais ou está adiantado demais para que adicionemos o CI. Embora seja muito melhor e mais fácil se colocar um projeto na CI desde o seu início, a verdade é que, muito do trabalho que é feito é justamente dentro de manutenção dos nossos projetos já existentes. Um projeto que já exista pode não ter Testes Unitários, mas podemos utilizar um SCM e precisar fazer builds destes. Podemos nos beneficiar da CI não importando o tempo e o tamanho do projeto. Se a CI for colocada em seu devido lugar, muitos dos problemas mais conhecidos dentro de um projeto de software: do desenvolvimento à entrega e manutenção devem ocorrer. Mais adiante, vemos muitas razões para que se utilize o CI em seu processo de desenvolvimento. Riscos Reduzidos. Implementando bons processos de CI, criaremos software com uma performance muito melhor que a habitual porque já teremos feito os testes unitários e testes de integração de código muito mais cedo dentro do processo, então aumentamos as chances de corrigir erros também muito cedo. Falaremos sobre Riscos na próxima e derradeira seção desta primeira parte. Produto implementado de forma simples. Se automatizarmos o processo de instalação. Nós saberemos sobre o comportamento de sua instalação antes de receber um feedback de problemas do cliente. Visibilidade de Projeto. O mecanismo de feedback permite aos membros da equipe saber sobre os resultados do build e onde estão os problemas. Os problemas podem ser corrigido o quanto antes e esta abordagem reduz custos e o tempo gasto corrigindo problemas. Não permita que as objeções dos membros nos obrigue a recuar ou resistir. A resistência inicial irá diminuir gradualmente quando a equipe começar a trabalhar diretamente com o Sistema de CI. Uma Terapeuta Familiar muito conhecido em outros países chamada Virginia Satir criou o Modelo de Mudanças Satir que se refere sobre como as famílias lidam com a mudança.

E transportando algumas diretrizes para lidar com a equipe, temos a seguir algumas boas recomendações. E este processo de mudança envolve cinco passos. Passo 1: Status Quo Tardio. Todos estão trabalhando normalmente no processo atual e todos sabem como ele funciona. Passo 2: Resistência. Um novo elemento é introduzido no seio da equipe. As pessoas são sempre hesitantes para mudar a sua rotina. Se o status quo funciona muito bem, por que modificá-lo? Passo 3: Caos. O novo elemento introduzido é adotado. Não há uma forma normal de fazer novas coisas. Rotinas diárias são despedaçadas. Passo 4: Integração. Pessoas se ajustam lentamente ao novo modo de se fazer coisas. Fica mais fácil fazer o trabalho de convencimento se utilizar esta abordagem. E começam a utilizá-lo, mas de forma gradual. Passo 5: Novo status quo. O novo elemento já está totalmente integrado ao Sistema. As pessoas agora o veem como Normal e voltamos ao passo 1. Quase todos os times acabam adotando novas metodologias de uma hora para outra. Este processo por soar familiar. Assim como lutamos contra a resistência da equipe, sejamos persistentes em implementar as mudanças.

Os membros do time em breve vão aceitá-las. Alguns membros vão adotar o CI mais rápido que outros alguns podem precisar de uma dose maior de convencimento. Talvez seja necessário mostrar a eles como o CI reduz os riscos e os custos e benefícios dentro do processo de desenvolvimento.

Custo Benefício da Integração Contínua É necessário ter planos para mitigar os riscos, a CI é sempre apontada como uma redução e controle dos riscos e o maior risco dentro de um ciclo de desenvolvimento de software é a demora na entrega. Por causa do mecanismo de feedback do processo de CI, o time terá um controle sobre o estado do build atual. O outro grande risco são os bugs. Como já mostramos anteriormente, que quanto mais tardia é a política para correção de defeitos aplicada a um projeto, maior será o custo para corrigi-los. Algumas estimativas sugerem que o custo para a correção de um defeito gira em torno de R$3.500,00 em média para corrigir um simples defeito de software em aplicações internas. Anos atrás, uma companhia de antivírus bem conhecida gerou defeito dentro de um de seus pacotes de atualização. Este pequeno defeito fez com que os clientes perdessem confiança naquele antivírus e forçaram a empresa a reduzir seus rendimentos trimestrais e previsões orçamentárias de receita em US$8 milhões.

Edição 115 .net Magazine

65

Integração Contínua em .NET – Parte 1

Não gostaríamos de ver a nossa empresa passar por algo parecido. Uma das vantagens da CI neste ponto é que os defeitos são corrigidos tão logo eles são identificados. Integrando e testando o software a cada build, podemos identificar e corrigir defeitos no processo. Discutiremos Testes Unitários mais adiante em nossa série de Artigos. Sempre fizemos algumas perguntas para saber o andamento de nosso projeto como: consideramos quantos caminhos diferentes podem existir em nosso código fonte? testamos a combinação de cada if/else? Quantos casos de declarações switch foram testadas? respondemos estas perguntas implementando a Cobertura de Código. Cobertura de Código é a metodologia que verifica quais caminhos serão testados e quais não serão. Uma grande solução quando o assunto é cobertura de código é que podemos automatizá-la em nosso processo de CI. É humanamente impossível de serem testadas todas as combinações de cobertura existentes, mas quanto mais for testado, menos problemas serão descobertos pelo seu cliente. Outro risco conhecido são as atualizações em bancos de dados. Nunca foi fácil adicionar campos para uma tabela ou novas tabelas em um banco de dados. Com Integração Contínua em banco de dados, teremos ciência se as mudanças implementadas trabalham corretamente e sem perda de dados. Demonstraremos Integração Contínua em bancos de dados mais adiante nesta série. Desenvolvedores odeiam padrões de codificação e arquiteturais, mas têm seu propósito útil: permitem que a aplicação siga as melhores práticas, fazem com que a aplicação funcione melhor e fica mais fácil de manter revisões de código, pois identificam muitos problemas. Mas como a revisão de código é um processo manual, algumas coisas podem se perder. Então, por que não automatizar a verificação da padronização em seu processo de CI? Comentários são colocados raramente no código e a documentação quase não existe. Muitos dizem que se formos ágeis, não precisamos de documentação, mas isso não é verdade. O Manifesto Ágil diz que o trabalho é mais valorizado que a documentação. Mas, a documentação é ainda necessária, especialmente se estivermos criando assemblies a serem utilizados por outras equipes ou outras pessoas em forma de APIs. Esta é outra oportunidade para automatizar seu processo com processos de CI. Como saberemos que o processo de instalação/implementação funcionou corretamente? Existem poucas coisas que frustram mais usuários do que não conseguirem instalar ou implementar uma aplicação. É fácil ver problemas escondidos no projeto que sem um sistema de CI só seria identificado muito depois do processo de desenvolvimento, quando os problemas já se tornaram bem mais difíceis e caros para se corrigir. O processo de CI, ao ser implementado gradualmente seguindo os ciclos informados nesse artigo consegue resolver esse desafio.

66 .net Magazine • Edição 115

O maior obstáculo para a implementação não está no projeto em si, mas na resistência das equipes em implementá-lo dentro das organizações. Assim que a resistência é combalida, demonstrando no dia a dia como a CI é útil e viável, a implementação começa a mudar de forma lenta, mas drástica, a forma como as organizações interagem dentro do projeto de software. Tendo mais agilidade, as equipes conseguem melhores resultados.

Autor Luís Gabriel Nascimento Simas [email protected] Atua como Desenvolvedor de Software desde 1996. É Coordenador das Revistas Infra Magazine e Delphi Magazine na Devmedia e Programador na Fundação Getúlio Vargas (FGV) na TIC - Tecnologia da Informação e Comunicação. Também é aluno de Análise e Desenvolvimento de Sistemas na Universidade Estácio de Sá no Campus Praça XI. Lida com Metodologias e Processos Ágeis e é proficiente nas Linguagens Java e C#. C

Links:

M

Y

Artigo de Martin Fowler sobre Integração Contínua www.martinfowler.com/articles/continuousIntegration.html

CM

MY

NUnitForms http://nunitforms.sourceforge.net/

CY

CMY

FitNesse http://www.fitnesse.org/ NUnit http://www.nunit.org/ xUnit http://xunit.codeplex.com/ MSTest http://msdn.microsoft.com/en-us/library/ms243147(v=vs.80).aspx Selenium http://docs.seleniumhq.org/projects/ Jenkins http://www.jenkins.org/ CruiseControl.NET http://www.cruisecontrolnet.org/

Você gostou deste artigo? Dê seu voto em www.devmedia.com.br/netmagazine/feedback Ajude-nos a manter a qualidade da revista!

K

Edição 115 .net Magazine

67

Integração Contínua em .NET – Parte 1

68 .net Magazine • Edição 115
NET-MAGAZINE_115_novidades do visual studio 2013

Related documents

68 Pages • 36,491 Words • PDF • 12.3 MB

479 Pages • 334,482 Words • PDF • 27.4 MB

4 Pages • 789 Words • PDF • 334.3 KB

29 Pages • 108 Words • PDF • 11.3 MB

9 Pages • PDF • 6.3 MB

47 Pages • 1,026 Words • PDF • 2.5 MB

8 Pages • 300 Words • PDF • 427.1 KB

16 Pages • 6,857 Words • PDF • 1.8 MB

84 Pages • 43,123 Words • PDF • 18.1 MB

12 Pages • 5,752 Words • PDF • 5.2 MB

27 Pages • 4,816 Words • PDF • 1.3 MB