Arquivo para Maio, 2009

Validar Campos no Cliente com .NET e Javascript

Uma ponto importante para quem desenvolve sistemas é o tráfego de rede. Espera-se que os sistemas de informações utilizem o mínimo possível os recursos da rede. Evitar acessos desnecessários ao servidor de aplicação e banco de dados é uma das providências que os desenvolvedores devem tomar pra diminuir esse tráfego.

Em sistemas web não seria diferente. Afinal o acesso a páginas web pode ocorrer via intranet, ou seja, na rede local, ou pela internet passando por vários servidores, bandas, nós, comutadores, etc. É importante evitar submissões de páginas desnecessárias. Isso pode fazer com que a navegação seja bem mais rápida e produtiva. Por exemplo, se for definido na aplicação uma regra que somentes CPF´s válidos podem ser gravados no banco de dados, a aplicação deve validar o CPF antes de gravar no banco. Mas onde essa validação deve acontecer? Algumas sugestões:

  1. Triggers na tabela – Antes do INSERT a trigger pode validar o CPF. O uso de trigger é desaconselhável, principalmente para validações de campo;
  2. Procedures -  Se o sistema utilizar as procedures para implementar as regras de negócio, um ótimo lugar para validar o CPF é durante a execução da procedure;

Essa duas formas tem um problema em relação ao tráfego: os dados trafegaram a rede inteira apartir da tela do cliente até o banco de dados apenas para retornar “CPF inválido.”

Se utilizar um servidor de aplicação em uma arquitetura de n-camadas pode-se implementar a validação nos objetos de négocio. Isso já diminui um pouco o tráfego. Afinal o servidor de aplicação deve estar em uma camada acima, em relação a camada onde é feito o acesso ao banco de dados. O servidor de aplicação pode validar os dados e quando forem enviados à camada infeiror, os dados já foram validados na camada de regra de négocios.

Mas podemos subir camada ainda mais nessa validação. Podemos colocar a validação do CPF na camada de apresentação, exatamente no servidor web. Plataformas como PHP, ASP, ASP.NET, JSP podem utilizar essa forma. A página é submetida ao servidor web que faria a validação dos dados. Note que o servidor web deve ficar numa camada acima do servidor de aplicação.  Agora o tráfego é apenas entre o cliente e o servidor web que já é muito bom.

Mas tem certas validações que podem ser feitas diretamente no cliente; lá no navegador. Vejamos alguns exemplos:

  • campos que não podem ser nulos;
  • data, cpf, cns, cnpj, etc. inválidos;
  • comparação de dados entre dos campos.

Ou seja, se determinadas validações, também chamadas de pré-validações, forem checadas antes de submeter a página ao servidor web podemos evitar ao máximo tráfegos desnecessários em situações elementares. O campo CPF pode ser validado antes de o usuário enviar os dados ao servidor, ou seja, a página só seria enviada ou submetida ao servidor se o CPF fosse digitado corretamente, com os dois dígitos verificadores válidos. O mesmo podemos pensar com datas, horas e outros valores. Assim a diminuição do tráfego seria total. A gravação do CPF, ao ser validado no navegador do cliente, quando fosse enviado ao servidor certamente seria gravado já que o CPF sempre estaria correto ao chegar no servidor. Isso vale para vários outros tipos de campos: data, hora, data e hora, cnpj, cns, números, campos com dígitos verificadores, entre outros.

Essa validação no cliente pode ser feita com Javascript. Uma problema: “E se o navegador não suportar Javascript?” Realmente. Aí a validação deverá também ser feita em alguma das camadas inferiores citadas acima. Foi dito que essas validações seriam um tipo de pré-validações. Nenhuma aplicação deve ser feita apenas com validações no navegador do cliente. Algum outro local deve fazer a validação principal. Os objetos de negócio devem implementar as validações dos campos. Em programação orientada a objetos isso passa a ser um requisito técnico. Se a validação no navegador do cliente não funcionar, a verificação em outra camada inferior deverá ser feita.

O fato é que validar no navegador do cliente utilizando Javascript é um boa prática para qualquer sistema web. Em ASP.NET existe alguns componentes que realizam essa tafera com muita qualidade.

  • RequiredFieldValidator: usado quando um campo não pode ser vazio;
  • RangeValidator: usado para verificar se o conteúdo do campo está dentro de uma determinada faixa;
  • RegularExpressionValidator: usado para validar campos utilizando expressões regulares;
  • CompareValidator: usado para comparar dois campos;
  • CustomValidator: usado para preparar uma verificação personalizada;

Todos esses validadores fazem verificações diretamente no navegador do cliente e só deixa os dados serem enviados ao servidor se os dados estiverem de acordo com as condições definidas nos validadores. Existe mais um componente chamado ValidatorSummary que é capaz de exibir mensagens de erro durante a validação. Leia mais sobre esses validadores neste link.

Gostaria de destacar a utilidade do CustomValidator. Ele permite utilizar validações personalizadas em Javascript. O desenvolvedor pode criar alguma validação de acordo com sua necessidade.  Para utilizar este validador genérico a função em Javascript segue uma padronização na sua definição. O script para validação pode vir entre tags <scripts></scripts> na própria página ou em arquivos .js e vinculados a página. A função de validação pode ter qualquer nome sendo que os parâmetros de entrada devem ser source e arguments.  Veja o exemplo:

<script language=”Javascript”>

function valida_vazio(source, arguments)

{

// O campo não pode ser vazio

if (arguments.Value!=”")

{

arguments.IsValid = true;

return true;

}

else

{

arguments.IsValid = false;

return false;

}

</script>
O exemplo acima faz a mesma coisa que o RequiredFieldValidator: valida campos que não podem ser vazio. O CustomValidator faz referência a esta função na propriedade ClientValidationFunction. Voce pode também combinar validators. Por exempo: O RequiredFieldValidator pode ser usado para verificar que um campo não pode ser vazio e o CustomValidator para verificar se o campo foi preenchido com um CPF válido por exemplo.

Note que essas validações no cliente apenas verificam a qualidade dos dados digitados. Elas não verificam, por exemplo, se o CPF está ou não cadastrado no banco. Esse tipo de validação tem que ser feita do lado do servidor.

Diversos tratamentos e validações pode ser feitos utilizando Javascript e o CustomValidator. Veja alguns exemplos:

  • CEP
  • CNPJ
  • CNS
  • CPF
  • Data
  • Data/Hora
  • Números decimal
  • Dígito verificador
  • Email
  • Hora
  • Números
  • PIS/PASEP

Essas validações são comumente utilizadas na maioria das aplicações. Eu implementei cada uma delas em Javascript e construi uma página em ASP.NET que demonstra a utilização de cada uma delas com o CustomValidator.  Se desejar ver ou ter todas ou alguma dessas validações clique aqui.

Então é isso.

Relatórios em .NET: ReportViewer e NHibernate

Quem utiliza sistemas de informações sabe da importância dos relatórios. Eles são tão importantes quanto o próprio banco de dados. Listagens, gráficos, resumos, sumários, formulários são alguns exemplos de resultados que essas ferramentas devem ser capazes de fornecer. Claro que dada tipo de resultado será aplicado em um contexto. Cada sistema precisa emitir relatórios de acordo com a necessidade do trabalho onde for utilizado. Por exemplo, os gráficos são normalmente utilizados para avaliação e gestão. As listagens são utilizadas para buscas, levantamentos, etc. O fato é que relatórios são de vital importância para quem utiliza algum sistema de gerenciamento de dados.

Por outro lado, os desenvolvedores de sistemas sabem da dificuldade de se construir um relatório. Isso sem falar das alterações que possam surgir posteriormente. Todos procuram alguma ferramenta que possa minimizar o desgaste natural causado pelo processo de construção e manutenção de relatórios. A situação tende a se agravar quando falamos de relatórios para sistemas web. Isso por que os navegadores trabalham com HTML. A situação natural é montar relatórios utilizando esta linguagem diretamente e isso não é tão trivial assim. Mesmo utilizando alguma outra linguagem que rode do lado do servidor o resultado final deve ser em HTML que é o que os navegadores são capazes de exibir. Para aumentar o poder desses navegadores alguns recursos podem ser utilizados: ActiveX, Plugins, Flash, Applets, etc. Essas e outras tecnologias, além de dar maior poder aos navegadores, aumentam a produtividade dos desenvolvedores já que podem utilizar ferramentas mais completas para gerar os relatórios que serão vistos nos navegadores.

Em .NET não seria diferente. Montar relatórios é um processo muito delicado. A pergunta é qual a melhor forma? Qual a melhor ferramenta? Resposta: EU NÃO SEI. Mas será que existe uma forma dita “melhor”?! Mas, como todo programador, eu também tenho a minha forma que pode não ser a melhor nem a mais ortodoxa. Mas é a minha forma e é com ela que tenho resolvido a maioria dos problemas. Vou compartilhar com voces.

A minha primeira experência em .NET foi quando eu tive que migrar um sistema do Delphi para o Visual Studio 2003. Neste sistema existe inúmeros relatórios. Inicialmente fiz as telas de usuário. Como o sistema em delphi utiliza as procedures de banco como regras de negócio não tive muitos problemas. Tive apenas que refazer as telas que iriam chamar as procedures. O problema começou na hora dos relatórios. Inicialmente tentei utilizar o Crystal Reports. Não me identifiquei com ele. Achei muito complicado e etc. A primeira solução que me veio a cabeça foi a seguinte: já que os relatórios estavam todos prontos em Delphi utilizando views e procedures do banco de dados decidi criar em Delphi um servidor de relatórios. O funcionamento era +ou- assim:

  1. Um programa executavel criado em delphi e instalado no servidor encapsulava todos os meus relatórios. Este programa tinha a capacidade de exportar relatórios em PDF para a pasta web da minha aplicação.
  2. Este programa era chamado de dentro da minha aplicação asp.net passando alguns parâmetros:  id-relatorio, arq-pdf-saida, param-1, param-2, … , param-n. O id-relatório identificava o relatório que eu gostaria de imprimir. Os parêmetros, de 1 a n, eram passados de acordo com a necessidade da instrução SQL do relatório.
  3. O programa recebia estes parêmtros, conectava-se ao banco, extraia os dados do banco, montava o relatório e exportava para pdf em uma pasta com nome e path indicado pelo arq-pdf-saida.
  4. A aplicação aguardava o término do processo até um certo limite e redirecionava o browser para o arquivo pdf gerado. Com o Adobe Reader instalado o navegador baixava este pdf e exibia ao usuário.

Durante muito tempo este sistema funcionou assim. Principalmente por que eu não tinha muito tempo para refazer toda aplicação inclusive os relatórios em 100% .NET utilizando o Crystal.

Mas, novas versões deste sistema foram surgindo e com elas, a necessidade de utilizar uma forma 100% .NET de fazer relatórios. Fiz algumas buscas e achei algumas ferramentas muito interessantes:

  1. DevExpress
  2. Afalinasoft
  3. StimulSoft
  4. PerpetuumSoft
  5. (…)

Algumas eu testei e gostei. Todas são muito boas e integradas ao IDE do Visual Studio. Cada uma com suas características e diferenciais. Mas todas tem a principal limitação para o tipo de trabalho que eu faço:  não são gratuitas. Porém nada impede de utilizar a versão demo convivendo com algumas situações. Uma coloca o nome DEMO no meio de cada página impressa. Outra limita o número de páginas impressas. Outra coloca uma pequena propaganda no final da página. Enfim…. Pra mim era inviável.

Há também quem prefira fazer relatórios em HTML para exibir diretamente no navegador. Separei também um link para esses programadores: http://www.webly.com.br/tutorial/net/8861/aspnet-gerar-relatorio-em-html.htm.

Foi quando eu conheci o ReportViewer. Estudei um pouco sobre ele. Dê uma olhada nos endereços abaixo e conheça também um pouco mais:

  1. http://www.macoratti.net/aspn_grv.htm
  2. http://www.devmedia.com.br/articles/viewcomp.asp?comp=5371
  3. http://blog.adsystems.com.br/2009/04/10/tutorial-c-relatorios-master-detail-com-reportviewer/
  4. http://www.macoratti.net/08/03/vbn5_rpv.htm
  5. http://www.macoratti.net/08/03/vb8_rpv2.htm
  6. http://csharpbrasil.com.br/2008/09/11/criando-relatorio-com-reportviewer-em-aspnet/

Não vou entrar em detalhes do funcionamento. Os links acima são bem explicativos.  Mas duas novas questões surgem:

  1. Eu não gostaria de utilizar o visualizador padrão do ReportViewer. Gostaria de exportar os relatórios diretamente para pdf para utilizar o Adobe Reader como visualizador no prórprio navegador.
  2. Gostaria da utilizar o NHibernate como minha fonte de dados também. O natural é conectar o banco com algum DataSource. Gostaria que os dados viessem da minha camada de negócio (BO) e não conectando diretamente o banco. Principalmente pelo fato da independência de dados que já comentei e posts anteriores.  Sem falar no fato de obedecer as regras da arquitetura em camadas.

Graças a Deus, consegui resolver os dois problemas. Não pretendo construir um tutorial para cada solução.Vou passar a idéia da solução. A implementação da proposta fica como exercício para o leitor.  É necessário ter conhecimento intermediário de OOP, persistência com NHibernate, Visual Studio e arquitetura em camadas. Em posts atenteriores dou uma ajuda nessas questões. Vale a pena dar uma olhada.

Vamos ao que interessa.

  1. Os relatórios desenvolvidos com ReportViewer podem ter como fonte de dados os DataTables. Esses DataTables podem ser criados tanto em tempo de execução quanto em tempo de desenvolvimento. Para nossa proposta é legal criá-los em tempo de desenvolvimento. Isso irá facilitar a confecção do arquivo de relatório (.rdlc). Faça isso. Abra um projeto no VS e adicione um item DataSet. Neste DataSet adicione um DataTable. As colunas do DataTable serão os campos que vc irá imprimir. Adicione as colunas com seus respectivos nomes.
  2. Adicione um novo item ao seu projeto. Este item deve ser um Report (.rdlc). Agora voce deverá formatar o relatório de acordo com sua necessidade. Os links acima dão uma ideia de como trabalhar com a IDE. Uma coisa importante: as colunas do seu relatórios devem ser vindas do DataTable que voce criou no item anterior. Mas para que seja possível fazer essa associação voce deve vincular o relatório ao DataTable. No menu Report, selecione o DataSource. Na caixa suspenda selecione o DataTable que voce criou indicando-o como fonte de dados do relatório. A partir daí voce já pode adicionar colunas ao seu relatório.
  3. Talvez vc queria indicar algumas informações no cabeçalho do seu relatório, tais como: nome da empresa, período, setor, etc. Isso deverá ser passado ao relatório através de parâmetros. No menu Report->Report Parameters voce pode indicar todos os parêmetros que desejar e posicioná-los no cabeçalho do relatório.

Neste relatório voce pode definir: grupos, sumários, totais, gráficos, tabelas com números de linhas e colunas variáveis, etc. Consulte documentação do ReportViewer.  Com um pouco de prática tudo vai parecer muito natural. No início eu támbem demorei um pouco a me familiarizar com o ambiente. Há quem diga que no ReportViewer não dá pra fazer relatórios muito complexos. Para os relatórios do dia a dia tenho tido ótimos resultados. Sem falar no fato: ReportViewer é uma solução gratuita. Qualquer relatório mais complexo que sua empresa precise, posivelmente tenha que meter a mão no bolso. ;)

Mas, continuando… A questão agora é o Nhibernate. Sem problemas! No seu DAO e/ou BO voce deve ter um método que retorne para a camada de apresentação os dados que prentende utilizar no relatório. Esses dados podem ser retornados de diversas formas: IList, IList<> ou o próprio DataTable, inclusive utilizando a estrutura definida no DataSet/DataTable do relatório. Não aconselho usar DataTable nas camadas BO e DAO para retornar dados. Surigo utilizar sempre IList<> nessas camadas e deixar pra conversão em DataTable na camada de apresentação utilizando algum foreach. (Já notou que eu uso C#, não é?) O DataTable destino será aquele mesmo que formatou o relatório do ReportViewer.  Associe o DataTable o relatório, preencha os campos de parâmetros e mande exibir. Vc pode seguir um dos tutoriais que indico acima.

Mas se vc não quiser utilizar o visualizador padrão do ReportViewer? Eu sempre exporto o relatório para PDF e envio  os bytes do arquivo diretamente para o STREAM de tela. No browser do cliente o Adobe Reader captura isso e abre no browser como arquivo PDF. Não há necessidade de gerar arquivo em disco como eu fazia no início.

Mas como fazer esta exportação! Vou dar duas sugestões. A primeira é aprender como se faz consultando os seguintes links: Link 1 e Link 2. A outra opção é “use o que tá pronto”. Na página de Sistemas c/ Fontes deste blog eu disponibilizo uma aplicação que faz exatamente as coisas que eu descrevi aqui. A aplicação é Contas a Pagar on-line. Nele voce pode encontrar os arquivos .rdlc criados, o DataSet com os DataTables criados e o método de exportação em PDF em funcionamento.  Há métodos para exportão para Excel e PDF, em vetor de bytes ou arquivo. Fica a sua escolha. Inclusive mostra como passar parâmetros para o relatório. Esse parâmetros podem ser exibidos, por exemplo, no cabeçalho do relatório como o nome do estabelecimento ou perído. Uma dica: visite esta dica que lá mostra como exportar diretamente para PDF ou Excel sem ter que passar pelo processo de seleção no ReportViewer.

Adiquira o  projeto e veja uma aplicação prontinha utilizando esses conceitos. Além de estar investindo em seu aprendizado está contribuindo para meus estudos e pesquisas. A implementação completa dos métodos fazem parte da Regisoft Library que voce também pode adquirir.

Bom, é isso. Obrigado pela atenção e até a próxima.


    Calendário

    Maio 2009
    D S T Q Q S S
    « Jan   Jun »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  

    Desde (04/11/07)

    • 43,992 visitas