Maio de 2017

Volume 32 - Número 5

Cutting Edge - ASP.NET Core para Desenvolvedores ASP.NET

De Dino Esposito | Maio de 2017

Dino EspositoGrande parte do burburinho sobre o ASP.NET Core se concentra na experiência multiplataforma que ele habilita. Embora isso seja uma grande realização, não será necessariamente um item a mais se você for um usuário normal do ASP.NET com uma grande base de código .NET 4.x e não tem planos de deixar o ambiente conhecido do IIS e do Windows. Nesse caso, qual é a proposta de valor do ASP.NET Core para esse desenvolvedor de ASP.NET?

A princípio, a nova plataforma pode parecer completamente diferente, como se alguém tivesse movido seu queijo para outro lugar durante a noite. O ASP.NET Core é novo, recriado desde o início, de acordo com práticas mais modernos. Isso pode ou não aumentar seu poder de programação e sua capacidade de tratar das preocupações dos clientes. Ninguém pode responder verdadeiramente a essa pergunta em seu nome. Essa coluna tenta abrir o caminho de qualquer hype, benchmark e foco de tecnologia e ir direto à substância. Se você já estiver acostumado à plataforma atual, quais aspectos do ASP.NET Core podem chamar a sua atenção?

Práticas comuns projetadas na estrutura

Quando os membros da equipe do ASP.NET projetaram a estrutura original do ASP.NET, pegaram as melhores práticas do Active Server Pages e as integraram a uma nova estrutura. Ao fazer isso, eles também introduziram muitas coisas novas, como código compilado e gerenciado, postbacks automáticos e controles de servidor. O ASP.NET Core segue o mesmo padrão evolutivo.

As práticas de desenvolvimento comuns, como o carregamento inicial de dados de configuração, a injeção de dependência, os pacotes NuGet, a autenticação baseada em declarações e os aprimoramentos do Razor, são recursos nativos da nova estrutura. A nova estrutura tam´bem tem um procedimento de inicialização diferente, um middleware de solicitação-resposta muito mais modular e até mesmo uma instrutura levemente mais flexível para a definição de controladores e exibições. O ASP.NET Core também é uma estrutura de plataforma cruzada e permite que você desenvolva aplicativos e os hospede no Windows, bem como no macOS e no Linux. De certa forma, o ASP.NET força você a escrever um código melhor, onde alguns poucos níveis adicionais de separação de preocupações são impostos por padrão. No entanto, não é nada que você não possa já ter obtido com disciplina.

Para qualquer forma de desenvolvimento raiz, o ASP.NET Core é uma excelente opção. Ainda assim, como é uma estrutura muito nova, ainda tem alguns custos iniciais inevitáveis: Todos na equipe devem se tornar proficientes nele. Além disso, todos devem ser, ou se tornar, proficientes no modelo de aplicativo MVC (Modelo-Exibição-Controlador). Nem tudo o que você pode rotular como desenvolvimento de raiz é completamente novo. A reutilização de trechos de código existente, ou pelo menos das habilidades existentes (ou seja, as habilidades de acesso a dados ou de segurança), é desejável. O quanto disso é realmente possível? Para tratar desse ponto, o ASP.NET Core vem em dois tipos.

Tipos do ASP.NET Core

Na Figura 1, você vê a caixa de diálogo do Visual Studio 2015 para criar um novo projeto. (É essencialmente o mesmo no Visual Studio 2017).

Criação de um novo projeto ASP.NET Core no Visual Studio
Figura 1 Criação de um novo projeto ASP.NET Core no Visual Studio

O primeiro modelo criará um projeto não Core clássico. Os dois outros modelos podem criar um projeto do ASP.NET Core para um .NET Framework diferente. É a primeira encruzilhada que você enfrenta em sua jornada pelo território inexplorado do ASP.NET Core.

Optar pelo .NET Framework completo oferece a você acesso a qualquer biblioteca de classes do .NET, mas limita a hospedagem ao Windows e ao IIS. A Figura 2 resume as diferenças.

Figura 2 Diferenças fundamentais entre os tipos de ASP.NET Core

Estrutura Fatos
.NET Framework

Somente ASP.NET MVC; nenhum WebForms

Novo ambiente de tempo de execução e API de programação

Todas as bibliotecas destinadas à versão selecionada do .NET Framework 

Somente hospedagem do IIS

.NET Core

Somente ASP.NET MVC; nenhum WebForms

Novo ambiente de tempo de execução e API de programação

Somente as bibliotecas do .NET Core

Hospedagem entre plataformas

Independentemente da opção do .NET Framework, adotar o ASP.NET Core expõe seu código a um novo ambiente de tempo de execução que unifica o tempo de execução MVC com base no system.web do tempo de execução da API Web inspirado pelos princípios de OWIN.

Separação com o IIS

Nos últimos anos, a estrutura da API Web tentou tratar da alta demanda de thin servers capazes de expor uma interface RESTful para qualquer cliente habilitado para HTTP. A API Web separou o modelo de aplicativo do servidor Web e levou à especificação OWIN, especificamente um conjunto de regras para a interoperação de servidores e aplicativos Web. No entanto, a API Web precisa de um host e, quando hospedada no contexto de um aplicativo ASP.NET, ela simplesmente adiciona outro ambiente de tempo de execução do volume de memória. Isso acontece ao mesmo tempo em que o setor está se movimentando em direção à Web supersimples. Um servidor Web mínimo supersimples é um ponto de extremidade HTTP para obter conteúdo o mais rápido possível, simplesmente uma fina camada HTTP em torno de alguma lógica de negócios. Tudo o que um servidor supersimples precisa fazer é processar a solicitação adequadamente e retornar uma resposta sem sobrecarga além da lógica de negócios.

Embora personalizável até certo ponto, o ambiente de tempo de execução atual do ASP.NET não foi projetado para atender a cenários semelhantes. A separação do ambiente ASP.NET do ambiente de hospedagem é uma mudança fundamental encontrada no ASP.NET Core e o motivo de muitas alterações subsequentes no nível do aplicativo.

Inicialização de um aplicativo

Depois de criar um novo projeto, a primeira coisa que você observa é a falta de um arquivo global.asx e a presença de um arquivo program.cs. Por mais chocante que possa parecer, um aplicativo ASP.NET Core é um aplicativo de console simples iniciado pela ferramenta de driver dotnet (bit.ly/2mLyHxe).

A ferramenta dotnet é a chave para o suporte multiplataforma. Assim que a ferramenta de linha de comando (e a estrutura do .NET Core) está disponível para uma nova plataforma, a hospedagem se reduz à conexão do servidor Web à ferramenta. No IIS, a publicação é realizada por meio de um módulo ad hoc, o pacote Windows Server Hosting do .NET Core (bit.ly/2i9cF4d). No Apache, em um servidor Ubuntu, isso é obtido por meio de um arquivo de configuração. Veja um exemplo em bit.ly/2lSd0aF.

O servidor Web real funciona como um proxy reverso e se comunica com o aplicativo de console sobre uma porta configurada. O aplicativo de console é criado em torno de outro servidor Web mais simples que recebe solicitações e dispara o pipeline de aplicativo interno para processá-las. O código a seguir cumpre a função:

var host = new WebHostBuilder()
  .UseKestrel()
  .UseContentRoot(Directory.GetCurrentDirectory())
  .UseIISIntegration()
  .UseStartup<Startup>()
  .Build();
Host.Run();

Kestrel é o nome do servidor Web ASP.NET que recebe solicitações de entrada e as processa por meio do pipeline. A chamada ao módulo de Integração do IIS no trecho de código só será necessária se você hospedar sob o IIS.

Ter um proxy reverso em torno do aplicativo ASP.NET é recomendável principalmente por motivos de segurança, já que o servidor Web interno Kestrel não inclui (no momento) filtros para impedir algo como ataques DDos (ataque de negação de serviço distribuído). De um ponto de vista puramente funcional, você não precisa estritamente de um proxy reverso habilitado.

Como mencionado, não há mais um arquivo global.asax em um aplicativo ASP.NET Core e a função do arquivo web.config foi tremendamente diminuída. Na verdade, ela só serve à finalidade de permitir que o IIS execute alguns trabalhos em nome do aplicativo, como servir algumas páginas de erro estáticas. O principal, como a configuração de tratamento de erros, a geração de logs, a autenticação e o armazenamento de dados globais de configuração é concluído por meio de uam nova API orquestrada da classe startup.

A classe Startup

A classe startup contém pelo menos dois métodos que o host chamará durante a fase de inicialização:

public class Startup
{
  public void ConfigureServices(IServiceCollection services)
  public void Configure(IApplicationBuilder app)
  {
    app.Run(async (context) =>
    {
      await context.Response.WriteAsync(DateTime.Now)
    });
  }
}

Por meio do método ConfigureServices, você declara os serviços do sistema que o aplicativo usará. Tecnicamente, o método é opcional, mas eu diria que ele é necessário em qualquer cenário real. Para um desenvolvedor do ASP.NET tradicional, pode ser chocante descobrir que mesmo o uso modelo de aplicativo MVC deve ser explicitamente declarado e habilitado. Entretanto, esse fato dá a medida da seriedade da modularização no ASP.NET Core:

public void ConfigureServices(IServiceCollection services)
{
  services.AddMvc();
}

No método Configure, você configura todos os serviços solicitados anteriormente. Por exemplo, se você tiver solicitado o serviço ASP.NET MVC, então pode especificar a lista de rotas com suporte em Configure. Observe que você também precisa de uma chamada explícita para habilitar o servidor Web interno para servir arquivos estáticos, incluindo arquivos comuns, como jQuery e Bootstrap:

public void Configure(IServiceCollection services)
{
  app.UseStaticFiles();
  app.UseMvcWithDefaultRoute();
  ...
}

A classe startup também é o local onde você configura o middleware do aplicativo. O middleware é um novo termo com uma sobreposição conceitual significativa com os módulos HTTP do ASP.NET atual. No ASP.NET Core, o middleware funciona como mostrado na Figura 3.

O middleware do ASP.NET Core
Figura 3 O middleware do ASP.NET Core

Você pode registrar trechos de código com uma chance de pré e pós-processar qualquer solicitação de entrada, o que significa que cada middleware pode registrar código executado antes ou depois do término do middleware — o método Run no método Configure da classe startup. O modelo geral é semelhante ao antigo modelo ISAPI do IIS. Veja um middleware de exemplo:

app.Use(async (httpContext, next) =>
{
  // Pre-process the request
  // Yield to the next middleware
  await next();
  // Post-process the request   
});

Um middleware é uma função que obtém um objeto HttpContext e retorna uma Task. A lista de componentes de middleware termina com o método Run. Em comparação ao pipeline atual do ASP.NET, o pipeline do ASP.NET Core é bidirecional e totalmente personalizável. Além disso, ele está vazio por padrão.

Serviços Web super simples

Sabe-se que sem um método Run no pipeline, nenhuma solicitação produzirá uma resposta. Ao mesmo tempo, um método Run é tudo o que você precisa para produzir uma resposta. Isso mostra como o pipeline pode ser curto em um aplicativo ASP.NET Core. Em WebForms e MVC do ASP.NET, muito acontece antes que seu próprio código seja executado para cada solicitação. A resolução de um método de controlador, por exemplo, é um procedimento longo que envolve um subsistema inteiro centrado no invocador da ação. Em vez disso, o método Run é uma chamada direta que segue imediatamente o recebimento da solicitação.

Suponha que você queira criar um servidor de arquivos que tenha uma lista de arquivos de imagem (digamos, bandeiras) e retorne uma imagem de um tamanho adequado com base em alguns parâmetros de entrada ou propriedades do dispositivo. No ASP.NET de hoje, a opção mais rápida é provavelmente escrever um manipulador de HTTP ad hoc — uma classe criada pela implementação da interface IHttpHandler mapeada para uma rota de URL fixa. Um manipulador de HTTP é mais rápido do que um ponto de extremidade ASPX e uma ação de controlador MVC por causa do pipeline mais estreito. Ele também tem uma superfície menor do que um ponto de extremidade de API Web, porque não exige um segundo pipeline OWIN por cima do pipeline básico do ASP.NET. (Esse não será o caso quando uma solução de API Web for hospedada fora do IIS).

No ASP.NET Core, a criação de um servidor de arquivos efetivo é mais fácil e mais efetivo do que nunca. Tudo o que você tem de fazer é criar a lógica adicional (ou seja, redimensão/recuperação) e associá-la ao método Run do método ConfigureServices:

public void Configure(IApplicationBuilder app)
{
  app.Run(async (context) =>
  {
    var code = context.Request.Query["c"];
    var size = context.Request.Query["s"];
    var file = FindAndResizeFlag(code, file);
    await context.Response.SendFileAsync(file);
  });
}

No exemplo, eu suponho ter alguma lógica personalizada para encontrar um nome de arquivo de servidor que corresponda a parâmetros fornecidos e então eu o sirvo de volta ao chamador por meio do objeto Response. Nenhum outro código, visível ou invisível, é necessário. Francamente, poderia ser mais fácil do que isso.

Sempre que você tiver um pressentimento sobre o ASP.NET Core, gostando ou não dele, o ASP.NET Core oferece um recurso exclusivo que não é encontrado em qualquer plataforma ASP.NET: a criação de serviços Web mínimos supersimples. Ao mesmo tempo, a mesma infraestrutura que permite a você criar serviços Web supersimples é a melhor garantia de que qualquer solicitação pode ser servida com o mínimo de sobrecarga que seja legitimamente possível.

Conclusão

Para ser um desenvolvedor de ASP.NET Core produtivo, você só precisará conhecer um modelo de aplicativo mais moderno do que o WebForms: isso significa o ASP.NET MVC ou o modelo de aplicativo de página única. Apesar das aparências, a maioria das alterações inovadoras do ASP.NET Core encontra-se no ambiente de tempo de execução. Compreender o modelo de hospedagem e o middleware é suficiente para compreender a nova plataforma. No fim, ainda se trata de criar controladores e de renderizar exibições do Razor. Algumas coisas comuns, como autenticação, registro em log e configuração, precisarão de uma API diferente, mas é rápido aprender sobre elas. Do meu ponto de vista, o desafio é encontrar o que é útil para você.


Dino Espositoé o autor de “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2014) e de “Modern Web Applications” (Microsoft Press, 2016). Evangelista técnico das plataformas .NET e Android no JetBrains e palestrante frequente em eventos do setor no mundo todo, Esposito compartilha sua visão de software em software2cents.wordpress.com e, no Twitter, em @despos.

Agradecemos aos seguintes especialistas técnicos da Microsoft pela revisão deste artigo: James McCaffrey