ASP.NET 5

Um mergulho profundo no tempo de execução do ASP.NET 5

Daniel Roth

Em novembro passado a Microsoft anunciou o ASP.NET 5 como uma nova estrutura de plataforma cruzada e de software aberto para criar aplicativos de nuvem e da Web modernos usando o Microsoft .NET Framework. Nós (a equipe de desenvolvimento do ASP.NET, da qual faço parte) lançamos o ASP.NET 5 Preview junto com o Visual Studio 2015 Preview no evento Connect(); em Nova York. Eu apresentei o tempo de execução do ASP.NET 5 e seu novo sistema de projeto do Visual Studio no artigo "Introdução ao ASP.NET 5 Preview" da edição especial de 15 de dezembro de 2014 da MSDN Magazine (bit.ly/1K4PY4U). Desde dessa última visualização do ASP.NET 5 em dezembro, houveram dois lançamentos de versões do ASP.NET 5: Beta2 com o Visual Studio 2015 CTP 5 e Beta3 com o Visual Studio 2015 CTP 6. Com cada lançamento, a estrutura continua a evoluir e melhorar. Em muitos casos, essas melhorias foram generosamente contribuídas pela comunidade .NET através do projeto ASP.NET público no GitHub (bit.ly/1DaY7Cd). Neste artigo, eu analisarei mais profundamente os bastidores do novo tempo de execução do ASP.NET 5 para ver o que mudou na versão mais recente.

O ambiente de tempo de execução K (KRE)

Como você viu em dezembro, o ASP.NET 5 baseia-se em um host de tempo de execução flexível e de plataforma cruzada que pode hospedar um dos vários CLRs .NET. Você pode executar aplicativos ASP.NET 5 no .NET Framework com seu conjunto de APIs completo para compatibilidade máxima. Você também pode executar o ASP.NET 5 no novo .NET Core, que permite verdadeiras implantações lado a lado que você pode copiar em ambientes existentes sem precisar alterar qualquer coisa no computador. No futuro, você também poderá executar a plataforma cruzada ASP.NET 5 no .NET Core e não há suporte da comunidade para a execução de plataforma cruzada no Mono hoje.

A infraestrutura de hospedagem do tempo de execução para ASP.NET 5 é atualmente chamada de Ambiente do Tempo de Execução K (KRE), que é um nome de espaço reservado genérico até finalizarmos o nome oficial. O KRE fornece um ambiente que tem tudo o que um aplicativo .NET precisa para funcionar: um processo de host, a lógica de hospedagem o CLR, descoberta do ponto de entrada gerenciada e assim por diante. O KRE foi criado para execução de aplicativos da Web .NET de plataformas cruzadas, mas ele também pode executar outros tipos de aplicativos .NET, como aplicativos de console. O KRE é baseado no mesmo CLR .NET e bibliotecas de classe base que os desenvolvedores .NET passaram a conhecer e amar, enquanto habilita o suporte de plataforma cruzada para a execução de aplicativos .NET no Windows, OS X e Linux.

Logicamente, o KRE tem cinco camadas de funcionalidades. Eu descreverei cada uma dessas camadas e suas responsabilidades.

Camada 1. Processo Nativo: O processo nativo é uma camada muito fina com a responsabilidade de encontrar e chamar o host CLR nativo, passando argumentos dados para o processo a ser usado pelo restante da pilha. No Windows, isso é um executável nativo (klr.exe); no Mac ou Linux é um script de bash executável. A execução no IIS é realizada com um novo módulo HTTP nativo ou usando o carregador Helios. O carregador Helios utiliza ganchos de extensibilidade no .NET Framework 4.5.1 para inicializar o KRE sem exigir a instalação de novos módulos do IIS. Com o módulo HTTP nativo, você pode executar aplicativos da Web baseados no .NET Core no IIS sem nenhuma dependência no .NET Framework. Enquanto o módulo HTTP nativo ainda não está disponível publicamente, planejamos disponibilizá-lo em uma visualização futura.

Camadas 2 e 3. Host CLR nativo e CLR: O host CLR nativo tem três responsabilidades principais:

  1. Inicializar o CLR. Como isso é feito depende da versão do CLR. Por exemplo, inicializar o .NET Core envolve carregar coreclr.dll, configurar e iniciar o tempo de execução e criar o AppDomain que todo o código gerenciado será executado. Para Mono e o .NET Framework 4.5.1, o processo varia um pouco, mas o resultado é o mesmo.
  2. Chame o ponto de entrada gerenciado, que é a próxima camada.
  3. Quando o ponto de entrada do host nativo é retornado, esse processo limpará e desligará o CLR — ou seja, descarregará o domínio de aplicativo e interromperá o tempo de execução.

Camada 4: Ponto de entrada gerenciado: Essa camada é a primeira camada escrita em código gerenciado. É responsável por:

  1. Carregar assemblies e satisfazer as dependências da pasta lib.
  2. Configurar o IApplicationEnvironment e a infraestrutura de injeção de dependência principal.
  3. Chamar o ponto de entrada principal do aplicativo especificado ou host do aplicativo.

Nessa camada, os assemblies são carregados somente de pastas lib especificadas ou do caminho base do aplicativo. É a próxima camada que adiciona carregadores adicionais para resolver dependências de pacotes NuGet ou até mesmo código compilado no tempo de execução.

Camada 5: Host do aplicativo/aplicativo: Se um desenvolvedor compila um aplicativo inteiro para assemblies no disco na pasta lib, essa camada é o aplicativo — o aplicativo do usuário final vê. Se você quiser fazer isso, é possível compilar seu aplicativo e passar o nome da DLL que contém um ponto de entrada principal padrão ao iniciar a camada 1.

No entanto, na maioria dos cenários, você usaria um host de aplicativos para ajudar a resolver as dependências de aplicativo e executar seu aplicativo. Microsoft.Framework.ApplicationHost é o host de aplicativo fornecido no KRE e suas responsabilidades incluem:

  1. Percorrer as dependências no project.json e acumular o fechamento de dependências que o aplicativo usará. A lógica dependência-­percorrer é descrita mais detalhadamente em bit.ly/1y5lZEm.
  2. Adicionar carregadores de assemblies que podem carregar assemblies de várias fontes, como pacotes NuGet instalados, fontes compiladas no tempo de execução usando o Roslyn e assim por diante.
  3. Chamar o ponto de entrada do assembly cujo nome foi fornecido como um argumento quando o processo nativo foi iniciado. O assembly pode ser qualquer coisa com um ponto de entrada que o ApplicationHost sabe como carregar. O ApplicationHost fornecido com o KRE sabe como localizar um método void Main público. Esse é o ponto de entrada usado para configurar a camada de hospedagem do ASP.NET, que sabe como localizar Startup.cs e executar o método de configuração para seu aplicativo da Web.

Uma coisa a observar enquanto você está aprendendo sobre o KRE é que se trata de uma parte de baixo nível da pilha. Ao operar no nível do KRE, o mundo ainda é muito sobre como localizar e carregar bibliotecas de vínculo dinâmico (DLLs). É o KRE que contém a lógica para permitir que você, no nível do aplicativo, pense apenas em pacotes e outras dependências de nível superior.

Ferramentas do SDK de plataforma cruzada

O KRE é empacotado com um SDK que contém tudo o que você precisa para criar aplicativos .NET de plataforma cruzada. No meu artigo anterior sobre o ASP.NET 5, descrevi como você pode usar a ferramenta Gerenciador de Versão do KRE (KVM) para listar os KREs instalados no computador, instalar novos e selecionar o KRE que você deseja usar. Você pode encontrar instruções sobre como instalar o KVM para seu sistema operacional em bit.ly/1y5mqyi.

O KVM instala KREs de um feed do NuGet configurado usando a variável de ambiente KRE_FEED. Os KREs não são pacotes NuGet no sentido tradicional porque eles não são pacotes nos quais você nunca dependeria; o NuGet é apenas uma maneira conveniente de distribuir e criar versão do KREs. Por padrão, um KRE é instalado copiando e extrair o arquivo .zip KRE em % USERPROFILE%\.k\runtimes.

Também apresentei a ferramenta do Gerenciador de Pacote K (KPM) para instalar, restaurar e criar pacotes NuGet. Planejamos renomear a ferramenta KPM para o nuget e alinhá-lo com o cliente NuGet existente. Como parte desse alinhamento, alguns dos subcomandos kpm já foram renomeados. Agora você pode usar o comando bundle para empacotar um aplicativo para a publicação e o comando pack para compilar e criar pacotes NuGet para um projeto. O comando updated built produz saídas de compilação brutas sem empacotar nada. Há também um novo comando wrap que permite que ferramentas façam referência a um projeto baseado em csproj existente no project.json. Por padrão, os pacotes agora estão instalados na pasta %USERPROFILE%\.k\packages, mas é possível controlar isso definindo um caminho de pacotes no arquivo global.json.

Um aplicativo de console .NET de plataforma cruzada

Agora mostrarei como criar um aplicativo de console .NET de plataforma cruzada simples usando o KRE. Primeiro, preciso criar uma DLL com o ponto de entrada e posso fazer isso usando o modelo de projeto de aplicativo de console do ASP.NET 5 no Visual Studio de 2015. O código deve ter esta aparência:

public class Program
{
  public void Main(string[] args)
  {
    Console.WriteLine("Hello World");
    Console.ReadLine();
  }
}

Isso parece bastante familiar, mas observe que o ponto de entrada é na verdade um método de instância. Além de um ponto de entrada Program.Main estático, o KRE oferece suporte a pontos de entrada com base em instância. Você também pode tornar o ponto de entrada principal assíncrono e retornar uma tarefa. Com o ponto de entrada principal como um método de instância, você pode ter serviços injetados no seu aplicativo pelo ambiente do tempo de execução.

Você pode executar esse aplicativo no Visual Studio ou na linha de comando executando "k run" no diretório que contém o arquivo project.json para o aplicativo. O comando K é realmente apenas um arquivo em lote simples e o comando "k run" pode ser expandido para o seguinte:

klr.exe --appbase . Microsoft.Framework.ApplicationHost run

O comando K executa o processo nativo (klr.exe), especifica o aplicativo base como o diretório atual e especifica o host de aplicativo padrão. O processo nativo não tem nenhum conhecimento especial do host de aplicativo padrão — ele simplesmente procura por um ponto de entrada padrão no assembly Microsoft.Framework.ApplicationHost e chama nele.

Se você não quiser usar o host de aplicativo padrão, você pode chamar a camada nativa para chamar diretamente em seu aplicativo. Para fazer isso, primeiro crie o projeto para gerar a DLL para o aplicativo de console. Verifique se que você marcou a opção "Produzir saídas na compilação" nas propriedades de compilação do projeto. Você pode encontrar a saída de compilação sob o diretório de artefatos na pasta da solução. Navegue até o diretório que contém a DLL interna para o tipo KRE que você está usando e chame "klr.exe <nome da DLL>" para ver a saída do aplicativo de console.

Chamar uma DLL diretamente é uma maneira muito baixo nível e bruta de criar um aplicativo. Você não está usando o host de aplicativo padrão para antecipar o suporte do project.json e o suporte do gerenciamento de dependências baseado em NuGet aprimorado. Em vez disso, todas as bibliotecas que você dependem são simplesmente carregadas das pastas lib especificadas. Para o restante deste artigo, usarei o host de aplicativo padrão.

Você pode usar o serviço IServiceManifest para enumerar todos os serviços que estão disponíveis no ambiente do tempo de execução. Você não precisa especificar as dependências adicionais para usar esse assembly em todos os porque ele é uma Interface Neutra de Assembly (ANI). ANIs são tipos que são identificados exclusivamente por seu nome e namespace e são um recurso do KRE. Dois tipos de assembly neutros em assemblies diferentes, mas com o mesmo nome e namespace são considerados equivalentes. Isso significa que as abstrações comuns podem simplesmente ser declaradas localmente em vez de declarar uma dependência em um componente comum.

Você pode definir sua própria interface IServiceManifest de assembly neutro em seu aplicativo de console como este:

namespace Microsoft.Framework.DependencyInjection.ServiceLookup
{
  [AssemblyNeutral]
  public interface IServiceManifest
  {
    IEnumerable<Type> Services { get; }
  }
}

Mas de onde vêm o AssemblyNeutralAttribute? Bem, é um assembly neutro claro! Então você o declara localmente também:

namespace Microsoft.Net.Runtime
{
  [AssemblyNeutral]
  [AttributeUsage(AttributeTargets.All, 
    Inherited = false, AllowMultiple = true)]
  public sealed class AssemblyNeutralAttribute : Attribute
  {
  }
}

Esses tipos de assembly neutros serão unificados no tempo de execução com os mesmos tipos que estão sendo usados pelo KRE.

O código na Figura 1 injeta o serviço IServiceManifest no aplicativo adicionando um construtor para a classe Program e itera por meio dos serviços.

Figura 1 Injetar o serviço IServiceManifest no aplicativo

namespace ConsoleApp1
{
  public class Program
  {
    public Program(IServiceManifest serviceManifest)
    {
      ServiceManifest = serviceManifest;
    }
    IServiceManifest ServiceManifest { get; }
    public void Main(string[] args)
    {
      foreach (Type type in ServiceManifest.Services)
      {
        Console.WriteLine(type.FullName);
      }
    }
  }
}

O host do aplicativo habilitará o suporte para project.json, adicionará resolvedores de assemblies (para lidar com pacotes NuGet, referências de projeto e assim por diante) e tornará vários serviços adicionais disponíveis para o aplicativo antes de chamar o ponto de entrada para o aplicativo. Quando você executar o aplicativo de console, a saída deverá ser a seguinte:

Microsoft.Framework.Runtime.IAssemblyLoaderContainer
Microsoft.Framework.Runtime.IAssemblyLoadContextAccessor
Microsoft.Framework.Runtime.IApplicationEnvironment
Microsoft.Framework.Runtime.IFileMonitor
Microsoft.Framework.Runtime.IFileWatcher
Microsoft.Framework.Runtime.ILibraryManager
Microsoft.Framework.Runtime.ICompilerOptionsProvider
Microsoft.Framework.Runtime.IApplicationShutdown

Há serviços para fazer observação de arquivo, percorrer a estrutura das "bibliotecas" (projetos, pacotes, assemblies) no aplicativo, obter as opções de compilação que estão sendo usadas e desligar o aplicativo. Como o ASP.NET 5 e o KRE ainda estão no modo de visualização e em desenvolvimento ativo, a lista exata de serviços que você vê pode diferir.

Hosts

A camada de hospedagem do ASP.NET é executada no topo do KRE e é responsável por encontrar o servidor Web para ser executado, localizar a lógica de inicialização para o aplicativo, hospedar o aplicativo no servidor e limpar quando o aplicativo for desligado. Ele também fornece um número de serviços relacionados à hospedagem adicionais para aplicativos.

A DLL de hospedagem do ASP.NET (Microsoft.AspNet.Hosting, em bit.ly/­1uB6ulW) tem um método do ponto de entrada que é chamado pelo host do aplicativo KRE. Você pode configurar qual servidor da Web você deseja usar especificando a opção da linha de comando --server ou outras fontes de dados de configuração, como variáveis de ambiente ou config.json. A camada de hospedagem carrega o assembly/tipo do servidor especificado para localizar um IServerFactory que pode ser usado para inicializar e iniciar o servidor. Normalmente, o servidor deve estar listado em suas dependências em project.json para que possa ser carregado.

Observe que os comandos definidos em project.json são realmente apenas conjuntos de argumentos da linha de comando adicionais para klr.exe. Por exemplo, o modelo de projeto do aplicativo Web do ASP.NET Starter padrão inclui uma série de comandos no project.json parecidos com o seguinte:

"commands": {
  /* Change the port number when you are self hosting this application */
  "web": "Microsoft.AspNet.Hosting 
    --server Microsoft.AspNet.Server.WebListener
    --server.urls http://localhost:5000",
  "gen": "Microsoft.Framework.CodeGeneration",
  "ef":  "EntityFramework.Commands"
},

Portanto, se você fosse executar "k web", o que você realmente está executando é:

klr.exe --appbase . Microsoft.Framework.ApplicationHost Microsoft.AspNet.Hosting
  --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000

Inicialização

A camada de hospedagem do ASP.NET também é responsável por localizar a lógica de inicialização para seu aplicativo. Normalmente, a lógica de inicialização do aplicativo é definida em uma classe Startup, com um método Configure para configurar o pipeline da solicitação e um método ConfigureServices para configurar quaisquer serviços que seu aplicativo precise, conforme mostrado na Figura 2.

Figura 2 A classe Startup

namespace WebApplication1
{
  public class Startup
  {
    public void ConfigureService(IServiceCollection services)
    {
      // Add services for your application here
    }
    public void Configure(IApplicationBuilder app)
    {
      // Configure your application pipeline here
    }
  }
}

Em seu método Configure, você usa a interface IApplicationBuilder para criar o pipeline de solicitação para o aplicativo. O construtor do aplicativo permite que você "Use" middleware, crie "Novo" compiladores de aplicativos e "Compile" uma solicitação delegada. O solicitação delegada é a construção de tempo de execução principal no ASP.NET 5. Uma solicitação delegada utiliza um HttpContext e faz alguma coisa útil com ele de modo assíncrono:

public delegate Task RequestDelegate(HttpContext context);

O middleware ASP.NET 5 utiliza como entrada a próxima solicitação delegada no pipeline e fornece uma solicitação delegada com a lógica de middleware. O delegado da solicitação retornada pode ou não chamar o delegado da próxima solicitação no pipeline. Como um atalho para a execução da lógica de middleware que não chama o próximo delegado da solicitação, você pode usar o método de extensão Run no IApplicationBuilder:

app.Run(async context => await context.Response.WriteAsync("Hello, world!"));

Isso seria o mesmo que escrever o seguinte middleware embutido onde o próximo parâmetro é simplesmente ignorado:

app.Use(next => async context =>
  await context.Response.WriteAsync("Hello, world!"));

Para criar middleware reutilizável, você pode escrevê-lo como uma classe onde, por convenção, o próximo representante de solicitação é injetado no construtor junto com quaisquer serviços ou parâmetros adicionais que o middleware precisa. Você implementa o representante de solicitação para o middleware como um método Invoke assíncrono, conforme mostrado na Figura 3.

Figura 3 implementação de middleware como uma classe reutilizável

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System.Threading.Tasks;
public class XHttpHeaderOverrideMiddleware
{
  private readonly RequestDelegate _next;
  public XHttpHeaderOverrideMiddleware(RequestDelegate next)
  {
    _next = next;
  }
  public Task Invoke(HttpContext httpContext)
  {
    var headerValue =
      httpContext.Request.Headers["X-HTTP-Method-Override"];
    var queryValue =
      httpContext.Request.Query["X-HTTP-Method-Override"];
    if (!string.IsNullOrEmpty(headerValue))
    {
      httpContext.Request.Method = headerValue;
    }
    else if (!string.IsNullOrEmpty(queryValue))
    {
      httpContext.Request.Method = queryValue;
    }
    return _next.Invoke(httpContext);
  }
}

Você pode usar o middleware depois dessa convenção usando o método de extensão UseMiddleware<T> no IApplicationBuilder. As opções adicionais que você passar para este método serão injetadas no construtor de middleware após o próximo representante de solicitação e quaisquer serviços injetados. Por convenção, o middleware deve também definir seu próprio método Use extension específico no IApplicationBuilder, como este:

public static class BuilderExtensions
{
  public static IApplicationBuilder UseXHttpHeaderOverride(
    this IApplicationBuilder builder)
  {
    return builder.UseMiddleware<XHttpHeaderOverrideMiddleware>();
  }
}

Adicione o middleware no pipeline do aplicativo da seguinte forma:

public class Startup
{
  public void Configure(IApplicationBuilder app)
  {
    app.UseXHttpHeaderOverride();
  }
}

O ASP.NET 5 é fornecido com um conjunto avançado de middleware pré-criado. Não há middleware para manipular arquivos estáticos, roteamento, tratamento de erros, diagnóstico e segurança. Você pode localizar, baixar e instalar middleware da Microsoft e da comunidade como pacotes NuGet em nuget.org.

Configuração de serviços

Como com todos os outros pontos de entrada vistos nessa pilha, a classe Startup pode ter serviços injetados da camada de hospedagem em seu construtor ou como parâmetros adicionais nos métodos Configure e ConfigureServices. Se você enumerar os serviços disponíveis na inicialização (usando IServiceManifest), verá que agora há ainda mais serviços disponíveis:

Microsoft.Framework.Runtime.IAssemblyLoaderContainer
Microsoft.Framework.Runtime.IAssemblyLoadContextAccessor
Microsoft.Framework.Runtime.IApplicationEnvironment
Microsoft.Framework.Runtime.IFileMonitor
Microsoft.Framework.Runtime.IFileWatcher
Microsoft.Framework.Runtime.ILibraryManager
Microsoft.Framework.Runtime.ICompilerOptionsProvider
Microsoft.Framework.Runtime.IApplicationShutdown
Microsoft.AspNet.Hosting.IHostingEnvironment
Microsoft.Framework.Runtime.IProjectResolver
Microsoft.Framework.Logging.ILoggerFactory
Microsoft.Framework.Runtime.ICache
Microsoft.Framework.Runtime.ICacheContextAccessor
Microsoft.Framework.DependencyInjection.ITypeActivator
Microsoft.Framework.Runtime.IAssemblyLoadContextFactory

Os serviços do IHostingEnvironment fornecem acesso para o caminho raiz da Web de seu aplicativo (normalmente sua pasta www) e também uma abstração do IFileProvider para a raiz da Web. O IProject­Resolver pode ser usado para localizar outros projetos na solução. Há registro em log e serviços de cache e um ativador de tipo que tem reconhecimento de injeção de dependência. O IAssemblyLoadContextFactory fornece uma abstração para criar novos contextos de carregamento do assembly.

Configure os serviços existentes e adicione novos para o seu aplicativo no método ConfigureServices em sua classe Startup. O método ConfigureServices usa um IServiceCollection para o qual você pode adicionar serviços ou modificar serviços existentes. O ASP.NET 5 é fornecido com um contêiner IoC interno simples que é configurado na camada do Ponto de Entrada Gerenciado para inicializar o sistema, mas você pode facilmente substituir o contêiner interno com seu contêiner de escolha.

Estruturas normalmente fornecem um método de extensão Add para adicionar seus serviços ao IServiceCollection. Por exemplo, aqui está como você pode adicionar serviços usados pelo ASP.NET MVC 6:

public void ConfigureServices(IServiceCollection services)
{
  // Add MVC services to the services container
  services.AddMvc();
}

Quando você adiciona serviços à coleção de serviço, eles podem ser um dos três tipos: temporário, escopo ou singleton. Serviços temporários são criados cada vez que são solicitados pelo contêiner. Serviços de escopo são criados somente se não existirem ainda no escopo atual. Para aplicativos Web, o escopo do contêiner é criado para cada solicitação, portanto, você pode pensar em serviços de escopo de acordo com a solicitação. Serviços de singleton são criados apenas uma vez.

Arquivos app.config de estilo Web.config e System.Configuration não têm suporte no ASP.NET 5. Em vez disso, o ASP.NET 5 é fornecido com uma nova API de configuração simplificada (Microsoft.Framework.ConfigurationModel, em bit.ly/1yxC7gA) para trabalhar com dados de configuração. A nova API de configuração permite recuperar e manipular dados de configuração de uma variedade de fontes. Provedores de configuração padrão são incluídos para JSON, XML, INI, parâmetros de linha de comando e variáveis de ambiente. Você pode especificar vários provedores e eles são usados na ordem em que são adicionados. Oferecendo suporte à configuração baseada em ambiente, você pode implantar mais facilmente um aplicativo em um ambiente e escolher as configurações apropriadas para esse ambiente.

Para inicializar os dados de configuração, adicione seus provedores de configuração desejados para uma nova instância Configuration:

public Startup(IHostingEnvironment env)
{
  Configuration = new Configuration()
    .AddJsonFile("config.json")
    .AddEnvironmentVariables();
}

Você pode solicitar valores de configuração por nome:

string user = Configuration.Get("user");
string password = Configuration.Get("password");

Você pode disponibilizar dados de configuração de uma forma fortemente tipada em todo o aplicativo usando o modelo de opções. As opções são apenas classes Plain Old C# Object (POCO) que têm várias propriedades usadas para configuração. Você disponibiliza opções em seu aplicativo chamando AddOptions, que adiciona o serviço IOptions<TOption> ao contêiner. Esse serviço pode ser usado para acessar opções de tipos diferentes sempre que há suporte para injeção de dependência.

Para configurar opções, você adiciona serviços IConfigureOptions<TOptions> ao contêiner. A implementação padrão do serviço IOptions<TOption> reunirá todos os serviços IConfigure­Options<TOption> e os usará para configurar a instância de opções antes de tornar a instância de opções disponível para os consumidores. Como um atalho para adicionar lógica de configuração de opções, você pode usar o método Configure<TOption>, como este:

services.Configure<MvcOptions>(options => options.Filters.Add(
  new MyGlobalFilter()));

O modelo de opções e o modelo de configuração trabalham em conjunto. Você pode associar facilmente dados de configuração para opções, correspondendo pelo nome da propriedade usando as sobrecargas Configure que utilizam uma instância Configuration, assim:

services.Configure<MyOptions>(Configuration);

Processamento de solicitação

Quando o servidor Web for iniciado, ele começa a ouvir para solicitações e chamar o pipeline do aplicativo com cada solicitação. O servidor faz superfície de solicitação como um objeto de ambiente de servidor que expõe um conjunto de interfaces de recurso refinado. Há interfaces de recurso para enviar arquivos, soquetes da Web, suporte de sessão, certificados de cliente e muito mais. Você pode ver a lista completa de interfaces de recursos suportados no GitHub em bit.ly/1Dh7eBC. Por exemplo, aqui está a interface do recurso para a solicitação HTTP:

[AssemblyNeutral]
public interface IHttpRequestFeature
{
  string Protocol { get; set; }
  string Scheme { get; set; }
  string Method { get; set; }
  string PathBase { get; set; }
  string Path { get; set; }
  string QueryString { get; set; }
  IDictionary<string, string[]> Headers { get; set; }
  Stream Body { get; set; }
}

Você normalmente não codifica diretamente com as várias interfaces de recursos. Os servidores Web usam interfaces de recurso para expor a funcionalidade de baixo nível para a camada do host. A camada de hospedagem envolve essas interfaces de recurso em um HttpContext fortemente tipado que será passado para o aplicativo. Esse nível de acoplamento livre entre o servidor Web, a camada de hospedagem e os aplicativos permite que os servidores sejam implementados e reutilizados sem serem vinculado a um modelo de hospedagem específico e permite que os aplicativos sejam hospedados em servidores diferentes. O ASP.NET 5 é fornecido com suporte interno para execução no IIS (Microsoft.AspNet.Server.IIS) diretamente em um wrapper HTTP.SYS fino (Microsoft.AspNet.Server.Web­Listener) e em um novo servidor Web de plataforma cruzada .NET chamado Kestrel (Microsoft.AspNet.Server.Kestrel).

A comunidade padrão Open Web Interface para .NET (OWIN) (owin.org) compartilha metas semelhantes de acoplamento fraco para aplicativos Web. O OWIN padroniza como aplicativos e servidores .NET devem conversar entre si. O ASP.NET 5 oferece suporte ao OWIN pelo pacote Microsoft.AspNet.Owin (bit.ly/15IQwA5). Você pode hospedar o ASP.NET 5 em um servidor Web baseado em OWIN (bit.ly/1DaU4FZ) e pode usar o middleware OWIN dentro do pipeline ASP.NET 5 (bit.ly/1EqmoIB).

O projeto Katana (katanaproject.codeplex.com) foi esforço inicial da Microsoft para implementar o suporte para OWIN e muitas das ideias e conceitos no ASP.NET 5 derivaram dele. O Katana tinha um modelo semelhante para a criação de um pipeline de middleware e para hospedagem em vários servidores. No entanto, ao contrário do Katana, que expôs as abstrações do OWIN de baixo nível diretamente para o desenvolvedor, o ASP.NET 5 preenche do OWIN para abstrações mais convenientes e amigáveis. Com um pouco mais de código, você ainda pode usar o middleware Katana no ASP.NET 5 usando a ponte OWIN (veja um exemplo de como fazer isso em bit.ly/1BpaXe2).

Conclusão

O tempo de execução do ASP.NET 5 foi criado desde o início para suporte de aplicativos Web de plataforma cruzada. O ASP.NET 5 tem uma arquitetura flexível e em camadas que pode ser executada no .NET Framework, .NET Core ou até mesmo de plataformas cruzadas no Mono (e no futuro também no .NET Core!). O novo modelo de hospedagem do ASP.NET 5 facilita criar aplicativos e hospedá-los no servidor Web de sua escolha. Todo o tempo de execução foi criado para oferecer suporte à injeção de dependência e ser fácil de configurar. Espero que você tenha gostado de aprender sobre o novo tempo de execução do ASP.NET 5! Seus comentários e contribuições são bem-vindos pelo nosso projeto GitHub em github.com/aspnet/home.


Daniel Roth é um gerente de programa sênior na equipe ASP.NET atualmente trabalhando em ASP.NET 5. Suas paixões incluem o desenvolvimento .NET e encantar os clientes, fazendo estruturas simples e fáceis de usar.

Agradecemos aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: Glenn Condron, David Fowler, Murat Girgin e Chris Ross