Cadastre-se Revistas DevMedia Cursos
 

Space de Renato Jose Groffe
Busca Autor


Últimas 20 atualizações de Renato Jose Groffe

Artigo - Integração WCF x jQuery: acessando Web Services via JavaScript

O desenvolvimento de novas soluções Web nos dias atuais está associado, na esmagadora maioria dos casos, ao uso de jQuery em atividades relacionadas à implementação de interfaces gráficas. Baseando-se totalmente em JavaScript, jQuery surgiu com o objetivo de simplificar a manipulação de HTML em sites (evitando a codificação de instruções muito extensas), além de oferecer uma alternativa que contasse com um grau mínimo de compatibilidade com os principais browsers do mercado.

Surgida ainda em 2006, a biblioteca jQuery encontra-se neste momento na versão 2.0.0 (Maio/2013). Grandes portais como Wikipédia e o WordPress representam exemplos notórios de uso da mesma. A própria Microsoft tem estimulado a utilização desta biblioteca: em versões mais recentes do Visual Studio (2010 e 2012), aplicações ASP.NET Web Forms e MVC criadas através de templates contam com versões de jQuery como parte de seu conteúdo.

Além da execução de operações sobre os elementos HTML em páginas da Web, jQuery também disponibiliza mecanismos para a implementação de eventos, animações e funcionalidades empregando recursos de AJAX (sigla do inglês “Asynchronous JavaScript and XML”). A flexibilidade que se conseguiu por meio desta biblioteca serviu de base, inclusive, para o lançamento de diversos plugins, controles e frameworks voltados à construção de interfaces gráficas.

Como não é difícil de imaginar, muitas dessas soluções concebidas em jQuery (como gráficos, grids e painéis de controle) utilizam dados em formatos como XML ou JSON (abreviação do inglês “JavaScript Object Notation”), os quais foram obtidas a partir de algum repositório. Tais fontes de informações podem ser representadas tanto por funcionalidades dentro uma aplicação que faz uso de recursos em jQuery, quanto por Web Services acessados de maneira remota.

A própria plataforma .NET permite, através da tecnologia WCF (Windows Communication Foundation), a construção de serviços que serão consumidos via instruções de código em jQuery/JavaScript. O objetivo deste artigo é demonstrar justamente como tais Web Services são implementados e, posteriormente, um exemplo em jQuery de acesso aos dados (no formato JSON) disponibilizados por estes componentes.

Criando o serviço WCF de exemplo

A solução que está sendo apresentada neste artigo foi criada no .NET Framework 4.5, através da utilização do Microsoft Visual Studio 2012 Professional. Inicialmente será criado o projeto TesteWCFJSON, o qual é baseado no template “WCF Service Application” (conforme indicado na Figura 1).

Criando o projeto TesteWCFJSON

Figura 1: Criando o projeto TesteWCFJSON

Basicamente, será construído um serviço que retornará informações anuais sobre as exportações e importações de uma indústria fictícia. Tais dados poderão estar organizados tanto por país, quanto por continente.

Como primeiro passo na implementação do projeto TesteWCFJSON, excluir os arquivos Service1.svc e IService1.cs (os mesmos foram gerados automaticamente ao se escolher o template “WCF Service Application”).

Em seguida, deverão ser implementadas as classes BalancoComercialPorPais e BalancoComercialPorContinente (Listagem 1). O tipo BalancoComercialPorPais corresponde ao resumo de exportações e importações para um país num determinado ano, ao passo que instâncias de BalancoComercialPorContinente possuem um conteúdo similar, mas com o agrupamento de informações por continentes.

Listagem 1: Classes BalancoComercialPorPais e BalancoComercialPorContinente

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;

namespace TesteWCFJSON
{
    [DataContract]
    public class BalancoComercialPorPais
    {
        [DataMember]
        public int AnoBase { get; set; }

        [DataMember]
        public string Pais { get; set; }

        [DataMember]
        public string Sigla { get; set; }

        [DataMember]
        public double ValorExportado { get; set; }

        [DataMember]
        public double ValorImportado { get; set; }
    }

    [DataContract]
    public class BalancoComercialPorContinente
    {
        [DataMember]
        public int AnoBase { get; set; }

        [DataMember]
        public string Continente { get; set; }

        [DataMember]
        public double ValorExportado { get; set; }

        [DataMember]
        public double ValorImportado { get; set; }
    }
}

Estas duas classes (BalancoComercialPorPais e BalancoComercialPorContinente) representam bons exemplos de um tipo de elemento conhecido dentro de WCF como Data Contract. Em termos gerais, um Data Contract nada mais é do que um tipo complexo, ou seja, uma estrutura composta pela combinação de tipos primitivos ou mesmo outras construções mais elaboradas (referências que apontem para outras classes). Data Contracts podem ser empregados tanto como parâmetros de entrada em operações de um serviço, quanto como valores retornados após a execução de tais métodos.

Para ser considerada um Data Contract, uma classe precisa ter associada à sua definição um atributo DataContractAttribute (namespace System.Runtime.Serialization).

É importante fazer ainda uma observação quanto ao uso do tipo DataContractAttribute: por convenção dentro da plataforma .NET, nomes de classes que representam atributos terminam com o sufixo Attribute. Instruções que envolvam um atributo vinculado a uma estrutura de código dispensam o uso de tal sufixo ao final do nome. Logo, ao se utilizar o atributo DataContractAttribute, emprega-se apenas “DataContract” na construção a ser marcada com este elemento.

Além da própria definição da classe, as propriedades de um Data Contract que serão expostas via serviço também deverão ter um atributo ligado às mesmas, fazendo-se uso neste caso do tipo DataMemberAttribute (pertencente ao namespace System.Runtime.Serialization).

Pelo fato do projeto TesteWCFJSON ter como objetivo a realização de testes envolvendo a utilização de serviços WCF que devolvam informações no formato JSON, esta aplicação não fará uso de um banco de dados relacional. Devido a este motivo, serão criadas duas classes estáticas (SimulacaoBalanco2011 e SimulacaoBalanco2012) que retornarão valores fictícios, com cada uma dessas estruturas produzindo como resultado dados de um ano específico.

Na Listagem 2 está a definição da classe SimulacaoBalanco2011. O método ObterBalancoPaises será utilizado para se ter acesso ao balanço comercial de diferentes países, enquanto a operação ObterBalancoContinentes provê o mesmo tipo de informação por continentes.

Listagem 2: Classe SimulacaoBalanco2011

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TesteWCFJSON
{
    public static class SimulacaoBalanco2011
    {
        public static List<BalancoComercialPorPais> ObterBalancoPaises()
        {
            List<BalancoComercialPorPais> dados =
                new List<BalancoComercialPorPais>();

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "Alemanha",
                Sigla = "DE",
                ValorExportado = 35.1,
                ValorImportado = 15.5
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "Canadá",
                Sigla = "CA",
                ValorExportado = 15.6,
                ValorImportado = 4.9
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "China",
                Sigla = "CN",
                ValorExportado = 45.3,
                ValorImportado = 30.2
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "Estados Unidos",
                Sigla = "US",
                ValorExportado = 50.4,
                ValorImportado = 25.3
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "Japão",
                Sigla = "JP",
                ValorExportado = 40.2,
                ValorImportado = 20.4
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2011,
                Pais = "Reino Unido",
                Sigla = "GB",
                ValorExportado = 30.9,
                ValorImportado = 9.7
            });

            return dados;
        }

        public static List<BalancoComercialPorContinente> ObterBalancoContinentes()
        {
            List<BalancoComercialPorContinente> dados =
                new List<BalancoComercialPorContinente>();

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2011,
                Continente = "América",
                ValorExportado = 66,
                ValorImportado = 30.2
            });

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2011,
                Continente = "Ásia",
                ValorExportado = 85.5,
                ValorImportado = 50.6
            });

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2011,
                Continente = "Europa",
                ValorExportado = 66,
                ValorImportado = 25.2
            });

            return dados;
        }
    }
}

Já na Listagem 3 está o código que implementa o tipo SimulacaoBalanco2012. Conforme pode ser observado, a estrutura aqui descrita é idêntica à da classe SimulacaoBalanco2011, diferindo apenas pelo conteúdo das informações retornadas.

Listagem 3: Classe SimulacaoBalanco2012


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TesteWCFJSON
{
    public static class SimulacaoBalanco2012
    {
        public static List<BalancoComercialPorPais> ObterBalancoPaises()
        {
            List<BalancoComercialPorPais> dados =
                new List<BalancoComercialPorPais>();

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "Alemanha",
                Sigla = "DE",
                ValorExportado = 38.6,
                ValorImportado = 20.2
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "Canadá",
                Sigla = "CA",
                ValorExportado = 17.2,
                ValorImportado = 3.4
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "China",
                Sigla = "CN",
                ValorExportado = 49.8,
                ValorImportado = 36.2
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "Estados Unidos",
                Sigla = "US",
                ValorExportado = 55.4,
                ValorImportado = 27.8
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "Japão",
                Sigla = "JP",
                ValorExportado = 44.2,
                ValorImportado = 18.4
            });

            dados.Add(new BalancoComercialPorPais()
            {
                AnoBase = 2012,
                Pais = "Reino Unido",
                Sigla = "GB",
                ValorExportado = 34,
                ValorImportado = 7.8
            });

            return dados;
        }

        public static List<BalancoComercialPorContinente> ObterBalancoContinentes()
        {
            List<BalancoComercialPorContinente> dados =
                new List<BalancoComercialPorContinente>();

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2012,
                Continente = "América",
                ValorExportado = 72.6,
                ValorImportado = 31.2
            });

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2012,
                Continente = "Ásia",
                ValorExportado = 94,
                ValorImportado = 54.6
            });

            dados.Add(new BalancoComercialPorContinente()
            {
                AnoBase = 2012,
                Continente = "Europa",
                ValorExportado = 72.6,
                ValorImportado = 28
            });

            return dados;
        }
    }
}

Concluindo agora a implementação do projeto TesteWCFJSON, será necessário criar um serviço de nome BalancoComercialWS, conforme demonstrado na Figura 2.

Criando o serviço BalancoComercialWS

Figura 2: Criando o serviço BalancoComercialWS

Como resultado disto, serão criados os seguintes elementos:

  • A interface IBalancoComercialWS, a qual corresponde ao contrato que define o serviço de exemplo;
  • A classe BalancoComercialWS, responsável por implementar as funcionalidades oferecidas pelo serviço de exemplo.

Na interface IBalancoComercialWS (Listagem 4) estão declaradas as operações que serão expostas através do serviço WCF abordado neste artigo. IBalancoComercialWS foi marcada com o atributo ServiceContractAttribute (namespace System.ServiceModel): este é um pré-requisito para se expor uma interface (ou mesmo uma classe) como um serviço quando se emprega a tecnologia WCF.

Além disso, é possível observar nas declarações das operações ObterBalancoPaises e ObterBalancoContinenetes:

  • O uso do atributo OperationContractAttribute (namespace System.ServiceModel), o qual deve estar associado a métodos que poderão ser invocados por consumidores de um serviço;
  • A presença do atributo WebGetAttribute (namespace System.ServiceModel.Web), característica esta que permite a aplicações-cliente acessar as operações de um serviço via requisições HTTP do tipo GET.

Ainda sobre a utilização do atributo WebGetAttribute, ao se definirem as operações da interface IBalancoComercialWS foram preenchidas as seguintes propriedades:

  • ResponseFormat: indica o formato de dados a ser utilizado no retorno do serviço (JSON ou XML), baseando-se para isto no enumeration WebMessageFormat (namespace System.ServiceModel.Web);
  • UriTemplate: permite customizar a URL para acesso a um método que faz parte um serviço. Os diferentes parâmetros esperados por tal operação devem estar entre "chaves" (“{”e “}”}, bem como especificados como sendo do tipo string.

Listagem 4: Interface IBalancoComercialWS


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace TesteWCFJSON
{
    [ServiceContract]
    public interface IBalancoComercialWS
    {
        [OperationContract]
        [WebGet(
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "paises/{anoBase}")]
        List<BalancoComercialPorPais> ObterBalancoPaises(
            string anoBase);

        [OperationContract]
        [WebGet(
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "continentes/{anoBase}")]
        List<BalancoComercialPorContinente> ObterBalancoContinentes(
            string anoBase);
 
    }
}

A classe BalancoComercialWS (Listagem 5) implementa a interface IBalancoComercialWS, sendo responsável por processar as requisições enviadas ao serviço WCF de exemplo.

Conforme é possível observar na definição de BalancoComercialWS, este tipo faz uso das classes SimulacaoBalanco2011 e SimulacaoBalanco2012 para a obtenção dos dados de simulação referentes aos de 2012 e 2012 respectivamente.

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
15/05/2013 09:10:00





Artigo - Modelagem de sistemas através de UML: uma visão geral

Independente do porte de uma solução, todo projeto de software é caracterizado por um estágio inicial, sendo este momento uma fase de análise em que se procura estudar de que forma o mesmo será conduzido. A ênfase que é dada a este tipo de atividade depende, basicamente, não apenas do tamanho do sistema a ser construído, como também da forma como a equipe envolvida encontra-se estruturada e do conhecimento desta última acerca de padrões e metodologias próprios da área de software.

As pressões do cotidiano (sobretudo prazos muito curtos e a impaciência das áreas que requisitaram uma solução) acabam, por vezes, relegando este trabalho de análise a um segundo plano. Tudo isto resulta em uma série de armadilhas, as quais podem culminar em projetos que levaram mais tempo para serem executados ou, mesmo, que estouraram o orçamento previsto para a realização das atividades.

Embora representem aspectos extremamente indesejáveis, tais problemas são parte do contexto com que se deparam muitos profissionais de Tecnologia da Informação no dia-a-dia. Diversos estudos já foram publicados e fornecem numerosas explicações para o cancelamento de projetos. Essas pesquisas são unânimes em afirmar, através da observação de organizações dos mais variados tipos, que a falta de uma melhor análise do que realmente necessita ser feito representa um dos principais motivos de tais fracassos.

A linguagem UML procura fornecer meios para auxiliar no levantamento dos requisitos que irão constituir um sistema, além de recursos para a modelagem de estruturas que farão parte do mesmo. O fato da UML ser um padrão de grande aceitação no mercado também se deve, em grande parte, à forte integração desta com conceitos da Orientação a Objetos (OO). Como muitos sistemas são concebidos a partir da aplicação de práticas e técnicas de OO, a elaboração de documentos modelando os componentes esperados é feita atualmente a partir de diagramas UML.

O objetivo deste artigo é apresentar um resumo dos diferentes diagramas disponibilizados pela UML, abordando ainda de que forma estes recursos podem ser úteis em sistemas baseados em elementos da Orientação a Objetos.

A linguagem UML

Figura 1: A linguagem UML

A UML na modelagem de sistemas

UML (sigla em inglês para "Unified Modeling Language") é uma linguagem que se presta à modelagem de estruturas que irão compor uma aplicação, estando fortemente amparada em conceitos de Orientação a Objetos. Em termos práticos, a UML contempla uma série de notações para a construção de diagramas representando diferentes aspectos de um software, além de não estar presa a metodologias ou tecnologias específicas de desenvolvimento. Sistemas construídos nas mais variadas linguagens e plataformas como C#, VB.NET, Java, Delphi etc. podem se beneficiar das vantagens decorrentes do uso desta linguagem.

O advento da UML como um dos principais meios para a documentação de sistemas aconteceu ainda no final dos anos 1990, graças ao trabalho conjunto de três especialistas da área de desenvolvimento de software: James Rumbaugh, Grady Booch e Ivar Jacobson. Diversos dos diagramas disponibilizados pela UML são resultado da evolução de representações propostas em momentos anteriores por estes especialistas, sendo que os mesmos procuram contemplar diferentes aspectos da construção de aplicações baseadas em técnicas da OO.

É bastante comum que se encontrem literaturas a respeito de design patterns que fazem uso da UML, empregando esta última como um meio para a representação esquemática das ideias que estão sendo discutidas. Além disso, metodologias de desenvolvimento como RUP (Rational Unified Process) têm nesta linguagem um importante pilar, já que os diversos diagramas existentes acabam por servir como parte da documentação de um projeto.

As diversas notações da UML podem ser utilizadas em várias situações:

  • Para esboçar estruturas de um sistema em discussões a respeito do mesmo. Isto costuma acontecer de um modo informal, através do desenho de um componente ou processo da aplicação considerada, buscando assim um melhor entendimento daquilo que está analisando;
  • Como documentação que servirá de base para atividades de codificação das estruturas de um sistema, bem como elaboração de testes das funcionalidades implementadas;
  • Na documentação de estruturas já existentes de um sistema, ou seja, como uma ferramenta de engenharia reversa, a partir da qual serão documentadas funcionalidades e outras estruturas da aplicação em questão.

Os diferentes diagramas que compõem a UML podem ser agrupados em categorias, levando em conta para isto o contexto em que cada uma dessas representações pode vir a ser empregada:

  • Diagramas Estruturais: priorizam a descrição estática de estruturas de um sistema, como classes, atributos e operações destas últimas, além de prováveis relacionamentos entre tais construções. A Tabela 1 lista os diversos diagramas que pertencem a esta classificação;
  • Diagramas Comportamentais: detalha o funcionamento (comportamento) de partes de um sistema ou processos de negócio relacionados a tal aplicação. Na Tabela 2 são apresentados os diversos diagramas que se enquadram nesta categoria;
  • Diagramas de Interação: considerados um subgrupo dos diagramas comportamentais, sendo normalmente utilizados na representação de interações entre objetos de uma aplicação. Os diferentes diagramas que fazem parte deste conjunto de representações foram descritos na Tabela 3.
DiagramaFunção
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
30/04/2013 15:07:00





Artigo - Alguns cuidados úteis na implantação de aplicações ASP.NET

Independente da tecnologia empregada em sua implementação (Web Forms, MVC, WCF), a implantação (deploy) de aplicações Web construídas sob o .NET Framework pode estar sujeita a alguns problemas que passaram de forma despercebida durante o desenvolvimento. Isto pode ser motivado tanto por falhas involuntárias de programadores, quanto por diferenças de configurações entre o servidor destinado à hospedagem de um projeto e os computadores utilizados por programadores durante a codificação.

Muito embora seja impossível conceber uma aplicação livre de falhas, cuidados podem ser tomados para minimizar imprevistos durante o deploy de sistemas Web. O objetivo deste artigo é descrever algumas ações que podem auxiliar neste sentido.

Timeout em páginas com os controles ScriptManager e UpdatePanel

Ao se implementar páginas numa aplicação ASP.NET, o comum é que as mesmas sejam desenvolvidas de uma forma na qual se procure evitar ao máximo problemas de timeout. Um formulário HTML cujo conteúdo demora a ser processado é normalmente abandonado pelos usuários, deixando com isto uma ação inacabada e que, não raro, pode terminar com a gravação de dados inconsistentes.

Uma prática comum para se impedir que isto aconteça é empregar, dentro de soluções Web Forms, os controles UpdatePanel e ScriptManager. Estes dois componentes são extensões do ASP.NET voltadas à utilização de mecanismos de AJAX (sigla do inglês "Asynchronous JavaScript and XML"), tendo por objetivo impedir as famosas "piscadas" (reprocessamento de todo o conteúdo) de uma página.

Por mais que se empreenda um grande esforço em tornar mais rápida uma aplicação Web, ainda poderão existir casos de funcionalidades que demandam um tempo maior a fim de produzir um determinado resultado. Exemplos disto são relatórios do SQL Server Reporting Services acessíveis a partir de sites Web Forms. Considerando que as páginas em que se encontram esses recursos também possuam componentes do AJAX, é bastante alta a probabilidade de ocorrência de problemas de timeout; se isto se confirmar, um erro em JavaScript será gerado e a ação que estava em progresso abortada.

A Figura 1 ilustra este tipo de problema ao se executar uma aplicação Web Forms a partir do Visual Studio 2012.

Timeout em uma página que faz uso de AJAX

Figura 1: Timeout em uma página que faz uso de AJAX

Uma solução para esta questão envolve a alteração do valor da propriedade AsyncPostBackTimeout, para o componente ScriptManager. Por default, esta propriedade assume um tempo de 90 segundos, sendo que no exemplo da Listagem 1 foram definidos 3 minutos (180 segundos).

Listagem 1: Configurando a propriedade AsyncPostBackTimeout de um controle ScriptManager

...

<asp:ScriptManager runat="server" AsyncPostBackTimeout="180">

    ...

</asp:ScriptManager>

Problemas com arquivos de scripts ao se fazer o deploy em um diretório virtual

A esmagadora maioria das aplicações Web fará uso, em algum momento, de instruções JavaScript/JQuery. O uso de scripts em sites está vinculado a ações executadas do lado cliente (browser), de forma a possibilitar uma maior interatividade com os recursos disponibilizados pela solução em questão.

Considerando tudo isso, será mais do que comum em aplicações ASP.NET Web Forms a declaração de arquivos contendo código JavaScript (extensão .js) dentro de Master Pages e outras páginas convencionais. O simples fato de se referenciar scripts a partir da tag criada para esta finalidade (“script”) é uma tarefa extremamente simples, a qual não requer grandes preocupações na maioria dos projetos.

No entanto, existe a probabilidade de erros no acesso a tais scripts em aplicações que foram publicadas em diretórios virtuais. Quando isto acontecer, uma página processada a partir do servidor Web será incapaz de “resolver” (referenciar/localizar) um ou mais arquivos JavaScript, gerando erros visíveis aos seus usuários.

Na Listagem 2, está um exemplo de declaração de script em uma Master Page, com esta referência podendo vir a ocasionar o tipo de problema relatado nesta seção.

Listagem 2: Exemplo de Master Page que faz uso de um arquivo de scripts

<%@ Master Language="C#"
           AutoEventWireup="true"
           CodeBehind="Site.master.cs"
           Inherits="TesteWebForms.SiteMaster" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-st
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
26/04/2013 09:16:00





Artigo - Segurança em aplicações .NET: utilizando o provider ASP.NET Membership

Muitas aplicações podem manipular em algum momento informações de caráter restrito, sobretudo quando se consideram sistemas direcionados ao ambiente corporativo. Em tais casos existirá uma forte preocupação no que se refere à privacidade dos dados, procurando-se evitar com isto o acesso não autorizado a funcionalidades de um software.

Estabelecer regras limitando o acesso a recursos é um procedimento rotineiro no mundo do desenvolvimento de softwares, principalmente em soluções concebidas para a utilização a partir de redes (sejam privadas ou, mesmo, a partir da própria Internet). A implementação de controles visando garantir a segurança de um sistema deve levar em conta alguns conceitos gerais:

  • Confidencialidade: ideia que gira em torno da necessidade de garantir a privacidade de um conjunto de informações, impedindo que pessoas não autorizadas tomem conhecimento de dados sigilosos de forma inadvertida;
  • Integridade: é a garantia de que os dados que estão sendo manipulados por uma aplicação não serão alterados de forma deliberada;
  • Autenticação: processo no qual um usuário apresenta sua identificação (normalmente um login e uma senha correspondente) junto a um mecanismo de validação, o qual tem por responsabilidade conceder ou não o acesso às diferentes funcionalidades de uma aplicação;
  • Autorização: uma vez que um usuário passe pela etapa de autenticação, este procedimento determina se o mesmo terá ou não acesso a uma determinada função do sistema em questão. A verificação de quem conseguirá utilizar uma funcionalidade ou informação pode envolver tanto a checagem de logins/contas individuais, quanto a análise de grupos de usuários (roles) aos quais uma pessoa esteja associada.

A criação de um mecanismo que gerencie o acesso de usuários a uma aplicação costuma demandar um tempo considerável, com o produto desse esforço podendo estar sujeito a vulnerabilidades não diagnosticadas num primeiro instante. Se realmente existirem falhas nos módulos que controlam a segurança de um sistema, as consequências poderão ser desastrosas, causando danos à imagem de uma organização, além de prováveis prejuízos financeiros e problemas legais.

Procurando oferecer uma alternativa simples e rápida para a segurança de aplicações ASP.NET, a Microsoft desenvolveu um provider conhecido como ASP.NET Membership. Trata-se de um conjunto de recursos voltados ao gerenciamento de regras de acesso, contas e perfis de usuários, sendo que este mecanismo pode utilizar como repositórios de informações as seguintes fontes:

  • Um banco de dados SQL Server;
  • O recurso Active Directory do Windows;
  • Um provider customizado desenvolvido em atendimento a uma finalidade específica.

Maiores informações sobre o ASP.NET Membership podem ser obtidas através do link:

http://msdn.microsoft.com/en-us/library/tw292whz(v=vs.100).aspx

Muito embora tenha sido projetado para soluções Web, o ASP.NET Membership pode ser facilmente integrado a outros tipos de aplicações .NET (como Windows Forms). Isto contribui, sem sombra de dúvidas, para uma maior produtividade no desenvolvimento de novos sistemas, desonerando os programadores de tarefas como a implementação de toda uma lógica de controle de acessos/gerenciamento de usuários.

O objetivo deste artigo é demonstrar, em termos gerais, como o ASP.NET Membership pode ser configurado para uso em projetos .NET. Além disso, serão apresentadas algumas das classes e estruturas que permitem o acesso às funcionalidades fornecidas por este provider.

Configurando as estruturas do ASP.NET Membership em um banco de dados SQL Server

Disponibilizado a partir da versão 2.0 do .NET Framework, o provider Membership foi concebido inicialmente para uso em aplicações Web, conforme já mencionado anteriormente. A menos que definido explicitamente no arquivo Web.config de um projeto, o acesso à funcionalidade conhecida como “Web Site Administration Tool” (menu “Project” > opção “ASP.NET Configuration” do Visual Studio) costuma gerar um banco de dados que contempla toda a estrutura requerida pelo ASP.NET Membership.

Para efeitos de testes, esta é certamente uma boa opção. No entanto, em cenários que envolvam a utilização desse mecanismo de segurança num ambiente de produção, muito provavelmente existirá um banco de dados que precisará ser configurado com todos os elementos esperados pelo ASP.NET Membership.

A fim de demonstrar como este ajuste pode ser realizado, estaremos considerando um banco de dados chamado TesteMembership. A Figura 1 apresenta a estrutura desta base antes da geração dos elementos de controle de acesso, sendo possível observar a existência de três tabelas.

Estrutura do banco de dados TesteMembership antes do ajuste

Figura 1: Estrutura do banco de dados TesteMembership antes do ajuste

Para a criação dos objetos de banco de dados necessários à utilização do provider Membership será necessário, primeiramente, acionar o utilitário Aspnet_regsql.exe a partir do prompt de comando do Visual Studio 2012 (no Windows 7: Menu Iniciar > Microsoft Visual Studio 2012 > Visual Studio Tools > Developer Command Prompt for VS2012). Na Figura 2 é possível ver o prompt em execução.

Prompt de comando do Visual Studio 2012

Figura 2: Prompt de comando do Visual Studio 2012

O Aspnet_regsql.exe é uma ferramenta que permite criar (ou ainda remover) os objetos usados pelo ASP.NET Membership em uma base de dados SQL Server. Para isto, o mesmo apresenta um wizard a partir do qual é possível selecionar a base de dados de destino (Figura 3).

Executando o utilitário Aspnet_regsql.exe

Figura 3: Executando o utilitário Aspnet_regsql.exe

Ao se clicar no botão “Next”, será exibida uma tela similar àquela que consta na Figura 4. Manter selecionada a opção “Configure SQL Server for application services”, clicando em seguida no botão “Next”.

Selecionando opção para a configuração do ASP.NET Membership em uma base SQL Server

Figura 4: Selecionando opção para a configuração do ASP.NET Membership em uma base SQL Server

Na janela que aparecerá neste momento (Figura 5) preencher as configurações para acesso à base TesteMembership. Executar em seguida a opção “Next”.

Selecionando uma base de dados via Aspnet_regsql.exe

Figura 5: Selecionando uma base de dados via Aspnet_regsql.exe

Confirmar então a realização dos ajustes na base TesteMembership, clicando no botão “Next” da tela que é apresentada na Fig

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
19/04/2013 09:57:00





Artigo - Excel x .NET Framework: gerando planilhas .xls sem o uso de Interop/COM

Por mais que mecanismos como os Web Services ganhem a cada dia mais espaço na integração entre sistemas, muitas companhias têm em arquivos como planilhas do Excel um importante meio para a transferência de informações. Atualmente, o formato mais empregado na geração de tais arquivos é o Office Open XML, padrão este introduzido a partir do Office 2007 e que combina tecnologias como compactação zip e XML.

A manipulação de arquivos no padrão Open XML também é suportada pela plataforma .NET, com isto acontecendo por meio do framework Open XML SDK (o qual é fornecido pela própria Microsoft). Maiores informações sobre este tecnologia podem ser encontradas no link:

http://msdn.microsoft.com/en-us/office/bb265236.aspx

Embora as versões mais recentes do pacote Office enfatizem a utilização deste novo padrão de arquivos, em muitos casos os desenvolvedores se verão às voltas com arquivos ainda no formato .xls (Excel 97-2003). Quando isto ocorre, a alternativa mais comum está no uso de funcionalidades de Interop para o acesso a planilhas deste tipo.

O mecanismo conhecido Interop combina recursos da plataforma .NET e de uma tecnologia conhecida como COM, tendo como objetivo principal possibilitar a comunicação entre softwares instalados no sistema operacional Windows e projetos criados a partir do Framework. Também de autoria da Microsoft, o padrão COM (sigla de "Component Object Model") é anterior ao surgimento do próprio .NET, estando baseado no consumo de bibliotecas (arquivos .dll) registradas em um computador e que expõem uma ou mais funcionalidades genéricas.

Qualquer aplicação .NET que manipule arquivos .xls via Interop dependerá, por sua vez, da presença de componentes Office no ambiente em que será implantada. Contudo, a instalação de tais recursos nem sempre será possível em um cenário real de produção, fato este que pode se transformar num grande empecilho.

Levando em consideração tais fatos, foi concebido um projeto conhecido como NPOI, o qual viabiliza a realização de operações de leitura/escrita em planilhas do Excel, sem que isto implique na obrigação de instalar recursos do pacote Office (dispensando assim o uso de Interop). Atualmente, a biblioteca NPOI (que é gratuita) encontra-se na versão 2.0 beta 1, com suporte à geração de arquivos nos formatos .xls, .xlsx (Excel 2007-2010) e .docx (Word 2007-2010). Maiores informações podem ser obtidas através do seguinte link:

http://npoi.codeplex.com/

O objetivo deste artigo é descrever a geração de arquivos .xls a partir das classes disponibilizadas pelo projeto NPOI. Para isto, será criada uma aplicação de testes que utiliza um arquivo do Excel 97-2003 como template; a partir de cópias deste último serão geradas novas planilhas, as quais conterão informações de um catálogo de produtos.

Criando a Aplicação de Testes

Com intuito de demonstrar a manipulação de planilhas .xls a partir da biblioteca NPOI, será criado um projeto do tipo Windows Forms Application chamado TesteExcelNPOI. O desenvolvimento desta aplicação foi efetuado por meio da utilização do Microsoft Visual Studio 2012 Professional, além do NPOI 2.0 beta 1 (este último poderá ser baixado a partir do link indicado anteriormente neste artigo).

Uma vez que o projeto TesteExcelNPOI tenha sido gerado, incluir neste último referências que apontem para as bibliotecas NPOI.dll (Figura 1) e System.Configuration.dll (Figura 2). A primeira destas dlls contempla os mecanismos de geração e leitura de arquivos disponibilizados pelo Open XML SDK. Já a segunda biblioteca será usada na manipulação de um arquivo de configurações, o qual contém definições utilizadas na execução da aplicação de testes.

Adicionando ao projeto uma referência à biblioteca NPOI.dll

Figura 1: Adicionando ao projeto uma referência à biblioteca NPOI.dll

Adicionando ao projeto uma referência à biblioteca System.Configuration.dll

Figura 2: Adicionando ao projeto uma referência à biblioteca System.Configuration.dll

Implementação das classes contendo informações de produtos

O exemplo que está sendo desenvolvido neste arquivo tem por meta permitir a geração de planilhas contendo informações sobre um catálogo de produtos. Trata-se da adaptação de uma outra aplicação que desenvolvi anteriormente, em um artigo que abordava o framework Open XML SDK:

http://www.devmedia.com.br/excel-e-open-xml-sdk-gerando-novas-planilhas-xlsx-a-partir-de-templates/25854

Para os diferentes itens comercializados foram levados em conta dados como o código de barras, o nome do produto em questão, a categoria/tipo deste, a data em que o mesmo foi cadastrado no catálogo, além de sua quantidade atual em estoque e seu preço unitário de venda. A representação deste conjunto de informações será feita por meio da classe Produto, cuja implementação está detalhada na Listagem 1.

Listagem 1: Classe Produto

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TesteExcelNPOI
{
    public class Produto
    {
        public string CodigoBarras { get; set; }
        public string NomeProduto { get; set; }
        public string Categoria { get; set; }
        public DateTime DataCadastro { get; set; }
        public int QtdEstoque { get; set; }
        public double PrecoVenda { get; set; }
    }
}

Já na Listagem 2 está a definição do tipo CatalogoProdutos. Esta classe estática disponibiliza um método chamado ObterCatalogo, a partir do qual serão retornados todos os itens que se encontram no catálogo (instâncias baseadas no tipo Produto).

Conforme pode ser facilmente observado, o código que implementa a operação estática ObterCatalogo tem validade apenas para efeitos de simulação. Em um caso real, as informações correspondentes seriam geralmente obtidas a partir de uma base de dados (via mecanismos de acesso como o Entity Framework ou, até mesmo, a partir de estruturas mais básicas disponibilizadas pela tecnologia ADO.NET).

Listagem 2: Classe CatalogoProdutos

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TesteExcelNPOI
{
    public static class CatalogoProdutos
    {
        public static List<Produto> ObterCatalogo()
        {
            // Inicialização da coleção de objetos
            List<Produto> _Produtos = _Produtos = new List<Produto>();

            // Criação de produtos que serão vinculados
            // à coleção de objetos
            Produto produto;

            produto = new Produto();
            produto.CodigoBarras = "7890000000111";
            produto.NomeProduto = "Iron Maiden - Powerslave";
            produto.Categoria = "CDs";
            produto.DataCadastro = new DateTime(2012, 09, 19);
            produto.QtdEstoque = 37;
            produto.PrecoVenda = 44.90;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000222";
            produto.NomeProduto = "Metallica - Black Album";
            produto.Categoria = "CDs";
            produto.DataCadastro = new DateTime(2012, 09, 10);
            produto.QtdEstoque = 45;
            produto.PrecoVenda = 39.95;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000333";
            produto.NomeProduto = "Invictus";
            produto.Categoria = "DVDs";
            produto.DataCadastro = new DateTime(2012, 09, 03);
            produto.QtdEstoque = 7;
            produto.PrecoVenda = 16.90;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000444";
            produto.NomeProduto = "Uma Mente Brilhante";
            produto.Categoria = "DVDs";
            produto.DataCadastro = new DateTime(2012, 08, 20);
            produto.QtdEstoque = 18;
            produto.PrecoVenda = 29.90;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000555";
            produto.NomeProduto = "Trilogia Senhor dos Anéis";
            produto.Categoria = "Blu-Ray";
            produto.DataCadastro = new DateTime(2012, 08, 13);
            produto.QtdEstoque = 34;
            produto.PrecoVenda = 129.90;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000666";
            produto.NomeProduto = "Box Star Wars - 6 episódios";
            produto.Categoria = "Blu-Ray";
            produto.DataCadastro = new DateTime(2012, 08, 06);
            produto.QtdEstoque = 55;
            produto.PrecoVenda = 299.90;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000777";
            produto.NomeProduto = "A Arte da Guerra";
            produto.Categoria = "Livros";
            produto.DataCadastro = new DateTime(2012, 07, 27);
            produto.QtdEstoque = 10;
            produto.PrecoVenda = 10.00;
            _Produtos.Add(produto);

            produto = new Produto();
            produto.CodigoBarras = "7890000000888";
            produto.NomeProduto = "Transformando Suor em Ouro";
            produto.Categoria = "Livros";
            produto.DataCadastro = new DateTime(2012, 07, 20);
            produto.QtdEstoque = 17;
            produto.PrecoVenda = 24.90;
            _Produtos.Add(produto);

            // Devolve a coleção de objetos como resultado
            return _Produtos;
        }
    }
}

Criando a planilha que será utilizada como modelo

Prosseguindo com a construção do projeto de exemplo, será montado agora o arquivo .xls que funcionará como modelo/template, a fim de permitir com isto a geração de planilhas contendo informações do catálogo de produtos.

A Figura 3 exibe uma aparência possível para este documento. Notam-se no mesmo as seguintes características:

  • A presença de uma única planilha chamada “Catálogo”;
  • Duas linhas de cabeçalho, com a segunda destas contendo os títulos de cada coluna existente;
  • As demais linhas que corresponderão às informações do catálogo não foram preenchidas com dados. O único ajuste realizado aqui está no formato empregado para cada coluna. Os campos “Cód. Barras”, “Nome do Produto” e “Categoria” são do tipo texto; “Data Cadastro” conterá datas, baseando-se para isto no padrão dd/mm/aaaa; “Qtd. Estoque” será um valor numérico inteiro; já a coluna “Preço Venda” armazenará valor monetários com 2 casas decimais.
Criando o arquivo de modelo Template_CatalogoProdutos.xls

Figura 3: Criando o arquivo de modelo Template_CatalogoProdutos.xls

Será preciso também definir um parâmetro (“TemplateArquivoExcelProdutos”) dentro da seção appSettings, no arquivo app.config do projeto. Nesta configuração será especificado o caminho completo do documento que funcionará como template (Listagem 3).

Listagem 3: Arquivo app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0"
             sku=".NETFramework,Version=v4.5" />
    </startup>
  <appSettings>
    <add key="TemplateArquivoExcelProdutos"
         value="C:\Devmedia\Template_CatalogoProdutos.xls"/>
  </appSettings>
</configuration>

Classes da biblioteca NPOI empregadas na manipulação de planilhas .xls

Na Tabela 1 estão listados alguns tipos do framework NPOI comumente utilizados na manipulação de arquivos do Excel.

Tipo Finalidade
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
15/04/2013 10:07:00





Artigo - Grids em ASP.NET MVC: utilizando o plugin Backgrid.js

A exibição de informações num formato tabular é, certamente, uma necessidade mais do que frequente na esmagadora maioria das aplicações voltadas à Internet.

Muitos controles (proprietários ou gratuitos) foram desenvolvidos procurando atender a este tipo de demanda. Diversas dessas soluções foram construídas sob a tecnologia JQuery, o que torna mais fácil a integração destas a sites concebidos nas mais diferentes plataformas. O plugin Backgrid.js é uma biblioteca com estas características, o que o transforma numa alternativa viável para a implementação de grids em aplicações ASP.NET MVC.

Atualmente na versão 0.2.0 (Abril/2013), a biblioteca Backgrid.js se destaca por procurar fornecer suporte aos seguintes recursos:

  • A leitura de informações no formato JSON, o qual é suportado pelas principais plataformas de desenvolvimento;
  • A paginação dos dados vinculados a uma grid;
  • A ordenação crescente/decrescente dos dados associados a uma grid, bastando para isto um simples clique no cabeçalho de uma coluna/campo;
  • Mecanismos para inclusão, alteração e/ou exclusão de registros.

Maiores informações (inclusive instruções para download e utilização da biblioteca) podem ser obtidas através do link:

http://wyuenho.github.io/backgrid/

O objetivo deste artigo é abordar a utilização do plugin Backgrid.js em uma aplicação ASP.NET MVC, permitindo assim a construção de grids que contem com funcionalidades de paginação e ordenação de dados. Isto implicará no uso da tecnologia ADO.NET (acessando um banco de dados SQL Server) e de JSON durante a implementação do site para testes.

Criando a solução de exemplo

A aplicação apresentada neste artigo foi criada a partir do Visual Studio 2012 Professional, fazendo uso para isto do .NET Framework 4.5 e da versão 4.0 do ASP.NET MVC. O exemplo a ser implementado fará uso de um banco de dados SQL Server (Northwind) via ADO.NET, com a conversão do resultado de uma consulta a informações de clientes para o formato JSON; serão estes dados a base para o preenchimento da grid criada por meio do plugin Backgrid.js.

Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New e, por fim, a opção Project. Dentro da tela New Project (Figura 1) selecionar o template ASP.NET MVC 4 Web Application, preenchendo o campo Name com o nome da aplicação a ser gerada (“TesteGridMVC”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.

Criando um projeto ASP.NET MVC 4 para testes

Figura 1: Criando um projeto ASP.NET MVC 4 para testes

Aparecerá então uma janela como a que consta na Figura 2. Deverão ser escolhidos o template para a criação do projeto (selecionar “Internet Application”), assim como o Engine utilizado para a geração das Views (marcar a opção “Razor”).

Criando um projeto ASP.NET MVC 4 para testes

Figura 2: Criando um projeto ASP.NET MVC 4 para testes

Configurando o acesso à base de dados

Para a obtenção das informações utilizadas pela aplicação de exemplo será empregado o banco de dados Northwind. Maiores informações sobre como habilitar esta base para uso no SQL Server 2012 podem ser encontradas no link:

http://msdn.microsoft.com/en-us/library/vstudio/8b6y4c7s.aspx

Com a base de dados já configurada, adicionar ao arquivo Web.config do projeto de testes a string de conexão “Nortwind” (conforme indicado na Listagem 1).

Listagem 1: Ajustes no arquivo Web.config da aplicação

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  ...

  <connectionStrings>
    <add name="Northwind"
        connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True"
        providerName="System.Data.SqlClient" />
  </connectionStrings>

  ...

</configuration>

Implementando as classes de acesso a dados

Com o projeto TesteGridMVC já criado e o acesso à base de dados devidamente configurado, chega o momento de prosseguir com a criação dos tipos empregados na manipulação de informações sobre clientes. As estruturas descritas nesta seção pertencerão à camada Model (namespace TesteGridMVC.Models).

Primeiramente será implementada a classe Cliente (Listagem 2). Foram definidos neste tipo (sob a forma de propriedades) o código do cliente, o nome da empresa, o responsável por negociações, o endereço da companhia, a cidade, o país, além do telefone para contatos.

Listagem 2: Classe Cliente

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TesteGridMVC.Models
{
    public class Cliente
    {
        public string CodCliente { get; set; }
        public string NomeCliente { get; set; }
        public string Responsavel { get; set; }
        public string Endereco { get; set; }
        public string Cidade { get; set; }
        public string Pais { get; set; }
        public string Telefone { get; set; }
    }
}

Já na Listagem 3 está o código referente à classe ClienteDAO. Este tipo baseia-se em um padrão conhecido Data Access Object (DAO), tendo por função centralizar o acesso à base de dados para a manipulação de informações sobre clientes.

Listagem 3: Classe ClienteDAO

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;

namespace TesteGridMVC.Models
{
    public class ClienteDAO
    {
        public List<Cliente> ObterInformacoesClientes()
        {
            List<Cliente> resultado = new List<Cliente>();

            using (SqlConnection conexao =
                new SqlConnection(ConfigurationManager
                    .ConnectionStrings["Northwind"].ConnectionString))
            {
                SqlCommand cmd = conexao.CreateCommand();
                cmd.CommandText =
                    "SELECT CustomerID AS CodCliente " +
                            ",CompanyName AS NomeCliente " +
                            ",ContactName AS Responsavel " +
                            ",Address AS Endereco " +
                            ",City AS Cidade " +
                            ",Country AS Pais " +
                            ",Phone AS Telefone " +
                    "FROM Customers " +
                    "ORDER BY 2";

                conexao.Open();
                using (SqlDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        resultado.Add(new Cliente(){
                            CodCliente =
                                reader["CodCliente"].ToString(),
                            NomeCliente =
                                reader["NomeCliente"].ToString(),
                            Responsavel =
                                reader["Responsavel"].ToString(),
                            Endereco =
                                reader["Endereco"].ToString(),
                            Cidade =
                                reader["Cidade"].ToString(),
                            Pais =
                                reader["Pais"].ToString(),
                            Telefone =
                                reader["Telefone"].ToString()
                        });
                    }

                    reader.Close();
                }

                conexao.Close();
            }

            return resultado;
        }
    }
}

Será o método ObterInformacoesClientes (definido em ClienteDAO) que fornecerá os dados necessários para o preenchimento do controle gerado via plugin Backgrid.js. Quanto ao funcionamento desta operação, é possível observar:

  • A partir da variável “conexao” (instância do tipo System.Data.SqlClient.SqlConnection) é estabelecida uma conexão com a base de dados utilizada pela aplicação de exemplo (empregando para isto a string de conexão “Northwind”);
  • A referência de nome “cmd” (objeto do tipo System.Data.SqlClient.SqlCommand) representa a instrução SQL que fará a consulta à tabela de clientes;
  • Ao se invocar o método ExecuteReader do objeto associado à variável “cmd” uma nova instância da classe SqlDataReader (namespace System.Data.SqlClient) é gerada. Será por meio desta referência que os diferentes registros serão lidos, com a conversão de tais informações em instâncias do tipo Cliente;
  • Os objetos da classe Cliente são armazenados em uma coleção, a qual será devolvida como resultado da execução do método ObterInformacoesClientes.

Implementando o Controller que processará informações de clientes

Com os tipos da camada Model já definidos, deve-se proceder agora com a implementação do Controller que retornará os dados no formato JSON (possi

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
11/04/2013 10:49:00





Artigo - HTML Helpers: criando componentes Web customizados em ASP.NET MVC

O desenvolvimento de componentes para posterior reutilização é, sem sombra de dúvidas, uma prática bastante difundida dentro da área de software. Diversas são as vantagens decorrentes desta abordagem:

  • O reuso de código, evitando assim a existência de trechos com instruções repetidas ao longo de todo um sistema;
  • Uma maior facilidade para a manutenção de funcionalidades encapsuladas por um controle, visto que o código que implementa o mesmo encontra-se normalmente centralizado em um uma biblioteca específica;
  • Novas aplicações podem ser elaboradas combinando componentes já criados anteriormente, fato este que contribui para uma maior agilidade no desenvolvimento de tais projetos.

A própria plataforma ASP.NET dispõe de alternativas que permitem o desenvolvimento de novos componentes. No caso de aplicações baseadas na tecnologia Web Forms, são oferecidas opções para a construção de controles tanto a partir de recursos pré-existentes (via herança de classes), quanto por meio da combinação de vários componentes formando assim uma nova estrutura (User Controls). Já em projetos criados através do framework MVC, um dos meios possíveis para isto está na definição de HTML Helpers customizados.

Considerando o processo de implementação de Views no ASP.NET MVC, um HTML Helper pode ser definido, em termos gerais, como um tipo de funcionalidade que auxilia no trabalho com elementos HTML. Muito embora pareça fácil a simples inclusão de tags HTML no conteúdo de uma View, o grande benefício decorrente do uso de HTML Helpers está na simplicidade que os mesmos oferecem para a codificação de instruções mais complexas como:

  • A geração de links que apontam automaticamente para os locais corretos, partindo para isto de caminhos relativos;
  • A execução de forma transparente do processo de data binding (ligação) entre dados de objetos pertencentes à camada Model com campos HTML presentes em uma View;
  • Validações de dados presentes em um formulário HTML (dispensando em muitos casos a escrita de extensos trechos de código em Javascript).

Na prática, um HTML Helper nada mais é do que um método acionado a partir da propriedade Html (instância do tipo System.Web.Mvc.HtmlHelper), com isto acontecendo dentro de uma View. Como resultado da execução de tal operação, espera-se que a mesma retorne uma string contendo um trecho de código HTML.

A Listagem 1 apresenta um exemplo bastante simples de utilização de um HTML Helper. Neste caso, foi empregado o método CheckBox, o qual produzirá como retorno de sua execução um item/caixa para seleção (recebendo como parâmetro o id/nome do controle a ser gerado), com o texto “CheckBox de Exemplo” posicionado à direita do mesmo.

Listagem 1: Utilizando um HTML Helper em ASP.NET MVC

@Html.CheckBox("chkExemplo")
CheckBox de Exemplo

A finalidade deste artigo é demonstrar como HTML Helpers customizados podem ser criados, adicionando assim novas funcionalidades para a construção de Views em aplicações ASP.NET MVC. Buscando cumprir este objetivo, será implementado um projeto de exemplo abordando os conceitos aqui descritos.

Criando a solução de exemplo

A aplicação apresentada neste artigo foi gerada a partir do Visual Studio 2012 Professional, utilizando para isto o .NET Framework 4.5, além da versão 4.0 do ASP.NET MVC. O exemplo aqui discutido procura demonstrar como um HTML Helper pode ser criado, a fim de possibilitar com isto o reuso de trechos de código HTML ao longo de uma ou mais aplicações.

Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New e, por fim, opção Project. Dentro da tela New Project (Figura 1) selecionar o template ASP.NET MVC 4 Web Application, preenchendo o campo Name com o nome da aplicação a ser gerada (“TesteHTMLHelper”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.

Criando um projeto ASP.NET MVC 4 para testes

Figura 1: Criando um projeto ASP.NET MVC 4 para testes

Aparecerá então uma janela como a que consta na Figura 2. Deverão ser escolhidos o template para a criação do projeto (selecionar “Internet Application”), assim como o Engine utilizado para a geração das Views (marcar a opção “Razor”).

Criando um projeto ASP.NET MVC 4 para testes

Figura 2: Criando um projeto ASP.NET MVC 4 para testes

Implementando um novo HTML Helper

Com o projeto TesteHTMLHelper já criado, chega o momento de prosseguir com a construção da classe em que será definido um novo HTML Helper. O objetivo é implementar um método que gere, como resultado de sua execução, um link (em código HTML) que permita ao usuário retornar a uma página em que se encontrava anteriormente; trata-se de uma funcionalidade de comportamento idêntico ao do botão “Voltar” dos browsers convencionais.

Para que isto seja possível, um novo projeto do tipo Class Library deverá ser criado, tendo por nome “TesteHTMLHelper.Html” (conforme indicado na Figura 3).

Criando a Class Library TesteHTMLHelper.Html

Figura 3: Criando a Class Library TesteHTMLHelper.Html

Como próximo passo, adicionar ao projeto referências aos assemblies System.Web e System.Web.Mvc (Figura 4). Este procedimento possibilitará a utilização das classes n

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
08/04/2013 09:35:00





Artigo - Efetuando o cache de Views no ASP.NET MVC

O tratamento de requisições enviadas a uma aplicação Web envolve, basicamente, o processamento de cada solicitação recebida e a produção dos resultados correspondentes. Sem sombra de dúvidas, ações deste tipo podem exigir, em determinados momentos, muito da infraestrutura associada a um website, sobretudo se considerada a performance do sistema em questão.

Em aplicações voltadas à Internet um aumento incomum no número de acessos pode, em muitos casos, comprometer seriamente a continuidade das operações. Dentre os prováveis desdobramentos disto estão falhas inesperadas durante o processamento de requisições ou, até mesmo, usuários que abandonam tais sistemas em virtude de problemas de lentidão.

Procurando uma melhor performance na consulta a informações acessadas com frequência, muitos servidores Web dispõe de mecanismos que possibilitam o armazenamento e o reuso de dados processados anteriormente, sendo esta técnica conhecida pelo nome de "caching". Na plataforma ASP.NET isto não é diferente, com as tecncologias Web Forms e MVC dispondo de recursos que permitem efetuar o cache de páginas ou, até mesmo, objetos para posterior reutilização.

O objetivo deste artigo é descrever como o cache de dados pode ser efetuado em aplicações ASP.NET MVC. Para isto, será implementado um exemplo que consome informações de um feed de notícias, de maneira que a atualização disto aconteça apenas em intervalos regulares de tempo.

Criando a solução de exemplo

A aplicação apresentada neste artigo foi criada a partir do Visual Studio 2012 Professional, fazendo uso para isto do .NET Framework 4.5 e da versão 4.0 do ASP.NET MVC. O exemplo aqui discutido procura abordar a construção de uma View em que será exibido um resumo das manchetes mais recentes disponibilizadas por um site de notícias. A atualização de tais dados ocorrerá periodicamente, de forma a evitar um novo processamento a cada vez que um usuário acessar a página inicial do Web site que estaremos implementando.

Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New e, por fim, opção Project. Dentro da tela New Project (Figura 1) selecionar o template ASP.NET MVC 4 Web Application, preenchendo o campo Name com o nome da aplicação a ser gerada (“TesteCacheMVC”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.

Criando um projeto ASP.NET MVC 4 para testes

Figura 1: Criando um projeto ASP.NET MVC 4 para testes

Aparecerá então uma janela como a que consta na Figura 2. Deverão ser escolhidos o template para a criação do projeto (selecionar “Internet Application”), assim como o Engine utilizado para a geração das Views (marcar a opção “Razor”).

Criando um projeto ASP.NET MVC 4 para testes

Figura 2: Criando um projeto ASP.NET MVC 4 para testes

Criação dos tipos utilizados na manipulação do feed de notícias

Com o projeto TestePartialViews já criado, chega o momento de prosseguir com a construção das classes utilizadas na manipulação das notícias que serão apresentadas aos usuários do site. As estruturas aqui criadas pertencerão à camada Model (namespace TesteCacheMVC.Models).

Muitos portais têm como prática comum disponibilizar serviços contendo um resumo de suas principais manchetes num determinado momento, utilizando para tanto um formato de dados conhecido como RSS. A partir disto, aplicações dos mais variados tipos podem consumir tais informações, oferecendo a seus respectivos usuários uma síntese do que pode estar acontecendo em um determinado canal de comunicação.

O formato RSS (sigla do inglês “Really Simple Syndication”) pode ser definido, em termos gerais, como uma implementação específica do padrão XML. Serviços baseados em RSS (e conhecidos popularmente como “feeds”) costumam ser empregados para a geração de notificações de atualizações em blogs, sites de notícias, dentre outros órgãos de informação.

Para o exemplo abordado por este artigo, estará sendo usado o feed de notícias econômicas do portal Yahoo: http://br.noticias.yahoo.com/rss/economia.

Primeiramente será implementada a classe Noticia (Listagem 1). Conforme pode ser observado, este tipo conta com uma estrutura bastante simples, servindo de base para a exibição de dados como o título, o link para acesso, a data de publicação, além de um resumo sobre as notícias mais recentes para o site considerado.

Listagem 1: Classe Noticia

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TesteCacheMVC.Models
{
    public class Noticia
    {
        public string Titulo { get; set; }
        public string Link { get; set; }
        public DateTime DataPublicacao { get; set; }
        public string Resumo { get; set; }
    }
}

Como próximo passo, adicionar ao projeto uma referência ao assembly System.ServiceModel (Figura 3). Este procedimento tornará o possível a utilização de classes voltadas à manipulação de feeds RSS e que se encontram definidas nesta biblioteca.

Adicionando uma referência à biblioteca System.ServiceModel

Figura 3: Adicionando uma referência à biblioteca System.ServiceModel

Já na Listagem 2 está o código que define a classe estática NoticiasReader. Este tipo será empregado na leitura de notícias de um feed, devolvendo através da operação ObterNoticias uma coleção de instâncias da classe Noticia.

Quanto ao método estático ObterNoticias, o mesmo foi estruturado para funcionar da seguinte maneira:

  • Inicialmente é gerada uma coleção de objetos do tipo Noticia;
  • Uma nova referência para a classe SyndicationFeed (namespace System.ServiceModel.Syndication) é gerada, invocando para isto o método estático Load. Esta última operação recebe como parâmetro um objeto do tipo XmlTextReader (namespace System.Xml), com a geração deste último tomando como base o endereço do feed RSS a ser consumido;
  • Com a instância do tipo SyndicationFeed, o conteúdo da propriedade Items deste objeto será lido dentro de um loop foreach. Esta propriedade nada mais é do que uma coleção de objetos baseados na classe SyndicationItem (namespace System.ServiceModel.Syndication); por meio destas referências serão geradas as instâncias do tipo Noticia, as quais correspondem ao conjunto de resultados esperado ao se acionar o método ObterNoticias;
  • Quanto aos objetos da classe SyndicationItem manipulados dentro da operação ObterNoticias, é possível observar o uso das propriedades Title (título de uma notícia), Links (endereço/link da notícia em questão), PublishDate (data em que a notícia foi publicada) e Summary (texto resumido descrevendo o conteúdo abordado por tal notícia).

Listagem 2: Classe NoticiasReader

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel.Syndication;
using System.Xml;

namespace TesteCacheMVC.Models
{
    public static class NoticiasReader
    {
        public static List<Noticia> ObterNoticias(
            string enderecoFeed)
        {
            List<Noticia> noticias = new List<Noticia>();
            
            SyndicationFeed feed = SyndicationFeed
                .Load(new XmlTextReader(enderecoFeed));
            foreach (SyndicationItem item in feed.Items)
            {
                noticias.Add(new Noticia()
                {
                    Titulo = item.Title.Text,
                    Link = item.Links.Count > 0 ?
                        item.Links[0].Uri.ToString() : null,
                    DataPublicacao = item.PublishDate.LocalDateTime,
                    Resumo = item.Summary.Text
                });
            }

            return noticias;
        }
    }
}

Ajustando o Controller que irá processar as Views da aplicação

Com os tipos da camada Model já definidos, deve-se proceder agora com o acerto do Controller responsável pelo processamento das diferentes Views deste projeto de exemplo (classe HomeController).

O primeiro passo será incluir uma configuração chamada “EnderecoFeedNoticias” na seção appSettings do arquivo Web.config (Listagem 3). Definir como valor deste item o endereço do feed de notícias a ser utilizado pela aplicação.

Listagem 3: Ajustes no arquivo Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>

    ...

    <add key="EnderecoFeedNoticias"
         value="http://br.noticias.yahoo.com/rss/economia"/>
  </appSettings>

  ...

</configuration>

Na Listagem 4 encontra-se o código que implementa o tipo HomeController.

Listagem 4: Classe HomeController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Configuration;
using TesteCacheMVC.Models;

namespace TesteCacheMVC.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [OutputCache(Duration = 120)]
        public PartialViewResult Noticias()
        {
            string enderecoFeed = ConfigurationManager
                .AppSettings["EnderecoFeedNoticias"];
            ViewBag.EnderecoFeedNoticias = enderecoFeed;
            return PartialView(NoticiasReader.ObterNoticias(
                enderecoFeed));
        }

        public ActionResult About()
        {
            return View();
        }

        public ActionResult Contact()
        {
            return View();
        }
    }
}

Estão definidas neste Controller as Actions:

  • Index:
  • corresponde à página inicial do site, a partir da qual também será possível a visualização da Partial View contendo as notícias mais recentes;
  • Noticias: Partial View que será processada e armazenada em cache durante dois minutos, evitando assim novos reprocessamentos a cada vez em que a View Index for acessada. Logo, um benefício direto da adoção de tal prática está em melhorar a performance na utilização da aplicação;
  • About: permite a visualização da página “Sobre”, a qual contém uma descrição resumida dos objetivos deste projeto de exemplo; Contact: responsável pelo processamento da View em que serão exibidas as informações para contato.

Diferente das demais operações implementadas em HomeController, a Action Noticias foi construída levando em conta os seguintes aspectos:

  • O resultado da execução da Action Noticias é um objeto do tipo PartialViewResult (namespace System.Web.Mvc), o qual é obtido ao se invocar o método PartialView. Uma Partial View é um tipo de estrutura cujo resultado de seu processamento (trechos de código HTML) pode ser utilizado dentro de uma outra View convencional;
  • O endereço do feed de notícias definido no arquivo Web.config é repassado ao método ObterNoticias da classe NoticiasReader, bem como associado a uma nova propriedade (“EnderecoFeedNoticias”) pertencente ao objeto dinâmico ViewBag;
  • É possível observar ainda que a coleção de instâncias do tipo Noticia é fornecida como parâmetro à operação PartialView, a fim de que tais objetos possam ser utilizados posteriormente pela Partial View de nome “Noticias” (com o intuito de gerar uma visualização das manchetes mais recentes que constam no feed RSS);
  • Por fim, o uso do atributo OutputCacheAttribute (namespace System.Web.Mvc) permite que o resultado da Partial View seja armazenado em cache por um período de dois minutos, especificando-se para isto o valor 120 (segundos) à propriedade Duration. Requisições subsequentes, ao longo do período especificado em Duration, retornarão a saída produzida ainda no processamento inicial. Expirado o tempo de dois minutos, o resultado em questão é descartado do cache, a fim de que uma nova solicitação force o reprocessamento da Partial View Noticias.

Na Tabela 1 estão relacionadas outras propriedades que podem ser configuradas ao se fazer uso do tipo OutputCacheAttribute:

Propriedade Tipo Descrição
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
31/03/2013 15:55:00





Artigo - Criando uma conta para acesso à plataforma Windows Azure

Buscando maior qualidade, redução de custos e alta disponibilidade em suas operações, muitas companhias têm enxergado soluções de cloud computing (“computação na nuvem”) como uma importante aposta tecnológica. Atenta a um mercado em expansão e que requer o desenvolvimento de aplicações robustas e interoperáveis, a Microsoft criou a plataforma Windows Azure.

Quanto ao conceito de cloud computing, o mesmo pode ser definido, em linhas gerais, como um modelo computacional em que serviços de software são oferecidos de maneira remota, normalmente através da Internet. Em tais casos, é comum a realização de acordos prévios entre os fornecedores de tais funcionalidades e seus respectivos consumidores, de forma a estabelecer limites de uso e garantias quanto à operação daquilo que se está contratando.

Dentre os motivos que têm levado as organizações a adotarem soluções na nuvem, merecem destaque fatos como a necessidade de se reduzirem os pesados custos comumente associados à infraestrutura de TI, além de um maior enfoque na condução de projetos de software (sem que isto implique num envolvimento direto em questões como o hardware necessário para viabilizar as operações).

Sendo uma plataforma na nuvem bastante robusta e abrangente, o Windows Azure oferece recursos como servidores para a hospedagem de aplicações (ASP.NET Web Forms, MVC, serviços WCF), bancos de dados relacionais (tecnologia SQL Azure), armazenamento de arquivos, serviços para autenticação/autorização de usuários, dentre outros mecanismos.

A finalidade deste artigo é demonstrar como uma conta para avaliação gratuita do Windows Azure pode ser criada. A realização deste procedimento irá possibilitar a realização de testes por um período de 90 dias.

Efetuando o cadastro para a avaliação gratuita do Windows Azure

Inicialmente, será necessário acessar a página da plataforma Windows Azure (Figura 1), a qual está localizada no seguinte endereço: http://www.windowsazure.com/pt-br/.

Página inicial da plataforma Windows Azure

Figura 1: Página inicial da plataforma Windows Azure

Clicando no botão “teste gratuitamente” é apresentada uma tela (Figura 2) com os diversos recursos previstos na avaliação gratuita da plataforma Azure.

Recursos da avaliação gratuita do Windows Azure

Figura 2: Recursos da avaliação gratuita do Windows Azure

Acionar então novamente a opção “teste gratuitamente”. Neste momento, será solicitada uma conta de acesso da Microsoft - antigo “Windows Live ID” (Figura 3); este login representa a base para o acesso aos diversos serviços disponibilizados remotamente pelo Windows Azure.

Informando uma conta para acesso ao Windows Azure

Figura 3: Informando uma conta para acesso ao Windows Azure

Uma vez fornecidos os dados para autenticação, aparecerá uma tela (Figura 4) para a criação da conta de acesso aos serviços da plataforma Windows Azure. Como é possível observar, estão listados os diferentes recursos previstos dentro da avaliação gratuita, além dos pré-requisitos, como um número de celular válido e um cartão de crédito (apenas para questões de comprovação de identidade).

Recursos da Avaliação gratuita do Windows Azure

Figura 4: Recursos da Avaliação gratuita do Windows Azure

Clicando no botão avançar (“seta que aponta para a direita”), aparecerá um formulário para o preenchimento do número de celular (Figura 5). O código de verificação que habilitará o acesso ao Windows Azure pode ser enviado tanto por mensagem de texto (opção escolhida neste exemplo), quanto através de uma ligação telefônica.

Assim que o telefone for informado, a Microsoft transmitirá o código de verificação para o celular. Preencher este dado no campo apropriado, clicando por fim no botão “Verificar código”.

Informações telefônicas solicitadas durante a criação da conta

Figura 5: Informações telefônicas solicitadas durante a criação da conta

Concluindo o processo, será apresentado um formulário (Figura 6) em que deverão ser inseridos os dados de um cartão de crédito válido. Conforme já mencionado anteriormente, a avaliação gratuita se estende por um período de 90 dias; as informações do cartão apenas serão utilizadas em lançamentos de débito caso se opte por recursos não previstos neste processo (inicialmente tais dados funcionam apenas como um comprovante da identidade de um usuário).

Informações de cobrança solicitadas na criação da conta de acesso à plataforma Azure

Figura 6: Informações de cobrança solicitadas na criação da conta de acesso à plataforma Azure

Encerrada esta última etapa, o usuário será redirecionado para a página a partir da qual é possível o acesso aos diferentes recursos que compõem a plataforma Windows Azure (Figura 7).

OBSERVAÇÃO: Acessos posteriores às funcionalidades de gerenciamento/configuração dos serviços do Windows Azure serão realizados por meio

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
20/03/2013 09:05:00





Artigo - Testes Unitários no Visual Studio 2012

Por mais que a realização de testes se constitua numa atividade de fundamental importância dentro do desenvolvimento de sistemas, não é um fato raro que esse tipo de prática acabe negligenciado em muitos projetos de software. Inúmeros podem ser os motivos que conduzam a problemas deste gênero, sendo que as causas mais comuns costumam girar em torno de aspectos como tempo escasso, equipes reduzidas e sobrecarregadas em suas tarefas rotineiras, a falta de hábito em se proceder com testes mais abrangentes, dentre outros fatores.

A principal meta que está por trás do teste de um software é garantir que o produto gerado atenda aquilo que foi especificado para o projeto em questão. Em termos práticos, isto implica verificar se a aplicação considerada funciona de maneira correta, dentro de uma série de parâmetros definidos previamente: pessoas envolvidas com essas tarefas conduzem uma série de atividades validando funcionalidades, tentando a partir de tais ações encontrar falhas que produzam dados inconsistentes ou, até mesmo, defeitos que comprometam a operação do sistema. Sem a realização de procedimentos deste gênero, tais problemas poderiam passar despercebidos, com consequências imprevisíveis às operações rotineiras de uma organização.

Existem diferentes maneiras de se testar uma aplicação, com cada uma destas levando em conta aspectos como quais profissionais estarão executando o processo de validação ou ainda, a extensão do que estará sendo verificado. Tomando por base estes critérios, os diferentes tipos de testes de software podem ser classificados em:

  • Teste de unidade (também conhecido como teste unitário): é uma modalidade que se concentra na verificação das menores unidades em um projeto de software. O teste é realizado em uma unidade lógica, utilizando dados suficientes apenas para verificar a lógica da estrutura em questão. Unidades em uma linguagem de programação orientada a objetos podem ser identificadas como um método, uma classe ou ainda um objeto;
  • Teste de integração: procura apontar erros verificando os relacionamentos (interfaces) entre as diferentes partes (módulos) que compõem uma aplicação. Testes de integração costumam auxiliar na construção da estrutura de um programa, considerando para isto os requisitos definidos dentro do projeto correspondente;
  • Teste de sistema: conduzido de maneira a simular a operação de uma aplicação por usuários finais, baseando-se para isto num ambiente similar ao do sistema já em produção e na manipulação de dados e informações próximas àquilo que será processado no dia-a-dia;
  • Teste de aceitação: normalmente um grupo de usuários finais do sistema participa desse tipo de teste, visando com isto simular operações cotidianas que determinem se a aplicação está em conformidade com o que se espera para a mesma;
  • Teste de regressão: realizado quando do lançamento de novas versões de um software, de forma a checar se as mudanças introduzidas na aplicação não produziram efeitos colaterais na execução de funcionalidades pré-existentes.

Este artigo tem por meta discutir a importância dos testes unitários no desenvolvimento de software e, em especial, dentro da plataforma .NET. Para isto, será construída uma aplicação de exemplo que faz uso dos recursos Visual Studio 2012 voltados à execução de testes de unidade automatizados.

Desenvolvimento baseado em Testes Unitários: uma visão geral

Conforme mencionado na seção anterior, testes unitários são comumente empregados na checagem de métodos, classes e transições de estados dentro de sistemas orientados a objetos. O trecho de código que estará sendo testado é conhecido como “System Under Test” ou, na forma abreviada, SUT; é comum também o uso do termo CUT (“Class Under Test” ou “Code Under Test”).

São características comumente atribuídas aos testes unitários:

  • São automatizados e repetíveis;
  • Podem ser implementados facilmente;
  • Uma vez escritos, os testes devem ser mantidos para reuso futuro;
  • Qualquer profissional envolvido com o desenvolvimento de uma aplicação deve ser capaz de executá-los;
  • Facilmente acionáveis, geralmente isso acontece a partir de um botão ou item de menu dentro de uma IDE;
  • Rapidez na execução.

As principais plataformas de desenvolvimento atuais contam com diversos frameworks e funcionalidades que viabilizam a implementação e, consequentemente, a execução automatizada de construções deste tipo. No caso específico do .NET Framework, isto pode ser feito através do uso de frameworks como MS Test (parte integrante da própria plataforma .NET) e NUnit (http://nunit.org/).

Testes unitários representam inclusive a base para uma forma de desenvolvimento que tem ganhado bastante espaço, sobretudo com a crescente popularidade de metodologias ágeis como Scrum: trata-se do “Desenvolvimento Guiado por Testes” ou, simplesmente, TDD.

TDD (sigla do inglês “Test Driven Development”) é um processo para desenvolvimento de software que enfatiza, através de uma série de princípios propostos por metodologias ágeis, a construção de soluções em um modo no qual as mesmas poderão ser facilmente integradas a uma ferramenta de automação de testes unitários.

A escolha do TDD como uma prática de desenvolvimento implica, obrigatoriamente, na codificação dos testes unitários antes mesmo da escrita das partes da aplicação que serão submetidas aos mesmos. Por mais que um teste possa ser formulado após a codificação de uma funcionalidade, isto não é adotado em projetos em conformidade com os princípios de TDD: se tal teste fosse elaborado após o desenvolvimento do recurso a ser verificado, o mesmo poderia ser concebido de uma maneira “viciada”, considerando neste caso apenas a possibilidade de execução com sucesso da função que se está considerando.

A implementação de um projeto baseado em técnicas de TDD é feita seguindo um ciclo conhecido como Red-Green-Refactor, com cada um destes termos correspondendo a uma fase na construção dos testes:

  • Red: o teste é escrito logo no início do desenvolvimento, com a funcionalidade-alvo sequer tendo sido implementada (normalmente, apenas um “esqueleto” existirá, procurando assim se aproximar da estrutura esperada para a função em questão). O objetivo principal é que esse teste realmente falhe (daí o nome “Red”, um sinal “vermelho” para um problema), cumprindo assim a meta de evitar uma verificação “viciada”, que sempre resultaria em sucesso na sua execução;
  • Green: nesta fase é efetuada a codificação da forma mais simples possível, atendendo àquilo que se espera para uma funcionalidade, além de garantir que os testes associados serão executados com sucesso (sinal “verde”, indicando assim que não existem problemas);
  • Refactor: com os testes tendo passado na etapa anterior, é possível que se consiga refatorar o item sob análise, eliminando prováveis duplicações e melhorando a forma como o código se encontra estruturado. Se este não for o caso, o comum é que se passe para os próximos testes unitários.

Inúmeros são os benefícios decorrentes das práticas de TDD:

  • Um código mais claro, uma vez que os testes unitários geralmente efetuam checagens em porções menos extensas de código;
  • Quando bem estruturado, um teste acaba por servir como uma forma de se documentar o código, visto que a partir da leitura do mesmo é possível se ter uma noção do funcionamento de uma classe, método e/ou objeto;
  • Um rápido feedback, com alertas para problemas encontrados. Isto é possível devido ao fato dos diversos testes serem repetidos a cada novo ciclo de desenvolvimento/manutenção em uma aplicação;
  • Testes unitários asseguram uma cobertura adequada de diferentes trechos de código, algo que poderia não se conseguir somente através de testes de sistema ou de aceitação (com prováveis “bugs” aparecendo apenas quando a aplicação estivesse em produção);
  • Maior economia de tempo e de recursos financeiros na manutenção de uma aplicação, haja visto que diversas falhas acabam sendo apontadas (e solucionadas) ainda durante a etapa de desenvolvimento.

Diante do exposto, conclui-se facilmente que as técnicas de TDD, ao favorecer um código mais simples e de fácil manutenção, acabam por também contribuir para uma melhor assimilação de boas práticas de desenvolvimento/arquitetura de software:

  • Desenvolver de uma forma guiada por testes permite separar a lógica de negócios ou de acesso a dados das camadas gráficas de uma aplicação. A este tipo de princípio se dá o nome de Separação de Responsabilidades (do inglês “Separation of Concerns”), sendo que o mesmo busca fornecer, através de uma série de recomendações, diretrizes que conduzam à obtenção de aplicações formadas por componentes mais coesos;
  • Quanto à noção de coesão, este conceito deve ser compreendido como a medida com a qual uma estrutura de software (classe ou componente) atende o objetivo inicial para o qual foi concebida. Uma alta coesão indica que o item que se está considerando não acumula responsabilidades além daquelas para as quais foi especificado, sendo esta uma característica perseguida por todos os projetos de software que procuram ser bem estruturados. Assim, projetar testes unitários de uma maneira simples é também uma ação que contribui para a obtenção de classes mais coesas;
  • Acoplamento é outro conceito empregado para se determinar o grau de relacionamento entre diferentes partes que constituem uma aplicação. Um alto acoplamento resulta em um nível de alta dependência entre os diversos componentes envolvidos, fato este que pode levar a dificuldades na manutenção futura das funcionalidades consideradas. Logo, o ideal é que exista um baixo nível de acoplamento entre as estruturas que constituem um determinado elemento. Mais uma vez, testes unitários bem estruturados podem auxiliar no objetivo de conseguir classes com baixo acoplamento, de forma a diminuir assim as dependências entre diferentes componentes da solução que está tomando por base.

Utilizando Testes Unitários no Visual Studio 2012

A solução que está sendo apresentada neste artigo foi criada no .NET framework 4.5, através da utilização do Microsoft Visual Studio 2012 Professional. Basicamente, será implementada uma biblioteca para o cálculo de tributos federais como PIS, COFINS, ISS e IRPJ; estes impostos estão geralmente associados a operação fiscais que envolvam a prestação de seguros.

O primeiro passo para a implementação do exemplo baseado em testes unitários consiste na criação de uma Solution chamada “TesteNF”, conforme demonstrado na Figura 1.

Criando a Solution TesteNF

Figura 1: Criando a Solution TesteNF

A solução TesteNF será formada pelos seguintes projetos:

  • TesteNF.Utils: conterá a classe estática TributacaoHelper, a qual disponibiliza operações para o cálculo de impostos como PIS, COFINS, IRPJ e CSLL;
  • TesteNF.Utils.UnitTesting: aplicação onde estarão os diversos testes unitários responsáveis por verificar as funcionalidades da classe TributacaoHelper.

Uma vez gerado o arquivo correspondente à Solution TesteNF, deve-se prosseguir com a criação de um projeto do tipo Class Library e que terá por nome “TesteNF.Utils” (Figura 2).

Criando a Class Library TesteNF.Utils

Figura 2: Criando a Class Library TesteNF.Utils

Neste primeiro momento, será implementada no projeto TesteNF.Utils uma versão extremamente simples da classe TributacaoHelper, com todos os métodos para cálculo de impostos retornando zero como resultado de sua execução. O objetivo deste procedimento é justamente assegurar que a primeira bateria de testes unitários falhe, de maneira que apenas num segundo momento sejam codificados os cálculos necessários.

Na Tabela 1 estão indicados as alíquotas para cada um dos impostos calculados por meio do tipo TributacaoHelper.

ImpostoAlíquota
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
14/02/2013 10:36:00





Artigo - Utilizando LINQ e Extensions Methods para a leitura de arquivos XML

O formato XML (sigla em inglês para “Extensible Markup Language”) surgiu ainda no final dos anos 1990, sendo um padrão aberto voltado à geração de documentos hierárquicos e que conta com uma ampla adesão por parte de sistemas computacionais dos mais variados tipos.

Do ponto de vista estrutural, o padrão XML possui vários pontos em comum com a linguagem HTML, estando baseados em marcações (tags). Contudo, diferente de HTML em que há um conjunto pré-definido destes elementos, o formato XML pode ser definido como uma metalinguagem: em termos práticos, isso significa que não existem tags pré-definidas, com esses itens podendo ser definidos conforme necessidades específicas.

Um documento XML é formado por um conjunto de elementos (nodes), com as relações de dependência entre estes elementos sendo estabelecidas por meio de níveis hierárquicos. Todo elemento é constituído por uma tag e seu respectivo conteúdo. Quanto àquilo que consta em um elemento, o mesmo pode estar vazio, possuir atributos ou ainda, conter um agrupamento de outros elementos. Já um atributo nada mais é do que um par formado por um nome identificador e um valor correspondente (este último entre aspas), com estes dois itens separados por um sinal de “=” (“igual”), além de terem sido declarados dentro da tag que define um elemento.

A estrutura flexível oferecida pelo padrão XML é utilizada em larga escala em processos de integração entre sistemas via Web Services, no conteúdo de sites da Internet, em dispositivos móveis etc. Atualmente, este formato é suportado pelas principais linguagens de programação e sistemas operacionais, existindo diversas técnicas para a manipulação de dados neste padrão.

Considerando o caso específico da plataforma .NET, diversos métodos permitem a implementação de funcionalidades baseadas na leitura e/ou escrita de informações no padrão XML. LINQ to XML é uma dessas tecnologias, oferecendo vários meios que viabilizam a realização de operações sobre dados hierárquicos. Além daquilo que é oferecido nativamente pela extensão LINQ to XML, outras funcionalidades podem ainda ser implementadas com base neste mecanismo, sem que isto implique necessariamente em herdar classes pré-existentes a fim de incluir ou, até mesmo, redefinir comportamentos: isto é possível graças ao uso de construções de código conhecidas como "Extension Methods".

O objetivo deste artigo é discutir como Extension Methods podem ser combinados a expressões que envolvam o uso de LINQ to XML, simplificando assim o processo de leitura de informações contidas em documentos XML.

Conteúdo do arquivo XML utilizado nos exemplos

Na Listagem 1 é apresentado o conteúdo do arquivo XML (Prestadores.xml) em que se baseiam os exemplos apresentados mais adiante.

No arquivo “Prestadores.xml” constam dados de prestadores de serviço contratados junto a uma hipotética Consultoria de Tecnologia. É possível constatar neste documento XML a presença dos seguintes campos:

  • ID: Número inteiro que identifica um prestador de serviços;
  • CPF: CPF do profissional;
  • NomeProfissional: nome do prestador de serviços;
  • Empresa: empresa da qual o prestador é proprietário;
  • CNPJ: CNPJ da empresa prestadora de serviços;
  • Cidade: cidade em que está aberta a empresa prestadora;
  • Estado: estado da empresa prestadora;
  • InscricaoEstadual: inscrição estadual da empresa prestadora de serviços (o conteúdo deste campo é opcional);
  • ValorHora: valor recebido por hora trabalhada (preenchido quando o prestador de serviços ser pago de acordo como o número de horas trabalhadas);
  • ValorMensal: valor recebido mensalmente (preenchido quando o prestador de serviços for pago de acordo com um valor fixo mensal);
  • DataCadastro: data em que foi efetuado o cadastro do prestador de serviços;
  • InicioAtividades: data em que o prestador de serviços iniciou suas atividades (o conteúdo deste campo é opcional).

Listagem 1: Arquivo Prestadores.xml

<?xml version="1.0" encoding="utf-8"?>
<Prestadores>
  <Prestador>
    <ID>131</ID>
    <CPF>111.111.111-11</CPF>
    <NomeProfissional>JOÃO DA SILVA</NomeProfissional>
    <Empresa>SILVA CONSULTORIA EM INFORMÁTICA LTDA</Empresa>
    <CNPJ>11.111.111/1111-11</CNPJ>
    <Cidade>São Paulo</Cidade>
    <Estado>SP</Estado>
    <InscricaoEstadual>1111-1</InscricaoEstadual>
    <ValorHora>50,00</ValorHora>
    <ValorMensal></ValorMensal>
    <DataCadastro>03/01/2013</DataCadastro>
    <InicioAtividades>03/01/2013</InicioAtividades>
  </Prestador>
  <Prestador>
    <ID>132</ID>
    <CPF>222.222.222-22</CPF>
    <NomeProfissional>JOAQUIM DE OLIVEIRA</NomeProfissional>
    <Empresa>SERVIÇOS DE TECNOLOGIA OLIVEIRA ME</Empresa>
    <CNPJ>22.222.222/2222-22</CNPJ>
    <Cidade>Belo Horizonte</Cidade>
    <Estado>MG</Estado>
    <InscricaoEstadual></InscricaoEstadual>
    <ValorHora></ValorHora>
    <ValorMensal>10527,35</ValorMensal>
    <DataCadastro>03/01/2013</DataCadastro>
    <InicioAtividades></InicioAtividades>
  </Prestador>
  <Prestador>
    <ID>133</ID>
    <CPF>333.333.333-33</CPF>
    <NomeProfissional>MARIA MARTINS</NomeProfissional>
    <Empresa>MARTINS TECNOLOGIA LTDA</Empresa>
    <CNPJ>33.333.333/3333-33</CNPJ>
    <Cidade>Rio de Janeiro</Cidade>
    <Estado>RJ</Estado>
    <InscricaoEstadual>33333</InscricaoEstadual>
    <ValorHora>65,00</ValorHora>
    <ValorMensal></ValorMensal>
    <DataCadastro>04/01/2013</DataCadastro>
    <InicioAtividades>10/01/2013</InicioAtividades>
  </Prestador>
  <Prestador>
    <ID>134</ID>
    <CPF>444.444.444-44</CPF>
    <NomeProfissional>JOANA SANTOS</NomeProfissional>
    <Empresa>CONSULTORIA SANTOS LTDA</Empresa>
    <CNPJ>44.444.444/4444-44</CNPJ>
    <Cidade>São Paulo</Cidade>
    <Estado>SP</Estado>
    <InscricaoEstadual></InscricaoEstadual>
    <ValorHora></ValorHora>
    <ValorMensal>8474,77</ValorMensal>
    <DataCadastro>04/01/2013</DataCadastro>
    <InicioAtividades></InicioAtividades>
  </Prestador>
</Prestadores>

Definindo a classe que corresponde ao conteúdo do arquivo XML de Prestadores

A Listagem 2 apresenta a implementação da classe Prestador. Instâncias deste tipo equivalem, basicamente, aos dados contidos em cada elemento “Prestador” do documento XML de exemplo.

É possível notar ainda que campos opcionais dos tipos decimal e DateTime estão com um sinal de interrogação (“?”). Este recurso é conhecido como Nullable, permitindo a propriedades e variáveis que o utilizam armazenar também o valor null, por mais que estas tenham sido definidas a partir de um tipo primitivo (decimal) ou estruturado (DateTime). Sem o uso de uma Nullable tais referências assumiriam, se nenhum valor fosse associado às mesmas, o valor default para seus respectivos tipos (o número zero no caso de um decimal).

Listagem 2: Classe Prestador

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TesteExtensionMethodsXML
{
    public class Prestador
    {
        public int ID { get; set; }
        public string CPF { get; set; }
        public string NomeProfissional { get; set; }
        public string Empresa { get; set; }
        public string CNPJ { get; set; }
        public string Cidade { get; set; }
        public string Estado { get; set; }
        public string InscricaoEstadual { get; set; }
        public decimal? ValorHora { get; set; }
        public decimal? ValorMensal { get; set; }
        public DateTime DataCadastro { get; set; }
        public DateTime? InicioAtividades { get; set; }
    }
}

Implementando a leitura do documento XML via LINQ to XML

A classe estática ArquivoPrestadores (Listagem 3) representa a estrutura responsável por efetuar a leitura do arquivo XML, a fim de com isto gerar uma coleção de objetos do tipo Prestador.

O processamento do documento XML e a posterior geração de instâncias da classe Prestador acontece através do método CarregarInformacoes:

  • Inicialmente é gerada uma nova instância de XDocument (namespace System.Xml.Linq), a partir de uma chamada ao método Load, passando-se como parâmetro a este o nome do arquivo XML a ser carregado (parâmetro “arquivo”);
  • Prossegue-se agora com a geração das instâncias baseadas na classe Prestador. Isso é feito através de um loop foreach, acionando-se para isto o método Element a partir da instância do tipo XDocument; esta primeira ação irá selecionar o node “Prestadores”. Em seguida, invoca-se o método Elements, o qual irá retornar como resultado uma coleção de referências da classe XElement (namespace System.Xml.Linq) e que correspondem aos elementos de nome “Prestador” (subordinados ao node principal “Prestadores”);
  • A cada iteração do loop foreach é criada uma nova referência do tipo Prestador, atribuído ...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
06/02/2013 10:27:00





Artigo - Maturidade no desenvolvimento de software: CMMI e MPS-BR

O dia-a-dia dentro da área de desenvolvimento de software é caracterizado por uma grande pressão no que se refere a prazos de entrega, custos e qualidade daquilo que se está produzindo. Independente do tamanho das equipes voltadas a tarefas deste tipo, muitas organizações possuem dificuldades em gerenciar tais atividades, sendo comum a ocorrência de atrasos, estouros orçamentários e sistemas que ficam aquém do esperado.

Levando em consideração esses fatos, alguns modelos foram desenvolvidos de forma a auxiliar a condução de atividades que envolvam projetos de software. O objetivo deste artigo é fornecer uma visão geral sobre dois destes modelos (CMMI e MPS-BR), baseando-se para isto em um conceito conhecido como “maturidade”.

O termo “maturidade” deve ser compreendido como a capacidade de se repetir uma série de resultados de uma maneira previsível. Importante ressaltar ainda que os modelos CMMI e MPS-BR contemplam diferentes níveis de maturidade, disponibilizando-se assim uma forma de mensurar o grau de progresso atingido por uma organização na implementação de projetos de software.

CMMI

O CMMI (Capability Maturity Model Integration) foi criado pelo SEI (Software Engineering Institute), o qual é um órgão integrante da universidade norte-americana Carnegie Mellon. Trata-se de um modelo que está atualmente na versão 1.3 (Janeiro/2013), com um enfoque voltado para a capacidade de maturidade de processos de software.

Um processo representa, dentro da área de software, um conjunto de atividades cujo objetivo é atingir uma meta previamente estipulada. Já por capacidade e maturidade de um processo, deve-se ter a noção do grau de qualidade com o qual um processo atinge um resultado esperado.

O CMMI está dividido em 5 níveis de maturidade (Figura 1) que atestam, por sua vez, o grau de evolução em que uma organização se encontra num determinado momento. Além disso, tem por objetivo principal funcionar como um guia para a melhoria dos processos da organização, considerando para isto atividades como o gerenciamento do desenvolvimento de software, prazos e custos previamente estabelecidos. O objetivo maior, considerando o CMMI e seus diferentes conceitos, está justamente na produção de software com maior qualidade e menos propenso a erros.

Os diferentes níveis de maturidade do CMMI

Figura 1: Os diferentes níveis de maturidade do CMMI

Dentre os principais benefícios da implantação do CMMI, vale a pena destacar:

  • Uma maior confiabilidade no que refere ao cumprimento de prazos e custos que foram acordados, inicialmente, perante o cliente que solicitou o desenvolvimento de um sistema. Essa previsibilidade é decorrente do rigor que o CMMI exige quanto à medição dos processos, fato este que conduz à obtenção de uma base histórica realista e confiável para estes fins;
  • O gerenciamento das atividades relativas à produção de software aumenta consideravelmente;
  • Uma maior qualidade nos softwares criados, já que processos bem definidos e controlados conduzem à produção de produtos mais confiáveis;
  • A menor dependência da empresa de desenvolvimento para com seus especialistas. Com um foco voltado para processos e melhoria contínua, além do uso intensivo de informações históricas, a organização deixa de depender única e exclusivamente de profissionais com um elevado grau de conhecimento técnico;
  • A busca por melhorias contínuas nos processos cotidianos.

Para se conseguir

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
22/01/2013 10:49:00





Artigo - Utilizando um Banco de Dados para Testes no SQL Server 2012

O surgimento dos bancos de dados relacionais revolucionou, sem sombra nenhuma de dúvidas, a forma como as organizações controlam suas atividades cotidianas. Este tipo de tecnologia viabilizou uma série de análises até então impensáveis, bem como permitiu a manipulação de grandes volumes de dados.

Do ponto de vista estrutural, um banco de dados relacional é definido como um repositório para armazenamento de informações que estão relacionadas de alguma forma. Tais dados estão normalmente agrupados logicamente sob a forma de tabelas, com cada uma destas sendo constituída por um conjunto de colunas (campos) e registros (linhas).

Através de instruções SQL (sigla do inglês "Structured Query Language") é possível a realização de operações consultando, inserindo, atualizando ou excluindo registros de uma tabela (comandos deste tipo fazem parte de um subconjunto de SQL conhecido como DML, sigla de "Data Manipulation Language").

Existem atualmente diversos produtos (proprietários ou de uso gratuito) voltados ao gerenciamento de bancos de dados. Além do SQL Server da Microsoft, podem ser mencionados como sistemas comercializados de grande aceitação o Oracle e o IBM DB2; já o Firebird, o PostgreSQL e o MySQL representam exemplos de soluções gratuitas que desfrutam de uma boa popularidade entre a comunidade de TI.

Para aqueles que estão habituados com o dia-a-dia da área de desenvolvimento de software ou, até mesmo, iniciando na mesma e tendo seus primeiros contatos com os bancos relacionais, é extremamente comum a necessidade de se utilizarem base de dados para a realização de testes. Na prática, isto costuma implicar na criação de um banco em que constarão tabelas, dados e ainda, outros tipos de estruturas como stored procedures, triggers e functions.

Considerando o SQL Server, por default este gerenciador não gera nenhuma base de testes ao ser instalado. Contudo, a equipe responsável pela evolução deste produto disponibiliza um banco de dados conhecido como Adventure Works, o qual já conta com uma estrutura em conformidade com as boas práticas de desenvolvimento, assim como estão inseridos no mesmo dados que possibilitam a execução dos mais variados tipos de testes.

Estão disponíveis algumas variantes do banco Adventure Works, sendo possível citar neste caso as seguintes versões:

  • AdventureWorks2012 Data File: banco de dados relacional, com toda uma estrutura e informações apropriadas para a realização de testes;
  • AdventureWorksDW2012 Data File: base que pode ser utilizada em aplicações de BI (sigla em inglês para “Business Intelligence”; termo também conhecido como “Inteligência Empresarial”). Conceitualmente falando, BI pode ser definido como um conjunto de técnicas que envolvem a coleta, o processamento e a geração de informações a partir de dados de operações cotidianas de uma organização. Este procedimento busca, assim, prover análises que auxiliem profissionais de gestão em atividades relacionadas à tomada de decisões.

O objetivo deste artigo é demonstrar como o banco “Ad

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
26/12/2012 00:48:00





Artigo - Visão geral das certificações do Visual Studio 2012 e .NET Framework 4.5

É de conhecimento de todos que grandes fornecedoras de soluções computacionais como Microsoft, Oracle, IBM e Cisco oferecem programas para a certificação em inúmeras tecnologias. Com tais iniciativas essas empresas procuram, em termos gerais, estabelecer parâmetros capazes de avaliar o nível real conhecimento de profissionais em um produto ou plataforma específicos.

Podem ser mencionados como fatores que atestam a importância das certificações na área de TI:

  • É um meio de se obterem conhecimentos de maneira abrangente e estruturada ou ainda, preencher lacunas de aprendizado;
  • Podem significar um diferencial em entrevistas, sendo utilizadas inclusive como critério de desempate na escolha por um candidato;
  • Atestam a disciplina e a capacidade de autoaprendizado do profissional;
  • Têm se tornado um requisito em muitas empresas de desenvolvimento; sobretudo naquelas que participam em licitações governamentais ou ainda, que estão buscando alguma tipo de parceria junto a um fornecedor de software/hardware;
  • Podem “abrir portas”, sobretudo quando a falta de uma maior experiência se revela um fator limitante.

Por enfatizar a busca e a consequente assimilação de novos conhecimentos, a certificação em uma tecnologia exige de um profissional:

  • Disciplina;
  • Auto-aprendizado (não basta apenas participar de um treinamento);
  • Paciência;
  • Conhecimento teórico e prático da tecnologia considerada;
  • A correta dosagem entre compreensão e memorização dos tópicos estudados;
  • Inglês técnico (muitas vezes uma prova pode não estar disponível em português ou mesmo não contar com uma tradução confiável; contudo, isto não implica na necessidade de se possuir um alto grau de proficiência na língua inglesa).

O planejamento para se conquistar uma certificação costuma envolver:

  • A participação em cursos presenciais voltados especificamente para este fim, muito embora esta prática seja opcional (exceto em situações nas quais a obrigatoriedade de um curso oficial seja um pré-requisito, o que não costuma ser o caso em certificações da Microsoft);
  • A realização de estudos por conta própria (fundamental em qualquer situação);
  • A utilização de livros voltados especificamente para um determinado exame. A Microsoft costuma publicar livros específicos para cada prova, sendo que estes são conhecidos como “Training Kits”;
  • A assimilação de conceitos teóricos e a realização de exercícios práticos emulando situações reais;
  • Efetuar o maior número possível de simulados, avaliando quais erros são cometidos de forma mais frequente; a partir disso, focar no estudo desses itens, enfatizando assim pontos em que há uma maior dificuldade de aprendizagem. Geralmente, a aquisição de um “Training Kit” contempla além do livro preparatório, um software contendo uma série de simulados. Alguns parceiros da Microsoft também comercializam este tipo de solução, podendo ser destacados neste caso as empresas MeasureUp (http://www.measureup.com/) e SelfTest (http://www.selftestsoftware.com/);
  • A participação em fóruns, grupos e listas de discussão (seja postando dúvidas ou ainda, acompanhando discussões iniciadas por outros usuários);
  • A elaboração de resumos e anotações sobre tópicos abordados pelo exame;
  • O agendamento da prova. No caso da Microsoft, a inscrição é realizada por meio do site da Prometric (http://www.prometric.com), empresa esta responsável pela aplicação de exames em um centro autorizado (durante o preenchimento das informações são exibidas todas as cidades brasileiras com estabelecimentos credenciados, bem como os respectivos endereços destes últimos). Importante destacar que a Prometric exige o pagamento pelo exame por meio do uso de um cartão de crédito internacional. Descontos e códigos promocionais podem ser concedidos através de “vouchers” (isto será discutido mais adiante);
  • E por fim, realizar a prova na data e local agendados previamente. Ao término da mesma será fornecido o resultado; em caso de reprovação, uma segunda tentativa implicará em um novo pagamento pelo mesmo exame em questão (a não ser que exista alguma campanha promocional, conforme será explicado mais adiante ao se considerar o caso das certificações Microsoft).

As novas certificações do Visual Studio 2012

O lançamento oficial da nova versão do Visual Studio no segundo semestre de 2012 trouxe uma série de novidades, tais como o suporte ao desenvolvimento de aplicações para o Windows 8 (através da nova interface conhecida como Metro), sites baseados em HTML 5, recursos visando uma maior produtividade no dia-a-dia dos progr

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
29/11/2012 15:24:00





Artigo - Criptografia em .NET: utilizando a classe Rijndael

Ataques envolvendo tentativas de roubo ou, até mesmo, a modificação indevida de informações representam uma ameaça constante em sistemas dos mais variados tipos. Senhas, mensagens de conteúdo sigiloso e números de cartões de crédito são apenas alguns exemplos de dados bastante visados pelos responsáveis em levar a cabo estas ações.

Diante de um cenário em que o acesso não autorizado a informações pode resultar em consequências imprevisíveis, muitas organizações empreendem grandes esforços buscando garantir a segurança de seus dados.

A criptografia é, sem sombra de dúvidas, uma das práticas mais difundidas para assegurar a integridade e a confidencialidade de informações. O conceito de integridade refere-se à garantia de que dados não serão alterados de forma acidental ou, mesmo, deliberadamente, em processos que envolvam a transmissão de informações de uma fonte a outra. Já a ideia de confidencialidade remete à noção de que elementos sem autorização não possuirão o acesso a dados classificados como restritos.

Basicamente, o processo de criptografia consiste na criação de uma codificação que protege um conjunto de informações, empregando para isto alguma espécie de algoritmo e configurações conhecidos apenas por um sistema (ou ainda, por prováveis aplicações relacionadas a este último).

Diversos algoritmos computacionais foram desenvolvidos ao longo do tempo. Tais métodos podem ser agrupados em duas formas de se proceder com a criptografia de dados:

  • Simétrica: envolve o uso de uma chave privada, a qual é compartilhada pelo mecanismo que gera um conjunto de dados criptografados, assim como por aquele que receberá tais informações. Na prática, isto significa que uma mesma chave será empregada tanto para encriptar, quanto para converter os dados protegidos ao seu estado original;
  • Assimétrica: emprega duas chaves de criptografia (pública e privada) e que estão relacionadas matematicamente entre si. Normalmente, informações são encriptadas por meio da chave pública, ao passo que a chave privada relacionada serve de base para se reverter a criptografia. A criptografia assimétrica oferece maior segurança que métodos simétricos, embora esteja normalmente associada à utilização de certificados digitais (o que envolverá custos adicionais para a aquisição deste tipo de serviço).

A plataforma .NET suporta nativamente os dois tipos de criptografia aqui descritos. Os diferentes recursos que permitem a proteção de informações seguindo estes princípios encontram-se no namespace System.Security.Cryptography. A classe Rijndael represente um bom exemplo de algoritmo simétrico .

O objetivo deste artigo é justamente demonstrar como o tipo Rijndael pode ser utilizado na criptografia de informações em aplicações .NET. Para isto será construído um projeto de testes, com funcionalidades que possibilitam encriptar e decodificar strings fornecidas por um usuário.

Criando a aplicação de exemplo

A solução apresentada neste artigo foi criada no .NET framework 4.5, através da utilização do Microsoft Visual Studio 2012 Professional.

Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New, sub opção Project. Dentro da tela New Project (Figura 1) selecionar o template Windows Forms Application, informando no campo Name o nome da aplicação a ser gerada (“TesteCriptografia”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.

Criando um projeto Windows Forms para testes

Figura 1: Criando um projeto Windows Forms para testes

Criação da classe utilizada para encriptar/decriptar textos

Com o projeto TesteCriptografia criado, será necessário prosseguir com a implementação das classe responsável por criptografar/descriptografar sequências de texto (este tipo será chamado de “CriptografiaHelper”).

A fim de gerar o arquivo necessário à codificação da classe CriptografiaHelper, clicar dentro do Solution Explorer com o botão direito do mouse sobre a aplicação TesteCriptografia, escolhendo em seguida no menu de atalho a opção Add, sub opção New Item. Neste momento será exibida a tela Add New Item (Figura 2); preencher o campo Name com “CriptografiaHelper.cs”.

Criando o arquivo para implementação da classe CriptografiaHelper

Figura 2: Criando o arquivo para implementação da classe CriptografiaHelper

Foram definidos no tipo estático CriptografiaHelper (Listagem 1) as seguintes operações envolvendo técnicas de criptografia simétrica:

  • CriarInstanciaRijndael: responsável pela criação de novas instâncias da classe Rijndael (namespace System.Security.Cryptography);
  • Encriptar: realiza a criptografia de texto normal, devolvendo como resultado uma string em que os diferentes bytes encriptados estão representados no formato hexadecimal;
  • ArrayBytesToHexString: converte um array de bytes em uma string, com cada elemento tendo sido transformado em um valor correspondente em texto hexadecimal;
  • Decriptar: efetua a decriptação de uma string, partindo do pressuposto que o valor a ser convertido é formado por uma sequência de caracteres representando o equivalente hexadecimal de um conjunto de bytes;
  • HexStringToArrayBytes: converte uma string com valores hexadecimais em um array cujos itens serão do tipo byte.

OBSERVAÇÃO: A fim de evitar problemas decorrentes da manipulação de caracteres especiais, optou-se pela conversão dos bytes criptografados para uma string no formato hexadecimal. Caso não se fizesse isto, haveria a probabilidade de ocorrerem erros ao se tentar decriptar uma string gerada anteriormente.

O método privado CriarInstanciaRijndael permite a geração de novos objetos do tipo Rijndael (através de uma chamada ao método estático Create), com essas instâncias sendo utilizadas pelas operações Encriptar e Decriptar.

A classe Rijndael é baseada em um algoritmo de mesmo nome e também conhecido como “Advanced Encryption Standard” (ou simplesmente “AES”); este padrão depende de uma chave e de um vetor de inicialização para a execução de operações de criptografia.

Um vetor de inicialização nada mais é do que um array de bytes que reforça, por meio de operações randômicas, a segurança em um processo de criptografia. O objetivo disto é dificultar o sucesso de ataques que buscam descobrir a chave que está sendo utilizada; normalmente, tais situações envolveriam a análise de diversas tentativas de encriptação/decriptação, procurando desse modo identificar algum padrão e assim se checar ao "segredo" empregado.

CriarInstanciaRijndael recebe como parâmetros duas strings, com a primeira destas correspondendo à chave de criptografia, ao passo que o segundo valor refere-se ao vetor de inicialização.

Ambos os parâmetros declarados em CriarInstanciaRijndael serão convertidos em arrays de bytes, invocando-se para isto o método GetBytes da propriedade ASCII, a qual pertence à classe estática Encoding (namespace System.Text). O conteúdo em bytes da chave será então associado à propriedade Key, já o valor do vetor de inicialização será atribuído à propriedade IV (sigla do inglês "Initialization Vector").

O algoritmo Rijndael suporte chaves de 128, 192 ou 256 bits; já para um vetor de inicialização, espera-se um valor formado por 128 bits. Pelo fato de cada caractere corresponder no padrão ASCII a 8 bits ou 1 byte, estão sendo efetuadas consistências para se garantir que a chave possua 16, 24 ou 32 caracteres, além do vetor de inicialização se basear em uma string com 16 caracteres.

Caberá à operação Encriptar executar a criptografia de textos utilizando instâncias da classe Rijndael. Este método recebe como parâmetros strings contendo a chave, o vetor de inicialização e um valor a ser encriptado.

Conforme pode ser observado, o processo de encriptação envolve as seguintes atividades:

  • Criação de uma instância da classe Rijndael (variável “algoritmo”), a qual é obtida realizando-se uma chamada ao método CriarInstanciaRijndael;
  • A invocação do método CreateEncryptor a partir da variável “algoritmo” irá gerar um objeto (referência “encryptor”) baseado na interface ICryptoTransform (namespace System.Security.Cryptography). Essa construção (interface ICryptoTransform) torna possível a execução de operações básicas de encriptação/decriptação;
  • A instanciação de um objeto (variável “streamResultado”) do tipo MemoryStream (namespace System.IO), de forma a possibilitar operações sobre um stream armazenado em memória. Stream é uma sequência de dados de qualquer tamanho; este tipo de estrutura representa a base a partir da qual a plataforma .NET permite a manipulação de arquivos e outros agrupamentos de informações;
  • A geração de uma referência ("csStream") da classe CryptoStream (namespace System.Security.Cryptography), empregando para isto os objetos do tipos MemoryStream e ICryptoTransform; além disso é utilizado o valor Write do enumeration CryptoStreamMode (namespace System.Security.Cryptography), indicando assim que o processo de criptografia procederá com a escrita de dados criptografados no objeto MemoryStream;
  • Uma instância do tipo StreamWriter é criada (variável “writer”), repassando-se ao construtor da mesma o objeto CryptoStream gerado no passo anterior; a invocação do método Write fará então que o valor associado ao parâmetro “textoNormal” seja criptografado;
  • Uma chamada ao método ArrayBytesToHexString, visando com isto converter um array de bytes (obtido através da operação ToArray do objeto MemoryStream) para uma string, em que cada posição equivale a um valor hexadecimal correspondente. Esta última ação encerra o processo de criptografia, retornando a quem invocou a operação Encriptar um texto já convertido.

Sobre o método privado ArrayBytesToHexString, é possível notar no mesmo a existência de uma chamada ao método estático ConvertAll da classe Array (namespace System). Este procedimento fará com que um array de bytes seja convertido numa construção equivalente, porém empregando o tipo string; o uso do formato "X2" permite a transformação de cada byte em uma string hexadecimal equivalente. Por fim, os itens do array de string são concatenados, gerando-se assim um texto criptografado.

O código da operação Decriptar é bastante semelhante à implementação do método Encriptar, contando apenas com algumas diferenças em virtude de se tratar de uma funcionalidade de decriptação:

  • Inicialmente é verificado se o texto a ser decriptado (parâmetro “textoEncriptado”) não corresponde a uma string vazia, bem como se o comprimento deste é valido (cada byte corresponde a duas posições de texto representado no formato hexadecimal; logo o tamanho da string em questão deve ser um número par);
  • Um objeto do tipo ICryptoTransform é então criado, acionando-se para isto o método CreateDecryptor a partir de uma instância da classe Rijndael;
  • Um MemoryStream também é gerado, baseando-se para isso num array de bytes obtido através da conversão do parâmetro "textoEncriptado" via método HexStringToArrayBytes;
  • Também será instanciado um objeto CryptoStream, utilizando neste caso as referências já criadas para os tipos MemoryStream e ICryptoTransform;
  • Finalmente, é gerada uma instância do tipo StreamReader (namespace System.IO), fornecendo-se ao construtor da mesma a referência CryptoStream obtida no passo anterior. A invocação do método ReadToEnd sobre o objeto StreamReader produzirá como resultado uma string cujo conteúdo já se encontra decriptado.

Quanto ao método HexStringToArrayBytes, esta operação recebe como parâmetro uma string criptografada e cujos bytes encontram-se representados no formato hexadecimal. HexStringToArrayBytes devolverá como resultado de seu processamento um array de bytes. Cada conjunto de 2 caracteres corresponde a um byte, de forma que esta informação é convertida através do método ToByte da classe Convert (repassando-se como parâmetros a esta última uma string de 2 caracteres, bem como o valor 16 que indica que se está sendo considerado um número na base hexadecimal).

Listagem 1: Classe CriptografiaHelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace TesteCriptografia
{
    public static class CriptografiaHelper
    {
        private static Rijndael CriarInstanciaRijndael(
            string chave, string vetorInicializacao)
        {
            if (!(chave != null && 
                  (chave.Length == 16 ||
                   chave.Length == 24 ||
                   chave.Length == 32)))
            {
                throw new Exception(
                    "A chave de criptografia deve possuir " +
                    "16, 24 ou 32 caracteres.");
            }

            if (vetorInicializacao == null ||
                vetorInicializacao.Length != 16)
            {
                throw new Exception(
                    "O vetor de inicialização deve possuir " +
                    "16 caracteres.");
            }

            Rijndael algoritmo = Rijndael.Create();
            algoritmo.Key =
                Encoding.ASCII.GetBytes(chave);
            algoritmo.IV = 
                Encoding.ASCII.GetBytes(vetorInicializacao);

            return algoritmo;
        }

        public static string Encriptar(
            string chave,
            string vetorInicializacao,
            string textoNormal)
        {
            if (String.IsNullOrWhiteSpace(textoNormal))
            {
                throw new Exception(
                    "O conteúdo a ser encriptado não pode " +
                    "ser uma string vazia.");
            }

            using (Rijndael algoritmo = CriarInstanciaRijndael(
                chave, vetorInicializacao))
            {
                ICryptoTransform encryptor =
                    algoritmo.CreateEncryptor(
                        algoritmo.Key, algoritmo.IV);

                using (MemoryStream streamResultado =
                       new MemoryStream())
                {
                    using (CryptoStream csStream = new CryptoStream(
                        streamResultado, encryptor,
                        CryptoStreamMode.Write))
                    {
                        using (StreamWriter writer =
                            new StreamWriter(csStream))
                        {
                            writer.Write(textoNormal);
                        }
                    }

                    return ArrayBytesToHexString(
                        streamResultado.ToArray());
                }
            }
        }

        private static string ArrayBytesToHexString(byte[] conteudo)
        {
            string[] arrayHex = Array.ConvertAll(
                conteudo, b => b.ToString("X2"));
            return string.Concat(arrayHex);
        }

        public static string Decriptar(
            string chave,
            string vetorInicializacao,
            string textoEncriptado)
        {
            if (String.IsNullOrWhiteSpace(textoEncriptado))
            {
                throw new Exception(
                    "O conteúdo a ser decriptado não pode " +
                    "ser uma string vazia.");
            }

            if (textoEncriptado.Length % 2 != 0)
            {
                throw new Exception(
                    "O conteúdo a ser decriptado é inválido.");
            }


            using (Rijndael algoritmo = CriarInstanciaRijndael(
                chave, vetorInicializacao))
            {
                ICryptoTransform decryptor =
                    algoritmo.CreateDecryptor(
                        algoritmo.Key, algoritmo.IV);

                string textoDecriptografado = null;
                using (MemoryStream streamTextoEncriptado =
                    new MemoryStream(
                        HexStringToArrayBytes(textoEncriptado)))
                {
                    using (CryptoStream csStream = new CryptoStream(
                        streamTextoEncriptado, decryptor,
                        CryptoStreamMode.Read))
                    {
                        using (StreamReader reader =
                            new StreamReader(csStream))
                        {
                            textoDecriptografado =
                                reader.ReadToEnd();
                        }
                    }
                }

                return textoDecriptografado;
            }
        }

        private static byte[] HexStringToArrayBytes(string conteudo)
        {
            int qtdeBytesEncriptados =
                conteudo.Length / 2;
            byte[] arrayConteudoEncriptado =
                new byte[qtdeBytesEncriptados];
            for (int i = 0; i < qtdeBytesEncriptados; i++)
            {
                arrayConteudoEncriptado[i] = Convert.ToByte(
                    conteudo.Substring(i * 2, 2), 16);
            }

            return arrayConteudoEncriptado;
        }
    }
}

Implementando a tela para testes

Concluída a codificação da classe CriptografiaHelper, será preciso agora renomear o formulário principal da aplicação. Isto é feito, dentro da janela Solution Explorer, clicando com o botão direito sobre o arquivo Form1.cs e selecionando a opção Rename: alterar então este nome de arquivo para FormPrincipal.cs. Tal procedimento fará com que a identificação da classe que corresponde ao formulário principal da aplicação também passe a ser FormPrincipal. Além disso, modificar por meio da janela Properties do Visual Studio a propriedade Text de FormPrincipal para “Teste de Criptografia - Utilizando a Classe Rijndael”.

Adicionar a este formulário os controles que se encontram listados na Tabela 1.

Tipo do ControleNome do Controle
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
26/11/2012 11:16:00





Artigo - Integração SQL Server 2012 x .NET: criando procedures utilizando código C#

Além de comandos para a consulta, inclusão, alteração e exclusão de informações, os principais bancos de dados relacionais contam ainda com mecanismos que estendem esses recursos básicos da linguagem SQL. Talvez uma das estruturas mais conhecidas desse tipo sejam as stored procedures (também chamadas de “procedimentos armazenados” ou, simplesmente, “procedures”).

Uma stored procedure é um objeto que combina instruções convencionais de acesso a dados a elementos como variáveis, estruturas de decisão e laços de repetição, conseguindo assim ampliar as capacidades oferecidas por comandos SQL padrão. Não existe, contudo, uma padronização quanto à forma como procedures são implementadas; cada fornecedor de banco de dados costuma disponibilizar um conjunto de recursos específicos e que, em muitos casos, não encontra paralelo em produtos similares da concorrência.

Podem ser citadas como vantagens proporcionadas pela utilização de stored procedures:

  • Uma maior performance em operações envolvendo dados, em virtude do fato de procedures permanecerem pré-compiladas dentro de um repositório de dados. Com isto se consegue uma maior velocidade de execução, visto que as instruções SQL utilizadas foram validadas no momento de criação da procedure, assim como tiveram seus respectivos planos de execução previamente montados. Esse comportamento não acontece com comandos SQL convencionais, em que a validação e elaboração de um plano de execução são processos repetidos a cada nova instrução SQL enviada ao banco de dados;
  • A redução do tráfego de dados em uma rede, através de operações que ficam centralizadas dentro do servidor de um banco. Isto pode ser um instrumento de grande valia, sobretudo ao se considerar processos de duração mais extensa e que englobem um grande volume de informações;
  • A possibilidade de reuso de procedures em várias aplicações que dependam de funcionalidades disponibilizadas por rotinas deste tipo;
  • Uma maior segurança na manipulação de informações, levando em conta a capacidade de administradores de bancos de dados concederem o direito de execução somente a stored procedures com uma finalidade específica (revogando dessa forma o acesso direto a prováveis tabelas contendo informações sensíveis);
  • Ainda sobre a questão da segurança, stored procedures são uma boa alternativa quando a meta é tornar uma aplicação menos sujeita a ataques de injeção de SQL (ou em inglês "SQL Injection"). Por receberem dados a serem processados sob a forma de parâmetros de entrada, construções deste tipo ajudam a evitar a ação de códigos que buscam causar danos às estruturas de uma base relacional.

Dentre as principais tecnologias de banco de dados da atualidade, o SQL Server é sem sombra de dúvidas uma das que conta com maior aceitação por parte do mercado. Por ser um produto robusto, escalável e extremamente flexível, não é de se estranhar que grandes corporações e órgãos governamentais façam uso de bancos de dados SQL Server em inúmeras aplicações de caráter crítico.

Sendo um banco de dados relacional, o SQL Server conta tanto com construções típicas da linguagem SQL (instruções baseadas nas cláusulas SELECT, INSERT, UPDATE e DELETE), quanto oferece mecanismos para a codificação de estruturas mais complexas. Neste último caso, objetos como stored procedures, triggers e functions são implementados utilizando uma extensão conhecida como T-SQL (sigla do inglês “Transact-SQL”).

Inúmeros foram os recursos introduzidos a partir da versão 2005 do SQL Server. Considerando o desenvolvimento voltado a banco de dados, merece destaque a integração que passou existir neste novo release com o Common Language Runtime (CLR) do .NET Framework: tornou-se possível desde então a criação de stored procedures, triggers e functions empregando linguagens compatíveis com a plataforma .NET, como C# ou VB.NET.

Procedures criadas em .NET permitem a realização de ações não suportadas por rotinas equivalentes escritas em Transact-SQL. Construções deste tipo são conhecidas como CLR Stored Procedures e, por serem baseadas em recursos da plataforma .NET, permitem a realização de operações como o acesso a diretórios, leitura/escrita de arquivos, criptografia, manipulação de arrays ou o tratamento de strings por meio de expressões regulares.

O objetivo deste artigo é demonstrar como procedures do SQL Server 2012 podem ser implementadas a partir de código .NET. Buscando cumprir essa meta, será apresentado um exemplo de implementação de uma stored procedure deste tipo através do Visual Studio.

Criando uma stored procedure através do Visual Studio

A solução apresentada neste artigo foi criada no .NET framework 4.5, através da utilização do Microsoft Visual Studio 2012 Professional. Basicamente, será construída biblioteca em que constará um método público definido em uma classe estática. Essa operação corresponde, por sua vez, à implementação da stored procedure a ser acionada a partir de comandos enviados a uma base do SQL Server.

Quanto ao funcionamento desta procedure, essa rotina receberá como parâmetro um diretório capaz de ser acessado pelo servidor SQL Server, produzindo como resultado de sua execução lista dos arquivos contidos em tal caminho (incluindo arquivos vinculados a subdiretórios da pasta-base).

Para gerar o projeto de testes será necessário, dentro do Visual Studio, acessar o menu File, opção New, sub opção Project. Dentro da tela New Project (Figura 1) selecionar o template SQL Server Database Project (que deve estar em “Installed > Templates > Other Languages > SQL Server”), informando no campo Name o nome da aplicação a ser gerada (“TesteCLRProcedure”, neste caso); no campo Location é possível ainda definir o diretório no qual serão criados os arquivos para este projeto.

Criando o projeto TesteCLRProcedure

Figura 1: Criando o projeto TesteCLRProcedure

Prosseguiremos agora com a implementação da procedure baseada em recursos do .NET Framework.

Clicar dentro do Solution Explorer com o botão direito do mouse sobre o projeto TesteCLRProcedure, escolhendo em seguida no menu de atalho a opção Add, sub opção New Item. Neste momento será exibida a tela Add New Item; selecionar do lado esquerdo o item “SQL CLR C#” e, após isto, o template “SQL CLR C# Stored Procedure”; preencher o campo Name com “SP_ListarArquivosDiretorio.cs”.

Criando a procedure SP_ListarArquivosDiretorio

Figura 2: Criando a procedure SP_ListarArquivosDiretorio

Como resultado dessa última ação, será criado o arquivo SP_ SP_ListarArquivosDiretorio.cs, em que estará o código que implementa uma procedure com este mesmo nome.

A operação SP_ListarArquivosDiretorio (Listagem 1) deve fazer parte de uma classe parcial chamada StoredProcedures. O uso desse tipo de construção (classes parciais) é próprio de projetos envolvendo a implementação de procedures por meio do Visual Studio, cabendo ao desenvolvedor apenas o trabalho de codificar as ações que serão disparadas ao se invocar tais rotinas.

Além do fato de estarem associadas a uma partial class, stored procedures baseadas em recursos do CLR possuem ainda as seguintes características:

  • O método que corresponde à procedure deve ser estático, assim como não devolver um valor (indicar isto através do uso da palavra-chave “void”);

  • Essas operações estarão obrigatoriamente marcadas com o atributo SqlProcedureAttribute (namespace Microsoft.SqlServer.Server);
  • Os tipos empregados na definição de parâmetros de entrada devem possuir equivalência dentro do SQL Server. Normalmente, isto não representará um problema, desde que partindo do pressuposto que serão utilizados apenas tipos primitivos ou mais simples (int, string, DateTime etc.).

No caso da procedure SP_ListarArquivosDiretorio, o método que define esta construção receberá como parâmetro de entrada uma string (referência “diretorio”) contendo um diretório a ser tomado como base. Foi especificado ainda o parâmetro de saída “qtdeArquivos”, no qual constará a quantidade de arquivos que existem no caminho informado ao se acionar a stored procedure.

Quanto ao funcionamento de SP_ListarArquivosDiretorio, é possível observar:

  • Inicialmente é criada uma variável chamada “nomeTabelaTemporaria”, atribuindo-se à mesma o nome da tabela temporária que servirá de base para a manipulação de dados so ...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
19/11/2012 16:37:00





Artigo - Debug de aplicações .NET e a propriedade InnerException

Durante o desenvolvimento de aplicações ou, mesmo, com um sistema já em operação, não é um fato incomum que ocorram erros. As prováveis causas disto podem ser as mais variadas possíveis: descuidos por parte de programadores envolvidos em um projeto, uma funcionalidade não concluída conforme o esperado ou ainda, falhas decorrentes de algum elemento externo ao próprio software (servidores de banco de dados inoperantes, problemas em uma rede corporativa, falha no acesso a Web Services etc.) são apenas alguns dos fatores que podem conduzir a situações inesperadas e, em muitos casos, indesejáveis.

Considerando as principais plataformas de desenvolvimento atuais (com destaque para .NET e Java), erros são representados através de objetos conhecidos como exceções. A gravação de dados relativos a exceções geradas por uma aplicação se revela como um instrumento de extrema importância, visto que a partir destas informações desenvolvedores terão meios para tentar reproduzir falhas que afetaram um sistema.

No .NET Framework informações sobre exceções estão associadas a objetos baseados no tipo Exception (namespace System). O comum é que existam diferentes classes que herdam dessa construção básica, com cada uma das mesmas estando normalmente vinculadas a um contexto bem específico.

Sobre a estrutura da classe Exception, esta última conta com algumas propriedades que detalham um erro gerado dentro de uma aplicação:

  • Message: mensagem que descreve o erro que levou ao lançamento da exceção que se está considerando;
  • InnerException: instância do tipo Exception que corresponde à falha original, estando associada a uma nova exceção. O preenchimento desta propriedade é opcional (logo, o valor desse elemento poderá ser “nul” em muitos casos);
  • StackTrace: string em que são listados os diferentes pontos pelos quais passou a aplicação antes de um erro. Graças a esta informação, é possível se rastrear a origem, bem como compreender melhor o que levou a esta situação anormal. Uma única ressalva deve ser feita quanto a disponibilizar essas informações a usuários, já que existirão tanto aqueles incapazes de entender o conteúdo desta propriedade, assim como outros que com conhecimentos mais avançados podem vir a explorar vulnerabilidades do sistema.

A seguir estão listados alguns exemplos de exceções bastante comuns em aplicações construídas sob o .NET Framework:

  • InvalidOperationException (namespace System): exceção que acontece quando a invocação de um método a partir de um objeto for inválida, normalmente devido a problemas com o estado atual em que este se encontra;
  • SqlException (namespace System.Data.SqlClient): geralmente lançada quando da ocorrência de erros em instruções enviadas a um banco de dados do SQL Server;
  • CommunicationException (namespace System.ServiceModel): representa erros em processos de comunicação envolvendo serviços, sendo bastante comum em soluções baseadas na tecnologia WCF (incluindo nisto aplicações-cliente que consomem funcionalidades de serviços deste tipo);
  • HttpUnhandledException (namespace System.Web): exceções deste tipo são lançadas quando erros não são tratados de modo apropriado dentro de aplicações Web;
  • ArithmeticException (namespace System): falha resultante de um erro durante o processamento de uma operação aritmética;
  • DivideByZeroException (namespace System): exceção derivada do tipo ArithmeticException, sendo disparada em casos que envolvem a tentativa de divisão de um número por zero;
  • OutOfMemoryException (namespace System): erro associado à falta de memória e que impossibilita a um programa de prosseguir com sua execução normal;
  • SecurityException (namespace System.Security): falha geralmente relacionada à detecção de problemas de segurança;
  • FileNotFoundException (namespace System.IO): corresponde a falhas ao se tentar realizar uma operação que acesse um arquivo;
  • DirectoryNotFoundException (namespace System.IO): exceção disparada quando um diretório que se está tentando acessar não existir.

A forma como estes problemas são registrados (técnica esta conhecida como "logging")

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
14/11/2012 16:39:00





Artigo - Carregando dados de forma mais eficiente com a classe SqlBulkCopy

Quando se leva em conta a necessidade de compartilhamento de informações entre diferentes sistemas, arquivos ainda são um meio ainda bastante comum de integração. Esse tipo de prática está normalmente associado ao processamento de um grande volume de dados, podendo tanto acontecer entre softwares de uma mesma companhia, quanto entre aplicações de organizações distintas.

Listas de preços geradas por um determinado fornecedor, lançamentos contábeis e/ou financeiros, movimentações bancárias e registros de folha de pagamento são apenas alguns exemplos comuns de agrupamento de dados comumente carregados em bases relacionais por meio de arquivos.

Existem inúmeras soluções que podem ser empregadas em cenários como os citados aqui. A própria Microsoft conta com o Integration Services, sendo este último um dos componentes do SQL Server. A grande vantagem deste serviço (Integration Services) está em permitir que se obtenham aplicações robustas e extremamente flexíveis no que se refere processamento de informações.

Ainda sobre o Integration Services, merece destaque o fato de que o mesmo dispõe de mecanismos capazes de processar grandes massas de dados organizadas sob a forma dos mais variados tipos de arquivos, sem que isto implique em grandes esforços de implementação. São suportados, neste caso, formatos como texto (em que cada posição pode corresponder a um campo/informação), CSV (sigla do inglês "Comma-separated values", com os diferentes valores de cada linha estando separados neste caso por ponto-e-vírgula), XML ou ainda, planilhas do Excel e bancos de dados Access.

No entanto, nem sempre será possível se contar com ferramentas que simplificam a importação de dados presentes em arquivos. Se o gerenciador de banco de dados utilizado for o SQL Server, a classe SqlBulkCopy do .NET Framework (namespace System.Data.SqlClient) pode se revelar como um instrumento de grande valia em tais situações.

Partindo de objetos dos tipos DataReader, DataTable ou DataRow, a classe SqlBulkCopy fornece meios para a carga eficiente de grandes volumes de dados em tabelas do SQL Server. Além disso, a performance conseguida através de instâncias da classe SqlBulkCopy costuma se mostrar bem superior, sobretudo se comparada à execução de centenas de instruções SQL através de referências to tipo Command ou ainda, com mecanismos como LINQ to SQL ou o Entity Framework.

A finalidade deste artigo é demonstrar como o tipo SqlBulkCopy pode ser utilizado na importação do conteúdo de arquivos para bases de dados do SQL Server. Visando cumprir este objetivo, será apresentado um exemplo prático de como se proceder com a carga de um arquivo com a extensão .csv.

Criando uma aplicação que faz uso da classe SqlBulkCopy

A solução apresentada neste artigo foi criada no .NET framework 4.5, através da utilização do Microsoft Visual Studio 2012 Professional.

Basicamente, será construída uma Console Application de nome “TesteSqlBulkCopy (Figura 1), a qual será responsável por importar informações de um arquivo .csv contendo preços de produtos comercializados por um estabelecimento comercial.

Criando o projeto TesteSqlBulkCopy

Figura 1: Criando o projeto TesteSqlBulkCopy

Num cenário real, este catálogo de produtos poderia estar sendo gerado por um fornecedor da empresa considerada, englobando neste caso um número extenso de itens que seriam reprocessados a cada novo arquivo recebido (ao menos para os testes aqui descritos, será efetuada a carga de um arquivo com poucos itens, somente para efeitos de simulação).

Uma vez que a solução e o projeto correspondente tenham sido gerados, faz-se necessária a inclusão de uma referência para a biblioteca System.Configuration (Figura 2). Este ajuste foi efetuado de maneira que se possam acessar funcionalidades disponibilizadas pelo tipo ConfigurationManager (conforme será demonstrado durante a implementação das classes que compõem a aplicação).

Adicionando ao projeto uma referência à biblioteca System.Configuration

Figura 2: Adicionando ao projeto uma referência à biblioteca System.Configuration

Quanto à estrutura das informações presentes no catálogo de produtos, o arquivo .csv em que constarão tais registros possuirá as seguintes colunas (já mencionadas aqui na ordem esperada pela aplicação de exemplo):

  • Código de barras do produto;
  • Nome do produto;
  • Categoria (corresponde ao tipo de um produto: CDs, DVDs, Blu-Ray, Livros);
  • Data em que o produto passou a fazer parte do catálogo;
  • Quantidade disponível para comercialização;
  • Preço de venda sugerido.

Na Figura 3 está um exemplo de como seria este arquivo.

OBSERVAÇÃO: Para efeito de testes, a aplicação de exemplo irá sempre procurar por um arquivo de nome “AtualizacaoCatalogo.csv” no diretório “C:\Temp\Catalogo\”.

Arquivo .csv contendo o catálogo de produtos

Figura 3: Arquivo .csv contendo o catálogo de produtos

A estrutura da tabela que receberá as informações do arquivo AtualizacaoCatalogo.csv é apresentada na Listagem 1. Conforme será demonstrado mais adiante, está se partindo do pressuposto que essa estrutura (TB_CARGA_CATALOGO) faz parte de um banco de dados também chamado “TesteSqlBulkCopy”.

Listagem 1: Estrutura da tabela TB_CARGA_CATALOGO

CREATE TABLE [dbo].[TB_CARGA_CATALOGO](
	[CodigoBarras] [varchar](13) NOT NULL,
	[NomeProduto] [varchar](50) NOT NULL,
	[Categoria] [varchar](30) NOT NULL,
	[DtIniComercializacao] [datetime] NOT NULL,
	[QtdDisponivel] [int] NOT NULL,
	[VlSugerido] [decimal](10,2) NOT NULL,
	CONSTRAINT [PK_TB_CARGA_CATALOGO] PRIMARY KEY ([CodigoBarras])
)

Já na Listagem 2 está o arquivo app.config do projeto TesteSqlBulkCopy. Encontram-se declarados no mesmo os seguintes itens:

  • Uma ConnectionString de nome “TesteSqlBulkCopy”, a qual aponta para a base em que serão importadas as informações de produtos;
  • O caminho em que consta o arquivo .csv correspondente ao catálogo de produtos (configuração “CaminhoArquivoCatalogo”).

Listagem 2: Arquivo app.config da aplicação TesteSqlBulkCopy

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="TesteSqlBulkCopy"
         providerName="System.Data.SqlClient"
         connectionString="Data Source=.;Initial Catalog=TesteSqlBulkCopy;Integrated Security=True"/>
  </connectionStrings>
  <appSettings>
    <add key="CaminhoArquivoCatalogo"
         value="C:\Temp\Catalogo\AtualizacaoCatalogo.csv"/>
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0"
                      sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>

Com as diferentes configurações do projeto de testes já definidas, chega o momento de se proceder com a implementação das classes que serão utilizadas por esta aplicação.

A primeira dessas construções será o tipo estático ArquivoCatalogo (Listagem 3), o qual será responsável pela conversão do conteúdo do arquivo .csv contendo o catálogo de produtos num objeto equivalente da classe DataTable (namespace System.Data).

Constam na classe ArquivoCatalogo as seguintes operações:

  • CreateDataTableCatalogo: método privado usado na criação novas instâncias do tipo DataTable, seguindo para isto a estrutura de colunas esperada para tais referências (o que é feito através de chamadas à operação Add, a partir da propriedade Columns);
  • GetI ...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
12/11/2012 15:10:00





Artigo - Desenvolvimento ágil com Scrum: uma visão geral

Considerando o cotidiano da maioria das organizações na atualidade, é inegável a importância desempenhada por sistemas computacionais dos mais variados tipos na condução de operações rotineiras. Esse suporte não apenas contribui para uma maior eficácia na execução de atividades do dia-a-dia, como também foi um fator determinante para um incremento substancial na produtividade de diversos processos de negócio.

A evolução da área de sistemas foi acompanhada pelo surgimento de diversas metodologias, com estas últimas normalmente englobando um conjunto de diretrizes e conceitos criados com o intuito de nortear o processo de construção de um software. Como de praxe, não há uma fórmula mágica para se chegar ao resultado final, ou seja, uma aplicação que atenda às expectativas dos usuários e seja capaz de funcionar dentro de uma série de parâmetros considerados como aceitáveis. Partindo de um conjunto de técnicas e diretrizes com eficácia já comprovada, os profissionais envolvidos empreendem esforços no sentido de adaptar um modelo para a realidade na qual se encontram inseridos.

É importante frisar sempre que desenvolver softwares não é uma tarefa das mais simples. Uma ampla gama de variáveis influencia no modo como uma aplicação será construída, somando-se ainda a isto influências como a pressão pela entrega do produto em um prazo muito curto, mudanças motivadas por alterações na legislação vigente, dificuldades dos usuários que solicitam um sistema em descrever de forma clara e concisa aquilo que realmente necessitam (com prováveis pedidos de modificações ao longo do projeto), dentre outros aspectos.

A noção de mudança também representa um elemento central na elaboração de aplicações. Por mais que todo um esforço procurando contemplar um número extenso de situações seja levado a cabo, é praticamente impossível construir um software que em determinado momento não precise passar por alterações. Aliás, é bastante comum que exista a necessidade de modificações durante a construção da aplicação, comprometendo assim uma parcela do tempo e de recursos que já haviam sido alocados para a implementação daquela solução.

Em um cenário de transformações constantes, a escolha pelo paradigma de desenvolvimento mais adequado a um determinado contexto é, sem sombra de dúvidas, um fator crucial para o sucesso do projeto. As primeiras técnicas formais voltadas à construção de sistemas possuíam um enfoque direcionado à elaboração de soluções com uma estrutura mais rígida e, portanto, eram menos suscetíveis a mudanças. A necessidade de uma rápida adaptação diante de situações imprevistas é um dos aspectos que caracteriza o mundo corporativo atual; procurando atender a este tipo de demanda, surgiriam práticas mais flexíveis para a criação de aplicações, com diversas destas sendo conhecidas como “metodologias ágeis”.

O objetivo deste artigo é abordar, em linhas gerais, como métodos ágeis podem ser empregados em atividades relacionadas com o desenvolvimento de sistemas. Isto será feito, basicamente, através de um estudo mais detalhado de um conjunto de práticas com uma grande aceitação na área de software atualmente: trata-se da metodologia Scrum.

Metodologias de desenvolvimento de software: uma visão geral

O modelo em cascata (em inglês “waterfall”) foi, ainda na década de 1970, um dos primeiros padrões a fornecer diretrizes para processos voltados ao desenvolvimento de software. Esta metodologia é caracterizada por fases que ocorrem dentro de uma sequência rígida, com o início das atividades de uma etapa acontecendo imediatamente após o término daquela que a precedeu. A implementação de um projeto que segue este modelo é geralmente dividida nas seguintes fases: análise de requisitos, projeto da aplicação, implementação, testes de validação, implantação e manutenção.

De certa forma, esta abordagem é bastante semelhante à da linha de montagem clássica do mundo fabril. Considerando o cenário atual, em que muitas organizações se veem às voltas de transformações profundas e muitas vezes repentinas, a maneira linear que este modelo impõe à atuação dentro de um projeto de software revela-se como um fator deveras limitante.

Após uma fase inicial em que se apresentam as expectativas e em que se estabelece o escopo da aplicação a ser gerada, a área que solicitou um sistema apenas terá uma visão do resultado ao término do projeto. Mudanças eventuais em requisitos ou, mesmo, em regras que definem o comportamento destes podem prejudicar todo um esforço de meses. Tais alterações podem ainda comprometer um orçamento previamente acordado, além de não ser raro que o produto resultante sequer chegue a ser utilizado (por estar distante daquilo que se aguardava).

Conforme já frisado neste artigo, o cotidiano dinâmico de muitas organizações acabaria impondo o surgimento de um novo enfoque para a construção de softwares. Com base em uma série de parâmetros pré-estipulados, mas que também se encontram sujeitos a mudanças ao longo de um projeto, outras abordagens foram desenvolvidas de forma a tornar o desenvolvimento de aplicações mais flexível e produzindo resultados mais próximos do esperado.

Procurando fazer um contraponto às deficiências do modelo cascata, a metodologia RUP (Rational Unified Process) foi criada para permitir um desenvolvimento incremental e com entregas sucessivas de partes do software combinado. Amparando-se em conceitos da Orientação a Objetos, além de representação de estruturas de sistemas por meio da linguagem UML.

RUP é uma boa alternativa para projetos de grande porte que exigem um processo bem estruturado e que prime por uma documentação rica em detalhes. Esta é uma demanda bastante comum em organizações sujeitas a rigorosos procedimentos de auditoria. Este modelo está dividido em fases de análise (Concepção), modelagem e arquitetura do sistema a ser entregue (Elaboração), implementação (Construção) e Transição (implantação), sendo possível ainda que as diferentes atividades destas etapas possam vir a acontecer de maneira paralela em determinados momentos.

Ainda sobre o RUP, esta metodologia é na verdade uma implementação de um processo conhecido como Unified Process, representando uma solução específica da IBM para a condução de atividades voltadas ao desenvolvimento de software. É importante destacar também que existe uma série de ferramentas disponibilizadas para a geração dos diversos artefatos previstos por este modelo.

Nem sempre um processo trabalhoso e extremamente detalhado como o RUP pode ser a melhor alternativa em projetos de software. Equipes de tamanho reduzido, projetos que não são extensos e requisitos mudando constantemente motivariam a busca por novas formas de se controlar o processo de desenvolvimento de uma aplicação. Essas necessidades levariam, consequentemente, ao desenvolvimento de uma série de padrões que compõem um agrupamento de técnicas conhecidas como metodologias ágeis.

Em 2001 seria publicado, a partir do trabalho conjunto de diversos especialistas da área de sistemas, o Manifesto para Desenvolvimento Ágil de Software. Tal declaração enfatiza a entrega de software operável, atuando em conjunto com o solicitante do mesmo, além de frisar a necessidade de uma interação adequada entre os diversos envolvidos num projeto e a flexibilidade diante de mudanças. São doze os princípios que norteiam o Manifesto Ágil (ou em inglês “Agile Manifesto”):

  • Satisfação das expectativas da área solicitante/cliente;
  • Uma postura mais positiva diante da necessidade de mudanças, procurando inclusive obter benefícios e explorar oportunidades não vislumbradas antes;
  • Entregas mais frequentes, a fim de possibilitar que o cliente possa acompanhar melhor a evolução do projeto, visando assegurar que os requisitos esperados realmente têm sido atendidos;
  • A colaboração entre todos aqueles que participam do projeto, quer sejam pessoas da área que solicitou a aplicação ou, mesmo, desenvolvedores focados em atividades de implementação, de forma a se agir como um time coeso;
  • Assegurar que existam condições para que todos possam trabalhar motivados;
  • Transmissão de informações através de conversas face-a-face;
  • Garantir que o software é entregue funcionando;
  • Manter um ritmo constante de trabalho, de forma que o processo como um todo continue de um modo sustentável, sem grandes percalços;
  • Forte ênfase na qualidade do que é produzido;
  • Foco na simplicidade;
  • Equipes auto-organizáveis, capazes de tomar decisões técnicas que viabilizem a evolução contínua do processo em que se encontram inseridas;
  • Uma reflexão constante dos rumos que estão sendo trilhados, a fim de se aumentar a eficácia da equipe, bem como ajustar o comportamento da mesma para com metas estabelecidas previamente.

Além do Scrum que será descrito em maiores detalhes nas próximas seções, outras modelos ágeis que desfrutam de uma boa aceitação na área de desenvolvimento de software são as metodologias XP e Lean IT.

XP (abreviação do inglês “Extreme Programming”) é uma metodologia de desenvolvimento de software que se caracteriza por uma forte ênfase na elaboração e execução contínua de testes unitários, bem como pela codificação em pares: uma dupla de desenvolvedores participa da implementação de uma ou mais funcionalidades, sendo que isto acontece em torno de um único computador, com a p

...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
09/11/2012 11:10:00





Artigo - Manipulação de arquivos .zip no .NET Framework 4.5

O uso de mecanismos para a compactação de arquivos é, sem sombra de dúvidas, um recurso bastante difundido no meio empresarial. Devido ao grande volume de informações processadas, diversas técnicas são empregadas com intuito de reduzir a quantidade de dados, tentando com isto maximizar o potencial de utilização dos meios de armazenamento e/ou transmissão.

Cópias de segurança (backups) são um exemplo notório de aplicação de meios para a compactação de informações. A realização de backups é um recurso vital em qualquer tipo de negócio, uma vez que possibilita a rápida recuperação de dados essenciais, viabilizando assim a retomada das operações rotineiras tão logo ocorram situações consideradas como desastrosas. A importância das cópias de segurança é atestada pelo enfoque dado a este tipo de questão por muitas auditorias corporativas, com uma série de procedimentos determinando que informações se prestam à realização de backups, além da periodicidade a ser levada em conta neste último caso.

Um dos formatos de compactação mais conhecidos é o ZIP. Este padrão aberto surgiu ainda em 1989, tendo passado por uma série de evoluções desde então. Sobre estruturas baseadas nesta especificação (extensão .zip), é comum que as mesmas possuam várias pastas e arquivos como parte de seus respectivos conteúdos, sendo possível inclusive configurar a taxa com a qual tais itens serão comprimidos (maior compactação significa, normalmente, um maior tempo em operações que envolvam a descompressão de arquivos).

O processo de descompactação de arquivos .zip também oferece uma flexibilidade considerável. Existe a alternativa de se descompactar um arquivo específico, sem que isto se traduza na necessidade de efetuar tal ação sobre todo o conteúdo que se está manipulando. A este comportamento que permite a execução de operações sobre um arquivo específico dá-se o nome de acesso randômico.

Todas essas características aqui mencionadas estão entre as razões que contribuíram para a popularização do padrão ZIP. Este formato é a base utilizada na geração de arquivos JAR (bibliotecas contendo classes e outros recursos Java compactados), no novo padrão para documentos, planilhas e apresentações do pacote Office (Open XML), além de ser suportado nativamente pelo próprio Windows (existem inclusive funcionalidades do sistema operacional que envolvem o uso de recursos de compactação).

A plataforma .NET conta desde a versão 2.0 com mecanismos que permitem a compactação de arquivos: trata-se da classe GZipStream (namespace System.IO.Compression). Contudo este tipo apresentava algumas limitações, como a impossibilidade de se comprimir vários arquivos numa mesma estrutura. Isso levou ao surgimento de alternativas que procuravam suprir esta demanda, sendo um bom exemplo disto a biblioteca SharpLibZip (http://sharpziplib.com/).

Já com o .NET Framework 3.5 seriam disponibilizadas as classes Package e PackagePart (namespace System.IO.Packaging). A partir de então, a plataforma .NET passou a contar com a capacidade de manipulação de arquivos compactados com uma estrutura mais complexa (considerando inclusive pastas com arquivos vinculados às mesmas).

Com o lançamento do .NET 4.5 outros melhoramentos foram introduzidos no que se refere ao suporte do formato ZIP. A finalidade deste artigo é descrever o funcionamento das classes ZipFile (http://msdn.microsoft.com/en-us/library/system.io.compression.zipfile.aspx) e ZipArchive (http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive.aspx), as quais foram disponibilizadas neste nova versão do Framework. Para isto, serão apresentados a seguir alguns exemplos de trechos de código que utilizam esses tipos.

Utilizando as classes ZipFile e ZipArchive em aplicações .NET

Antes de iniciar a discussão sobre as características das classes ZipFile e ZipArchive, é necessário ressaltar que referências a duas bibliotecas precisarão ser adicionadas a projetos que venham a empregar esses tipos.

Este procedimento pode ser realizado, dentro do Solution Explorer do Visual Studio 2012, clicando com o botão direito sobre o item "References" de um projeto e selecionando na sequência a opção "Add Reference...".

Aparecerá então a janela “Reference Manager”. Em “Assemblies > Framework” localizar as bibliotecas “System.IO.Compression” e “System.IO.Compression.FileSystem”, selecionando as mesmas (Figura 1). Acionar finalmente o botão “OK”, de maneira que a referências seja incluídas no projeto que se estiver criando.

Adicionando referências à bibliotecas de compressão a um projeto

Figura 1: Adicionando referências à bibliotecas de compressão a um projeto

ZipFile será a primeira das classes abordada por este artigo. Trata-se de um tipo estático, o qual disponibiliza métodos que podem ser usados em operação de criação, extração ou leitura de arquivos gerado segundo o padrão ZIP.

Supondo que seja preciso compactar toda uma estrutura de diretórios e arquivos de um projeto ASP.NET, como aquela que consta na Figura 2.

Exemplo de estrutura de diretórios e arquivos a ser compactada

Figura 2: Exemplo de estrutura de diretórios e arquivos a ser compactada

A Listagem 1 apresenta um exemplo de como isto pode ser feito através da classe ZipFile. No caso, foi utilizado o método CreateFromDirectory, o qual cria um novo arquivo .zip a partir de um diretório específico; devem ser fornecidos como parâmetros a esta operação:

  • O caminho do diretório que estará sendo comprimido;
  • ...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
07/11/2012 09:47:00





 

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), Oracle Certified Associate (PL/SQL), Sun Certified (SCJP, SCWCD), ITIL Foundation V2, Cobit 4.1 Foundation.
Arquivo de atualizações
 2013
 2012
 2011

Estatísticas do Autor:
Número de posts: 82
Características dos posts deste autor:
Conteúdo:
Utilidade:
39 0
 
DevMedia Group - Tel: (21) 3382-5038 - www.devmedia.com.br
Todos os Direitos Reservados a DevMedia Group