Latest Publications

Certificado digital da Caixa e Windows 7

Olá a todos.

Recentemente um cliente nosso comprou um certificado digital na Caixa econômica federal e encontrou alguns problemas pra utilizar ela no Windows 7 (E talvez no Vista também).
No nosso caso, os erros eram:

Erro interno. Pode ser que o perfil do usuário não esteja acessível ou que a chave privada que você está importando exija um provedor de serviço de criptografia que não está instalado no sistema

Ou em Inglês:

An internal error occurred. This can be either the user profile is not accessible or the private key that you are importing might require a cryptographic service provider that is not installed on your system.

Para corrigir esse problema, verifique se você possui as seguintes pastas criadas:

%USERPROFILE%\Application Data\Microsoft\SystemCertificates
%USERPROFILE%\Application Data\Microsoft\Protect
%USERPROFILE%\Application Data\Microsoft\Credentials
%USERPROFILE%\Application Data\Microsoft\Crypto

PS: O %USERPROFILE% refere-se a pasta AppData, na pasta do seu usuário (Pasta oculta).

Se as pastas acima não existem, crie-as e verifique suas permissões.

Aqui resolvemos o problema desta forma.

Update: Instale também o gerenciador de certificados da caixa, que pode ser encontrado no link:
http://icp.caixa.gov.br/_downloads/CSPSetup6aVersao.zip

Continuamos ainda sem uma solução pra funcionar no Windows Server 2008, se alguem tiver alguma idéia, favor poste nos comentários :)
Abraço

O Diário Nerd – Criando o Projeto no VS2008

Para começar:
1) Abra o Visual Studio 2008 SP1;

Ícone VS2008

2) Clique em File->New->Project;

2

3) Na guia Project types, selecione Visual C#, e na guia Templates, selecione ASP.NET MVC Web Application;

4) No campo Name informe o nome do projeto digitando DiarioNerd;

3

5) Clique em OK;

Ao seguir os procedimentos acima, uma nova tela aparecerá solicitando se desejamos criar um projeto de testes ou não. Apenas marque Yes, create a unit test project (que já vem selecionada por padrão), conforme a figura abaixo:

5

Após clicar em Ok, um novo projeto estará criado com alguns arquivos e uma estrutura padrão de pastas do ASP.NET MVC.

6

E o nosso projeto está criado.

No próximo post iremos criar o Banco de Dados da aplicação, até lá!

O Diário Nerd – Introdução

A aplicação que iremos construir aqui é parecida, em alguns aspectos, com o Twitter. A idéia é ter um microblog que não tenha tão poucos caracteres disponíveis, ou seja, os usuários podem postar inclusive artigos com muito conteúdo. Em tese o “post” seria como o de um blog normal, com a diferença de que no Diário Nerd os posts dos usuários ficam misturados, mostrando os últimos incluídos na página principal, ou seja, mais “atração” em um único lugar.

A imagem abaixo ilustra a página principal do experimento:

O Diário Nerd

Através da imagem acima, nota-se que os títulos dos posts, no lado direito da tela, estão em “azul”, sinalizando um hyperlink e, ao clicar sobre o título, podemos ver a visualização do conteúdo deste post. Se clicarmos no apelido do usuário que postou, mais ao lado direito, teremos também a lista paginada dos posts daquele usuário. Isso pode ser observado na figura abaixo:

Posts do usuário

Ao clicar no título de um dos posts, o usuário é redirecionado para a “view” (página) ilustrada pela figura abaixo:

Página de detalhes (visualização)

E também, na mesma “view” de detalhamento do post (mostrada acima), o usuário pode visualizar e inserir os comentários, conforme podemos notar na imagem abaixo:

Comentários

O usuário pode apagar os conteúdos que são de sua autoria, mas não pode apagar/alterar os conteúdos dos outros usuários.
Veja, na imagem abaixo, os links que aparecem no detalhamento de um post quando o usuário é o seu criador:

Detalhes do post para o Criador

E veja o menu superior que aparece para o usuário logado:

Menu do usuário

A idéia é adidionar vários recursos, para criar um verdadeiro ponto de troca de informações, mas sem ter a necessidade de um domínio isolado para cada blogger.
Veja o que está envolvido neste rápido experimento: inclusão, alteração, deleção, validação, paginação, autenticação, autorização, master pages, views, partial views, actions, controllers, models, helpers e url routing, entre outros.

Este é o primeiro post introdutório da série “O Diário Nerd”.

Novo treinamento presencial

No último dia 29, tive a oportunidade de, mais uma vez, ministrar um curso presencial de ASP.NET MVC em São Paulo/SP pela escola Treinando.NET.

Os cursos passarão a ser oferecidos regularmente. A idéia é de oferecer um por mês.

Para os interessados, basta acompanhar o endereço http://www.treinando.net. Assim que as inscrições são abertas, o curso aparece nesse endereço.

abs.

Thiago Rheinheimer Costa

Geração de XML, validação e assinatura digital

Olá pessoal.

Estou disponibilizando um sistema de exemplo para geração de XML, validação e assinatura digital.

Atenção: A classe disponibilizada foi bastante alterada daquela que eu utilizo nas empresas no dia a dia, visando torna-la ainda mais automatizada com Reflection, portanto, não testei todas as situações possíveis, mas já aviso antecipadamente que qualquer problema com a classe vocês podem perguntar que vou ajustando.

Antes de tudo, esta classe não é para ser um exemplo demonstrando a melhor forma de se gerar um XML para NFe, na verdade quando iniciei o desenvolvimento a intenção era uma geração de XML com manutenção fácil para que no futuro as alterações de Layout fossem o mais simples possível.

Portanto, explicando basicamente, a classe foi inteiramente escrita conforme o manual de Integração, utiliza Reflection para uma geração mais automatizada e atributos para facilitar a formatação e outras configurações do XML. Acredito que o meu objetivo inicial com ela, que era ter uma classe de fácil manutenção foi atingida.

Vou começar explicando como a classe funciona e no final deste posto você encontra um aplicativo exemplo com a classe em uso. No meu sistema original esta classe está mais organizada, mas para o exemplo, coloquei as classes um pouco bagunçadas dentro de arquivos, mas acredito que está bem fácil de entender.

Bom, a classe não tem muito segredo, foi inteiramente digitada, é necessário apenas explicar alguns dos recursos que implementei.

Atributos
Entre as várias propriedades da classe, em algumas você encontra atributos como no exemplo abaixo:

                [Formato("#####0.0000", "en-US")]
                public decimal qCom { get; set; }

O Atributo [Formato] define o formato que o valor precisa no XML, além de informar a cultura, como “en-US” ou “pt-br”.

            [Obrigatorio]
            public string IE { get; set; }

O Atributo [Obrigatorio] define se o campo deve sair no XML mesmo quando não tiver um valor definido, como o IE por exemplo, que mesmo que esteja em branco deve ser informado no XML ( ou ).

Além disso, várias propriedades podem ser nulas, como esta no exemplo abaixo:

public decimal? qTrib { get; set; }

Estas propriedades serão ignoradas pelo reflection se não tiverem um valor definido, utilize quando a TAG não deve ser informada no XML quando não possuir um valor.

Geração do XML
Pretendo explicar basicamente como desenvolvi a geração do XML através do Reflection. Vale lembrar que talvez algumas coisas devem ser arrumadas aqui ainda, visto que para este Post no Blog eu alterei a classe visando tornar ela ainda mais automatizada. Além disso, não me crucifiquem por algumas linhas de código, em algumas funções eu realmente não encontrei uma melhor de forma de fazer, mas uma das razões de postar esta classe é ter um feedback de vocês e melhorar ela ainda mais :P

Com a classe preenchida, a geração do XML é simples:

            NFe teste = new NFe();
            //Código para preencher a classe... no exemplo ele está disponível, aqui resolvi economizar espaço pulando esta parte
            XmlDocument xmlGerado = teste.GerarXML();
            //Salva uma cópia do XML não assinado - ATENÇÃO - se você está utilizando Windows Vista/7/Server, salvar na Unidade C pode não ser possível caso o VS2008 não esteja rodando como administrador
            xmlGerado.Save("c:\\testeXMLNaoAssinado.xml");
            //Seleciona o certificado
            X509Certificate2 certificado = CertificadoDigital.SelecionarCertificado();
            //assina o xml
            XmlDocument xmlAssinado = CertificadoDigital.Assinar(xmlGerado, "infNFe", certificado);                        

            //Valida o XML assinado
            string resultado = ValidaXML.ValidarXML(xmlAssinado);

            if (resultado.Trim().Length == 0)
                resultado = "Xml gerado com sucesso, nenhum erro encontrado";

            //Opcional - Função para gerar o Lote e deixar o arquivo pronto para ser enviado.
            //teste.GerarLoteNfe(ref xmlAssinado);

            //Importante:
            //Salvar através do TextWriter evita que o XML saia formatado no arquivo, desta forma o mesmo
            //pode ser rejeitado por alguns estados e/ou não validar nos programas teste
            using (XmlTextWriter xmltw = new XmlTextWriter("C:\\testeXML.xml", new UTF8Encoding(false)))
            {
                xmlAssinado.WriteTo(xmltw);
                xmltw.Close();

Eis a função GerarXML() – Veja os comentários no código para entender melhor

        public XmlDocument GerarXML()
        {
            XmlWriterSettings configXML = new XmlWriterSettings();
            configXML.Indent = true;
            configXML.IndentChars = "";
            configXML.NewLineOnAttributes = false;
            configXML.OmitXmlDeclaration = false;            

            Stream xmlSaida = new MemoryStream();

            XmlWriter oXmlGravar = XmlWriter.Create(xmlSaida, configXML);

            oXmlGravar.WriteStartDocument();
            oXmlGravar.WriteStartElement("NFe","http://www.portalfiscal.inf.br/nfe"); //abre nfe
            oXmlGravar.WriteStartElement("infNFe");
            oXmlGravar.WriteAttributeString("xmlns","xsi",null,"http://www.w3.org/2001/XMLSchema-instance");
            oXmlGravar.WriteAttributeString("Id", "NFe" + Id.ToString());
            oXmlGravar.WriteAttributeString("versao", versao.ToString());

            Type tipoObjeto;
            tipoObjeto = infNFE.Ide.GetType();
            PropertyInfo[] propriedades;
            propriedades = tipoObjeto.GetProperties();

            //A Função objetoParaXML utiliza o reflection para ler as propriedades da classe e gerar o XML
            objetoParaXML(oXmlGravar, infNFE.Ide,false);
            objetoParaXML(oXmlGravar, infNFE.Emit,false);
            objetoParaXML(oXmlGravar, infNFE.Dest, false);

            foreach (infNFE.det detalhe in infNFE.Det)
            {
                oXmlGravar.WriteStartElement("det");
                oXmlGravar.WriteAttributeString("nItem", detalhe.nItem.ToString());

                objetoParaXML(oXmlGravar, detalhe.Prod, false);

                oXmlGravar.WriteStartElement("imposto");
                objetoParaXML(oXmlGravar, detalhe.Imposto.Icms, false);
                objetoParaXML(oXmlGravar, detalhe.Imposto.Ii, false);
                objetoParaXML(oXmlGravar, detalhe.Imposto.Ipi, false);
                objetoParaXML(oXmlGravar, detalhe.Imposto.Pis, false);
                objetoParaXML(oXmlGravar, detalhe.Imposto.Cofins, false);                

                oXmlGravar.WriteEndElement(); //fecha TAG imposto...
                oXmlGravar.WriteEndElement(); //fecha TAG det...
            }

            objetoParaXML(oXmlGravar, infNFE.Total, false);
            objetoParaXML(oXmlGravar, infNFE.Transp, false);
            objetoParaXML(oXmlGravar, infNFE.Cobr, false);
            objetoParaXML(oXmlGravar, infNFE.InfAdic, false);

            oXmlGravar.WriteEndElement(); //fecha infNFe
            oXmlGravar.WriteEndElement(); //fecha NFe            

            oXmlGravar.Flush();
            xmlSaida.Flush();
            xmlSaida.Position = 0;

            XmlDocument documento = new XmlDocument();
            documento.Load(xmlSaida);

            oXmlGravar.Close();                      

            return documento;
        }

Função objetoParaXML, que gera o XML

        private void objetoParaXML(XmlWriter xmlWriter, object objeto, bool ignorarDeclaracaoElemento)
        {
            if (objeto == null)
                return;

            Type tipoObjeto;
            tipoObjeto = objeto.GetType();
            PropertyInfo[] propriedades;
            propriedades = tipoObjeto.GetProperties();

            if (!ignorarDeclaracaoElemento)
                xmlWriter.WriteStartElement(tipoObjeto.Name);                 

            foreach (PropertyInfo propriedade in propriedades)
            {
               //A Função novaTag verifica se a propriedade em sí é um novo elemento, como o enderEmit
               //no caso do emitente, e verifica tbm se esta propriedade foi declarada (!= null), se não ignora

                if (Funcoes.novaTag(propriedade) && !(propriedade.GetValue(objeto, null) == null))
                {
                   //utilizando recursão
                    objetoParaXML(xmlWriter, propriedade.GetValue(objeto, null), false);
                    continue;
                }

                object[] obj = propriedade.GetCustomAttributes(false);
                Funcoes.gravarElemento(xmlWriter, propriedade.Name, propriedade.GetValue(objeto, null), obj);
            }
            if (!ignorarDeclaracaoElemento)
                xmlWriter.WriteEndElement();
        }

Bom, por enquanto é isso, não sei se consegui deixar claro sobre como funciona a classe, e agora estou com o tempo curto e vou postar assim mesmo, mas os comentários estão abertos para que todos possam perguntar, e assim vou melhorando este post e os códigos disponíveis.

Detalhe: A Classe está sendo disponibilizada gratuitamente, mas por favor, se você fizer alterações, notifique-me para que eu possa melhorar o código disponível.

Link para Download do Exemplo

Para usar, mude o código do button1, adicionando um CNPJ válido, IE, nome de empresa e etc.

Funções básicas

Iniciando o primeiro post desta categoria mostrando algumas das funções básicas (Mas essenciais) na utilização da NFe com .NET.

Módulo 11 – Para calculo do digito verificado da Chave.
Com certeza esta função pode ser reduzida para menos linhas… se o fizer, por favor deixe um comentário com o código, sugestões são sempre bem vindas :P

        public static int modulo11(string chaveNFE)
        {
            if (chaveNFE.Length != 43)
                throw new Exception("Chave inválida, não é possível calcular o digito verificador");

            string baseCalculo = "4329876543298765432987654329876543298765432";
            int somaResultados = 0;

            for (int i = 0; i <= chaveNFE.Length - 1; i++)
            {
                int numNF = Convert.ToInt32(chaveNFE[i].ToString());
                int numBaseCalculo = Convert.ToInt32(baseCalculo[i].ToString());

                somaResultados += (numBaseCalculo * numNF);
            }

            int restoDivisao = (somaResultados % 11);
            int dv = 11 - restoDivisao;
            if ((dv == 0) || (dv > 9))
                return 0;
            else
                return dv;
        }

Remover Acentos
Esta função não é de minha autoria, peguei no Google um tempo atrás e realmente não lembro mais de onde ela foi retirada.

        public static string TirarAcento(string palavra)
        {
            string palavraSemAcento = "";
            string caracterComAcento = "áàãâäéèêëíìîïóòõôöúùûüçÁÀÃÂÄÉÈÊËÍÌÎÏÓÒÕÖÔÚÙÛÜÇ";
            string caracterSemAcento = "aaaaaeeeeiiiiooooouuuucAAAAAEEEEIIIIOOOOOUUUUC";

            for (int i = 0; i < palavra.Length; i++)
            {
                if (caracterComAcento.IndexOf(Convert.ToChar(palavra.Substring(i, 1))) >= 0)
                {
                    int car = caracterComAcento.IndexOf(Convert.ToChar(palavra.Substring(i, 1)));
                    palavraSemAcento += caracterSemAcento.Substring(car, 1);
                }
                else
                {
                    palavraSemAcento += palavra.Substring(i, 1);
                }
            }

            return palavraSemAcento;
        }

Remove formatação
Remove formatação de CNPJ/IE/RG/CPF, entre outros

        public static string removeFormatacao(string texto)
        {
            string txt = "";

            txt = texto.Replace(".", "");
            txt = txt.Replace("-", "");
            txt = txt.Replace("/", "");
            txt = txt.Replace("(", "");
            txt = txt.Replace(")", "");
            txt = txt.Replace(" ", "");

            return txt;
        }

Por enquanto é isso, em breve (Ainda esta semana acredito eu) estarei postando uma classe para geração de XML, assim como exemplos para conexão com WebService, assinatura digital, cadeias de certificado, utilização de certificados A1 e A3 e etc.

Abraços

Principais detalhes ao utilizar o Firebird com .NET

Este post não é um passo a passo de como utilizar o Firebird, mas sim para esclarecer boa parte das dúvidas que geram os principais problemas ao trabalhar com o Firebird em .NET que eu e outros usuários já enfrentamos.

O Firebird .NET não adiciona as DLLs no GAC (Global Assembly Cache) quando instalado, então, por muitas vezes você pode encontrar alguns problemas ao utilizar o Firebird no .NET, por exemplo:

Não foi possível localizar o Provedor de Dados .Net Framework solicitado. Talvez ele não esteja instalado.

Isso acontece principalmente ao tentar utilizar o Firebird com DbCommand, um exemplo do comando que dispara esta exception:

DbProviderFactory factory =  DbProviderFactories.GetFactory("FirebirdSql.Data.FirebirdClient")

Por isso, vale lembrar aqui alguns detalhes ao utilizar o Firebird no .NET

Definir a propriedade Copy Local = True nas Dlls do Firebird referenciadas no projeto.
Adicionar a DLL ao GAC, para isso, abra o Visual Studio 2008 Command Prompt, localizado no Iniciar => Programas => Visual Studio Tools

Digite gacutil -i FirebirdSql.Data.FirebirdClient (Se você não estiver na mesma pasta em que a DLL se encontra, defina o caminho com a DLL, por  exemplo C:\FirebirdSql.Data.FirebirdClient)

Com a DLL adicionada ao GAC, digite gac -l FirebirdSql.Data.FirebirdClient para listar as informações, que deve aparecer conforme abaixo:

The Global Assembly Cache contains the following assemblies:
  FirebirdSql.Data.FirebirdClient, Version=2.1.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c, processorArchitecture=MSIL

Number of items = 1

Prestando atenção a detalhes como a Versão (Version) e PublicKeyToken.

Além disso, no web.config (ou app.config no caso de um aplicação winform), adicionar as linhas abaixo:

<system.data>
<DbProviderFactories>
<remove invariant="CoreLab.Oracle"/>
<add name="FirebirdClient Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description=".Net Framework Data Provider for Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient, Version=2.1.0.0, Culture=neutral,PublicKeyToken=3750abcc3150b00c" />
</DbProviderFactories>
</system.data>

Ao adicionar as linhas acima, fique atendo a detalhes como Version e PublicKeyToken, eles devem ser iguais aos listados quando executamos o comando gacutil -l

Bom, acho que é isso, dúvidas perguntem nos comentários :D

Vídeo- ASP.NET 3.5 – Introdução

Vídeo – Entendendo Models-Views-Controllers

Vídeo – ASP.NET MVC – Apresentação