Uma visão geral do projeto Katana

por Howard Dierking

O ASP.NET Framework existe há mais de dez anos e a plataforma habilitou o desenvolvimento de inúmeros sites e serviços. À medida que as estratégias de desenvolvimento de aplicativos Web evoluíram, a estrutura foi capaz de evoluir em etapas com tecnologias como ASP.NET MVC e ASP.NET Web API. À medida que o desenvolvimento de aplicativos Web entra em seu próximo passo evolutivo no mundo da computação em nuvem, o projeto Katana fornece o conjunto subjacente de componentes para ASP.NET aplicativos, permitindo que eles sejam flexíveis, portáteis, leves e forneçam melhor desempenho – dito de outra forma, a nuvem do projeto Katana otimiza seus aplicativos ASP.NET.

Por que Katana – Por que agora?

Independentemente de se se está discutindo uma estrutura de desenvolvedor ou produto de usuário final, é importante entender as motivações subjacentes para criar o produto – e parte disso inclui saber para quem o produto foi criado. ASP.NET foi originalmente criado com dois clientes em mente.

O primeiro grupo de clientes foi os desenvolvedores clássicos do ASP. Na época, o ASP era uma das principais tecnologias para a criação de sites e aplicativos dinâmicos e controlados por dados por meio da marcação de interweaving e do script do lado do servidor. O runtime do ASP forneceu um script do lado do servidor com um conjunto de objetos que abstraíram os principais aspectos do protocolo HTTP subjacente e do servidor Web e forneceram acesso a serviços adicionais, como gerenciamento de estado de sessão e aplicativo, cache etc. Embora poderosos, os aplicativos ASP clássicos se tornaram um desafio para gerenciar à medida que cresciam em tamanho e complexidade. Isso ocorreu em grande parte devido à falta de estrutura encontrada em ambientes de script, juntamente com a duplicação de código resultante da intercalação de código e marcação. Para aproveitar os pontos fortes do ASP clássico enquanto abordava alguns de seus desafios, ASP.NET aproveitava a organização de código fornecida pelas linguagens orientadas a objetos do .NET Framework ao mesmo tempo em que preservava o modelo de programação do lado do servidor ao qual os desenvolvedores clássicos do ASP se acostumaram.

O segundo grupo de clientes de destino para ASP.NET foram os desenvolvedores de aplicativos de negócios do Windows. Ao contrário dos desenvolvedores clássicos do ASP, que estavam acostumados a escrever marcação HTML e o código para gerar mais marcação HTML, os desenvolvedores do WinForms (como os desenvolvedores do VB6 antes deles) estavam acostumados a uma experiência de tempo de design que incluía uma tela e um conjunto avançado de controles de interface do usuário. A primeira versão do ASP.NET – também conhecida como "Web Forms" forneceu uma experiência de tempo de design semelhante junto com um modelo de evento do lado do servidor para componentes de interface do usuário e um conjunto de recursos de infraestrutura (como ViewState) para criar uma experiência de desenvolvedor perfeita entre a programação do lado do cliente e do servidor. Web Forms efetivamente escondeu a natureza sem estado da Web em um modelo de evento com estado que era familiar para os desenvolvedores do WinForms.

Desafios gerados pelo modelo histórico

O resultado líquido foi um modelo de programação de desenvolvedor e runtime maduro e rico em recursos. No entanto, com essa riqueza de recursos veio alguns desafios notáveis. Em primeiro lugar, a estrutura era monolítica, com unidades logicamente diferentes de funcionalidade sendo firmemente acopladas no mesmo assembly de System.Web.dll (por exemplo, os principais objetos HTTP com a estrutura de formulários da Web). Em segundo lugar, ASP.NET foi incluído como parte da .NET Framework maior, o que significava que o tempo entre as versões estava na ordem dos anos. Isso tornou difícil para ASP.NET acompanhar todas as mudanças que ocorrem no desenvolvimento da Web em rápida evolução. Por fim, System.Web.dll em si foi acoplado de algumas maneiras diferentes a uma opção de hospedagem na Web específica: Serviços de Informações da Internet (IIS).

Etapas evolutivas: ASP.NET MVC e ASP.NET Web API

E muita mudança estava acontecendo no desenvolvimento para a Web! Os aplicativos Web estavam cada vez mais sendo desenvolvidos como uma série de componentes pequenos e focados em vez de estruturas grandes. O número de componentes, bem como a frequência com que foram liberados, aumentou a uma taxa cada vez mais rápida. Ficou claro que manter o ritmo com a Web exigiria que as estruturas fossem menores, desacopladas e mais focadas do que maiores e mais ricas em recursos, portanto, a equipe de ASP.NET tomou várias etapas evolutivas para permitir ASP.NET como uma família de componentes Web conectáveis em vez de uma única estrutura.

Uma das primeiras mudanças foi o aumento da popularidade do conhecido padrão de design MVC (model-view-controller) graças a estruturas de desenvolvimento web como Ruby on Rails. Esse estilo de criação de aplicativos Web deu ao desenvolvedor maior controle sobre a marcação de seu aplicativo, preservando ainda a separação de marcação e lógica de negócios, que foi um dos pontos de venda iniciais para ASP.NET. Para atender à demanda por esse estilo de desenvolvimento de aplicativos Web, a Microsoft aproveitou a oportunidade para se posicionar melhor para o futuro desenvolvendo ASP.NET MVC fora de banda (e não incluindo-o no .NET Framework). ASP.NET MVC foi lançado como um download independente. Isso deu à equipe de engenharia a flexibilidade para fornecer atualizações com muito mais frequência do que havia sido possível anteriormente.

Outra mudança importante no desenvolvimento de aplicativos Web foi a mudança de páginas da Web dinâmicas geradas pelo servidor para marcação inicial estática com seções dinâmicas da página geradas do script do lado do cliente comunicando-se com APIs Web de back-end por meio de solicitações AJAX. Essa mudança arquitetônica ajudou a impulsionar a ascensão das APIs Web e o desenvolvimento da estrutura ASP.NET Web API. Como no caso de ASP.NET MVC, o lançamento do ASP.NET Web API proporcionou outra oportunidade de evoluir ASP.NET ainda mais como uma estrutura mais modular. A equipe de engenharia aproveitou a oportunidade e criou ASP.NET Web API de modo que não tinha dependências em nenhum dos principais tipos de estrutura encontrados no System.Web.dll. Isso permitiu duas coisas: primeiro, isso significava que ASP.NET Web API poderia evoluir de maneira completamente autocontida (e poderia continuar a iterar rapidamente porque é entregue via NuGet). Em segundo lugar, como não havia dependências externas para System.Web.dll e, portanto, nenhuma dependência do IIS, ASP.NET Web API incluía a capacidade de execução em um host personalizado (por exemplo, um aplicativo de console, serviço Windows etc.)

O Futuro: Uma Estrutura Nimble

Ao desacoplar os componentes da estrutura uns dos outros e, em seguida, liberá-los no NuGet, as estruturas agora podem iterar de forma mais independente e rápida. Além disso, o poder e a flexibilidade da funcionalidade de auto-hospedagem da API Web se mostraram muito atraentes para desenvolvedores que queriam um host pequeno e leve para seus serviços. Mostrou-se tão atraente, na verdade, que outras estruturas também queriam essa funcionalidade, e isso apresentou um novo desafio em que cada estrutura era executada em seu próprio processo de host em seu próprio endereço base e precisava ser gerenciada (iniciada, interrompida etc.) de forma independente. Um aplicativo Web moderno geralmente dá suporte ao serviço de arquivos estáticos, geração de página dinâmica, API Web e, mais recentemente, notificações em tempo real/push. Esperar que cada um desses serviços deve ser executado e gerenciado de forma independente simplesmente não era realista.

O que era necessário era uma abstração de hospedagem única que permitiria que um desenvolvedor redigisse um aplicativo de uma variedade de componentes e estruturas diferentes e, em seguida, executasse esse aplicativo em um host de suporte.

OWIN (Open Web Interface para .NET)

Inspirados pelos benefícios obtidos pelo Rack na comunidade Ruby, vários membros da comunidade do .NET se prepararam para criar uma abstração entre servidores Web e componentes de estrutura. Duas metas de design para a abstração OWIN eram que ela era simples e que ele tinha o menor número possível de dependências em outros tipos de estrutura. Essas duas metas ajudam a garantir:

  • Novos componentes podem ser mais facilmente desenvolvidos e consumidos.
  • Os aplicativos podem ser portados com mais facilidade entre hosts e plataformas/sistemas operacionais potencialmente inteiros.

A abstração resultante consiste em dois elementos principais. O primeiro é o dicionário de ambiente. Essa estrutura de dados é responsável por armazenar todo o estado necessário para processar uma solicitação e resposta HTTP, bem como qualquer estado relevante do servidor. O dicionário de ambiente é definido da seguinte maneira:

IDictionary<string, object>

Um servidor Web compatível com OWIN é responsável por preencher o dicionário de ambiente com dados como fluxos de corpo e coleções de cabeçalho para uma solicitação e resposta HTTP. Em seguida, é responsabilidade dos componentes do aplicativo ou da estrutura preencher ou atualizar o dicionário com valores adicionais e gravar no fluxo do corpo da resposta.

Além de especificar o tipo para o dicionário de ambiente, a especificação OWIN define uma lista de pares de valores de chave do dicionário principal. Por exemplo, a tabela a seguir mostra as chaves de dicionário necessárias para uma solicitação HTTP:

Nome da Chave Descrição do valor
"owin.RequestBody" Um Stream com o corpo da solicitação, se houver. Stream.Null PODE ser usado como um espaço reservado se não houver nenhum corpo da solicitação. Consulte Corpo da Solicitação.
"owin.RequestHeaders" Um IDictionary<string, string[]> de cabeçalhos de solicitação. Consulte Cabeçalhos.
"owin.RequestMethod" Um string que contém o método de solicitação HTTP da solicitação (por exemplo, "GET", "POST").
"owin.RequestPath" Um string que contém o caminho da solicitação. O caminho DEVE ser relativo à "raiz" do delegado do aplicativo; consulte Caminhos.
"owin.RequestPathBase" Um string que contém a parte do caminho de solicitação correspondente à "raiz" do delegado do aplicativo; consulte Caminhos.
"owin.RequestProtocol" Um string que contém o nome e a versão do protocolo (por exemplo, "HTTP/1.0" ou "HTTP/1.1").
"owin.RequestQueryString" Um string que contém o componente de cadeia de caracteres de consulta do URI de solicitação HTTP, sem o "?" à esquerda (por exemplo, "foo=bar&baz=quux"). O valor pode ser uma cadeia de caracteres vazia.
"owin.RequestScheme" Um string que contém o esquema de URI usado para a solicitação (por exemplo, "http", "https"); consulte Esquema de URI.

O segundo elemento chave do OWIN é o delegado do aplicativo. Essa é uma assinatura de função que serve como a interface primária entre todos os componentes em um aplicativo OWIN. A definição para o delegado do aplicativo é a seguinte:

Func<IDictionary<string, object>, Task>;

Em seguida, o delegado do aplicativo é simplesmente uma implementação do tipo delegado Func em que a função aceita o dicionário de ambiente como entrada e retorna uma Tarefa. Esse design tem várias implicações para os desenvolvedores:

  • Há um número muito pequeno de dependências de tipo necessárias para gravar componentes OWIN. Isso aumenta muito a acessibilidade do OWIN para os desenvolvedores.
  • O design assíncrono permite que a abstração seja eficiente com o tratamento de recursos de computação, especialmente em operações com uso intensivo de E/S.
  • Como o delegado do aplicativo é uma unidade atômica de execução e como o dicionário de ambiente é transportado como um parâmetro no delegado, os componentes OWIN podem ser facilmente encadeados para criar pipelines de processamento HTTP complexos.

Do ponto de vista da implementação, o OWIN é uma especificação (http://owin.org/html/owin.html). Sua meta não é ser a próxima estrutura da Web, mas sim uma especificação de como as estruturas da Web e os servidores Web interagem.

Se você investigou o OWIN ou o Katana, talvez também tenha notado o pacote NuGet Owin e Owin.dll. Essa biblioteca contém uma única interface, [IAppBuilder]/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder), que formaliza e codifica a sequência de inicialização descrita na seção 4 da especificação OWIN. Embora não seja necessária para criar servidores OWIN, a interface [IAppBuilder]/dotnet/api/microsoft.aspnetcore.builder.iapplicationbuilder) fornece um ponto de referência concreto e é usada pelos componentes do projeto Katana.

Projeto Katana

Enquanto a especificação OWIN e Owin.dll são de propriedade da comunidade e da comunidade executam código aberto esforços, o projeto Katana representa o conjunto de componentes OWIN que, embora ainda código aberto, são criados e lançados pela Microsoft. Esses componentes incluem componentes de infraestrutura, como hosts e servidores, bem como componentes funcionais, como componentes de autenticação e associações a estruturas como SignalR e ASP.NET Web API. O projeto tem as três metas de alto nível a seguir:

  • Portátil – os componentes devem ser facilmente substituídos por novos componentes à medida que se tornam disponíveis. Isso inclui todos os tipos de componentes, desde a estrutura até o servidor e o host. A implicação dessa meta é que as estruturas de terceiros podem ser executadas perfeitamente em servidores Microsoft, enquanto as estruturas da Microsoft podem potencialmente ser executadas em servidores e hosts de terceiros.
  • Modular/flexível– ao contrário de muitas estruturas que incluem uma miríade de recursos que são ativados por padrão, os componentes do projeto Katana devem ser pequenos e focados, dando controle ao desenvolvedor de aplicativos para determinar quais componentes usar em seu aplicativo.
  • Leve/com desempenho/escalonável – ao dividir a noção tradicional de uma estrutura em um conjunto de componentes pequenos e focados que são adicionados explicitamente pelo desenvolvedor de aplicativos, um aplicativo Katana resultante pode consumir menos recursos de computação e, como resultado, lidar com mais carga do que com outros tipos de servidores e estruturas. Como os requisitos do aplicativo exigem mais recursos da infraestrutura subjacente, eles podem ser adicionados ao pipeline OWIN, mas isso deve ser uma decisão explícita por parte do desenvolvedor de aplicativos. Além disso, a substituição de componentes de nível inferior significa que, à medida que eles se tornam disponíveis, novos servidores de alto desempenho podem ser introduzidos perfeitamente para melhorar o desempenho de aplicativos OWIN sem interromper esses aplicativos.

Introdução com componentes katana

Quando foi introduzido pela primeira vez, um aspecto da estrutura Node.js que imediatamente chamou a atenção das pessoas foi a simplicidade com que se poderia criar e executar um servidor Web. Se as metas de Katana foram enquadradas à luz de Node.js, pode-se resumi-las dizendo que Katana traz muitos dos benefícios de Node.js (e estruturas como ela) sem forçar o desenvolvedor a jogar fora tudo o que ela sabe sobre o desenvolvimento de aplicativos Web ASP.NET. Para que essa instrução se mantenha verdadeira, começar a usar o projeto Katana deve ser igualmente simples por natureza para Node.js.

Criando "Olá, Mundo!"

Uma diferença notável entre o desenvolvimento do JavaScript e do .NET é a presença (ou ausência) de um compilador. Assim, o ponto de partida para um servidor Katana simples é um projeto do Visual Studio. No entanto, podemos começar com o mínimo de tipos de projeto: o Aplicativo Web vazio ASP.NET.

Captura de tela do menu ASP.Net Project – WebApplication1, mostrando como começar o painel de janelas para criar um projeto 'Olá, Mundo'. Mostra uma janela com modelos diferentes para selecionar e as opções para adicionar referências principais e testes de unidade.

Em seguida, instalaremos o pacote NuGet Microsoft.Owin.Host.SystemWeb no projeto. Esse pacote fornece um servidor OWIN executado no pipeline de solicitação ASP.NET. Ele pode ser encontrado na galeria do NuGet e pode ser instalado usando a caixa de diálogo gerenciador de pacotes do Visual Studio ou o console do gerenciador de pacotes com o seguinte comando:

install-package Microsoft.Owin.Host.SystemWeb

A instalação do Microsoft.Owin.Host.SystemWeb pacote instalará alguns pacotes adicionais como dependências. Uma dessas dependências é Microsoft.Owin, uma biblioteca que fornece vários tipos auxiliares e métodos para desenvolver aplicativos OWIN. Podemos usar esses tipos para gravar rapidamente o servidor "olá, mundo".

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Run(context =>
      {
         context.Response.ContentType = "text/plain";
         return context.Response.WriteAsync("Hello World!");
      });
   }
}

Esse servidor Web muito simples agora pode ser executado usando o comando F5 do Visual Studio e inclui suporte completo para depuração.

Alternar hosts

Por padrão, o exemplo "olá, mundo" anterior é executado no pipeline de solicitação ASP.NET, que usa System.Web no contexto do IIS. Isso pode, por si só, agregar um valor tremendo, pois nos permite aproveitar a flexibilidade e a capacidade de composição de um pipeline OWIN com os recursos de gerenciamento e a maturidade geral do IIS. No entanto, pode haver casos em que os benefícios fornecidos pelo IIS não são necessários e o desejo é para um host menor e mais leve. O que é necessário, então, para executar nosso servidor Web simples fora do IIS e do System.Web?

Para ilustrar a meta de portabilidade, mover de um host de servidor Web para um host de linha de comando requer simplesmente adicionar as novas dependências de servidor e host à pasta de saída do projeto e, em seguida, iniciar o host. Neste exemplo, hospedaremos nosso servidor Web em um host Katana chamado OwinHost.exe e usaremos o servidor baseado em Katana HttpListener. Da mesma forma que os outros componentes do Katana, eles serão adquiridos do NuGet usando o seguinte comando:

install-package OwinHost

Na linha de comando, podemos navegar até a pasta raiz do projeto e simplesmente executar o OwinHost.exe (que foi instalado na pasta ferramentas de seu respectivo pacote NuGet). Por padrão, OwinHost.exe é configurado para procurar o servidor baseado em HttpListener e, portanto, nenhuma configuração adicional é necessária. Navegar em um navegador da Web para http://localhost:5000/ mostrar o aplicativo agora em execução por meio do console.

Captura de tela do Promt de Comando do Desenvolvedor e da janela do navegador, mostrando uma comparação dos comandos inseridos na Linha de Comando e como seria a aparência do Projeto 'Olá, Mundo' no navegador da Web.

Arquitetura katana

A arquitetura do componente Katana divide um aplicativo em quatro camadas lógicas, conforme descrito abaixo: host, servidor, middleware e aplicativo. A arquitetura do componente é fatorada de forma que as implementações dessas camadas possam ser facilmente substituídas, em muitos casos, sem a necessidade de recompilação do aplicativo.

Diagrama das Camadas de Arquitetura mostra quatro barras ilustrando as camadas lógicas nas quais a arquitetura do aplicativo é dividida.

Host

O host é responsável por:

  • Gerenciando o processo subjacente.

  • Orquestrando o fluxo de trabalho que resulta na seleção de um servidor e na construção de um pipeline OWIN por meio do qual as solicitações serão tratadas.

    Atualmente, há três opções de hospedagem primárias para aplicativos baseados em Katana:

IIS/ASP.NET: usando os tipos HttpModule e HttpHandler padrão, os pipelines OWIN podem ser executados no IIS como parte de um fluxo de solicitação ASP.NET. ASP.NET suporte à hospedagem é habilitado instalando o pacote NuGet Microsoft.AspNet.Host.SystemWeb em um projeto de aplicativo Web. Além disso, como o IIS atua como um host e um servidor, a distinção de servidor/host OWIN é confundida neste pacote NuGet, o que significa que, se estiver usando o host SystemWeb, um desenvolvedor não poderá substituir uma implementação de servidor alternativa.

Host Personalizado: o pacote de componentes do Katana oferece a um desenvolvedor a capacidade de hospedar aplicativos em seu próprio processo personalizado, seja um aplicativo de console, serviço Windows etc. Essa funcionalidade é semelhante à funcionalidade de auto-host fornecida pela API Web. O exemplo a seguir mostra um host personalizado do código da API Web:

static void Main()
{
    var baseAddress = new Uri("http://localhost:5000");

    var config = new HttpSelfHostConfiguration(baseAddress);
    config.Routes.MapHttpRoute("default", "{controller}");
       
    using (var svr = new HttpSelfHostServer(config))
    {
        svr.OpenAsync().Wait();
        Console.WriteLine("Press Enter to quit.");
        Console.ReadLine();
    }
}

A configuração de auto-host para um aplicativo Katana é semelhante:

static void Main(string[] args)
{
    const string baseUrl = "http://localhost:5000/";

    using (WebApplication.Start<Startup>(new StartOptions { Url = baseUrl })) 
    {
        Console.WriteLine("Press Enter to quit.");
        Console.ReadKey();
    }
}

Uma diferença notável entre os exemplos de auto-host da API Web e do Katana é que o código de configuração da API Web está ausente do exemplo de auto-host do Katana. Para habilitar a portabilidade e a capacidade de composição, Katana separa o código que inicia o servidor do código que configura o pipeline de processamento de solicitação. O código que configura a API Web, em seguida, está contido na classe Inicialização, que é especificada adicionalmente como o parâmetro de tipo em WebApplication.Start.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        config.Routes.MapHttpRoute("default", "{controller}");
        app.UseWebApi(config);
    }
}

A classe de inicialização será discutida com mais detalhes mais adiante no artigo. No entanto, o código necessário para iniciar um processo de auto-host do Katana é surpreendentemente semelhante ao código que você pode estar usando hoje em ASP.NET Web API aplicativos auto-host.

OwinHost.exe: embora alguns queiram escrever um processo personalizado para executar aplicativos Web Katana, muitos preferem simplesmente iniciar um executável pré-criado que possa iniciar um servidor e executar seu aplicativo. Para esse cenário, o pacote de componentes do Katana inclui OwinHost.exe. Quando executado de dentro do diretório raiz de um projeto, esse executável iniciará um servidor (ele usa o servidor HttpListener por padrão) e usará convenções para localizar e executar a classe de inicialização do usuário. Para um controle mais granular, o executável fornece vários parâmetros de linha de comando adicionais.

Captura de tela do Prompt de Comando do Desenvolvedor, mostrando um exemplo do código do Prompt de Comando enquanto ele executa o aplicativo no servidor.

Servidor

Embora o host seja responsável por iniciar e manter o processo no qual o aplicativo é executado, a responsabilidade do servidor é abrir um soquete de rede, escutar solicitações e enviá-las por meio do pipeline de componentes OWIN especificados pelo usuário (como você já deve ter notado, esse pipeline é especificado na classe startup do desenvolvedor de aplicativos). Atualmente, o projeto Katana inclui duas implementações de servidor:

  • Microsoft.Owin.Host.SystemWeb: como mencionado anteriormente, o IIS em conjunto com o pipeline ASP.NET atua como um host e um servidor. Portanto, ao escolher essa opção de hospedagem, o IIS gerencia preocupações no nível do host, como ativação de processo e escuta solicitações HTTP. Para ASP.NET aplicativos Web, ele envia as solicitações para o pipeline ASP.NET. O host Katana SystemWeb registra um ASP.NET HttpModule e HttpHandler para interceptar solicitações à medida que fluem pelo pipeline HTTP e enviá-las por meio do pipeline OWIN especificado pelo usuário.
  • Microsoft.Owin.Host.HttpListener: como seu nome indica, este servidor Katana usa a classe HttpListener do .NET Framework para abrir um soquete e enviar solicitações para um pipeline OWIN especificado pelo desenvolvedor. Atualmente, essa é a seleção de servidor padrão para a API de auto-host do Katana e OwinHost.exe.

Middleware/estrutura

Conforme mencionado anteriormente, quando o servidor aceita uma solicitação de um cliente, ele é responsável por passá-la por meio de um pipeline de componentes OWIN, que são especificados pelo código de inicialização do desenvolvedor. Esses componentes de pipeline são conhecidos como middleware.
Em um nível muito básico, um componente de middleware OWIN simplesmente precisa implementar o delegado de aplicativo OWIN para que ele seja callable.

Func<IDictionary<string, object>, Task>

No entanto, para simplificar o desenvolvimento e a composição de componentes de middleware, a Katana dá suporte a um punhado de convenções e tipos auxiliares para componentes de middleware. A mais comum delas é a OwinMiddleware classe . Um componente de middleware personalizado criado usando essa classe seria semelhante ao seguinte:

public class LoggerMiddleware : OwinMiddleware
{
    private readonly ILog _logger;
 
    public LoggerMiddleware(OwinMiddleware next, ILog logger) : base(next)
    {
        _logger = logger;
    }
 
    public override async Task Invoke(IOwinContext context)
    {
        _logger.LogInfo("Middleware begin");
        await this.Next.Invoke(context);
        _logger.LogInfo("Middleware end");
    }
}

Essa classe deriva de OwinMiddleware, implementa um construtor que aceita uma instância do próximo middleware no pipeline como um de seus argumentos e, em seguida, passa-o para o construtor base. Argumentos adicionais usados para configurar o middleware também são declarados como parâmetros de construtor após o próximo parâmetro middleware.

No runtime, o middleware é executado por meio do método substituído Invoke . Esse método usa um único argumento do tipo OwinContext. Esse objeto de contexto é fornecido pelo Microsoft.Owin pacote NuGet descrito anteriormente e fornece acesso fortemente tipado ao dicionário de solicitação, resposta e ambiente, juntamente com alguns tipos auxiliares adicionais.

A classe middleware pode ser facilmente adicionada ao pipeline OWIN no código de inicialização do aplicativo da seguinte maneira:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

   }
}

Como a infraestrutura do Katana simplesmente cria um pipeline de componentes de middleware OWIN e, como os componentes simplesmente precisam dar suporte ao delegado do aplicativo para participar do pipeline, os componentes de middleware podem variar em complexidade de agentes simples a estruturas inteiras, como ASP.NET, API Web ou SignalR. Por exemplo, adicionar ASP.NET Web API ao pipeline OWIN anterior requer a adição do seguinte código de inicialização:

public class Startup
{
   public void Configuration(IAppBuilder app)
   {
      app.Use<LoggerMiddleware>(new TraceLogger());

      var config = new HttpConfiguration();
      // configure Web API 
      app.UseWebApi(config);

      // additional middleware registrations            
   }
}

A infraestrutura do Katana criará o pipeline de componentes de middleware com base na ordem em que eles foram adicionados ao objeto IAppBuilder no método Configuration. Em nosso exemplo, então, LoggerMiddleware pode lidar com todas as solicitações que fluem pelo pipeline, independentemente de como essas solicitações são tratadas em última instância. Isso permite cenários poderosos em que um componente de middleware (por exemplo, um componente de autenticação) pode processar solicitações para um pipeline que inclui vários componentes e estruturas (por exemplo, ASP.NET Web API, SignalR e um servidor de arquivos estático).

Aplicativos

Conforme ilustrado pelos exemplos anteriores, o OWIN e o projeto Katana não devem ser considerados como um novo modelo de programação de aplicativos, mas sim como uma abstração para separar modelos e estruturas de programação de aplicativos da infraestrutura de servidor e hospedagem. Por exemplo, ao criar aplicativos de API Web, a estrutura do desenvolvedor continuará a usar a estrutura ASP.NET Web API, independentemente de o aplicativo ser executado ou não em um pipeline OWIN usando componentes do projeto Katana. O único lugar em que o código relacionado ao OWIN ficará visível para o desenvolvedor de aplicativos será o código de inicialização do aplicativo, em que o desenvolvedor compõe o pipeline OWIN. No código de inicialização, o desenvolvedor registrará uma série de instruções UseXx, geralmente uma para cada componente de middleware que processará solicitações de entrada. Essa experiência terá o mesmo efeito que registrar módulos HTTP no mundo atual do System.Web. Normalmente, um middleware de estrutura maior, como ASP.NET Web API ou SignalR, será registrado no final do pipeline. Componentes de middleware de corte cruzado, como aqueles para autenticação ou cache, geralmente são registrados no início do pipeline para que eles processem solicitações para todas as estruturas e componentes registrados posteriormente no pipeline. Essa separação dos componentes de middleware entre si e dos componentes de infraestrutura subjacentes permite que os componentes evoluam em diferentes velocidades, garantindo que o sistema geral permaneça estável.

Componentes – Pacotes NuGet

Como muitas bibliotecas e estruturas atuais, os componentes do projeto Katana são entregues como um conjunto de pacotes NuGet. Para a próxima versão 2.0, o pacote katana grafo de dependência tem a aparência a seguir. (Clique na imagem para uma exibição maior.)

Diagrama da hierarquia Componentes – Pacotes NuGet. Esta imagem retrata as árvores de biblioteca nas quais as estruturas estão conectadas para os componentes do projeto e são entregues por meio de um conjunto de NuGets.

Quase todos os pacotes do projeto Katana dependem, direta ou indiretamente, do pacote Owin. Você deve se lembrar de que esse é o pacote que contém a interface IAppBuilder, que fornece uma implementação concreta da sequência de inicialização do aplicativo descrita na seção 4 da especificação OWIN. Além disso, muitos dos pacotes dependem do Microsoft.Owin, que fornece um conjunto de tipos auxiliares para trabalhar com solicitações e respostas HTTP. O restante do pacote pode ser classificado como hospedagem de pacotes de infraestrutura (servidores ou hosts) ou middleware. Pacotes e dependências externos ao projeto Katana são exibidos em laranja.

A infraestrutura de hospedagem para Katana 2.0 inclui os servidores baseados em SystemWeb e HttpListener, o pacote OwinHost para executar aplicativos OWIN usando OwinHost.exe e o pacote Microsoft.Owin.Hosting para auto-hospedagem de aplicativos OWIN em um host personalizado (por exemplo, aplicativo de console, serviço Windows etc.)

Para o Katana 2.0, os componentes de middleware se concentram principalmente em fornecer diferentes meios de autenticação. Um componente de middleware adicional para diagnóstico é fornecido, o que permite o suporte para uma página inicial e de erro. À medida que o OWIN cresce na abstração de hospedagem de fato, o ecossistema de componentes de middleware, tanto os desenvolvidos pela Microsoft quanto por terceiros, também aumentará em número.

Conclusão

Desde o início, o objetivo do projeto Katana não era criar e, assim, forçar os desenvolvedores a aprender mais uma estrutura da Web. Em vez disso, o objetivo foi criar uma abstração para dar aos desenvolvedores de aplicativos Web do .NET mais opções do que antes era possível. Ao dividir as camadas lógicas de uma pilha típica de aplicativos Web em um conjunto de componentes substituíveis, o projeto Katana permite que os componentes em toda a pilha melhorem a qualquer taxa que faça sentido para esses componentes. Ao criar todos os componentes em torno da abstração OWIN simples, o Katana permite que as estruturas e os aplicativos criados sobre eles sejam portáteis em uma variedade de servidores e hosts diferentes. Ao colocar o desenvolvedor no controle da pilha, Katana garante que o desenvolvedor faça a escolha final sobre o quão leve ou rica em recursos sua pilha web deve ser.

Para obter mais informações sobre Katana

Confirmações