Geração de Documentação para ASP.NET WebApi

Há algum tempo eu comentei aqui sobre REST e WSDL, onde a ideia era apontar a maneira de se trabalhar com serviços sem a necessidade de ter um schema que define o que serviço disponibiliza e, principalmente, toda a estrutura das mensagens (SOAP) que são trocadas entre as partes.

Mas é importante dizer que mesmo serviços baseados em REST, também precisam, de alguma forma, expor alguma espécie de documentação, para descrever as ações que as APIs estão disponibilizando aos consumidores, apontando o caminho (URI) até aquele ponto, método/verbo (HTTP), informações que precisam ser passadas, formatos suportados, etc.

A ideia é apenas ser informativo, ou seja, isso não será utilizado pelo cliente para a criação automática de uma proxy. Pensando nisso, a Microsoft incluiu no ASP.NET Web API a opção para gerar e customizar as documentações de uma API.

Mas a documentação é sempre exibida, na maioria das vezes, de forma amigável ao consumidor, para que ele possa entender cada uma das ações, suas exigências, para que ele possa construir as requisições da forma correta. Sendo assim, podemos na própria aplicação onde nós temos as APIs, criar um controller que retorna uma view (HTML), contendo a descrição das APIs que estão sendo hospedadas naquela mesma aplicação.

public class DeveloperController : Controller
{
    public ActionResult Apis()
    {
        var explorer = GlobalConfiguration.Configuration.Services.GetApiExplorer();

        return View(explorer.ApiDescriptions);
    }
}

Note que estamos recorrendo ao – novo – método GetApiExplorer, disponibilizado através da configuração global das APIs. Este método retorna um objeto que implementa a interface IApiExplorer, que como o próprio nome sugere, define a estrutura que permite obter a descrição das APIs. Nativamente já temos uma implementação chamada ApiExplorer, que materializa todoas as APIs em instâncias da classe ApiDescription, e uma coleção deste objeto é retornada através da propriedade ApiDescriptions, e que repassamos para que a view possa renderizar isso.

Na view, tudo o que precisamos fazer é iterar pelo modelo, e cada elemento dentro deste laço representa uma ação específica que está dentro da API. A classe que representa a ação, possui várias propriedades, fornecendo tudo o que é necessário para que os clientes possam consumir qualquer ums destas ações. Abaixo temos o código que percorre e exibe cada uma delas:

@model IEnumerable<System.Web.Http.Description.ApiDescription>

<body>
    @foreach (var descriptor in this.Model)
    {
        <ul>
            <li><b>@descriptor.HttpMethod – @descriptor.RelativePath</b></li>
            <li>Documentation: @descriptor.Documentation</li>

            @if (descriptor.SupportedResponseFormatters.Count > 0)
            {
              <li>Media Types
                <ul>
                  @foreach (var mediaType in descriptor.SupportedResponseFormatters.Select(
                     mt => mt.SupportedMediaTypes.First().MediaType))
                  {
                    <li>@mediaType</li>
                  }
                </ul>
              </li>
            }

            @if (descriptor.ParameterDescriptions.Count > 0)
            {
              <li>Parameters
                  <ul>
                    @foreach (var parameter in descriptor.ParameterDescriptions)
                    {
                      <li>Name: @parameter.Name</li>
                      <li>Type: @parameter.ParameterDescriptor.ParameterType</li>
                      <li>Source: @parameter.Source</li>
                    }
                  </ul>
              </li>
            }
        </ul>
    }
</body>

Ao acessar essa view no navegador, temos a relação de todas as ações que estão expostas pelas APIs. A visibilidade das ações é controlada a partir do atributo ApiExplorerSettingsAttribute, que possui uma propriedade boleana chamada IgnoreApi, que quando definida como True, omite a extração e, consequentemente, a sua visualização.

É importante notar que na imagem acima, estamos apresentando a propriedade Documentation. A mensagem que aparece ali é uma customização que podemos fazer para prover essa informação, extraindo-a de algum lugar. Para definir a descrição da ação, vamos criar um atributo customizado para que quando decorado no método, ele será extraído por parte da infraestrutura do ASP.NET, alimentando a propriedade Documentation. O primeiro passo, consiste na criação de um atributo para definir a mensagem:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ApiDocumentationAttribute : Attribute
{
    public ApiDocumentationAttribute(string message)
    {
        this.Message = message;
    }

    public string Message { get; private set; }
}

O próximo passo é decorá-lo em cada uma das ações que quisermos apresentar uma informação/descrição. A classe abaixo representa a nossa API, e o atributo recentemente criado foi decorado em todas as ações, descrevendo suas respectivas funcionalidades:

public class ClientesController : ApiController
{
    [ApiDocumentation(“Retorna todos os clientes.”)]
    public IEnumerable<Cliente> Get()
    {
        //…
    }

    [ApiDocumentation(“Retorna um cliente pelo seu Id.”)]
    public Cliente Get(int id)
    {
        //…
    }

    [ApiDocumentation(“Inclui um novo cliente.”)]
    public void Post(Cliente cliente)
    {
        //…
    }

    [ApiDocumentation(“Exclui um cliente existente.”)]
    public void Delete(int id)
    {
        //…
    }
}

Só que o atributo por si só não funciona. Precisamos de algum elemento para extrair essa customização que fizemos, e para isso, a temos uma segunda interface, chamada IDocumentationProvider, que fornece dois métodos com o mesmo nome: GetDocumentation. A diferença entre eles é o parâmetro que cada um deles recebe. O primeiro recebe um parâmetro do tipo HttpParameterDescriptor, o que permitirá descrever, também, cada um dos parâmetros de uma determinada ação. Já o segundo método, recebe um parâmetro do tipo HttpActionDescriptor, qual utilizaremos para extrair as informações pertinentes à uma ação específica.

public class ApiDocumentationAttributeProvider : IDocumentationProvider
{
    public string GetDocumentation(HttpParameterDescriptor parameterDescriptor)
    {
        return null;
    }

    public string GetDocumentation(HttpActionDescriptor actionDescriptor)
    {
        var attributes =
            actionDescriptor.GetCustomAttributes<ApiDocumentationAttribute>();

        if (attributes.Count > 0)
            return attributes.First().Message;

        return null;
    }
}

Aqui extraímos o atributo que criamos, e se ele for encontrado, retornamos o valor definido na propriedade Message. A ausência deste atributo, faz com que um valor nulo seja retornado, fazendo com que nenhuma informação extra seja incluída para a ação.

E, finalmente, para incluir o provedor de documentação ao runtime do ASP.NET, recorremos à configuração das APIs, substituindo qualquer implementação existente para este serviço, para o nosso provedor que extraí a documentação do atributo customizado.

GlobalConfiguration.Configuration.Services.Replace(
    typeof(IDocumentationProvider),
    new ApiDocumentationAttributeProvider());

Recursos da Palestra do MVC Summit 2012

 

Acabei de efetuar uma palestra no MVC Summit 2012. Entre os vários temas que foram discutidos sobre o desenvolvimento Web, eu falei sobre o ASP.NET Web API, que pode ser utilizado para a construção de serviços baseados em REST. Peço desculpas, mas infelizmente não houve tempo suficiente para abrir para perguntas e respostas, então para aqueles que gostaríamos de fazer algum questionamento, peço encarecidamente para que vocês coloquem nos comentários deste post, ou se desejarem, podem me contatar diretamente através da seção de contato.

Gostaria imensamente de agradecer a todos os presentes, e também ao Vinicius Quaiato, Andre Baltieri, Victor Cavalcante e ao Alexandre Tarifa por esta oportunidade. Para aqueles interessados, o download do projeto pode ser baixado clicando aqui, e se desejarem, aqui também estão os slides da apresentação.

Substituindo o Framework de AOP

Quando desenvolvemos um software, ou uma parte dele, além da parte relacionada ao negócio em si, nas maioria das vezes, precisamos recorrer a códigos de infraestrutura, que são responsáveis por gerenciar alguns recursos que estão indiretamente relacionados ao processo.

Geralmente mencionamos o termo cross-cutting concerns, que se referem a funcionalidades que podem se estender e afetar várias partes do sistema. Autenticação, Autorização, Logging e Transação, são algumas das funcionalidades que poderiam ser candidatas a serem encaradas e implementadas desta forma.

Apesar de possível, não é interessante misturar este tipo de funcionalidade com o código de negócio, pois facilmente você poderá agregar mais funcionalidade do que deveria. Além disso, a modularização é extremamente importante, pois facilita a manutenção, e eventuais alterações mais complexas. Como estas funcionalidades interceptam várias partes do sistema e em diversos níveis, uma das formas mais comuns de se acoplar isso à execução, é através da técnica de AOP, Aspect Oriented Programming.

Em .NET, existe um framework chamado PostSharp. Este é um framework fornece alguns atributos para decorar em elementos do nosso código, e onde o aplicamos, ele utilizará IL Weaving durante a compilação, reescrevendo o código para adicionar os comportamentos necessários, e durante a execução, serão executados de forma automática (e mágica?), sem que o nossos códigos de negócios mencionem diretamente funcionalidades de cross-cutting.

Apesar do framework fazer um grande trabalho, reescrevendo a IL para injetar o código customizado em torno do local onde o aplicamos, poderíamos trabalhar de forma semelhante, sem qualquer mágica envolvida. Tudo isso, utilizando apenas classes customizadas, onde você poderá ter o controle total, e tudo isso, sem a necessidade de envolver algum framework de terceiro.

Para exemplificar, podemos criar uma classe que representa um comando a ser executado. Basicamente, cada comando carrega as informações necessárias para que o mesmo possa ser executado, como por exemplo: criar, configurar e por fim, gravar um novo cliente na base de dados. Mas o comando por si só não funcionará. Isso quer dizer que vamos precisar de um tratador, ou seja, aquele que irá recepcionar o comando (que contém os dados), executando-o para que o cliente seja efetivamente gravado na base de dados.

Neste comando, poderíamos envolvê-lo em um bloco transacionado, efetuar o logging de algumas informações, mensurar o tempo de execução, etc. Mas como dito acima, colocar códigos de cross-cutting aqui, faria com que tivessemos algumas outras preocupações, e isso, voltaria a acontecer em todos os comandos que nossa aplicação venha a ter. Redundância e descentralização seriam alguns dos problemas que poderíamos enfrentar, sem contar a eventual necessidade de ter que injetar dependências indiretas ao comando (aquelas exigidas pela infraestrutura).

Abaixo temos o diagrama de classes que resume todos os tipos utilizados na solução. Classes sufixidas com a palavra “Handler”, correspondem aos tratadores dos comandos, e como eles estão implementados no formato de russian-dolls, podemos adicionar um dentro do outro, fazendo com que eles sejam executados antes ou depois do outro comando que você adicionou.

Repare que no código abaixo, LogingHandler, ele herda da classe abstrata CommandHandler, recebendo em seu construtor a instância de um próximo comando, qual será executado “entre este comando”.

public class LoggingHandler : CommandHandler
{
private readonly CommandHandler next;

public LoggingHandler(CommandHandler next)
{
this.next = next;
}

protected override void ExecuteInternal(Command command)
{
Console.WriteLine(“* Início da Execução do Comando.”);
this.next.ExecuteCommand(command);
Console.WriteLine(“* Fim da Execução do Comando.”);
}
}

Se evoluirmos um pouco mais o código, podemos criar métodos de extensão, para que cada um deles seja responsável por retornar um novo tratador, envolvendo nele o tratador atual, aquele onde está sendo aplicado a estensão. Neste caso, podemos nomear os métodos, de acordo com a funcionalidade que cada um deles agrega à execução:

public static class Estensoes
{
public static CommandHandler ComTransacao(this CommandHandler handler)
{
return new TransactionHandler(handler);
}

public static CommandHandler MedindoTempo(this CommandHandler handler)
{
return new TimerHandler(handler);
}

public static CommandHandler GerandoLog(this CommandHandler handler)
{
return new LoggingHandler(handler);
}
}

Como os métodos de estensão criados acima estão sendo aplicados ao tipo CommandHandler, podemos agregar ao mesmo qualquer uma das funcionalidades, de uma “forma fluente”. Com todos os tratadores do diagrama acima implementados, podemos escrever um código parecido com esse:

new CadastrarClienteHandler()
.ComTransacao()
.GerandoLog()
.MedindoTempo()
.ExecuteCommand(new CadastrarCliente() { Nome = “Israel” });

E, finalmente, o resultado depois da execução:

  • Início da Execução do Comando ‘CadastrarCliente’.
  • Início do Bloco Transacionado.
  • Cadastrando o Cliente ‘Israel’.
  • Commit da Transação.
  • Fim do Bloco Transacionado.
  • Fim da Execução do Comando ‘CadastrarCliente’.
  • Tempo Decorrido: 00:00:00.0042806.

Configuração dinâmica no WCF

Existem duas formas de configurar um serviço WCF: imperativa e declarativa. A primeira opção consiste em criar explicitamente a classe ServiceHost, configurá-la e gerenciar a sua execução, e tudo isso é feito diretamente através da linguagem (C# e VB.NET). Já no modelo declarativo, recorremos ao arquivo de configuração (App.config ou Web.config), onde tudo é configurado dentro deles, o que te dá uma maior flexibilidade, já que te permite alterar mesmo depois de instalado no servidor.

Quando queremos algum dinamismo na configuração do serviço, podemos recorrer a primeira opção. Mas quando estamos hospedando o serviço em um projeto Web, através de um arquivo *.svc, a construção da classe ServiceHost é criada automaticamente pelo WCF/ASP.NET.

Nestes casos, para conseguir atingir o nosso objetivo, devemos construir uma factory customizada, e para isso, precisamos criar uma classe herdando de ServiceHostFactory, sobrescrever o método CreateServiceHost, onde dentro dele, criaremos o ServiceHost de acordo com nossa necessidade e, finalmente, acoplamos  à execução através da diretiva @ServiceHost no arquivo *.svc. Mais detalhes aqui.

Na versão 4.5 do WCF, a Microsoft facilitou isso, sem a necessidade de fazer várias customizações e configurações. Basicamente colocamos na classe que representa o serviço, um método estático chamado Configure, que receberá como parâmetro a instância da classe ServiceConfiguration, e como o próprio nome diz, corresponde as configurações daquele serviço, e que será aplicado ao ServiceHost. O código abaixo ilustra este novo recurso. Isso irá eliminar tudo aquilo que fazíamos até então, para conseguir customizar e/ou gerar a configuração para os serviços que são hospedados no IIS.

public class Servico : IContrato
{
    public static void Configure(ServiceConfiguration config)
    {
        config.Description.Behaviors.Add(
            new ServiceMetadataBehavior() { HttpGetEnabled = true });

        config.Description.Behaviors.Add(
            new ServiceDebugBehavior() { IncludeExceptionDetailInFaults = true });
    }

    public string Ping(string value)
    {
        return value + ” ping”;
    }
}

Compressão no .NET Framework 4.5

Há algum tempo, eu falava aqui sobre compressão de arquivos no .NET Framework. Temos à disposição as classes GZipStream e DeflateStream para manipular arquivos, ou melhor, conteúdos que necessitam ser compactados ou descompactados utilizando estes dois algoritmos (Deflate e GZip).

Apesar de funcionar em alguns cenários, é um pouco difícil trabalhar em situações mais comuns quando precisamos lidar com (des)compactação. Um exemplo típico é quando precisamos compactar um diretório todo, ou múltiplos arquivos em um único arquivo *.zip. Além disso, toda a manipulação precisa ser realizada através do uso de streams, ou seja, temos que lidar com a alocação e cópia dos bytes entre a origem e o destino.

Como as operações comuns são as mais complicadas de serem utilizadas, recorremos à frameworks externos, como é o caso do SharpZipLib, que fornece várias funcionalidades interessantes acerca da utilização de ZIPs. Finalmente, a partir da versão 4.5 do .NET Framework, a Microsoft incluiu novas classes que visa facilitar a manipulação destes tipos de arquivos em aplicações .NET.

Apesar dos novos tipos estarem debaixo do namespace System.IO.Compression, eles são fornecidos através da referência de novos assemblies que fazemos em nossas aplicações: System.IO.Compression.dll e System.IO.Compression.FileSystem.dll. O primeiro assembly fornece os tipos de mais baixo nível para trabalhar com ZIP; já as classes disponíveis dentro do segundo assembly, temos apenas alguns utilitários (classes estáticas) que tornam ainda mais fácil a geração e consumo de ZIPs pela aplicação.

A primeira classe que vamos falar é a ZipArchive, que corresponde a um pacote de arquivos comprimidos, que pode ser um ou N arquivos. Para cada conteúdo (arquivo) dentro do ZipArchive, existe uma classe que o descreve: ZipArchiveEntry. E como já era de se esperar, a classe ZipArchive fornece uma propriedade chamada Entries, que retorna a coleção de entradas, e podemos notar isso na imagem abaixo:

A classe ZipArchiveEntry não é criada diretamente, ou seja, através de um construtor público. A primeira opção para a sua criação, é através do método CreateEntry da classe ZipArchive, que recebe como parâmetro o nome da entrada, e que muitas vezes, se você estiver compactando um arquivo, o nome da entrada pode refletir o nome do arquivo que está sendo inserido.

No exemplo abaixo, abrimos a conexão com um arquivo de destino via FileStream. Esse arquivo será o arquivo compactado, ou seja, as entradas criadas serão colocadas nele. O stream que aponta para o arquivo Dados.zip, é passado no construtor da classe ZipArchive, e logo em seguida, percorremos os arquivos do diretório C:Temp, onde para cada arquivo, criamos uma entrada dentro do ZipArchive. Por fim, copiamos o conteúdo do arquivo da origem para o destino, ainda operando com streams. O código abaixo ilustra este trabalho:

using (var output = new FileStream(“Dados.zip”, FileMode.Create))
using (var archive = new ZipArchive(output, ZipArchiveMode.Create))
    foreach (var filename in Directory.GetFiles(@”C:Temp”))
        using (var source = File.Open(filename, FileMode.Open))
        using (var destination = archive.CreateEntry(Path.GetFileName(filename)).Open())
            source.CopyTo(destination);

Ao rodar esse código, efetuamos a compactação de todos os arquivos que estão no diretório C:Temp. Para os testes, existem dois arquivos neste diretório, totalizando cerca de 11 MB. E depois de serem compactados, e colocados no arquivo Dados.zip, o valor cai para 316 KB, assim como podemos perceber através da imagem abaixo:

Como comentei acima, com o intuito de facilitar ainda mais a criação de conteúdo compactado, vamos reescrever este código utilizando um novo método de estensão, chamado CreateEntryFromFile, que dado o arquivo de origem e o nome da entrada, ele automaticamente cria a mesma, já copiando todo o conteúdo para dentro dela. Vemos que o código fica mais simples ao utilizar essa opção:

using (var output = new FileStream(“Dados.zip”, FileMode.Create))
using (var archive = new ZipArchive(output, ZipArchiveMode.Create))
    foreach (var filename in Directory.GetFiles(@”C:Temp”))
        archive.CreateEntryFromFile(
            filename,
            Path.GetFileName(filename),
            CompressionLevel.Optimal);

E para facilitar ainda mais, temos um método estático disponível através da classe ZipFile, chamado CreateFromDirectory, que dado o endereço do diretório e o caminho para o arquivo de destino, ele já cria as entradas para cada arquivo, copia o conteúdo e, finalmente, gera o arquivo compactado. Por fim, em uma única linha, conseguimos reescrever os mesmos códigos que vimos acima:

ZipFile.CreateFromDirectory(@”C:Temp”, @”C:Dados.zip”);

Este método ainda fornece um overload, que além de permitir informar o nível da compactação, recebe um boleano, indicando se a pasta que está sendo compactada, deve ou não ser incluída como raiz do arquivo compactado. Abaixo, as imagens mostram quando utilizamos true, e logo na sequência, false, para este parâmetro:

ZipFile.CreateFromDirectory(
            @”C:Temp”,
            @”C:Dados.zip”,
            CompressionLevel.Optimal,
            true);

A extração do arquivo compactado para os arquivos isolados, são trabalhados de forma semelhante. E da mesma forma que na compactação, a descompactação também fornece alguns métodos utilitários que podem ser utilizados para realizar a extração dos arquivos que estão dentro do arquivo *.zip. Para exemplificar, no código abaixo, fazemos o uso do método estático ExtractToDirectory, exposto pela classe ZipFile. Este método recebe como fonte, o arquivo compactado, e o segundo parâmetro, corresponde ao caminho onde queremos extrair todo o conteúdo:

ZipFile.ExtractToDirectory(@”C:Dados.zip”, @”C:Output”);

Utilizando o DataReader Assincronamente

Na versão 2.0 do .NET Framework, a Microsoft incluiu uma série de novas funcionalidades em sua API de acesso a dados, o ADO.NET. Entre elas, podemos destacar o código genérico, MARS, Bulk-Copy e execução assíncrona de comandos e consultas.

O que tínhamos disponível naquela época é a implementação através do modelo assíncrono do .NET, que era implementado utilizando um par de métodos BeginXXX/EndXXX. Sendo assim, o método ExecuteReader passou a ter os métodos BeginExecuteReader e EndExecuteReader, enquanto o método ExecuteNonQuery, ganhou os métodos BeginExecuteNonQuery e EndExecuteNonQuery.

Da mesma forma, para ficar alinhado a nova forma de se trabalhar assincronamente nas linguagens, a execução assíncrona de comandos e consultas no ADO.NET 4.5 sofreu algumas mudanças, para seguir o modelo baseado em Tasks. Além das mudanças em nível das interfaces das classes, um detalhe importante é que não é mais necessário definir o flag Asynchronous Processing para True no arquivo de configuração, algo que sempre era descoberto somente depois que a aplicação estava em execução.

Para iniciar, a classe que representa a conexão (SqlConnection/DbConnection) fornecem a versão assíncrona do método Open, que é o OpenAsync. Este método retorna uma Task, o que a torna “aguardável”, e com isso, podemos utilizar a keyword await para que a abertura possa ser realizada de forma assíncrona. Abaixo o código ilustra o uso deste método:

private async static Task Executar()
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync();

        //…
    }
}

Como já era de se esperar, os mesmos métodos fornecidos na versão 2.0 do ADO.NET para processamento assíncrono, ganharam na versão baseada em Tasks na versão 4.5. No caso do ExecuteReader, temos o ExecuteReaderAsync. Já para o método ExecuteNonQuery, temos o ExecuteNonQueryAsync e, finalmente, para o ExecuteScalar, existe o ExecuteScalarAsync.

Todos estes métodos tratam-se da nova versão assíncrona, que basicamente retornam um objeto do tipo Task, que representa a tarefa que está sendo executada assincronamente. E, qualquer exceção que eventualmente ocorra dentro do processo assíncrono, ela será retornada/acessada através da Task que foi retornada pelo método. Abaixo temos um exemplo de como ler os dados através de DataReader, utilizando este novo modelo assíncrono:

private async static Task Executar()
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync();

        using (var cmd = new SqlCommand(“SELECT * FROM Cliente”, conn))
            using (var dr = await cmd.ExecuteReaderAsync())
                while (await dr.ReadAsync())
                    if (!await dr.IsDBNullAsync(1))
                        Console.WriteLine(dr.GetString(1));
    }
}

Acima utilizamos o método ExecuteReaderAsync, mas ao percorrer o result-set retornado, utilizamos o – também novo – método ReaderAsync, que é a versão assíncrona, também baseada em Task,  do método Read do DataReader. Esse método em conjunto os métodos NextResultAsync, IsDBNullAsync e GetFieldValueAsync<T>, fornecem um controle muito mais refinado aos dados que estão sendo extraídos, pois quando olhamos um pouco mais de perto os internals de cada um deles, percebemos que a versão síncrona pode custar caro, prejudicando assim a escalabilidade.

Além disso, todos os métodos que vimos até aqui, possuem um segundo overload que suporta o cancelamento da tarefa custosa que está sendo executada. Para controlar o cancelamento, eles fazem uso da estrutura CancellationToken, e que podemos criar e informar ao invocar o método. Com uma pequena mudança na assinatura do método de exemplo que criamos acima (Executar), ele passará a receber o token que controla e propaga a notificação de cancelamento. Uma vez que o mesmo é repassado às tarefas que são executadas internamente, periodicamente o token é consultado para ver se o cancelamento foi ou não solicitado. A mudança é ligeira:

private async static Task Executar(CancellationToken ct)
{
    using (var conn = new SqlConnection(“…”))
    {
        await conn.OpenAsync(ct);

        using (var cmd = new SqlCommand(“SELECT * FROM Cliente”, conn))
            using (var dr = await cmd.ExecuteReaderAsync(ct))
                while (await dr.ReadAsync(ct))
                    if (!await dr.IsDBNullAsync(1, ct))
                        Console.WriteLine(dr.GetString(1));
    }
}

Como percebemos, para preparar o método para permitir o cancelamento, é receber no parâmetro um CancellationToken, e propagá-lo para os métodos internos. Abaixo, estamos consumindo o método Executar que criamos, só que agora estamos passando um token que que será cancelado em dois segundos. Se depois deste tempo o método não concluir, uma exceção será disparada, informando que a tarefa foi cancelada.

var cts = new CancellationTokenSource();

try
{
    cts.CancelAfter(TimeSpan.FromSeconds(2));
    Executar(cts.Token).Wait();
}
catch (Exception ex)
{
    //trata exceção
}

Microsoft Fakes no Visual Studio 2011

Ao escrever testes unitários antes do código que define as regras dos negócios, conseguimos identificar uma série de detalhes que nos ajuda a definir uma interface clara e consistente para nossos tipos, afinal, já estamos tendo uma visão do consumidor dos mesmos.

Além disso, essa técnica nos ajuda a identificar eventuais dependências que nossos tipos exigem e, consequentemente, isolá-las para que tenham certa flexibilidade, que com isso conseguiremos alternar facilmente entre uma implementação dummy e outra real. E mesmo durante a execução dos testes, é comum utilizarmos uma implementação fictícia, para que ela nos auxilie a testar uma regra específica, onde é irrelevante o uso de uma dependência real.

Outra questão que geralmente ocorre ao escrever testes, é o uso (dependência) de recursos estáticos ou de alguma outra coisa que é díficil simular, como uma classe que não permite sobrescrever seus membros. Um outro grande exemplo dessa dificuldade, é quando temos um código a ser testado que é sensível à data/hora. Como a propriedade Now da estrutura DateTime sempre retorna o horário atual, chamá-la duas vezes, sempre retornará valores diferentes, o que fica difícil definir se o teste sucedeu ou não.

Como parte de diversas melhorias que foram adicionadas na parte de testes do Visual Studo 2011, a Microsoft também incluiu novos recursos para resolver estes pequenos problemas que vimos acima. Microsoft Fakes é framework que ajuda na criação de implementações dummies em nossos testes, onde podemos facilmente simular certas situações injetando um código customizado.

Primeiramente vamos analisar um cenário em que essas novas funcionalidades podem ser interessantes. A classe abaixo, Log, define a estrutura de um item a ser logado. Recebemos em seu construtor a mensagem, e na sequência ele atribui a data atual à propriedade Data.

public class Log
{
    public Log(string mensagem)
    {
        this.Mensagem = mensagem;
        this.Data = DateTime.Now;
    }

    public string Mensagem { get; private set; }

    public DateTime Data { get; set; }
}

Ao escrever um teste que avalie se a data é mesmo atribuída, ele não vai passar. Note que como recorremos à propriedade Now, ela sempre retorna uma data diferente, e por mais que sejam poucos milisegundos, é o suficiente para ser diferente e, consequentemente, o teste falhará.

[TestMethod]
public void DeveAtribuirDataAtualAoLogCriado()
{
    Assert.AreEqual(DateTime.Now, new Log(“Mensagem de Log”).Data);
}

Eis que entra em cena os Shims. Esse tipo de fake nos permite fornecer uma implementação alternativa a membros estáticos ou tipos que não podem ser facilmente customizados (via herança, por exemplo). Para habilitá-o, temos que ir até o projeto de testes, onde o assembly com os tipos que estão sendo testados está referenciado, e clicar com o botão direito em cima daquele que queremos criar os fakes, e em seguida, na opção “Add Fakes Assembly”, assim como vemos na imagem abaixo:

Isso pode ser feito em nossos próprios assemblies ou naqueles do .NET Framework, e independente de qual você escolha, um novo assembly será criado com a infraestrutura necessária para guiar e realizar essa simulação. Os shims são baseados em delegates, o que nos permitirá interceptar a chamada para qualquer método/propriedade, definindo uma “nova” implementação para eles, e que durante a execução, ela será executada, retornando assim, o resultado de acordo com a nossa necessidade. Abaixo a imagem ilustra os assemblies fakes que foram criados para os exemplos:

Logicamente que com esse procedimento, novos tipos foram criados. Como precisamos intervir no retorno da data atual, um novo tipo está disponível: ShimDateTime. A estrutura DateTime fornece a propriedade Now, e neste novo tipo, temos a propriedade NowGet (Get porque Now é somente leitura). Essa propriedade recebe a instância de um delegate do tipo Func<DateTime>, ou seja, deve apenas retornar um DateTime. Abaixo temos o código que exibe como configurá-la para retornar uma data específica.

[TestMethod]
public void DeveAtribuirDataAtualAoLogCriado()
{
    using (ShimsContext.Create())
    {
        ShimDateTime.NowGet = () => new DateTime(2012, 4, 18);

        Assert.AreEqual(DateTime.Now, new Log(“Mensagem de Log”).Data);
    }
}

Além dos tipos que foram criados durante o procedimento de criação dos fakes, existem alguns outros tipos que dão suporte à configuração e execução destes testes. O principal deles é ShimContext, que controla o tempo de vida dos shims. A forma mais fácil de criá-la é através do método estático Create, mas é extremamente importante envolve-lo em um bloco using, para delimitar claramente o bloco onde eles serão utilizados e, principalmente, encerrar o contexto quando os shims não forem mais necessários. Se não fizer isso, a propriedade NowGet retornará sempre 18 de abril de 2012.

Em uma outra situação, imaginemos uma classe que é responsável por avaliar certos índices, e quando eles ultrapassarem um certo valor, uma mensagem deve ser logada para posterior análise. O nosso monitor deverá depender de uma definição e não de uma implementação do repositório de logs, ou em outras palavras, a ideia é durante os testes, injetar um repositório que armazena os logs em memória, mas ao consumir isso por uma aplicação, utilizamos um repositório real, onde por exemplo, poderia gravar isso em um banco de dados. Abaixo temos a estrutura da interface IRepositorioDeLogs e da classe Monitor:

public interface IRepositorioDeLogs
{
    void Adicionar(Log log);

    IEnumerable<Log> Todos { get; }
}

public class Monitor
{
    private IRepositorioDeLogs repositorioDeLogs;

    public Monitor(IRepositorioDeLogs repositorioDeLogs)
    {
        this.repositorioDeLogs = repositorioDeLogs;
    }

    public void AvaliarIndice(double indice)
    {
        if (indice > 75)
            repositorioDeLogs.Adicionar(
                new Log(string.Format(“O índice está acima dos 75.”, indice)));
    }
}

Para efetuar o teste, precisamos passar uma classe que implemente a interface IRepositorioDeLogs, onde neste caso, adicionará os logs em uma lista na memória. Vale lembrar aqui, que os testes garantem que se o índice estiver acima, ele deve gravar o log, independente se está armazenado na memória ou não.

Ao invés de criar uma implementação dummy, podemos recorrer aos stubs, que também são fornecidos por este novo recurso do Visual Studio 2011. Stubs fornecem uma implementação padrão para cada um dos membros fornecidos, neste caso, pela interface IRepositorioDeLogs. Novamente, aqui também recorreremos ao uso de delegates para customizar a funcionalidade de cada membro.

Como criamos também os fakes para o assembly que contém nossos tipos, ele já criou a classe StubIRepositorioDeLogs. Essa classe fornece os campos AdicionarLog e TodosGet. O primeiro recebe um delegate do tipo Action<Log>, enquanto o segundo define um delegate do tipo Func<IEnumerable<Log>>. Com uma implementação simples, conseguiremos simular um repositório que conseguirá acomodar o log que será adicionado ao mesmo, mas isso se a regra da classe Monitor, alvo do teste, estiver em correta.

Para o exemplo, criamos uma coleção do tipo List<Log>, e no delegate do campo AdicionarLog, invocamos o método Add da coleção, enquando ao acessar a propriedade Todos, irá retorná-la na íntegra, e é justamente a propriedade Count que determinará o sucesso ou a falha do teste. O código abaixo ilustra esse procedimento utilizando o stub recém criado:

[TestMethod]
public void SeIndiceEstiverAcimaDe75DeveIncluirLog()
{
    var repositorio = new List<Log>();
    var stub = var StubIRepositorioDeLogs()
    {
        AdicionarLog = log => repositorio.Add(log),
        TodosGet = () => repositorio
    };

    var indice = 78D;
    new Monitor(stub).AvaliarIndice(indice);

    Assert.AreEqual(1, repositorio.Count);
}

Autenticação – Mix entre WebApi e Interfaces

Para criar controllers que representem uma Web Api, trabalhamos de forma parecida com a criação de controllers para o ASP.NET MVC. Como trata-se apenas de um tipo específico de controller, podemos facilmente disponibilizar esta Api para consumo dentro da própria aplicação, para seu próprio consumo ou acesso por terceiros.

Apesar de suportado, podemos nos deparar com um problema específico ao hospedar a Api em uma aplicação que já possua uma interface com o usuário, e que controla a autenticação da mesma através do Forms Authentication.

Por padrão, as Web Apis possuem em sua rota um prefixo chamado /api/, mas independentemente disso, toda e qualquer requisição às ações (do Web Api ou não), serão interceptadas pelo módulo FormsAuthenticationModule, qual identifica se o usuário está ou não logado (baseando-se em um cookie), e se não estiver, irá redirecioná-lo para a página que login. Ele retorna para o navegador o código de 302 do HTTP, e quando ele (o navegador) receber este código, irá redirecionar para o endereço definido no header Location. Abaixo vemos o fluxo capturado pelo Fiddler:

A questão é que um serviço não espera que alguém se identifique “manualmente”; nem saberemos se estamos acessando-o via navegador ou através de uma outra aplicação. Sendo assim, a autenticação deve ser tratada pela própria requisição.

Remover ou “desligar” o FormsAuthenticationModule seria uma alternativa, mas isso faria com que a aplicação toda ficasse disponível para qualquer um acessar, inclusive de forma anônima. A solução mais simples seria separar fisicamente as aplicações, onde você teria uma para servir as aplicações que fornecem uma interface com o usuário, enquanto a outra, seria responsável apenas por hospedar as Apis que serão consumidas pelas outras aplicações (internas ou externas). Essa última opção, permitiria você tratar de forma independente cada uma delas, optando por qualquer meio de autenticação, sem que uma afeta no bom comportamento da outra.

Ainda há alguns truques que podemos recorrer para conseguir realizar esse mix de recursos em uma mesma aplicação, onde podemos identificar o código 302, e alterá-lo para 401 (Unauthorized), mas isso, tendo que escrever alguma customização, e em seguida, acoplar à execução para que ela funcione.

Co e Contra Variância em Interfaces

Os parâmetros genéricos foram recursos que foram incluídos no C# em sua versão 2.0. Desde então, podemos criar classes, interfaces, delegates, etc., que podem determinar um ou vários parâmetros e, consequentemente, utilizá-los definindo o tipo que acharmos necessário. No momento da criação/uso deste tipo, definimos o tipo do(s) parâmetro(s), e todos os membros em que o mencionamos passam a operar com ele, mas já fazendo diversas verificações ainda em tempo de compilação.

A partir do momento que podemos definir qualquer tipo, é comum queremos mencionar tipos que estão relacionados por herança, mas apesar disso ser suportado, algumas coisas que são comuns e fazemos normalmente, são barrados se utilizarmos em conjunto com tipos genéricos. Um caso específico que quero mencionar aqui, é o uso deste tipo genérico com interfaces. Para melhor ilustrar isso, vamos nos basear na estrutura de classes abaixo:

Note que Documento serve como base para todo e qualquer documento controlado pelo sistema. A partir deste momento, podemos criar interface que será responsável por definir um criador de objetos, e o tipo passa a ser determinado pelo parâmetro genérico T. Note que T é usado como retorno pelo método Criar.

interface ICriador<T>
{
T Criar();
}

Com esta interface, podemos construir uma classe que representará o criador de objetos padrão do sistema, e para demonstração, tudo o que vamos fazer é instanciar o tipo definido em T, o que nos obriga a defnir uma constraint, ou seja, que o tipo T possua um construtor público.

class CriadorPadrao<T> : ICriador<T> where T : new()
{
public T Criar()
{
return new T();
}
}

A ideia desta classe, é concentrar a criação do objetos, ou melhor, dos documentos utilizados pelo nosso sistema. Sendo assim, como queremos trabalhar da forma mais genérica possível, ou seja, não quero lidar diretamente em meu código com ICriador<Cnpj>, ICriador<Cpf>, etc., isso me obriga a criar uma variável do tipo ICriador<Documento> (Documento é a classe base). Com isso, a qualquer momento atribuimos à esta variável a instância do criador genérico, apontando em T o tipo Cnpj, Cpf, etc., assim como sugere o código abaixo:

ICriador<Documento> c = new CriadorPadrao<Cnpj>();
Console.WriteLine(c.Criar());

Apesar de CriadorPadrao implementar a interface ICriador, e mesmo pelo fato de Cnpj (tipo genérico definido em T) herdar de Documento, o C# não permite a compilação deste código. O fato aqui é que toda interface genérica, até a versão 3.0 do C#, é sempre invariante. Apesar dos tipos – isoladamente – estarem relacionados, CriadorPadrao<Cnpj> não implementa a interface ICriador<Documento>, o que viola a regra do polimorfismo.

A versão 4.0 do C# introduziu um recurso chamado de covariância. Ele nos permitirá, com um ligeira mudança na interface, fazer com que o código acima seja compilado e executado com sucesso. A mudança qual me refiro, é a introdução da keyword “out” antes do tipo genérico T, assim como mostrado abaixo:

interface ICriador<out T>
{
T Criar();
}

Isso dirá ao compilador que T somente será usado como retorno de métodos e/ou propriedades de somente leitura. Como o CriadorPadrao<Cnpj> vai retornar a instância da classe Cnpj no método Criar, ela pode ser acessada através da interface ICriador<Documento>, afinal, Documento é a classe base dela. Se definirmos na interface um parâmetro do tipo T, como o acesso à instância é através de ICriador<Documento>, poderia entrar qualquer coisa, ou seja, uma instância da classe Cnh, o que fará com que uma exceção seja disparada. Abaixo temos uma imagem que ajuda a entender:

Em um outro cenário, poderíamos ter uma interface que ao invés de retornar, passa a receber um tipo T. Dado um tipo, a interface define a estrutura de validação, que em seu método Validar recebe um parâmetro T, e devolve um bool indicando o resultado da validação. Abaixo temos a definição desta interface:

interface IValidador<T>
{
bool Validar(T documento);
}

Teremos também um validador padrão, que define a estrutura de validação genérica para qualquer tipo. Note que temos a classe ValidadorPadrao, que define T e propaga para a interface e, consequentemente, para o método Validar. Note que neste momento, o T está entrando.

class ValidadorPadrao<T> : IValidador<T>
{
public bool Validar(T documento)
{
//Validação
return true;
}
}

Agora a situação é que temos em mãos um validador exclusivo para Cnpj, e atribuímos a ele a instância da classe ValidadorPadrao, definindo T como Documento, ou seja, a classe base de todos os documentos, incluindo o próprio Cnpj.

IValidador<Cnpj> v = new ValidadorPadrao<Documento>();
v.Validar(new Cnpj());

Ao compilar o código, novamente temos um erro. Novamente, apesar de ValidadorPadrao implementar a interface IValidador, a atribuição não será possível. Apesar de estarmos tomando cuidado de passar para o método Criar um Cnpj (que herda de Documento), isso daria margem para definir o validador com um tipo sem relação alguma, como por exemplo, uma string, e através do método Validar passar a instância de CNPJ, e durante a execução, um erro ocorreria porque não é possível fazer tal conversão.

Para resolver isso, temos a contravariância. Também com uma pequena mudança na criação da interface, teremos um código mais flexível. Aqui teremos que adicionar antes do parâmetro T a keyword “in”, assim como é mostrado abaixo:

interface IValidador<in T>
{
bool Validar(T documento);
}

Isso dirá ao compilador que T somente será usado como parâmetros de entrada em métodos e/ou propriedades de somente escrita. Como o ValidadorPadrao<Documento> vai receber uma instância da classe Documento no método Validar, ela pode ser definida através da interface IValidador<Cnpj>, afinal, Cnpj é um tipo de Documento. Se definirmos na interface uma saída do tipo T, como o acesso à instância do validor é através de IValidador<Cnpj>, poderia retornar qualquer coisa, ou seja, uma classe Cnh, o que fará com que uma exceção seja disparada, pois não é possível converter Cnh em Cnpj. Abaixo temos uma imagem que ajuda a entender:

Contratos Assíncronos no WCF 4.5

Há algum tempo eu mencionei aqui como criar um contrato assíncrono para um serviço WCF. A finalidade deste tipo de contrato é permitir a sua implementação de forma, também, assíncrona, para que possamos tirar um hor proveito dos recursos (leia-se threads), do servidor onde o serviço estará sendo hospedado.

Como o formato segue o padrão estabelecido pelo .NET Framework, somos obrigados a construir o contrato nos mesmos moldes do padrão definido por ele, ou seja, um par de métodos Begin/End. Além disso, ainda temos a necessidade de uma eventual implementação da interface IAsyncResult, callbacks, etc., ou seja, com toda a complexidade que estamos acostumados quando precisamos lidar com programação assíncrona no .NET.

As linguagens (C# e VB.NET) redefiniram a forma como escrevemos código assíncrono, e para tirar proveito disso, o WCF sofreu algumas mudanças internas, e agora a criação e implementação de contratos assíncronos são bem mais fáceis de serem implementados do que anteriormente.

Apesar das mudanças serem internas, para que seja possível esse tipo de utilização, algumas regras são exigidas ao (re)escrever o contrato. É necessário que a operação retorne um objeto do tipo Task (quando a mesma não retorna nenhum resultado) ou Task<T> (quando a mesma deve retornar um resultado (T refere-se ao tipo de resultado)). Abaixo temos a interface que define o contrato do serviço:

[ServiceContract]
public interface IContrato
{
[OperationContract]
Task<string> Ping(string value);
}

Ao implementar esse contrato na classe que representará o serviço, entre em cena as keywords do C# que faz toda a mágica para executar de forma assíncrona: async e await, quais já falamos aqui, e que em conjunto com os ajustes internos que a Microsoft fez no WCF (a crição de um operation invoker chamado TaskMethodInvoker), faz com que a operação seja executada sem qualquer grande impacto ao desenvolvedor. Abaixo temos um exemplo de implementação do contrato acima criado:

public class Servico : IContrato
{
public async Task<string> Ping(string value)
{
return await Task.Factory.StartNew(() => value + ” ping”);
}
}

Em termos que hosting, nada é necessário. Por fim, como já mencionado, em tempo de execução, teremos uma melhor reusabilidade das threads, o que nos permite executar algum recurso custoso, como por exemplo, chamado à bancos de dados, outros serviços, sem que a thread fique bloqueada esperando pelo resultado que não depende das capacidades do processamento local.

Já o consumo por parte de uma aplicação também .NET, temos uma ligeira mudança. Trata-se de uma nova opção chamada “Generate task-based operations”. Ao efetuar a referência para um serviço e se esta opção estiver selecionada, fará com que a versão assíncrona das operações do proxy, sejam criadas utilizando o modelo baseado em tasks. Enquanto a outra opção, fará com que ele crie no modelo tradicional, ou seja, baseado em eventos XXXCompleted para cada uma das operações expostas pelo serviço. A imagem abaixo ilustra esta nova opção: