Migrando um projeto ASP.NET Core RC 1 para RC 2

Olá pessoal, tudo bem?

Recentemente fiz a migração do projeto que estou trabalhando atualmente na Lambda3 do ASP.NET Core RC 1 para RC 2. Foram feitas muitas mudanças significativas no framework, principalmente no ferramental do .NET Core.
Nesse post vou indicar as principais mudanças que você vai precisar fazer para realizar a migração e contar algumas experiências dessa transição.

.NET CLI

A principal alteração foi a introdução do .NET CLI, como dito pelo Giovanni Bassi aqui. Basicamente, ele substitui as três ferramentas que usávamos para buildar e executar nossa aplicação (DNX, DNVM e DNU).

O primeiro passo para a migração é instalar o .NET CLI usando o .NET SDK, disponível aqui. Instale também a última versão do NuGet Manager para o Visual Studio. Rode o comando dotnet na linha de comando para identificar se o .NET CLI foi instalado corretamente.

Feito isso, partimos para as mudanças no projeto.

global.json

Troque a versão do SDK de 1.0.0-rc1-update1 para 1.0.0-preview1-002702. É por esse arquivo que o Visual Studio determina qual ferramental será utilizado para restaurar pacotes, buildar, etc.

project.json

Esse arquivo foi o que sofreu mais alterações (e vai morrer em breve).

Primeiro, troque os nomes dos frameworks para o novo estilo. No meu caso, a mudança foi de dnx451 para net452. A lista completa dos frameworks disponíveis está aqui (ignore os que começam com dnx).

O elemento compilationOptions agora se chama buildOptions.

Troque o nome de todas as dependências que tenham Microsoft.AspNet.* para Microsoft.AspNetCore.*, assim como suas versões de rc1 para rc2.

Os elementos exclude e publishExclude foram substituídos pelo elemento publishOptions, onde você define os arquivos a serem incluídos na publicação ao invés do excluídos.

O elemento runtimeOptions foi criado para configuração do garbage collector.

Nos projetos de teste, caso seu framework for o xUnit, a dependência deve ser trocada de xunit.runner.dnx para dotnet-test-xunit. Também deve ser adicionado o elemento "testRunner" para indicar qual runner será usado para rodar os testes do projeto.

Por último, a principal mudança: o elemento commands não existe mais. No .NET CLI, ele foi substituído pelo elemento tools, que funciona de forma diferente.

Antes tínhamos dentro de commands vários “atalhos” para executar algumas dependências, como o servidor Kestrel, o Entity Framework, etc.

Agora, como tudo é simplesmente uma Console Application (até projetos web ASP.NET Core), você somente chama diretamente a sua aplicação ou alguma dependência que estiver em tools. Para subir sua aplicação ASP.NET Core, basta chamar dotnet run. Para rodar os testes, onde tínhamos um comando "test": "xunit.runner.dnx", agora basta chamar dotnet test.

Se você quiser desenvolver uma aplicação que seja invocável via tools, o executável precisa ter o nome no padrão dotnet-{nome}. Por exemplo, o nome do executável do DotNet Watcher é dotnet-watch.exe e você pode chamá-lo com o comando dotnet watch.

Mais detalhes sobre as atualizações no project.json podem ser vistas aqui. Coloquei nesse gist o project.json completo para referência.

launchSettings.json

Esse arquivo tem as configurações para o launch da sua aplicação. Normalmente, ele deveria ter um elemento web.

Troque todo esse elemento por esse:

WebApplication1 é o nome do seu projeto, o commandName com o valor Project indica que essa configuração será usada no dotnet run e a variável de ambiente Hosting:Environment foi trocada para ASPNETCORE_ENVIRONMENT.

appsettings.json

Nesse arquivo, apenas uma modificação: troque a configuração Logging:LogLevel:Default de Verbose por Debug:

xproj

O arquivo .xproj tem algumas referências ao DNX que você precisa alterar manualmente. Dê unload no seu projeto e faça as seguintes alterações no arquivo .xproj:

  • Substitua \DNX\Microsoft.DNX.Props por \DotNet\Microsoft.DotNet.Props
  • Em \DNX\Microsoft.DNX.targets, substitua DNX por DotNet.Web em projetos web ou por DotNet em projetos Class Library/Console Application
  • Substitua todo o elemento BaseIntermediateOutputPath por <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
  • Substitua todo o elemento OutputPath por <OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
  • Adicione o seguinte elemento depois de OutputPath: <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>

Coloquei nesse gist o .xproj completo de um projeto web para referência.

Método Main de projetos web

Antes, o entry point do nosso projeto web era algo parecido com isso na classe Startup:

Agora temos um pouco mais de poder nesse momento. Troque todo o método Main pelo abaixo:

O template do Visual Studio cria esse método numa classe separada chamada Program, mas isso não é necessário.

Startup.cs

Ao construir as configurações do seu projeto usando a classe ConfigurationBuilder, agora é necessário setar o BasePath para o runtime encontrar suas configurações:

Se você usava o middleware app.UseIISPlatformHandler(), pode removê-lo. Agora ele está configurado no método Main.

web.config

O arquivo web.config deve ser criado para a configuração do handler AspNetCoreModule, um novo módulo do IIS para redirecionar os requests para o Kestrel:

Trocas de namespaces

Basicamente, todos os namespaces que começavam com Microsoft.AspNet.* foram renomeados para Microsoft.AspNetCore.*. As principais trocas são:

  • Microsoft.AspNet.Authorization > Microsoft.AspNetCore.Authorization
  • Microsoft.AspNet.Mvc > Microsoft.AspNetCore.Mvc
  • Microsoft.AspNet.Hosting > Microsoft.AspNetCore.Hosting
  • Microsoft.AspNet.Http > Microsoft.AspNetCore.Http
  • Microsoft.Extensions.OptionsModel > Microsoft.Extensions.Options

MVC

Os seguintes métodos da classe Controller foram renomeados:

  • HttpUnauthorized > Unauthorized
  • HttpNotFound > NotFound
  • HttpBadRequest > BadRequest

Experiências

Realizar a conversão deve ser algo simples para a maioria dos projetos. Algumas APIs que não estão listadas acima foram modificadas, mas nada muito relevante.

Não deixe de olhar o guia oficial de migração. Veja também esse post do Shawn Wildermuth, principalmente se você também precisa migrar o Entity Framework Core e o Identity.

A unificação dos comandos dnx, dnvm e dnu em dotnet facilitou um pouco o dia-a-dia. Porém, algumas coisas mudaram para pior.

O dotnet watch está praticamente inutilizável. Enquanto o DNX usava o Roslyn para fazer a compilação (gerando assemblies in-memory), o DotNet Watcher recompila os assemblies fisicamente, o que aumentou drasticamente o tempo de reload da aplicação.

A substituição de commands por tools no project.json também mudou bastante a forma como trabalhamos com algumas dependências. No meu caso, por exemplo, tive bastante dificuldade para conseguir chamar o Fluent Migrator pois ele não tem ainda suporte ao .NET CLI (estão trabalhando nisso, na verdade).

Por fim, caso tenha alguma dúvida, você pode tirá-la no Slack do ASP.NET Core. Tem bastante gente fazendo a migração e você pode acompanhar as novidades praticamente em tempo real, já que vários desenvolvedores do time do .NET Core estão lá.


É isso pessoal. Obrigado pela leitura e vamos esperar pelo RTM, que deve sair no fim desse mês.

Até mais!