Conversão de Datas em Ações da API

Há momentos em que precisamos parametrizar as ações de controllers com outros tipos de dados que vão além de inteiros e strings, e sem ainda falar de tipos de complexos, o tipo DateTime pode ser uma necessidade muito comum em alguns casos. O problema é que este tipo de dado possui diversas formatações e sua validade varia de acordo com a cultura contra qual ele está sendo validado.

Sendo assim, podemos nos deparar com alguns problemas, onde apesar de ser uma data válida se considerarmos o formato brasileiro, ela pode ser considerada inválida pela API que utiliza o formato americano para tratar e vice versa. Mesmo que a cultura da aplicação esteja definida para a região correta, os componentes internos do ASP.NET Web API não são capazes de entender o formato da data que o cliente deve passar. Se considerarmos a data 20 de dezembro de 2015, 20/12/2015 é um formato válido para nós mas inválido para os Estados Unidos; já a data 12/20/2015 é o contrário.

Para especificar o formato exato para realizar a conversão, podemos criar um model binder específico para a data, e no interior do mesmo fazer a formatação desejada para todas as datas que são recebidas em parâmetros dos serviços. Abaixo está o exemplo de como poderíamos codificar este formatador:

public class CustomDateTimeModelBinder : IModelBinder
{
    private readonly string format;

    public CustomDateTimeModelBinder(string format)
    {
        this.format = format;
    }

    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
    {
        var date = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;

        if (string.IsNullOrWhiteSpace(date))
            return false;

        bindingContext
            .ModelState
            .SetModelValue(
                bindingContext.ModelName,
                bindingContext.ValueProvider.GetValue(bindingContext.ModelName));

        DateTime result = DateTime.MinValue;

        if (DateTime.TryParseExact(date, format, Thread.CurrentThread.CurrentCulture, DateTimeStyles.None, out result))
        {
            bindingContext.Model = result;
            return true;
        }

        bindingContext.ModelState.AddModelError(
            bindingContext.ModelName,
            string.Format(“”{0}” is invalid.”, bindingContext.ModelName));

        return false;
    }
}

Por fim, basta acoplá-lo à execução e indicar ao ASP.NET Web API que ele trata e valida o tipo DateTime. Para isso, basta utilizar a configuração do serviço para inclui-lo e as requisições que mandarem a data no formato especificado em seu construtor serão corretamente convertidas em DateTime respeitando o dia, mês e ano.

config.BindParameter(typeof(DateTime), new CustomDateTimeModelBinder(“dd/MM/yyyy”));

Performance com Server Push

No post anterior eu comentei sobre os benefícios da utilização do server push, recurso que foi disponibilizado a partir do HTTP/2. Lá mencionei sobre a melhor reutilização da conexão TCP quando ela é estabelecida para extrair algum recurso que desejamos solicitar, como por exemplo, uma página HTML.

É comum qualquer página HTML depender de recursos extras, tais como arquivos de scripts, estilos (CSS) e imagens. Considere o exemplo abaixo, que é uma página extremamente simples que referencia cinco arquivos de estilos.

<html>
    <head>
        <link href=”Estilos1.css” rel=”stylesheet” type=”text/css” />
        <link href=”Estilos2.css” rel=”stylesheet” type=”text/css” />
        <link href=”Estilos3.css” rel=”stylesheet” type=”text/css” />
        <link href=”Estilos4.css” rel=”stylesheet” type=”text/css” />
        <link href=”Estilos5.css” rel=”stylesheet” type=”text/css” />
    </head>
    <body>
        Testando
    </body>
</htm>

Quando fazemos a requisição para esta página HTML, é possível notar no log abaixo uma barra cinza em cada linha de acesso para os arquivos *.css. Essa cor indica o período de tempo em que o navegador fica aguardando para iniciar a requisição para o respectivo recurso. É importante notar que neste exemplo estamos utilizando o HTTP 1.1.

Já agora se fizermos a requisição utilizando o HTTP/2, podemos perceber que não existe mais a barra cinza, ou seja, isso indica que os recursos são carregados de forma concorrente, sem a necessidade de ter um delay. Isso tudo é possível perceber na imagem abaixo.

Server Push no HTTP/2

Quando fazemos a solicitação para alguma página de um site, além de seu próprio conteúdo, ela referencia alguns outros recursos (tais como arquivos de scripts, imagens, estilos (CSS), etc.), e para cada um destes itens, novas requisições partem do navegador do cliente para baixa-los e, finalmente, apresentar o resultado final do usuário que a solicitou.

Na maioria das vezes estes recursos extras estão debaixo do mesmo servidor, e como sabemos, os navegadores limitam o número máximo de conexões simultâneas para um determinado domínio, o que gera certa lentidão no acesso, pois dependendo do tamanho e tempo de download destes arquivos, o resultado levará ainda mais tempo para ser exibido.

Como alternativa, é comum utilizarmos uma técnica conhecida domain-sharding, que nos permite espalhar os recursos extras por diferentes domínios e permitir o download simultâneo de todos eles; a outra opção é utilizar scripts ou estilos inline, que evita round-trips extras, mas acaba dificultando a manutenção e reutilização de código, e ainda, perdemos a opção de realizar caching destes recursos do lado do cliente.

Entre os novos recursos que o HTTP/2 fornece, um deles é o server push, que nos permite otimizar os problemas descritos acima, fornecendo uma opção que viabiliza o uso de referências externas sem comprometer a performance. A versão HTTP/2 faz um melhor uso das conexões TCP, e devido a restruturação de como a mensagem é enviada e recebida, passa a ser possível utilizar uma mesma conexão para requisitar e receber o resultado da solicitação e também dos recursos por ela utilizados e que não solicitados explicitamente.

Quando o servidor entende que o recurso solicitado faz uso de outras referências, ele é capaz de empurrar ao cliente essas referências indicando que elas serão utilizadas no futuro; na sequência ele devolve o resultado (HTML) da página e quando o navegador percebe que há imagens, CSS ou scripts, antes dele fazer a requisição para cada um deles, ele percebe que os mesmos já foram entregues, evitando o round-trip para cada um destes recursos extras, diminuindo consideravelmente o tempo de exibição do conteúdo como um todo.

Apesar de que isso não afete em nada as aplicações que já estão rodando ou que serão desenvolvidas, é importante saber da existência e comportamento desta funcionalidade para tirar proveito destas novas funcionalidades de mais baixo nível. Com o Windows 10, Internet Information Services (IIS) e o Edge, é possível ver isso em funcionamento. É importante mencionar que, por enquanto, a Microsoft apenas implementou este recurso apenas quando o site está sendo acessado através de HTTPS. É possível visualizar o HTTP/2 sendo usado através do log do Edge. E claro, se o cliente não suportar o HTTP/2, ele utilizará o HTTP 1.1 como fallback.

Criação e Gerenciamento de Conexões HTTP

Desde o início do .NET Framework temos uma classe chamada HttpWebRequest, que tem a finalidade de realizar requisições HTTP para algum recurso disponível. E como era de se esperar, ela expõe diversos métodos e propriedades para configurar as requisições que partem da instancia desta classe.

A cada requisição que é realizada, internamente ela recorre a classe ServicePointManager para criar a conexão até o recurso desejado, e a partir dai passa a reutilizar a mesma conexão nas chamadas subsequentes, poupando recursos da máquina de onde a requisição esta sendo feita. O objeto de conexão é criado considerando o protocolo, o host e a porta; se algum destes parâmetros variar, uma nova conexão é criada para atender este novo endereço e, consequentemente, reutilizada nas próximas requisições.

Só que existe a possibilidade de interferir na criação e gestão destas conexões. A classe HttpWebRequest define uma proprieade chamada ConnectionGroupName, e como o próprio nome sugere, ele considera o valor especificado nesta propriedade para criar a conexão, ou seja, para cada valor distinto definido nesta propriedade, uma nova conexão é criada. Se o valor se repetir, a conexão criada previamente é reutilizada.

Como sabemos, o WCF utiliza a classe HttpWebRequest nos bastidores quando acessa um serviço através do protocolo HTTP, e até então ele não disponibilizava qualquer propriedade no binding para configurar este pool de conexões HTTP. A partir da versão 4.6 do .NET Framework, a Microsoft permite ajustar este parâmetro (adicionando um prefixo) a fim de fazer uma melhor gestão e reuso das conexões HTTP pelos serviços WCF.

Por padrão, uma única conexão é mantida e compartilhada por todos os channels factories (proxy) que são instanciados pelo cliente. O que essa nova configuração irá fazer é criar uma conexão dedicada para cada channel factory criado pelo cliente, utilizando uma espécie de contador de instâncias para definir a propriedade ConnectionGroupName.

Para isso funcionar, basta ligar o flag useUniqueConnectionPoolPerFactory através do arquivo de configuração (app.config ou web.config) da aplicação cliente, assim como é mostrado no código abaixo.

<appSettings>
    <add key=”wcf:httpTransportBinding:useUniqueConnectionPoolPerFactory”
         value=”true” />
</appSettings>

Agora, se quiser um controle mais refinado e, de repente, variar a conexão de acordo com alguma regra ou parâmetro de negócio, você pode extrair e definir o nome do pool de conexões através das propriedades da mensagem do WCF, que em baixo nível, também vai utilizar o valor definido aqui para configurar a propriedade ConnectionGroupName.

OperationContext
    .Current
    .OutgoingMessageProperties
    .Add(“HttpTransportConnectionGroupNamePrefix”, “ValorCustomizado”);

Por fim, para ver isso em funcionamento, considere o código a seguir, que cria um laço e dentro dele instancia o channel factory e invoca o método do serviço. Antes de rodar, vamos configurar o flag como True para ver o impacto causado, provocando a criação de uma conexão dedicada para cada proxy. Por fim, é possível visualizar as conexões criadas através do utilitário TCPView.

var endereco = “http://localhost:9388&#8221;;

using (var host = new ServiceHost(typeof(Teste), new Uri(endereco)))
{
    host.AddServiceEndpoint(typeof(IServico), new BasicHttpBinding(), “”);
    host.Open();

    for (int i = 1; i < 11; i++)
        using (var srv = new ChannelFactory<IServico>(
            new BasicHttpBinding(), new EndpointAddress(endereco)))
                Console.WriteLine(srv.CreateChannel().Ping(“Teste ” + i.ToString()));
}

Propagando Transações

Como já sabemos, desde a versão 2.0 o .NET Framework possui uma API para criar e gerenciar transações dentro da aplicação. É o assembly System.Transactions.dll que disponibiliza um conjunto de APIs que podemos criar blocos transacionais, e assim alistar recursos que precisam de “proteção” para garantir que tudo seja efetivado ou desfeito caso algum problema ocorra (independente se o problema for de infraestrutura ou regra de negócio).

A principal classe que temos para isso é a TransactionScope, que ao ser envolvida em um bloco using, no método Dispose ela realiza o commit ou o rollback, dependendo se o método Complete foi ou não chamado. É dentro deste escopo criado que o .NET gerencia, e dependendo do que está envolvido nele, ele utiliza uma transação local (LTM) ou escala para uma transação distribuída (DTC).

Aqui estamos falando de um mesmo processo que é responsável por criar a transação, alistar os recursos, e por fim, finalizar a mesma (com sucesso ou falha). Mas como fazer quando a transação é iniciada pelo processo A e precisamos envolver as tarefas executadas por outro processo (B)? Ainda dentro deste mesmo assembly, temos uma classe chamada TransactionInterop, que expõe alguns métodos para “expandir” a transação entre processos.

Basicamente ele fornece métodos que geram uma chave e métodos que permitem recriar a transação a partir da mesma. Isso nos permitirá na aplicação A gerar a chave e importar na aplicação B, e com isso, ambas aplicações estarão envolvidas na mesma transação. É através do método estático GetTransmitterPropagationToken que geramos um array de bytes que representa o token de identificação da transação. Para exemplificar, vamos gerar este token a partir da aplicação A e armazenar este token um arquivo no disco para compartilhar com a aplicação B. No código abaixo estou removendo os logs para poupar espaço.

//Aplicação A
using (var ts = new TransactionScope())
{
    File.WriteAllBytes(@”C:TempTransactionToken.bin”,
        TransactionInterop.GetTransmitterPropagationToken(Transaction.Current));

    ts.Complete();
}

Do outro lado, utilizamos o método (também estático) GetTransactionFromTransmitterPropagationToken da classe TransactionInterop. Ele recebe como parâmetro um array de bytes (que estamos extraindo do arquivo) e recria a transação. Aqui o detalhe importante é reparar que o resultado deste método está sendo passado diretamente para um dos construtores da classe TransactionScope, que faz uso desta transação (criada pela outra aplicação) e envolve nela tudo o que está em seu próprio bloco using.

//Aplicação B
using (var ts =
    new TransactionScope(
        TransactionInterop.GetTransactionFromTransmitterPropagationToken(
            File.ReadAllBytes(@”C:TempTransactionToken.bin”))))
{
    ts.Complete();
}

Se repararmos as imagens abaixo, notamos que na a aplicação A possui o identificador de transação distribuída (DI) zerado, e quando a aplicação B se envolve na mesma transação, o identificador da transação distribuída na aplicação A reflete o mesmo identificador da aplicação B, ou seja, ambas aplicações estão envolvidas na mesma transação. Por fim, é possível ver na última imagem o log do DTC, indicando que a mesma foi promovida à uma transação distribuída.

Curiosidade: sabemos que o WCF fornece suporte à transações em serviços, podendo o cliente iniciar a mesma e o serviço participar. O id da transação viaja do cliente para o serviço através de headers do envelope SOAP, e quando o serviço recebe a informação, ele recria a transação utilizando os recursos (classes e métodos) que vimos neste artigo.

Validando XML com Schemas da NF-e

No post anterior comentei como configurar os certificados para realizar consultas nos serviços da NF-e. Naquele exemplo estamos montando o XML manualmente que corresponde ao corpo da mensagem enviada ao serviço. Montar o XML manualmente é uma tarefa complicada, já que estamos sujeito à erros de digitação e, consequentemente, o serviço irá rejeitar a requisição por não estar dentro do formato esperado.

Mas qual é esse formato? Felizmente temos schemas (arquivos XSD) que são fornecidos pelo governo para que possamos validar as mensagens localmente antes de fazermos a requisição. O .NET Framework já fornece classe nativas para tal validação, e tudo o que precisamos fazer, é submeter o XML (sendo um arquivo ou até mesmo uma string) para que a validação possa ser realizada.

É através da classe XmlReaderSettings que devemos configurar o arquivo XSD a ser utilizado e o namespace que será utilizado para varrer o XML e validá-lo. Apesar de informar apenas um arquivo XSD, internamente ele referencia outros schemas que o complementam, e é importante que eles existam fisicamente no mesmo local para que a validação possa ser realizada. 

Esta classe também fornece um evento chamado ValidationEventHandler, que podemos assinar e recebermos as notificações dos problemas que ocorrerem durante a validação. Com os argumentos deste evento, podemos extrair a severidade e mensagem do erro. O código abaixo ilustra a criação e configuração desta classe:

var config = new XmlReaderSettings()
{
    ValidationType = ValidationType.Schema
};

config.Schemas.Add(“http://www.portalfiscal.inf.br/nfe&#8221;, “consStatServ_v3.10.xsd”);
config.ValidationEventHandler += (s, e) =>
{
    Console.WriteLine(“{0}: {1}”, e.Severity, e.Message);
};

Depois dela devidamente configurada, informamos a mesma durante a criação do XmlReader. No exemplo abaixo, estou optando por validar o conteúdo XML que está em uma string, mas nada impede do conteúdo vir de um arquivo no disco.

var mensagem = “<?xml version=”1.0″ encoding=”utf-8″ ?>” +
            “<consStatServ xmlns=”http://www.portalfiscal.inf.br/nfe&#8221; versao=”3.10″>” +
            “<tpAmb>1</tpAmb>” +
            “<cUFx>35</cUFx>” +
            “<xServ>STATUS</xServ>” +
            “</consStatServ>”;

using (var reader = XmlReader.Create(new StringReader(mensagem), config))
    while (reader.Read()) { }

Propositalmente eu alterei o elemento cUF para cUFx, que é um elemento que não é suportado pelo XSD. Ao rodar a aplicação, a mensagem abaixo é exibida indicando o problema:

Error: The element ‘consStatServ’ in namespace ‘http://www.portalfiscal.inf.br/n
fe’ has invalid child element ‘cUFx’ in namespace ‘http://www.portalfiscal.inf.b
r/nfe’. List of possible elements expected: ‘cUF’ in namespace ‘http://www.porta
lfiscal.inf.br/nfe’.

Consumindo Serviços da NF-e com WCF

Todas as empresas, quando vendem uma mercadoria são obrigadas a emitir nota fiscal. Até pouco tempo atrás, as notas não eram padronizadas e cada empresa utilizava em modelo diferente. O governo decidiu então criar um mecanismo para que fosse possível a emissão de forma eletrônica.

Com isso cada estado brasileiro criou uma porção de web services que permite a emissão, autorização, cancelamento, consulta de status, etc. Como é possível perceber nas URLs dos serviços, eles utilizam o ASP.NET Web Services (ASMX) para expor estas funcionalidades.

Como sabemos, o WCF é o pilar de comunicação dentro do .NET Framework, e mantém compatibilidade com os antigos serviços desenvolvidos em ASMX. Isso quer dizer que é possível consumir estes serviços com a API do WCF. Para que isso seja possível, alguns cuidados precisam ser tomados para garantir que o acesso será permitido.

Os serviços são protegidos e para acessá-los é necessário apresentar um certificado digital válido. Os certificados podem ser adquiridos por entidades certificadores, tais como Serasa, Certsign, VeriSign, etc. E vale dizer que até mesmo o WSDL, documento que descreve as funcionalidades do serviço, também está protegido, e precisamos também apresentar um certificado para simplesmente adicionar a referência no Visual Studio.

Vale lembrar que existem alguns tipos de certificados, e no meu caso, estou utilizando um certifcado de cartão A3 (e-CNPJ) que está protegido por um PIN (senha) que é necessário informá-la sempre que o certificado está prestes a ser utilizado. Como estou com ele devidamente instalado, ao acessar a URL do serviço no navegador, já aparece uma lista com os possíveis certificados, assim como podemos notar na imagem abaixo. Uma vez que o certificado é escolhido, então a senha será exigida e, consequentemente, teremos acesso à página padrão do ASP.NET que descreve o serviço.

Da mesma forma que acontece acima, o Visual Studio também exigirá o certificado ao realizar o “Add Service Reference“, e informando corretamente, o download do WSDL será realizado e a referência para o serviço será configurada. Atente-se aqui que não estamos utilizando a opção “Add Web Reference“, pois ela recorre a API antiga (SoapHttpClientProtocol) para acesso e não utiliza o WCF.

Apesar da ferramenta já criar uma configuração padrão, ela não é válida para o acesso. Precisamos ajustar para informar ao WCF que ele precisa utilizar um certificado antes de fazer a requisição ao serviço. Estamos optando por utilizar um binding customizado para que seja possível adequar a segurança e a serialização de acordo com as exigências da SEFAZ.

Entre as customizações, temos que utilizar a versão 1.2 do SOAP. Além disso, informar que o transporte será baseado em HTTPS e que é necessário um certificado do cliente para apresentar ao serviço para ter acesso ao recurso. A configuração do certificado é feita através de um behavior e associado ao endpoint do serviço. Abaixo temos o resumo do arquivo de configuração válido para realizar o acesso. Por questões de simplicidade, estou utilizando o serviço que retorna o status (operante ou não) dos demais serviços da SEFAZ.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name=”NFe”>
          <textMessageEncoding messageVersion=”Soap12″ />
          <httpsTransport requireClientCertificate=”true” />
        </binding>
      </customBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name=”NFe”>
          <clientCredentials>
            <clientCertificate storeName=”My”
                               storeLocation=”CurrentUser”
                               x509FindType=”FindBySubjectName”
                               findValue=”ISRAEL AECE ME:………”/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address=”https://nfe.fazenda.sp.gov.br/ws/nfestatusservico2.asmx&#8221;
                binding=”customBinding”
                bindingConfiguration=”NFe”
                behaviorConfiguration=”NFe”
                contract=”ServiceReference1.NfeStatusServico2Soap12″
                name=”ServiceReference1.NfeStatusServico2Soap12″ />
    </client>
  </system.serviceModel>
</configuration>

Uma vez que a configuração está concluída, podemos acessar o serviço e visualizarmos o retorno. Note que o código C# nada sabe sobre as configurações de certificado. É importante ressaltar que como este certificado tem um PIN, um prompt irá aparecer automaticamente para a digitação do mesmo. Na sequencia é possível visualizar o resultado que foi devolvido pelo serviço.

using (var client = new NfeStatusServico2Soap12Client())
{
    var corpo = new XmlDocument();
    var mensagem = “<?xml version=”1.0″ encoding=”utf-8″ ?>” +
                “<consStatServ xmlns=”http://www.portalfiscal.inf.br/nfe&#8221; versao=”3.10″>” +
                “<tpAmb>1</tpAmb>” +
                “<cUF>35</cUF>” +
                “<xServ>STATUS</xServ>” +
                “</consStatServ>”;

    corpo.LoadXml(mensagem);

    var resultado = client.nfeStatusServicoNF2(new nfeStatusServicoNF2Request()
    {
        nfeCabecMsg = new nfeCabecMsg()
        {
            cUF = “35”,
            versaoDados = “3.10”
        },
        nfeDadosMsg = corpo
    });

    Console.WriteLine(resultado.nfeStatusServicoNF2Result.OuterXml);
}

<retConsStatServ versao=”3.10″ xmlns=”http://www.portalfiscal.inf.br/nfe”><tpAmb
>1</tpAmb><verAplic>SP_NFE_PL_008f</verAplic><cStat>107</cStat><xMotivo>Serviço
em Operaçao</xMotivo><cUF>35</cUF><dhRecbto>2015-03-19T08:31:31-03:00</dhRecbto>
<tMed>1</tMed></retConsStatServ>

Protegendo Formulários com reCaptcha

É comum termos formulários disponíveis em áreas públicas de sites. Esses formulários servem para que os usuários possam, geralmente, realizar cadastros, assinar newsletters, etc. Por estar público me refiro à não ser necessário se identificar para o site (login se senha) para poder ter acesso aquele recurso, e como já era de se esperar, alguém de má fé (ou não) pode começar a criar robôs para realizar diversas requisições de forma automática ao site, simulando ser um usuário e, consequentemente, tendo acesso ao recurso que é oferecido após o preenchimento do formulário.

Desconsiderando quem utiliza de má fé, quando clientes começam a desenvolver robôs para acessar um determinado recurso, é provável que seja o momento de criar algum serviço (API) para consumo direto por outros sistemas. Isso vai ao contrário do escopo deste artigo, ou seja, veremos aqui como fazer uso do reCAPTCHA, que é uma tecnologia oferecida gratuitamente pelo Google para proteger aplicações Web de robôs que tentam se passar por pessoas para acessar os recursos.

O primeiro passo para fazer uso, é cadastrar a aplicação (necessário uma conta do Google para isso). Ao fazer isso, um par de chaves será criado para fazermos uso em nossa aplicação. Abaixo está as configurações da aplicação de criei para o teste. A primeira chave (Site Key) é embutida no próprio HTML da aplicação, enquanto a segunda (Secret Key) deve ser mantida em sigilo e será utilizada para validar a resposta que o usuário informou, e isso será feito através do C# neste exemplo.

Para exibir o controle que faz toda a inteligência, basta adicionarmos a referência para um arquivo Javascript e adicionar um DIV no HTML, posicionando-o no local da tela que deseja que ele seja exibido. Repare que há um atributo chamado data-sitekey, que é onde colocaremos o Site Key gerado para a nossa aplicação. O HTML gerado deve ficar parecido com o código abaixo (estou omitindo o restante por questões de espaço e relevância):

<html>
<head>
    https://www.google.com/recaptcha/api.js
</head>
<body>
    <form>
       

 </form>
</body>

Ao executar a aplicação, teremos o formulário como vemos abaixo. Ao clicar no checkbox, uma pequena janela se abre para informar o texto que é apresentado. Quando você digita e clica no botão Confirmar, o componente gera um novo campo chamado g-recaptcha-response, que será submetido para o servidor e lá é onde iremos verificar junto ao Google se o que foi digitado está correto ou não. As imagens abaixo ilustram as três etapas antes de submeter o formulário para o servidor:



Agora chega o momento de validarmos o que foi digitado pelo usuário do lado do servidor. Essa validação garantirá que os dados digitados são válidos e correspondem a chave gerada para a nossa aplicação. O Google fornece uma URL que permite fazermos uma requisição (GET), passando alguns parâmetros para a validação, sendo eles: secret, response e remoteip. O primeiro é a chave privada (Secret Key) que foi gerada para nosso site; o segundo parâmetro, response, é todo o conteúdo postado no campo g-recaptcha-response e, finalmente, o terceiro parâmetro é o endereço IP do cliente, mas trata-se de um parâmetro opcional.

Para realizar esta requisição, vamos utilizar a classe HttpClient de forma assíncrona para termos uma melhor performance no servidor. O resultado, codificado em JSON, pode ser convertido em um objeto para manipular de forma mais intuitiva no C#.

Basicamente estamos gerando a URL de acordo com os parâmetros exigidos, e através de uma requisição GET, vamos até o Google para validação do valor informado pelo usuário. Se o resultado for positivo (success = true), então seguimos adiante para armazenar o e-mail em nossa base de dados. Por questões de simplicidade, não estou recuperando os possíveis erros que podem acontecer durante a validação pelo Google, mas a resposta da requisição também contempla uma coleção chamada error-codes, que como o próprio nome diz, retorna os erros encontrados.

public class NewsletterController : Controller
{
    private const string ChaveSecreta = “6LfJqw………….06U1uL”;
    private const string UrlDeValidacao =
        “https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}&remoteip={2}”;

    [HttpPost]
    public async Task<ActionResult> Assinar(FormCollection fc)
    {
        var email = fc[“email”];
        var respostaDoUsuario = fc[“g-recaptcha-response”];
        var houveFalha = !(await ValidarCaptcha(respostaDoUsuario));

        if (!houveFalha)
        {
            //Incluir E-mail na Base de Dados
        }

        ViewBag.HouveFalha = houveFalha;
        return View();
    }

    private async Task<bool> ValidarCaptcha(string respostaDoUsuario)
    {
        var url =
            string.Format(UrlDeValidacao, ChaveSecreta, respostaDoUsuario, Request.UserHostAddress);

        using (var cliente = new HttpClient())
        {
            var resposta = await cliente.GetAsync(url);
            var resultado = await resposta.Content.ReadAsAsync<Resultado>();

            return resultado.Success;
        }
    }
}

public class Resultado
{
    public bool Success { get; set; }
}

BufferManager

O WCF faz uso internamente de uma classe chamada BufferManager. Como o próprio nome sugere, ela faz o gerenciamento de memória durante as requisições, e ao invés de ficar criando array de bytes para ler ou escrever uma mensagem, o BufferManager gerencia um pool de buffers para fazer uma melhor reutilização quando o recurso não é mais necessário.

Quando a requisição é lida e a memória reservada para isso não é mais necessária, este gestor recicla a mesma ao invés de descartar, evitando assim ter todo o custo de criação e alocação quando uma nova requisição chegar. A não utilização de um gestor de memória pode degradar a performance do serviço, do host e, consequentemente, da máquina onde tudo isso é executado.

Os bindings já fornecem propriedades para criar e gerenciar o BufferManager, a saber: MaxBufferPoolSize e MaxBufferSize. A primeira indica a quantidade máxima de memória (em bytes) que ele terá, enquanto a segunda, indicará o máximo de memória que cada item dentro do pool poderá ter, também em bytes. É importante dizer que a propriedade MaxBufferSize deve ter o mesmo valor da propriedade MaxReceivedMessageSize.

Engana-se quem acha que esta classe só traz benefícios. Se ela for mal configurada, a memória pode não ser devolvida/reciclada, e em pouco tempo, esgotará os recursos disponíveis na máquina. O algoritmo utilizado por esta classe, cria os pools de acordo com o tamanho das mensagens que precisam ser manipuladas, e se não havendo nenhum pool que atenda a mesma ou a mensagem é maior que o valor estipulado na configuração, o WCF aloca memória diretamente na HEAP, ou seja, não gerenciada pelo BufferManager.

Se isso ocorrer com frequência, ao longo do tempo os recursos estarão esgotados e as mensagens não serão mais processadas. É comum ver cenários onde todos as configurações são definidas com seus valores máximos (int.MaxValue), e isso poderá impactar consideravelmente o serviço. É importante dimensionar as configurações de acordo com a necessidade de cada serviço, baseando-se, principalmente, na demanda e tamanho das mensagens que chegam até ele.

Há uma forma de informar ao runtime do WCF para não utilizer o pool de buffers. Para isso basta configurar a propriedade MaxBufferPoolSize com o valor 0 (zero). Isso fará com que o WCF crie um buffer para cada requisição diretamente na memória HEAP, e fica a cargo do Garbage Collector gerenciar o seu tempo de vida. Para confirmar isso, no interior da classe BufferManager, se o valor informado for zero, a classe GCBufferManager é criada, e caso contrário, a classe PooledBufferManager é utilizada.

Se criarmos um pequeno exemplo de um serviço que retorna uma coleção de objetos (5000), podemos perceber no resumo do profiler que foi aplicado à execução, uma diferença significativa da quantidade de bytes que foram alocados quando utilizamos a propriedade MaxBufferPoolSize com valor diferente de zero e com valor igual a zero.

O buffer é útil quando falamos de mensagens pequenas. Quando se tratam de mensagens que ultrapassam 64KB, opte por não utilizar este recurso.

Validando a Assinatura Digital da NF-e

Atualmente as empresas emitem as notas fiscais em formato eletrônico. Para isso, foi desenvolvido um projeto que especifica e rege a emissão destas notas em ambiente nacional, que é conhecido como Nota Fiscal Eletrônica ou, simplesmente, NF-e. Este projeto faz uso de diversas tecnologias para garantir a segurança e, principalmente, a integridade da mesma.

A integridade é a garantia de que o arquivo XML que a representa não tenha sido alterado desde a sua emissão. Quando uma empresa emite uma nota fiscal, a SEFAZ gera um arquivo XML digitalmente assinado, utilizando o certificado digital da empresa emitente. Como sabemos, esse arquivo XML é a nota fiscal em formato eletrônico, e essa assinatura está embutida nele. A assinatura digital nada mais é que um cálculo matemático que é realizado sobre todo o arquivo XML, e se qualquer mudança ocorrer neste depois da assinatura, a mesma se tornará inválida.

Se você recebe este arquivo e quer garantir que ele não tenha sido alterado, então podemos recorrer à classes que estão dentro do .NET Framework para realizar esta validação. Basicamente devemos carregar o conteúdo XML para o objeto XmlDocument, e em seguida, procurar pelo elemento <Signature /> que é armazena o hash calculado e o certificado serializado que foi utilizado para realizar a assinatura.

var xml = new XmlDocument();
xml.Load(“00000000000000000000000000000000000000000000.xml”);

var nfe = (XmlElement)xml.GetElementsByTagName(“NFe”)[0];
var signature = (XmlElement)nfe.GetElementsByTagName(“Signature”)[0];
var signer = new SignedXml();

signer.LoadXml(signature);
Console.WriteLine(signer.CheckSignature());

Depois de carregado e separado os elementos que serão avaliados, recorrermos a classe SignedXml para validar a assinatura, onde devemos submeter o elemento que contém a assinatura para o método LoadXml, e em seguida, invocar o método CheckSignature, que retorna um valor boleano indicando se ela está ou não válida.

O overload do método CheckSignature utilizado acima (sem parâmetros) analisa o elemento <Signature /> tentando extrair os certificados de forma automática. Caso queira ter um maior controle sobre os certificados utilizados para analisar a assinatura, podemos utilizar um código mais rebuscado para atingir este objetivo:

private static bool ValidateWithCertificate(SignedXml signer)
{
    var keyInfoEnumerator = signer.KeyInfo.GetEnumerator();

    while (keyInfoEnumerator.MoveNext())
    {
        var x509Data = keyInfoEnumerator.Current as KeyInfoX509Data;

        if (x509Data != null && x509Data.Certificates.Count > 0)
            foreach (var cert in x509Data.Certificates)
                if (signer.CheckSignature((X509Certificate2)cert, true))
                    return true;
    }

    return false;
}

Como o próprio nome sugere, a propriedade KeyInfo contém informações referentes à chave que foi utilizada para realizar a assinatura. E, utilizando um enumerador, identificamos se trata-se de um certificado, e ao iterar pela coleção, invocamos o método CheckSignature, e através de um segundo overload, passamos o certificado que queremos que ele considere para realizer a validação. Apesar de ter o mesmo resultado, aqui é possível extrair informações do certificado utilizado, caso seja necessário.

Importante: um erro bastante comum é que alguns sistemas incluem novas informações no XML depois que ele foi assinado. Ao fazer isso, a assinatura digital é corrompida, e ao submetermos o XML para o código que escrevemos acima, a assinatura será dada como inválida. Entre essas informações, é comum ver namespaces como os que são mostrados abaixo (em negrito), e segundo a Nota Técnica 2010/009 da SEFAZ, eles não devem ser incluídos, nem antes, e muito menos depois, da assinatura.

<?xml version=”1.0″ encoding=”UTF-8″?>
<nfeProc xmlns=”http://www.portalfiscal.inf.br/nfe&#8221;
         xmlns:ds=”http://www.w3.org/2000/09/xmldsig#&#8221;
         xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

         versao=”2.00″>
  <NFe xmlns=”http://www.portalfiscal.inf.br/nfe”&gt;
    <infNFe Id=”NFe…” versao=”2.00″>