Request Features no ASP.NET

O ASP.NET 5 está sendo construído para ser completamente independente do hosting em que ele está sendo executado, permitindo assim, que este tipo de aplicação seja também levado para outras plataformas (Linux e Mac). Atualmente o ASP.NET 5 pode ser hospedado no IIS (incluindo a versão Express), via self-host (WebListener) ou através do Kestrel (que é um servidor multi-plataforma baseado no libuv.

Mesmo que seja independente do hosting, o ASP.NET fornece um conjunto de tipos que permite interagir, de forma genérica e abstrata, com as funcionalidades que são expostas pelo HTTP, e que na maioria das vezes, são criadas e abastecidas pelo receptor da requisição, ou seja, o próprio hosting. Esses tipos são chamados de request features, e estão incluídas no pacote chamado Microsoft.AspNet.Http.Features. Entre os tipos (funcionalidades) disponíveis temos as interfaces IHttpRequestFeatureIHttpResponseFeature, que representam o básico para o funcionamento de qualquer servidor web, que é receber a requisição, processar e devolver o resultado. Um outro exemplo é a interface ITlsConnectionFeature, que pode ser utilizada para interagir com os certificados enviados pelo cliente. Para uma relação completa, consulte a documentação.

Cada um dos servidores disponíveis já implementam as interfaces definidas (desde que eles suportem), e nos permite acessar essas funcionalidades durante a execução da aplicação, incluindo a possibilidade de acesso através de qualquer middleware. A classe HttpContext expõe uma propriedade chamada Features, que nada mais é que uma coleção das funcionalidades que são incluídas (e, novamente, suportadas) pelo hosting onde a aplicação está rodando. Essa coleção fornece um método genérico chamado Get<TFeature>, onde podemos definir a funcionalidade que queremos acessar. Abaixo um trecho do código de exemplo:

public Task Invoke(HttpContext httpContext)
{
    var clientCertificate =
        httpContext.Features.Get<ITlsConnectionFeature>()?.ClientCertificate;

    if (clientCertificate != null)
    {
        //…
    }

    return _next(httpContext);
}

Além da possibilidade de extrair alguma funcionalidade, é possível também incluir funcionalidade durante a execução, e como já era de se esperar, basta utilizar o método, também genérico, Set<TFeature>. E o mais interessante é que não estamos restritos a utilizar uma das interfaces expostas pelo ASP.NET; podemos criar novas funcionalidades e incorporá-las na execução.

Considere o exemplo abaixo, onde criamos uma funcionalidade para simular a proteção da requisição por uma transação. Basta utilizarmos uma interface para descrever a funcionalidade e criar uma classe que a implemente.

public interface ITransactionFeature
{
    string TransactionId { get; }
    void Commit();
    void Abort();
}

public class TransactionFeatureContext : ITransactionFeature
{
    public string TransactionId { get; } = Guid.NewGuid().ToString();

    public void Commit()
    {
        //…
    }

    public void Abort()
    {
       //…
    }
}

A classe TransactionFeatureContext faz toda a gestão da transação, desde a sua criação (identificando-a) e expõe métodos para conclusão com sucesso (Commit) ou falha (Abort). Repare que tanto a interface quanto a classe não referenciam nenhum tipo do ASP.NET; estamos livres para determinarmos toda a estrutura da nossa funcionalidade. Só que estas classes precisam ser incorporadas na execução, e para isso, vamos criar um middelware que incluirá esta funcionalidade na coleção de Features do contexto da requisição.

public class TransactionMiddleware
{
    private readonly RequestDelegate _next;

    public TransactionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        var transactionContext = new TransactionFeatureContext();
        httpContext.Features.Set<ITransactionFeature>(transactionContext);

        try
        {
            await _next(httpContext);
            transactionContext.Commit();
        }
        catch
        {
            transactionContext.Abort();
            throw;
        }
    }
}

O middleware é criado é os middlewares internos que serão invocados a partir dele estarão sendo gerenciados pela transação. Qualquer exceção não tratada que ocorra, a transação será automaticamente abortada. Por fim, depois do middleware criado, incluímos ele na aplicação através do método UseMiddleware.

Vale lembrar que a ordem em que se adiciona os middlewares são importantes. Como a classe TransactionMiddleware adiciona a feature TransactionFeature que criamos, os middlewares que vem a seguir podem acessar a funcionalidade através do método Get<TFeature>, conforme falado acima. Opcionalmente podemos criar na interface métodos para que os middlewares da sequência possam votar no sucesso ou falha e este, por sua vez, avalia os votos antes de chamar o método Commit.

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
    app.UseTransactionMiddleware();
    app.UseClientCertificateLogMiddleware();
    app.UseMvc();
}

Publicidade

Convenções no ASP.NET

Durante a construção e evolução do ASP.NET MVC e Web API a Microsoft foi assumindo algumas regras, que durante a execução, os frameworks alteram e geram informações de acordo com o código escrito por nós. Isso é conhecido como convention-over-configuration, e tem como foco diminuir algumas configurações explícitas por parte do desenvolvedor, focando em detalhes mais importantes para atender o negócio e o framework se responsabiliza por realizar as configurações necessárias para o funcionamento daquele código respeitando as tais convenções.

Apesar de as vezes não notarmos, isso está bastante presente em nosso dia a dia. Quando criamos um controller, dentro dele uma ação e esta, por sua vez, retornarmos uma view, o ASP.NET MVC assume a estrutura física de Views/NomeDoController/NomeDaAcao.cshtml para armazenar o arquivo e localiza-lo para exibir para o cliente. Outro exemplo é quando utilizamos o Entity Framework e queremos que a entidade Cliente seja persistida na base de dados; o ORM irá criar, automaticamente, a tabela com o mesmo nome daquela entidade. Já no ASP.NET Web API, se criarmos uma ação com o método chamado Get, ele estará automaticamente acessível através do verbo GET do HTTP, sem precisar decorar o mesmo com o atributo HttpGetAttribute.

Note que nos dois exemplos a Microsoft assumiu essas regras e as asseguram durante a execução, ficando, de certa forma, transparente para nós. Se não houvesse isso, teríamos que configurar as mesmas coisas em 100% dos casos; com essas convenções predefinidas, precisamos apenas nos preocupar quando queremos algo diferente do padrão.

O ASP.NET MVC e Web API expõem tipos para que possamos customizar o framework de acordo com nossas necessidades. Até então, isso poderia ser realizado customizando alguns serviços de baixo nível (controller factory, por exemplo), mas o problema desta técnica é que estaremos tocando em outras atividades e que qualquer descuido poderemos ter problemas ao executar e, consequentemente, não atingirmos o objetivo esperado.

O ASP.NET 5 simplifica bastante essa customização expondo uma interface chamada IApplicationModelConvention. Ao implementar ela e acopla-la a execução, o ASP.NET identificará todos os controllers, ações, rotas e filtros candidatos a serem expostos (de acordo com a convenção predefinida) e entregará para analisarmos (através da classe ApplicationModel), e com isso, podemos customizar da forma que precisamos. Tudo isso através de uma API de mais fácil utilização, sem a necessidade de conhecer detalhes dos bastidores para implementar convenções que estão em um nível mais superficial.

Para exemplificar o uso, considere o controller abaixo, que possui duas ações e que retornam uma string. Como podemos perceber, o código foi escrito utilizando o português. Por convenção, o ASP.NET Web API assumirá que o nome dos membros (classe e métodos) serão os mesmos que serão expostos e utilizados pelo sistema de roteamento para montar os links de acesso à API e suas ações.

public class UtilitariosController : Controller
{
    [HttpGet]
    public string ExecutarTarefa()
    {
        return “…” ;
    }

    [HttpGet]
    public string EnviarEmail()
    {
        return “…”;
    }
}

A ideia é deixar o desenvolvedor livre para codificar no idioma desejado, e através do recurso de convenção, vamos estipular que o framework irá traduzir de acordo com a escolha realizada durante a sua configuração. Na ausência do idioma, a nomenclatura utilizada no código será exposta.

O que fazemos abaixo é no método Apply (único, exposto pela interface IApplicationModelConvention) percorremos os controllers encontrados pelo ASP.NET, procuramos pela chave no dicionário (que em um ambiente real, poderíamos estar recorrendo à algum outro repositório ao invés de hard-code), e por fim substituímos o nome do controller e da ação pelo encontrado no dicionário, baseado na cultura escolhida.

public class LocalizedApiNamingModelConvention : IApplicationModelConvention
{
    private string culture;

    private IDictionary<string, Tuple<string, string>> mapping =
        new Dictionary<string, Tuple<string, string>>();

    public LocalizedApiNamingModelConvention(string culture)
    {
        this.culture = culture;

        mapping.Add(
            “en-US.Utilitarios.ExecutarTarefa”,
            Tuple.Create(“Utilities”, “RunTask”));

        mapping.Add(
            “en-US.Utilitarios.EnviarEmail”,
            Tuple.Create(“Utilities”, “SendEmail”));
    }

    public void Apply(ApplicationModel application)
    {
        foreach (var c in application.Controllers)
        {
            var controllerName = c.ControllerName;

            foreach (var a in c.Actions)
            {
                var key = BuildKey(controllerName, a.ActionName);

                if (this.mapping.ContainsKey(key))
                {
                    var info = this.mapping[key];

                    c.ControllerName = info.Item1;
                    a.ActionName = info.Item2;
                }
            }
        }
    }

    private string BuildKey(string controllerName, string actionName)
    {
        return $”{culture}.{controllerName}.{actionName}”;
    }
}

Depois da classe criada, basta incluirmos na coleção chamada Conventions, e fazemos isso através do método AddMvcCore, conforme é mostrado no código abaixo:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvcCore(o =>
        o.Conventions.Add(new LocalizedApiNamingModelConvention(“en-US”)));
}

Repare que criamos a classe e no construtor passamos a cultura en-US e ao rodar a aplicação, os links acessíveis serão /Utilities/RunTask e /Utilities/SendEmail. Os links em português retornarão o erro 404 do HTTP (Not Found).

Web Sockets com ASP.NET Web API

Há algum tempo eu comentei sobre a possibilidade do WCF expor serviços para serem consumidos utilizando a tecnologia de Web Sockets. Neste mesmo artigo eu falei sobre os detalhes do funcionamento deste protocolo, e que se quiser saber o seu funcionamento e implementação em um nível mais baixo, aconselho a leitura.

Como sabemos, o WCF é uma tecnologia que roda do lado do servidor. Da mesma forma que temos o ASP.NET Web API, que é uma tecnologia que utilizamos para criarmos APIs e expor para os mais diversos tipos de clientes. Assim como a Microsoft adicionou o suporte à web sockets no WCF, ela também fez o mesmo com o ASP.NET Web API e MVC, ou seja, incorporou no próprio framework o suporte para criação de recursos que são expostos utilizando web sockets.

É importante dizer que a Microsoft também criou uma outra tecnologia chamada de SignalR, que fornece diversos recursos para a criação de aplicações que precisam gerar e consumir informações que são consideradas de tempo real. Este framework já possui classes que abstraem a complexidade de exposição destes tipos de serviços, fornecendo classes de mais alto nível para trabalho.

Entre os novos tipos que foram adicionados, temos a propriedade IsWebSocketRequest (exposta pela classe HttpContext), que retorna um valor boleano indicando se a requisição está solicitando a migração do protocolo para web sockets. Caso seja verdadeiro, então recorremos ao método AcceptWebSocketRequest da mesma classe para especificarmos a função que irá periodicamente ser executada.

Para o exemplo, vamos criar um publicador de notícias, que quando o cliente optar por assiná-lo, ele irá receber as notícias de forma randômica em um banner a cada 2 segundos. Como podemos ver no código abaixo, o método Assinar da API é exposto para que os clientes cheguem até ele através do método GET do HTTP. Como se trata de uma solicitação de migração, retornamos o código 101 do HTTP indicando a troca do protocolo para web sockets.

public class PublicadorController : ApiController
{
    private static IList<string> noticiais;
    private static Random random;

    static PublicadorController()
    {
        noticiais = new List<string>()
        {
            “You can buy a fingerprint reader keyboard for your Surface Pro 3”,
            “Microsoft’s new activity tracker is the $249 Microsoft Band”,
            “Microsoft’s Lumia 950 is the new flagship Windows phone”,
            “Windows 10 will start rolling out to phones in December”,
            “Microsoft’s Panos Panay is pumped about everything (2012–present)”
        };

        random = new Random();
    }

    [HttpGet]
    public HttpResponseMessage Assinar()
    {
        var httpContext = Request.Properties[“MS_HttpContext”] as HttpContextBase;

        if (httpContext.IsWebSocketRequest)
            httpContext.AcceptWebSocketRequest(EnviarNoticias);

        return new HttpResponseMessage(HttpStatusCode.SwitchingProtocols);
    }

    private async Task EnviarNoticias(AspNetWebSocketContext context)
    {
        var socket = context.WebSocket;

        while (true)
        {
            await Task.Delay(2000);

            if (socket.State == WebSocketState.Open)
            {
                var noticia = noticiais[random.Next(0, noticiais.Count – 1)];
                var buffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(noticia));

                await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
            }
            else
            {
                break;
            }
        }
    }
}

Já dentro do método EnviarNoticias criamos um laço infinito que fica selecionando randomicamente uma das notícias do repositório e enviando para o(s) cliente(s) conectado(s). É claro que também podemos receber informações dos clientes conectados. Para o exemplo estou me limitando a apenas gerar o conteúdo de retorno, sem receber nada. Se quiser, pode utilizar o método ReceiveAsync da classe WebSocket para ter acesso à informação enviada por ele. E, por fim, para não ficar eternamente rodando o código, avaliamos a cada iteração se o estado da conexão ainda continua aberto, caso contrário, encerramos o mesmo.

E do lado do cliente, se for uma aplicação web, vamos recorrer ao código Javascript para consumir este serviço. Temos também a disposição deste lado a classe WebSocket, que quando instanciada, devemos informar o endereço para o método que assina e migra o protocolo para web sockets. Repare que a instância é criada dentro do evento click do botão Conectar e também já nos associamos aos eventos – autoexplicativos – onopen, onmessage e onclose (e ainda tem o onerror).

<!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
<head>
    <title></title>
    https://code.jquery.com/jquery-2.1.4.min.js
   
        var ws;

        $().ready(function ()
        {
            $(“#Conectar”).click(function () {
                ws = new WebSocket(“ws://localhost:2548/api/Publicador/Assinar”);

                ws.onopen = function () {
                    $(“#Status”).text(“Conectado. Recuperando Notícias…”);
                };

                ws.onmessage = function (evt) {
                    $(“#Status”).text(“”);
                    $(“#Banner”).text(evt.data);
                };

                ws.onclose = function () {
                    $(“#Banner”).text(“”);
                    $(“#Status”).text(“Desconectado”);
                };
            });

            $(“#Desconectar”).click(function () {
                ws.close();
            });
        });
   
</head>
<body>
    <input type=”button” value=”Conectar” id=”Conectar” />
    <input type=”button” value=”Desconectar” id=”Desconectar” />
    <br /><br />
    <span id=”Status”></span>
    <span id=”Banner”></span>
</body>
</html>

Quando acessar a página HTML e clicar no botão Conectar, o resultado é apresentado abaixo. A qualquer momento podemos pressionar no botão Desconectar e indicar ao servidor que não estamos mais interessados no retorno das informações. A cada envio de mensagem do servidor para o cliente, o evento onmessage é disparado, e estamos exibindo a mensagem em um campo na tela.

Apenas para informação, o Fiddler é capaz de identificar quando a conexão é migrada para web sockets, e a partir daí consegue capturar as mensagens que são enviados para o cliente. A imagem abaixo é possível visualizar o log capturado depois da assinatura realizada:

Protegendo Configurações no ASP.NET

Quando construímos uma aplicação, temos diversos itens para realizar a configuração. Entre estes itens, estão configurações que guiam a execução da aplicação, o gerenciamento de algum recurso que foi incorporado a ela ou simplesmente valores que são necessários para o negócio para qual a mesma está sendo construída.

Entre estas configurações, temos strings de conexões com base de dados, endereços de servidor SMTP para envio de e-mails, chave de identificação para serviços de autenticação (Google, Facebook, etc.), etc. Não é comum manter estes valores em hard-code, pois pode mudar a qualquer momento e variar de ambiente para ambiente, e precisamos ter a flexibilidade de alterar sem a necessidade de recompilar a aplicação.

Isso nos obriga a manter a chave em um arquivo de configuração. Até então trabalhamos com o arquivo chamado web.config, que serve justamente para incluir diversas configurações da aplicação. A nova versão do ASP.NET (5) muda isso, disponibilizando um novo sistema de configuração mais simples e não menos poderoso. Apesar de continuar dando suporte ao formato XML, a versão mais recente adotou como padrão o formato JSON.

O problema desse modelo é a exposição das configurações. Quando trabalhamos com projetos e que podemos expor o repositório do código publicamente (através do GitHub ou qualquer outro gerenciador de código fonte), deixar armazenado neste arquivo informações sigilosas e, consequentemente, torna-las públicas, é algo que nem sempre desejamos. O ASP.NET 5 resolve isso através de um recurso chamado de User Secrets.

Esta funcionalidade permite externalizar certas configurações em um arquivo que fica de fora do controle de versão do código fonte. Sendo assim, para as chaves que são colocadas no arquivo de configuração da aplicação (config.json) e que precisam ser protegidas, podemos recorrer à este recurso, que basicamente consiste em criar um novo arquivo (chamado de secrets.json) e que será armazenado, no Windows, no seguinte endereço: %APPDATA%microsoftUserSecrets<userSecretsId>secrets.json.

É importante dizer que o local deste arquivo varia de acordo com o sistema operacional onde a aplicação está sendo desenvolvida, e não é aconselhável tornar a aplicação dependente dele; futuramente a Microsoft se dá o direito de mudar (como, por exemplo, criptografar o seu conteúdo), e a aplicação corre o risco de parar de funcionar. O <userSecretsId> é substituído pela chave que é colocada no arquivo project.json, e dentro deste diretório teremos o arquivo secrets.json, conforme comentado acima. É importante notar também que precisamos adicionar a dependência para usar este recurso, e para isso, devemos incluir o pacote chamado Microsoft.Framework.Configuration.UserSecrets:

{
  “commands”: {
    “web”: “Microsoft.AspNet.Hosting –config hosting.ini”
  },
  “dependencies”: {
    “Microsoft.AspNet.Server.IIS”: “1.0.0-beta5”,
    “Microsoft.AspNet.Server.WebListener”: “1.0.0-beta5”,
    “Microsoft.Framework.Configuration.UserSecrets”: “1.0.0-beta5”
  },
  “userSecretsId”: “WebApplication1-12345”,
  “version”: “1.0.0-*”,
  “webroot”: “wwwroot”
}

Com essa configuração realizada, podemos adicionar no arquivo config.json todas as configurações necessárias para o funcionamento da aplicação e incluir no arquivo secrets.json somente as configurações que queremos proteger.

[config.json]
{
  “Data”: {
    “DefaultConnection”: {
      “ConnectionString”: “Server=(localdb)\MSSQLLocalDB;Database=Teste;Trusted_Connection=True;”
    }
  },
  “Certificado”:  “123”
}

[secrets.json]
{
  “Certificado”:  “128372478278473248378”
}

Opcionalmente você pode recorrer à uma opção que existe se clicar com o botão direito sobre o projeto e, em seguida, em “Manage User Secrets“, e assim ter acesso ao arquivo secrets.json sem a necessidade de saber onde o Visual Studio está armazenando-o. Mas isso não basta para o ASP.NET entender que ele deve, também, considerar a busca no arquivo secrets.json. Para isso precisamos indicar que à ele que vamos utilizar o recurso de User Secrets, conforme podemos ver abaixo:

public class Startup
{
    public void Configure(IApplicationBuilder app, IApplicationEnvironment appEnv)
    {
        this.Configuration =
            new ConfigurationBuilder(appEnv.ApplicationBasePath)
                .AddJsonFile(“config.json”)
                .AddUserSecrets()
                .Build();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(this.Configuration[“Certificado”]);
        });
    }

    public IConfiguration Configuration { get; set; }
}

A ordem em que invocamos o método é importante, ou seja, neste caso se ele encontrar a chave “Certificado” no arquivo secrets.json o seu valor será apresentado. Caso o valor não exista, então ele extrairá o valor do arquivo config.json.

Registrando Recursos para Eliminação

Apesar do ASP.NET Web API possui um mecanismo que nos permite estender e acoplar algum gerenciador de dependências, temos a possibilidade de registrar um determinado objeto para que ele seja descartado quando a requisição for completamente atendida.

É muito comum em aplicações Web criar um determinado objeto e querer mante-lo por toda a requisição, e em vários momentos e locais por onde a requisição trafega, podemos recuperar o referido objeto e reutiliza-lo para fazer alguma atividade complementar. Bancos de dados, loggers, entre outros, são exemplos de recursos que são úteis durante a vida da requisição dentro do pipeline onde ela está sendo processada.

A classe HttpRequestMessage possui uma propriedade chamada Properties (IDictionary<string, object>) que permite catalogarmos diversas informações inerentes à requisição, bem como recursos que podem ser (re)utilizados durante todas as etapas da execução. Uma vez adicionados, eles podem ser extraídos em qualquer momento no futuro que venha a precisar deles, mesmo que seja em outras camadas.

A dificuldade não é adicionar, mas saber o momento certo de descarta-lo. Simplesmente adicionar o recurso no dicionário não é suficiente para o ASP.NET Web API fazer a eliminação correta do mesmo. A Microsoft disponibilizou um método de extensão chamado RegisterForDispose, exposto pela classe HttpRequestMessageExtensions. Devemos utilizar este método para indicar explicitamente ao ASP.NET Web API que aquele objeto deve ser descartado no final da requisição. E, como era de se esperar, este método recebe objetos que implementam obrigatoriamente a interface IDisposable.

public class LoggerHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var logger = new TextLogger(@”C:TempLog.txt”);
        request.RegisterForDispose(logger);
        request.Properties.Add(“TextLogger”, logger);

        return base.SendAsync(request, cancellationToken).ContinueWith(tr =>
        {
            var response = tr.Result;

            logger.Write(“Request: ” + request.ToString()).ContinueWith(_ =>
                logger.Write(“Response: ” + response.ToString())).Wait();

            return response;
        }, cancellationToken);
    }
}

Curiosamente o método RegisterForDispose também recorre a propriedade Properties da classe HttpRequestMessage para acomodar os objetos que serão descartados quando a mesma também for removida. Caso encontre um momento mais oportuno para fazer o descarte, podemos recorrer ao método (também de extensão) chamado DisposeRequestResources para antecipar essa rotina, ou ainda, se preferir inspecionar os objetos marcados, pode-se utilizar o método GetResourcesForDisposal para isso.

Outro uso para o que vimos aqui é quando você opta por interceptar a criação do controller (através da implementação da interface IHttpControllerActivator), onde o mesmo pode necessitar de recursos em seu construtor e que sejam necessários serem marcados para descarte no término da requisição.

Externalizando a Emissão de Tokens

No artigo anterior eu mostrei como emitir tokens para aplicações que consomem APIs. Como podemos notar naquele artigo, o mesmo projeto e, consequentemente, a mesma aplicação, é responsável por gerenciar, validar e autenticar os usuários. Enquanto isso é o suficiente para aplicações pequenas, pode não ser muito produtivo e de fácil gerenciamento quando temos outras aplicações que também precisam de autenticação.

Se for analisar mais friamente, talvez até quando temos uma pequena aplicação, seja mais viável manter uma segunda aplicação que seria responsável por todo o processo de autenticação, e a medida em que novos serviços são criadas, eles confiariam neste autenticador que já está pronto.

O que faremos neste artigo é separar o código que é responsável por validar e emitir os tokens da aplicação (API) que consome o token e libera o acesso aos recursos mediante a validade do mesmo. A imagem abaixo ilustra o fluxo que será executado a partir de agora:

Note que o Autenticador é responsável por validar e emitir o token para o usuário que se identifica para ele; o Serviço é onde está hospedada a aplicação que irá consumir o token. Basicamente temos que dividir aquele código do outro artigo em dois projetos, ou seja, não há necessidade nem de por nem tirar qualquer linha de código. O serviço passa a ter apenas o código que pluga no pipeline de execução a validação do token:

public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();

    ConfigureOAuth(app);
WebApiConfig.Register(config);

    app.UseWebApi(config);
}

private static void ConfigureOAuth(IAppBuilder app)
{
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}

O restante do código, que é onde configuramos a validação do usuário, é movido para a aplicação chamada de Autenticador. A aplicação cliente passa a apontar para os endereços, agora em diferentes locais, para emitir o token em um deles, e passar o token gerado para a aplicação.

using (var client = new HttpClient())
{
using (var tokenResponse = await
client.PostAsync(“http://www.autenticador.com.br:81/issuer/token“, CreateContent()))
{

        using (var requestMessage =
new HttpRequestMessage(HttpMethod.Get, “http://www.servico.com.br:82/api/Test/GetData“))
{

}
}
}

Por fim, se rodarmos ele não irá funcionar. O motivo é que o token é protegido utilizando as chaves que estão no elemento machineKey dentro do arquivo Web.config. Se as aplicações (Autenticador e Serviço) tiverem chaves diferentes, então o token gerado pelo Autenticador não será possível ser consumido pelo Serviço. O que precisamos fazer aqui é gerar uma chave e copiar a mesma para as duas aplicações. Para gerar essas chaves, podemos recorrer à um recurso que temos no próprio IIS (mais detalhes aqui). Abaixo tem o arquivo Web.config já com esta configuração realizada. Vale lembrar que o tamanho das chaves foi reduzido por questões de espaço.

validationKey=”D2E9D0907…47BC9F8A598″
decryptionKey=”7278E7F93…658B70DE07E21CF”
validation=”SHA1″
decryption=”AES” />

Depois desta informação espelhada em ambas as aplicações, já é possível uma das aplicações gerar o token e a outra consumi-lo.

Emissão de Tokens no ASP.NET Web API

Em aplicações Web é comum o cliente precisar se autenticar para ter acesso à determinados recurso da aplicação. Quando o usuário se identifica para a aplicação, e se ela validar o mesmo, gravamos um cookie no navegador para que ele possa manter a autenticação válida durante a sua navegação (e enquanto o mesmo não expirar), evitando assim que ele tenha que se (re)autenticar toda cada vez que quer acessar um recurso protegido.

Quando estamos trabalhando com serviços, onde são outros sistemas que os consomem, precisamos autenticar a aplicação/usuário para que ele possa acessar os recursos que eles disponibilizam. Enquanto aplicações Web (que possuem uma interface) mantém um cookie, os serviços lidam de uma forma diferente, ou seja, recorrem à tokens para autenticar e identificar o chamador, e a partir deste momento, o mesmo deverá apresentar o token a cada vez que deseja acessar algum dos recursos expostos pelo serviço.

Ao invés de termos controllers e actions que servirão para esse tipo de atividade, podemos (e devemos) recorrer à alguns recursos que a própria tecnologia nos oferece. Quando optamos por hospedar e executar o ASP.NET Web API no OWIN, ele já traz alguns middlewares para autenticação, e entre eles, a possibilidade de utilizar o a tecnologia OAuth2 para guiar todo o processo de autenticação. O primeiro passo é instalar os seguintes pacotes (via Nuget): Microsoft.Owin.Host.SystemWeb, Microsoft.AspNet.WebApi.Owin e Microsoft.Owin.Security.OAuth.

Esses pacotes irão disponibilizar um conjunto de classes para trabalharmos com o OWIN dentro do ASP.NET Web API. O primeiro passo é realizar duas configurações dentro da classe Startup (exigência do OWIN): um middleware que será responsável pela geração de tokens e o outro que terá o papel de validar os tokens apresentados para o serviço antes deles serem executados.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        ConfigureAuthentication(app);
        WebApiConfig.Register(config);
        app.UseWebApi(config);
    }

    private static void ConfigureAuthentication(IAppBuilder app)
    {
        app.UseOAuthAuthorizationServer
        (
            new OAuthAuthorizationServerOptions()
            {
                AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString(“/issuer/token”),
                Provider = new OAuthAuthorizationServerProvider()
                {
                    OnValidateClientAuthentication = async ctx =>
                    {
                        await Task.Run(() => ctx.Validated());
                    },
                    OnGrantResourceOwnerCredentials = async ctx =>
                    {
                        await Task.Run(() =>
                        {
                            if (ctx.UserName != “Israel” || ctx.Password != “12345”)
                            {
                                ctx.Rejected();
                                return;
                            }

                            var identity = new ClaimsIdentity(
                                new[] {
                                        new Claim(ClaimTypes.Name, ctx.UserName),
                                        new Claim(ClaimTypes.Role, “Admin”)},
                                ctx.Options.AuthenticationType);

                            ctx.Validated(identity);
                        });
                    }
                }
            }
        );

        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Através do método UseOAuthAuthorizationServer realizamos as configurações do emissor de tokens. As propriedades expostas pela classe OAuthAuthorizationServerOptions nos permite customizar diversas informações críticas para o processo de emissão. Entre elas temos o endpoint em que os clientes deverão visitar para gerar o token, o tempo de expiração para cada token e, por fim, e não menos importante, o provider. É o provider que podemos customizar a validação do usuário, verificando se ele é ou não um usuário válido. Para essa customização, basta herdar da classe OAuthAuthorizationServerProvider e sobrescrever (se assim desejar) diversos métodos para controlar todos os eventos gerados pelo protocolo OAuth2.

Para o exemplo estou optando por definir a propriedade AllowInsecureHttp como true, evitando a necessidade de expor o serviço sobre HTTPS, mas é importante que isso seja reavaliado antes de colocar em produção. Outro detalhe é que estou definindo, em hard-code, o nome e senha válidos; em um cenário real, é neste momento que deveríamos recorrer à algum repositório de usuários e validar se ele existe lá.

Depois de configurado o emissor de tokens, o middleware que habilitamos através do método UseOAuthBearerAuthentication é o responsável por validar os tokens que são enviados nas futuras requisições e identificar se eles são ou não válidos.

O fluxo necessário para a geração do token e para envio subsequente em novas requisições é bastante simples. Basta realizar um post para o endereço configurado na propriedade TokenEndpointPath, passando no corpo da mensagem três parâmetros: grant_type, username e password. Esses parâmetros serão utilizados pelo protocolo OAuth para validar o usuário e gerar o token caso ele seja válido. O parâmetro grant_type indica ao OAuth o tipo de autenticação que queremos fazer; neste caso o valor deverá ser “password”. Já os parâmetros username e password são autoexplicativos.

Se o usuário for válido, então o resultado será devolvido através do corpo da mensagem de resposta, formatado em JSON. Abaixo está um exemplo da resposta, mas o token foi reduzido por questões de espaço. O seu tamanho é muito maior que isso.

{
    “access_token”:”CPIA6Ha-9Bg2Yh8PZD-7Terzl9At…..UBp-WlpkNYn5ioD85U”,
    “token_type”:”bearer”,
    “expires_in”:3599
}

Agora compete à aplicação que consome este serviço armazenar o token e embutir nas futuras requisições. A exigência do protocolo é que o token seja incluído através do header Authorization na requisição, especificando além do token, também o seu tipo, que neste caso é bearer, e ele também é devolvido pelo emissor do token.

Para realizarmos os testes, vamos criar um controller e expor um método para que seja consumido apenas por usuários que estejam devidamente autenticados. Para isso, basta decorar o controller ou a ação com o atributo AuthorizeAttribute, conforme podemos visualizar no código abaixo:

public class TestController : ApiController
{
    [HttpGet]
    [Authorize]
    public string GetData()
    {
        return “Testing…”;
    }
}

Para exemplificar o consumo por parte do cliente, estou utilizando uma aplicação console para solicitar a emissão do token, e na sequência invocamos o método GetData da API passando o token como header, conforme o fluxo que foi explicado acima.

private async static void Invoke()
{
    using (var client = new HttpClient())
    {
        using (var tokenResponse = await client.PostAsync(“http://localhost:1195/issuer/token&#8221;, CreateContent()))
        {
            var tokenBody = await tokenResponse.Content.ReadAsStringAsync();
            dynamic parsedTokenBody = JsonConvert.DeserializeObject(tokenBody);

            using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, “http://localhost:1195/api/Test/GetData&#8221;))
            {
                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue(
                        parsedTokenBody.token_type.ToString(),
                        parsedTokenBody.access_token.ToString());

                using (var responseMessage = await client.SendAsync(requestMessage))
                {
                    var responseBody = await responseMessage.Content.ReadAsStringAsync();

                    Console.WriteLine(responseBody);
                }
            }
        }
    }
}

private static FormUrlEncodedContent CreateContent()
{
    return new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>(“grant_type”, “password”),
        new KeyValuePair<string, string>(“username”, “Israel”),
        new KeyValuePair<string, string>(“password”, “12345”)
    });
}

Um detalhe importante é que dentro do controller, podemos fazer o (down)casting da propriedade User e chegar na instância da classe ClaimsPrincipal e, consequentemente, acessar o conjunto de claims que foi gerada pelo emissor do token para este usuário. Como disse anteriormente, claims estão em todo lugar.

((ClaimsPrincipal)this.User).Claims.First().Value;

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”));

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; }
}

Mantendo objetos durante a requisição

Quando a requisição chega em um determinado serviço ela tem como alvo executar uma determinada tarefa e devolver um resultado. Antes da requisição chegar ao seu destino, ela passa por algumas etapas, e depois que a tarefa é de fato executada, outras etapas também são executadas antes de devolver a resposta para o cliente.

A manutenção de estado de objetos muitas vezes se faz necessária, pois ele servirá como uma espécie de contexto que viverá do início ao fim da requisição. Um exemplo comum disso é quando temos um objeto que gerencia uma transação (Unit of Work), e com ele seria possível envolver tudo o que acontece na requisição em um mesmo contexto transacional, pois se no fim do processamento alguma falha ocorrer, será possível reverter tudo o que fora realizado até ali.

Como sabemos, a ação dentro do controller de fato é a tarefa que queremos executar, mas o que ocorre antes e depois (geralmente são atividades de cross-cutting) também pode ser envolvido para contextualizar todo o processo. Este artigo exemplifica em como implementar e gerenciar isso no ASP.NET Web API. Para o exemplo, vamos ter um recurso que interceptará vários estágios da requisição, e logará todos os passos por onde ela passou. A interface IRequestTracking servirá como base para qualquer tipo de rastreador de requisições. A classe que está a seguir (MemoryRequestTracking) é uma implementação dela, que basicamente armazena os passos em uma coleção e persiste no Trace.

[InheritedExport]
public interface IRequestTracking
{
    Guid RequestId { get; }

    IEnumerable<string> Steps { get; }

    void AddStep(string message);

    void Flush();
}

public class MemoryRequestTracking : IRequestTracking
{
    private readonly IList<string> steps;

    public MemoryRequestTracking()
    {
        this.RequestId = Guid.NewGuid();
        this.steps = new List<string>();
    }

    public void AddStep(string message)
    {
        this.steps.Add(
            string.Format(“{0:dd/MM/yyyy HH:mm:ss} – Id: {1} – {2}”,
                DateTime.Now, this.RequestId, message));
    }

    public Guid RequestId { get; private set; }

    public IEnumerable<string> Steps { get { return this.steps; } }

    public void Flush()
    {
        foreach (var step in this.Steps)
            Trace.WriteLine(step);
    }
}

O ASP.NET Web API já traz nativamente uma espécie de repositório de dependências, que durante o runtime, a medida em que recursos vão sendo solicitados, esse repositório é consultado para resolver a(s) dependência(s), retornando uma implementação concreta do recurso solicitado. Felizmente podemos customizar esse repositório e utilizar algum container de injeção de dependências (DI) de sua preferência para auxiliar no gerenciamento e na criação das instâncias.

A customização resume em se criar uma classe que implemente a interface IDependencyResolver, e através dos métodos autoexplicativos, retornamos os recursos solicitados. É no interior desta classe que, eventualmente, podemos utilizar um container de DI, e para este exemplo estou utilizando o MEF (Managed Extensibility Framework).

public class MefResolver : IDependencyResolver
{
    private readonly CompositionContainer container;

    public MefResolver()
        : this(new CompositionContainer(
            new AssemblyCatalog(Assembly.GetExecutingAssembly()))) { }

    public MefResolver(CompositionContainer container) { this.container = container; }

    public IDependencyScope BeginScope() { return new MefResolver(); }

    public object GetService(Type serviceType)
    {
        return GetServices(serviceType).FirstOrDefault();
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        var services = this.container.GetExports(serviceType, null, null);

        return !services.Any() ? Enumerable.Empty<object>() : services.Select(s => s.Value);
    }

    public void Dispose() { this.container.Dispose(); }
}

Basicamente a classe acima recebe em seu construtor o container que servirá como “base de dados” das dependências e resolverá as solicitações procurando por implementações dentro do próprio assembly que está em execução. Só que a classe por si só não funcionará, pois precisamos acoplá-la à execução, e para isso, devemos configurar definer a instância dela na propriedade DependencyResolver exposta pela classe HttpConfiguration, assim como é mostrado abaixo:

public static void Register(HttpConfiguration config)
{
    config.DependencyResolver = new MefResolver();

    //outras configurações
}

Agora que toda a configuração já está realizada, precisamos começar a adicionar os passos nos locais que desejarmos interceptar. Como falei anteriormente, vamos querer acessar o rastreador em várias etapas diferentes, e felizmente, o ASP.NET Web API e seu container de DI são capazes de criar e disponibilizar a instância quando precisarmos, e isso quer dizer que poderemos acessar esses recursos não só no interior do controller, mas também em filtros, handlers, formatters, etc.

O gestor de dependência que temos (MefResolver) é construído no ínicio da requisição e é adicionado às propriedades da classe HttpRequestMessage, que nada mais é do que um dicionário de dados e mantém uma relação de objetos que são utilizados durante a requisição. Como o gestor de dependência é criado para cada requisição, então os objetos que são criados a partir dele também serão mantidos.

O primeiro lugar que vamos acessar é dentro de um filtro customizado. Note que a classe base ActionFilterAttribute fornece métodos para interceptar o antes e depois da ação executada.

public class RequestTrackingFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        ((IRequestTracking)actionContext
            .Request
            .GetDependencyScope()
            .GetService(typeof(IRequestTracking)))
            .AddStep(“OnActionExecuting”);

        base.OnActionExecuting(actionContext);
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        ((IRequestTracking)actionExecutedContext
            .Request
            .GetDependencyScope()
            .GetService(typeof(IRequestTracking)))
            .AddStep(“OnActionExecuted”);

        base.OnActionExecuted(actionExecutedContext);
    }
}

Graças à um método de extensão chamado GetDependencyScope atribuído a classe HttpRequestMessage, é fácil chegarmos à esse gestor e solicitar o recurso que queremos. Para expressar o recurso que queremos, basta informar a interface IRequestTracking, que ele devolverá a instância criada ou criará uma nova caso ela ainda não exista. Depois basta fazer a conversão explícita (casting) e acessar os seus membros.

Já dentro do controller, a forma de chegar até este recurso é bem semelhante. Note que no código abaixo temos o rastreador declarado como um campo na classe, e como ele está decorado com o atributo ImportAttribute (do MEF), o container resolve a dependência e injeta a instância nesta classe, neste campo, assim que ela for construída. Com isso, basta utilizar o mesmo no interior da ação/controller.

[Export]
public class TesteController : ApiController
{
    [Import]
    private IRequestTracking tracking;

    [HttpGet]
    [RequestTrackingFilter]
    public string Ping(string valor)
    {
        tracking.AddStep(string.Format(“TesteController.Ping({0})”, valor));

        return valor + ” ping”;
    }
}

É importante notar que o atributo criado anteriormente é decorado no méotdo Ping, e é a presença dele que faz com o que o runtime do ASP.NET o execute.

Além destas opções, podemos também acessar e utilizar este rastreador, por exemplo, dentro de um message handler. Além de utilizar para também adicionar mais um passo ao rastreador, é também o momento de invocar o método Flush para que o conteúdo armazenado até o momento seja definitivamente adicionado no arquivo de trace, previamente configurado. Como podemos notar no código abaixo, fazemos todo este trabalho depois que a requisição foi processada por todos os componentes (de mais baixo nível), incluindo a ação que está dentro do controller. O flush é feito momentos antes de retornar a resposta para o cliente.

public class FlushingRequestTrackingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        return await base.SendAsync(request, cancellationToken).ContinueWith(r =>
        {
            var tracking =
                ((IRequestTracking)request
                    .GetDependencyScope()
                    .GetService(typeof(IRequestTracking)));

            tracking.AddStep(“FRTH.SendAsync”);
            tracking.Flush();

            return r.Result;
        });
    }
}

E, ao rodar e visualizarmos o arquivo de tracing, teremos:

13/11/2014 15:44:34 – Id: 724b2a97-3bcf-428b-a65e-5ec582bb1f70 – OnActionExecuting
13/11/2014 15:44:34 – Id: 724b2a97-3bcf-428b-a65e-5ec582bb1f70 – TesteController.Ping(teste)
13/11/2014 15:44:34 – Id: 724b2a97-3bcf-428b-a65e-5ec582bb1f70 – OnActionExecuted
13/11/2014 15:44:34 – Id: 724b2a97-3bcf-428b-a65e-5ec582bb1f70 – FRTH.SendAsync

Importante: Apesar de tentador, é necessário tomar cuidado ao acessar o gestor de dependências através da propriedade fornecida pela GlobalConfiguration.Configuration.DependencyResolver. O problema é que esta propriedade sempre retornará uma nova instância do gestor (no nosso caso, do MefResolver) e não teremos os objetos sendo mantidos por toda a requisição.