Migrar do ASP.NET Core 2.2 para o 3.0

Por Scott Addie e Rick Anderson

Este artigo explica como atualizar um projeto do ASP.NET Core 2.2 existente para ASP.NET Core 3.0. Pode ser útil criar um novo projeto do ASP.NET Core 3.0 para:

  • Compare com o código do ASP.NET Core 2.2.
  • Copie as alterações relevantes para o projeto do ASP.NET Core 3.0.

Pré-requisitos

Atualizar a versão do SDK do .NET Core no global.json

Se a solução depender de um arquivo global.json para direcionar uma versão específica do SDK do .NET Core, atualize sua propriedade version para a versão 3.0 instalada no computador:

{
  "sdk": {
    "version": "3.0.100"
  }
}

Atualizar o arquivo de projeto

Atualizar a Estrutura de Destino

O ASP.NET Core 3.0 e posterior são executados somente no .NET Core. Configure o TFM (Moniker da Estrutura de Destino) como netcoreapp3.0:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

Remover referências de pacote obsoletas

Um grande número de pacotes NuGet não são produzidos para ASP.NET Core 3.0. Essas referências de pacote devem ser removidas do arquivo de projeto. Considere o seguinte arquivo de projeto para um aplicativo Web do ASP.NET Core 2.2:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App"/>
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
  </ItemGroup>

</Project>

O arquivo de projeto atualizado para ASP.NET Core 3.0:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>

O arquivo de projeto do ASP.NET Core 3.0 atualizado:

  • No <PropertyGroup>:

    • Atualiza o TFM para netcoreapp3.0
    • Remove o elemento <AspNetCoreHostingModel>. Para obter mais informações, confira Modelo de hospedagem em processo neste documento.
  • No <ItemGroup>:

    • Microsoft.AspNetCore.App foi removido. Para obter mais informações, confira Referência de estrutura neste documento.
    • Microsoft.AspNetCore.Razor.Design é removido e na lista a seguir de pacotes que não estão mais sendo produzidos.

Para ver a lista completa de pacotes que não são mais produzidos, selecione a lista de expansão a seguir:

Clique para expandir a lista de pacotes que não estão mais sendo produzidos
  • Microsoft.AspNetCore
  • Microsoft.AspNetCore.All
  • Microsoft.AspNetCore.App
  • Microsoft.AspNetCore.Antiforgery
  • Microsoft.AspNetCore.Authentication
  • Microsoft.AspNetCore.Authentication.Abstractions
  • Microsoft.AspNetCore.Authentication.Cookies
  • Microsoft.AspNetCore.Authentication.Core
  • Microsoft.AspNetCore.Authentication.OAuth
  • Microsoft.AspNetCore.Authorization.Policy
  • Microsoft.AspNetCore.CookiePolicy
  • Microsoft.AspNetCore.Cors
  • Microsoft.AspNetCore.Diagnostics
  • Microsoft.AspNetCore.Diagnostics.HealthChecks
  • Microsoft.AspNetCore.HostFiltering
  • Microsoft.AspNetCore.Hosting
  • Microsoft.AspNetCore.Hosting.Abstractions
  • Microsoft.AspNetCore.Hosting.Server.Abstractions
  • Microsoft.AspNetCore.Http
  • Microsoft.AspNetCore.Http.Abstractions
  • Microsoft.AspNetCore.Http.Connections
  • Microsoft.AspNetCore.Http.Extensions
  • Microsoft.AspNetCore.HttpOverrides
  • Microsoft.AspNetCore.HttpsPolicy
  • Microsoft.AspNetCore.Identity
  • Microsoft.AspNetCore.Localization
  • Microsoft.AspNetCore.Localization.Routing
  • Microsoft.AspNetCore.Mvc
  • Microsoft.AspNetCore.Mvc.Abstractions
  • Microsoft.AspNetCore.Mvc.Analyzers
  • Microsoft.AspNetCore.Mvc.ApiExplorer
  • Microsoft.AspNetCore.Mvc.Api.Analyzers
  • Microsoft.AspNetCore.Mvc.Core
  • Microsoft.AspNetCore.Mvc.Cors
  • Microsoft.AspNetCore.Mvc.DataAnnotations
  • Microsoft.AspNetCore.Mvc.Formatters.Json
  • Microsoft.AspNetCore.Mvc.Formatters.Xml
  • Microsoft.AspNetCore.Mvc.Localization
  • Microsoft.AspNetCore.Mvc.Razor
  • Microsoft.AspNetCore.Mvc.Razor.ViewCompilation
  • Microsoft.AspNetCore.Mvc.RazorPages
  • Microsoft.AspNetCore.Mvc.TagHelpers
  • Microsoft.AspNetCore.Mvc.ViewFeatures
  • Microsoft.AspNetCore.Razor
  • Microsoft.AspNetCore.Razor.Runtime
  • Microsoft.AspNetCore.Razor.Design
  • Microsoft.AspNetCore.ResponseCaching
  • Microsoft.AspNetCore.ResponseCaching.Abstractions
  • Microsoft.AspNetCore.ResponseCompression
  • Microsoft.AspNetCore.Rewrite
  • Microsoft.AspNetCore.Routing
  • Microsoft.AspNetCore.Routing.Abstractions
  • Microsoft.AspNetCore.Server.HttpSys
  • Microsoft.AspNetCore.Server.IIS
  • Microsoft.AspNetCore.Server.IISIntegration
  • Microsoft.AspNetCore.Server.Kestrel
  • Microsoft.AspNetCore.Server.Kestrel.Core
  • Microsoft.AspNetCore.Server.Kestrel.Https
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
  • Microsoft.AspNetCore.Session
  • Microsoft.AspNetCore.SignalR
  • Microsoft.AspNetCore.SignalR.Core
  • Microsoft.AspNetCore.StaticFiles
  • Microsoft.AspNetCore.WebSockets
  • Microsoft.AspNetCore.WebUtilities
  • Microsoft.Net.Http.Headers

Analisar as alterações interruptivas

Analisar as alterações interruptivas

Referência de estrutura

Os recursos do ASP.NET Core que estavam disponíveis por meio de um dos pacotes listados acima estão disponíveis como parte da estrutura compartilhada do Microsoft.AspNetCore.App. A estrutura compartilhada é o conjunto de assemblies (arquivos .dll) que estão instalados no computador e inclui um componente de runtime e um pacote de destino. Saiba mais em A estrutura compartilhada.

  • Projetos direcionados ao SDK Microsoft.NET.Sdk.Web referenciam a estrutura Microsoft.AspNetCore.App implicitamente.

    Não são necessárias referências adicionais para esses projetos:

    <Project Sdk="Microsoft.NET.Sdk.Web">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
        ...
    </Project>
    
  • Projetos direcionados ao SDK Microsoft.NET.Sdk ou Microsoft.NET.Sdk.Razor devem adicionar um FrameworkReference explícito a Microsoft.AspNetCore.App:

    <Project Sdk="Microsoft.NET.Sdk.Razor">
      <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <FrameworkReference Include="Microsoft.AspNetCore.App" />
      </ItemGroup>
        ...
    </Project>
    

Builds dependentes de estrutura usando o Docker

Os builds dependentes de estrutura de aplicativos de console que usam um pacote que depende da estrutura compartilhada do ASP.NET Core podem fornecer o seguinte erro de runtime:

It was not possible to find any compatible framework version
The specified framework 'Microsoft.AspNetCore.App', version '3.0.0' was not found.
  - No frameworks were found.

Microsoft.AspNetCore.App é a estrutura compartilhada que contém o runtime do ASP.NET Core e está presente apenas na imagem dotnet/core/aspnet do Docker. O SDK 3.0 reduz o tamanho de builds dependentes de estrutura que usam o ASP.NET Core não incluindo cópias duplicadas de bibliotecas disponíveis na estrutura compartilhada. Essa é uma economia potencial de até 18 MB, mas requer que o runtime do ASP.NET Core esteja presente/instalado para executar o aplicativo.

Para determinar se o aplicativo tem uma dependência (direta ou indireta) na estrutura compartilhada do ASP.NET Core, examine o arquivo runtimeconfig.json gerado durante um build/publicação do seu aplicativo. O seguinte JSarquivo ON mostra uma dependência na estrutura compartilhada do ASP.NET Core:

{
  "runtimeOptions": {
    "tfm": "netcoreapp3.0",
    "framework": {
      "name": "Microsoft.AspNetCore.App",
      "version": "3.0.0"
    },
    "configProperties": {
      "System.GC.Server": true
    }
  }
}

Se o aplicativo estiver usando o Docker, use uma imagem base que inclui o ASP.NET Core 3.0. Por exemplo, docker pull mcr.microsoft.com/dotnet/core/aspnet:3.0.

Adicionar referências de pacote para assemblies removidos

O ASP.NET Core 3.0 remove alguns assemblies que anteriormente faziam parte da referência do pacote Microsoft.AspNetCore.App. Para visualizar quais assemblies foram removidos, compare as duas pastas de estrutura compartilhada. Por exemplo, uma comparação das versões 2.2.7 e 3.0.0:

shared framework assemblies comparison

Para continuar usando os recursos fornecidos pelos assemblies removidos, faça referência às versões 3.0 dos pacotes correspondentes:

Alterações de inicialização

A imagem a seguir mostra as linhas excluídas e alteradas em um aplicativo Web de páginas Razor do ASP.NET Core 2.2:

the deleted and changed lines in an ASP.NET Core 2.2 Razor Web app

Na imagem anterior, o código excluído é mostrado em vermelho. O código excluído não mostra o código de opções cookie, que foi excluído antes de comparar os arquivos.

A imagem a seguir mostra as linhas adicionadas e alteradas em um aplicativo Web de páginas Razor do ASP.NET Core 3.0:

the added and changed lines in an ASP.NET Core 3.0 Razor Web app

Na imagem anterior, o código adicionado é mostrado em verde. Para obter informações sobre as seguintes alterações:

Suporte ao analisador

Os projetos direcionados a Microsoft.NET.Sdk.Web implicitamente referenciam analisadores enviados anteriormente como parte do pacote Microsoft.AspNetCore.Mvc.Analyzers . Nenhuma referência adicional é necessária para habilitá-los.

Se seu aplicativo usa analisadores de API enviados anteriormente usando o pacote Microsoft.AspNetCore.Mvc.Api.Analyzers, edite o arquivo de projeto para fazer referência aos analisadores enviados como parte do SDK Web do .NET Core:

<Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
        <IncludeOpenAPIAnalyzers>true</IncludeOpenAPIAnalyzers>
    </PropertyGroup>

    ...
</Project>

Biblioteca de Classes da Razor

Os projetos da Biblioteca de Classes da Razor que fornecem componentes de interface do usuário para MVC devem definir a propriedade AddRazorSupportForMvc no arquivo de projeto:

<PropertyGroup>
  <AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>

Modelo de hospedagem em processo

Os projetos são padrão para o modelo de hospedagem em processo no ASP.NET Core 3.0 e posterior. Opcionalmente, você poderá remover a propriedade <AspNetCoreHostingModel> no arquivo de projeto se seu valor for InProcess.

Kestrel

Configuração

Migrar a configuração Kestrel para o construtor de host da Web fornecido por ConfigureWebHostDefaults (Program.cs):

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

Se o aplicativo criar o host manualmente com ConfigureWebHost em vez de ConfigureWebHostDefaults, chame UseKestrel no construtor de host da Web:

public static void Main(string[] args)
{
    var host = new HostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder.UseKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseIISIntegration()
            .UseStartup<Startup>();
        })
        .Build();

    host.Run();
}

O Middleware de Conexão substitui os Adaptadores de Conexão

Os adaptadores de Conexão (Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal.IConnectionAdapter) foram removidos de Kestrel. Substitua Adaptadores de Conexão pelo Middleware de Conexão. O Middleware de Conexão é semelhante ao Middleware HTTP no pipeline do ASP.NET Core, mas para conexões de nível inferior. HTTPS e registro em log de conexão:

  • Os Adaptadores de Conexão foram movidos para o Middleware de Conexão.
  • Esses métodos de extensão funcionam como em versões anteriores do ASP.NET Core.

Para obter mais informações, confira o exemplo TlsFilterConnectionHandler na seção ListenOptions.Protocols do artigo Kestrel.

Abstrações de transporte movidas e tornadas públicas

A camada de transporte Kestrel foi exposta como uma interface pública no Connections.Abstractions. Como parte dessas atualizações:

  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions e tipos associados foram removidos.
  • NoDelay foi movido de ListenOptions para as opções de transporte.
  • Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal.SchedulingMode foi removido de KestrelServerOptions.

Para obter mais informações, confira os seguintes recursos do GitHub:

Cabeçalhos de trailer de solicitação do Kestrel

Para aplicativos direcionados a versões anteriores do ASP.NET Core:

  • Kestrel adiciona cabeçalhos de trailer em partes HTTP/1.1 à coleção de cabeçalhos de solicitação.
  • Os trailers ficam disponíveis depois que o corpo da solicitação é lido até o final.

Isso causa algumas preocupações sobre ambiguidade entre cabeçalhos e trailers, portanto, os trailers foram movidos para uma nova coleção (RequestTrailerExtensions) na 3.0.

Os trailers de solicitação HTTP/2 são:

  • Não disponível no ASP.NET Core 2.2.
  • Disponível em 3.0 como RequestTrailerExtensions.

Novos métodos de extensão de solicitação estão presentes para acessar esses trailers. Assim como no HTTP/1.1, os trailers ficam disponíveis depois que o corpo da solicitação é lido até o final.

Para a versão 3.0, os seguintes métodos RequestTrailerExtensions estão disponíveis:

  • GetDeclaredTrailers: obtém o cabeçalho Trailer da solicitação que lista quais trailers são esperados após o corpo.
  • SupportsTrailers: indica se a solicitação dá suporte ao recebimento de cabeçalhos de trailer.
  • CheckTrailersAvailable: verifica se a solicitação dá suporte a trailers e se eles estão disponíveis para leitura. Esta verificação não pressupõe que haja trailers para ler. Talvez não haja trailers para ler, mesmo que true seja retornado por esse método.
  • GetTrailer: obtém o cabeçalho de trailer solicitado da resposta. Verifique SupportsTrailers antes de chamar GetTrailer ou um NotSupportedException pode ocorrer se a solicitação não dá suporte a cabeçalhos de trailer.

Para obter mais informações, confira Colocar trailers de solicitação em uma coleção separada (dotnet/AspNetCore #10410).

AllowSynchronousIO desabilitado

AllowSynchronousIO habilita ou desabilita as APIs de E/S síncronas, como HttpRequest.Body.Read, HttpResponse.Body.Write e Stream.Flush. Essas APIs são uma fonte de falta de threads que leva a falhas no aplicativo. No 3.0, AllowSynchronousIO está desabilitado por padrão. Para obter mais informações, confira a seção E/S síncrona no artigo Kestrel.

Se a E/S síncrona for necessária, ela poderá ser habilitada configurando a opção AllowSynchronousIO no servidor que está sendo usado (ao chamar ConfigureKestrel, por exemplo, se estiver usando Kestrel). Observe que os servidores (Kestrel, HttpSys, TestServer etc.) têm sua própria opção AllowSynchronousIO que não afetará outros servidores. A E/S síncrona pode ser habilitada para todos os servidores por solicitação usando a opção IHttpBodyControlFeature.AllowSynchronousIO :

var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();

if (syncIOFeature != null)
{
    syncIOFeature.AllowSynchronousIO = true;
}

Se você tiver problemas com implementações TextWriter ou outros fluxos que chamam APIs síncronas em Descartar, chame a nova API DisposeAsync.

Para obter mais informações, confira [Comunicado] AllowSynchronousIO desabilitado em todos os servidores (dotnet/AspNetCore #7644).

Buffer do formatador de saída

Os formatadores de saída baseados em Newtonsoft.Json, XmlSerializer e DataContractSerializer dão suporte apenas à serialização síncrona. Para permitir que esses formatadores funcionem com as restrições AllowSynchronousIO do servidor, o MVC armazena em buffer a saída desses formatadores antes de gravar em disco. Como resultado do buffer, o MVC incluirá o cabeçalho Content-Length ao responder usando esses formatadores.

System.Text.Json dá suporte à serialização assíncrona e, consequentemente, o formatador baseado em System.Text.Json não armazena em buffer. Considere usar esse formatador para melhorar o desempenho.

Para desabilitar o buffer, os aplicativos podem configurar SuppressOutputFormatterBuffering em sua inicialização:

services.AddControllers(options => options.SuppressOutputFormatterBuffering = true)

Observe que isso pode fazer com que o aplicativo gere uma exceção de runtime se AllowSynchronousIO também não estiver configurado.

Assembly Microsoft.AspNetCore.Server.Kestrel.Https removido

No ASP.NET Core 2.1, o conteúdo de Microsoft.AspNetCore.Server.Kestrel.Https.dll foram movidos para Microsoft.AspNetCore.Server.Kestrel.Core.dll. Esta foi uma atualização ininterrupta usando os atributos TypeForwardedTo. Para 3.0, o assembly Microsoft.AspNetCore.Server.Kestrel.Https.dll vazio e o pacote NuGet foram removidos.

As bibliotecas que fazem referência ao Microsoft.AspNetCore.Server.Kestrel.Https devem atualizar as dependências do ASP.NET Core para a versão 2.1 ou posterior.

Os aplicativos e bibliotecas destinados ao ASP.NET Core 2.1 ou posterior devem remover todas as referências diretas ao pacote Microsoft.AspNetCore.Server.Kestrel.Https.

Suporte ao Newtonsoft.Json (Json.NET)

Como parte do trabalho para melhorar a estrutura compartilhada do ASP.NET Core, o Newtonsoft.Json (Json.NET) foi removido da estrutura compartilhada do ASP.NET Core.

O serializador JSON padrão para ASP.NET Core agora é System.Text.Json, que é novo no .NET Core 3.0. Considere usar System.Text.Json quando possível. É de alto desempenho e não requer uma dependência de biblioteca adicional. No entanto, como System.Text.Json é novo, atualmente pode estar faltando alguns recursos que seu aplicativo precisa. Para obter mais informações, confira Como migrar do Newtonsoft.Json para o System.Text.Json.

Usar Newtonsoft.Json em um projeto SignalR do ASP.NET Core 3.0

  • Instale o pacote NuGet Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson.

  • No cliente, encadeie uma chamada de método AddNewtonsoftJsonProtocol para a instância HubConnectionBuilder:

    new HubConnectionBuilder()
        .WithUrl("/chathub")
        .AddNewtonsoftJsonProtocol(...)
        .Build();
    
  • No servidor, encadeie uma chamada de método AddNewtonsoftJsonProtocol para a chamada de método AddSignalR em Startup.ConfigureServices:

    services.AddSignalR()
        .AddNewtonsoftJsonProtocol(...);
    

Usar Newtonsoft.Json em um projeto do ASP.NET Core 3.0 MVC

  • Instale o pacote Microsoft.AspNetCore.Mvc.NewtonsoftJson.

  • Atualize Startup.ConfigureServices para chamar AddNewtonsoftJson.

    services.AddMvc()
        .AddNewtonsoftJson();
    

    AddNewtonsoftJson é compatível com os novos métodos de registro de serviço MVC:

    • AddRazorPages
    • AddControllersWithViews
    • AddControllers
    services.AddControllers()
        .AddNewtonsoftJson();
    

    As configurações Newtonsoft.Json podem ser definidas na chamada para AddNewtonsoftJson:

    services.AddMvc()
        .AddNewtonsoftJson(options =>
               options.SerializerSettings.ContractResolver =
                  new CamelCasePropertyNamesContractResolver());
    

    Observação: se o método AddNewtonsoftJson não estiver disponível, verifique se você instalou o pacote Microsoft.AspNetCore.Mvc.NewtonsoftJson. Um erro comum é instalar o pacote Newtonsoft.Json em vez do pacote Microsoft.AspNetCore.Mvc.NewtonsoftJson.

Para obter mais informações, confira Adicionar suporte ao JSformato ON baseado em Newtonsoft.Json.

Registro do serviço MVC

O ASP.NET Core 3.0 adiciona novas opções para registrar cenários de MVC dentro de Startup.ConfigureServices.

Três novos métodos de extensão de nível superior relacionados a cenários de MVC em IServiceCollection estão disponíveis. Os modelos usam esses novos métodos em vez de AddMvc. No entanto, AddMvc continua a se comportar como nas versões anteriores.

O exemplo a seguir adiciona suporte para controladores e recursos relacionados à API, mas não para exibições ou páginas. O modelo de API usa este código:

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

O exemplo a seguir adiciona suporte para controladores, recursos relacionados à API e exibições, mas não para páginas. O modelo de Aplicativo Web (MVC) usa este código:

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

O exemplo a seguir adiciona suporte para páginas Razor e suporte mínimo ao controlador. O modelo de Aplicativo Web usa este código:

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

Os novos métodos também podem ser combinados. O exemplo a seguir é equivalente a chamar AddMvc no ASP.NET Core 2.2:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
}

Código de inicialização de roteamento

Se um aplicativo chamar UseMvc ou UseSignalR, migre o aplicativo para Roteamento de Ponto de Extremidade, se possível. Para melhorar a compatibilidade do Roteamento de Ponto de Extremidade com versões anteriores do MVC, revertemos algumas das alterações na geração de URL introduzidas no ASP.NET Core 2.2. Se você tiver tido problemas ao usar o Roteamento de Ponto de Extremidade na versão 2.2, espere melhorias no ASP.NET Core 3.0 com as seguintes exceções:

  • Se o aplicativo implementar IRouter ou herdar de Route, use DynamicRouteValuesTransformer como substituto.
  • Se o aplicativo acessar diretamente RouteData.Routers dentro do MVC para analisar URLs, você poderá substituí-lo pelo uso de LinkParser.ParsePathByEndpointName.
    • Defina a rota com um nome de rota.
    • Use LinkParser.ParsePathByEndpointName e passe o nome de rota desejado.

O Roteamento de Ponto de Extremidade dá suporte à mesma sintaxe de padrão de rota e recursos de criação de padrão de rota que IRouter. O Roteamento de Ponto de Extremidade dá suporte a IRouteConstraint. O roteamento de ponto de extremidade dá suporte a [Route], [HttpGet] e a outros atributos de roteamento MVC.

Para a maioria dos aplicativos, somente Startup requer alterações.

Migrar Startup.Configure

Conselhos gerais:

  • Adicione UseRouting.

  • Se o aplicativo chamar UseStaticFiles, coloque UseStaticFilesantesUseRouting.

  • Se o aplicativo usar recursos de autenticação/autorização, como AuthorizePage ou [Authorize], coloque a chamada para UseAuthentication e UseAuthorization: depois, UseRouting e UseCors, mas antes de UseEndpoints:

    public void Configure(IApplicationBuilder app)
    {
      ...
    
      app.UseStaticFiles();
    
      app.UseRouting();
      app.UseCors();
    
      app.UseAuthentication();
      app.UseAuthorization();
    
      app.UseEndpoints(endpoints => {
         endpoints.MapControllers();
      });
    
  • Substitua UseMvc ou UseSignalR por UseEndpoints.

  • Se o aplicativo usar cenários CORS, como [EnableCors], coloque a chamada para UseCors antes de qualquer outro middleware que use CORS (por exemplo, coloque UseCors antes de UseAuthentication, UseAuthorization e UseEndpoints).

  • Substitua IHostingEnvironment por IWebHostEnvironment e adicione uma instrução using para o namespace Microsoft.AspNetCore.Hosting.

  • Substitua IApplicationLifetime por IHostApplicationLifetime (namespace Microsoft.Extensions.Hosting).

  • Substitua EnvironmentName por Environments (namespace Microsoft.Extensions.Hosting).

O código a seguir é um exemplo de Startup.Configure em um aplicativo do ASP.NET Core 2.2 típico:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseSignalR(hubs =>
    {
        hubs.MapHub<ChatHub>("/chat");
    });

    app.UseMvc(routes =>
    {
        routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Depois de atualizar o código Startup.Configure anterior:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseStaticFiles();

    app.UseRouting();

    app.UseCors();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>("/chat");
        endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Aviso

Para a maioria dos aplicativos, as chamadas para UseAuthentication, UseAuthorization e UseCors devem aparecer entre as chamadas para UseRouting e UseEndpoints para serem eficazes.

Verificações de Integridade

As Verificações de Integridade usam o roteamento de ponto de extremidade com o Host Genérico. No Startup.Configure, chame MapHealthChecks no construtor de ponto de extremidade com a URL de ponto de extremidade ou o caminho relativo:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

Os pontos de extremidade de Verificações de Integridade podem:

  • Especificar um ou mais hosts/portas permitidos.
  • Exigir autorização.
  • Exigir CORS.

Para obter mais informações, confira Verificações de integridade no ASP.NET Core.

Diretrizes do middleware de segurança

O suporte para autorização e CORS é unificado em torno da abordagem do middleware . Isso permite o uso do mesmo middleware e funcionalidade nesses cenários. Um middleware de autorização atualizado é fornecido nesta versão e o Middleware do CORS é aprimorado para que ele possa entender os atributos usados pelos controladores MVC.

CORS

Anteriormente, o CORS era difícil de configurar. O middleware foi fornecido para uso em alguns casos de uso, mas os filtros MVC foram destinados a ser usados sem o middleware em outros casos de uso. Com o ASP.NET Core 3.0, recomendamos que todos os aplicativos que exigem CORS usem o Middleware do CORS em conjunto com o Roteamento de Ponto de Extremidade. UseCors pode ser fornecido com uma política padrão e os atributos [EnableCors] e [DisableCors] podem ser usados para substituir a política padrão quando necessário.

No exemplo a seguir:

  • O CORS está habilitado para todos os pontos de extremidade com a política nomeada default.
  • A classe MyController desabilita o CORS com o atributo [DisableCors].
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseCors("default");

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[DisableCors]
public class MyController : ControllerBase
{
    ...
}

Autorização

Em versões anteriores do ASP.NET Core, o suporte à autorização era fornecido por meio do atributo [Authorize]. O middleware de autorização não estava disponível. No ASP.NET Core 3.0, o middleware de autorização é necessário. Recomendamos colocar o Middleware de Autorização do ASP.NET Core (UseAuthorization) imediatamente após UseAuthentication. O Middleware de Autorização também pode ser configurado com uma política padrão, que pode ser substituída.

No ASP.NET Core 3.0 ou posterior, UseAuthorization é chamado em Startup.Configure e o seguinte HomeController requer um usuário conectado:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

public class HomeController : Controller
{
    [Authorize]
    public IActionResult BuyWidgets()
    {
        ...
    }
}

Ao usar o roteamento de ponto de extremidade, recomendamos não configurar AuthorizeFilter e confiar no Middleware de autorização. Se o aplicativo usar um AuthorizeFilter como um filtro global no MVC, recomendamos refatorar o código para fornecer uma política na chamada para AddAuthorization.

O DefaultPolicy é configurado inicialmente para exigir autenticação, portanto, nenhuma configuração adicional é necessária. No exemplo a seguir, os pontos de extremidade MVC são marcados como RequireAuthorization para que todas as solicitações precisem ser autorizadas com base no DefaultPolicy. No entanto, o HomeController permite o acesso sem que o usuário entre no aplicativo devido a [AllowAnonymous]:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute().RequireAuthorization();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

Autorização para pontos de extremidade específicos

A autorização também pode ser configurada para classes específicas de pontos de extremidade. O código a seguir é um exemplo de conversão de um aplicativo MVC que configurou um AuthorizeFilter global em um aplicativo com uma política específica que exige autorização:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    static readonly string _RequireAuthenticatedUserPolicy = 
                            "RequireAuthenticatedUserPolicy";
    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        // Pre 3.0:
        // services.AddMvc(options => options.Filters.Add(new AuthorizeFilter(...));

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(o => o.AddPolicy(_RequireAuthenticatedUserPolicy,
                        builder => builder.RequireAuthenticatedUser()));

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute()
                .RequireAuthorization(_RequireAuthenticatedUserPolicy);
            endpoints.MapRazorPages();
        });
    }
}

As políticas também podem ser personalizadas. O DefaultPolicy está configurado para exigir autenticação:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(
                 options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddControllersWithViews();
        services.AddRazorPages();
        services.AddAuthorization(options =>
        {
            options.DefaultPolicy = new AuthorizationPolicyBuilder()
              .RequireAuthenticatedUser()
              .Build();
        });

    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute().RequireAuthorization();
            endpoints.MapRazorPages();
        });
    }
}
[AllowAnonymous]
public class HomeController : Controller
{

Como alternativa, todos os pontos de extremidade podem ser configurados para exigir autorização sem [Authorize] ou RequireAuthorization configurando um FallbackPolicy. O FallbackPolicy é diferente de DefaultPolicy. O DefaultPolicy é disparado por [Authorize] ou RequireAuthorization, enquanto o FallbackPolicy é disparado quando nenhuma outra política é definida. FallbackPolicy é configurado inicialmente para permitir solicitações sem autorização.

O exemplo a seguir é o mesmo que o exemplo DefaultPolicy anterior, mas usa o FallbackPolicy para sempre exigir autenticação em todos os pontos de extremidade, exceto quando [AllowAnonymous] for especificado:

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddAuthorization(options =>
    {
        options.FallbackPolicy = new AuthorizationPolicyBuilder()
          .RequireAuthenticatedUser()
          .Build();
    });
}

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapDefaultControllerRoute();
    });
}

[AllowAnonymous]
public class HomeController : Controller
{
    ...
}

A autorização por middleware funciona sem que a estrutura tenha conhecimento específico da autorização. Por exemplo, as verificações de integridade não têm conhecimento específico da autorização, mas as verificações de integridade podem ter uma política de autorização configurável aplicada pelo middleware.

Além disso, cada ponto de extremidade pode personalizar seus requisitos de autorização. No exemplo a seguir, UseAuthorization processa a autorização com o DefaultPolicy, mas a o ponto de extremidade de verificação de integridade /healthz requer um usuário admin:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints
            .MapHealthChecks("/healthz")
            .RequireAuthorization(new AuthorizeAttribute(){ Roles = "admin", });
    });
}

A proteção é implementada em alguns cenários. O Middleware de pontos de extremidade gerará uma exceção se uma autorização ou política CORS for ignorada devido à falta de middleware. O suporte do analisador para fornecer comentários adicionais sobre configuração incorreta está em andamento.

Manipuladores de autorização personalizados

Se o aplicativo usar manipuladores de autorização personalizados, o roteamento de ponto de extremidade passará um tipo de recurso diferente para manipuladores diferentes do MVC. Os manipuladores que esperam que o recurso de contexto do manipulador de autorização seja do tipo AuthorizationFilterContext (o tipo de recurso fornecido pelos filtros MVC) precisarão ser atualizados para lidar com recursos do tipo RouteEndpoint (o tipo de recurso fornecido aos manipuladores de autorização pelo roteamento de ponto de extremidade).

O MVC ainda usa recursos AuthorizationFilterContext, portanto, se o aplicativo usa filtros de autorização MVC junto com a autorização de roteamento de ponto de extremidade, pode ser necessário lidar com ambos os tipos de recursos.

SignalR

O mapeamento de hubs SignalR agora ocorre dentro de UseEndpoints .

Mapeie cada hub com MapHub. Como nas versões anteriores, cada hub está explicitamente listado.

No exemplo a seguir, o suporte para o hub ChatHubSignalR é adicionado:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHub<ChatHub>();
    });
}

Há uma nova opção para controlar os limites de tamanho da mensagem dos clientes. Por exemplo, em Startup.ConfigureServices:

services.AddSignalR(hubOptions =>
{
    hubOptions.MaximumReceiveMessageSize = 32768;
});

No ASP.NET Core 2.2, você poderia definir o TransportMaxBufferSize e isso controlaria efetivamente o tamanho máximo da mensagem. No ASP.NET Core 3.0, essa opção agora controla apenas o tamanho máximo antes que a contrapressão seja observada.

Assemblies SignalR na estrutura compartilhada

Os assemblies do lado do servidor SignalR do ASP.NET Core agora são instalados com o SDK do .NET Core. Para obter mais informações, confira Remover referências obsoletas do pacote neste documento.

Controladores MVC

O mapeamento de controladores agora ocorre dentro de UseEndpoints.

Adicione MapControllers se o aplicativo usar o roteamento de atributo. Como o roteamento inclui suporte para muitas estruturas no ASP.NET Core 3.0 ou posterior, a adição de controladores roteado por atributo é opcional.

Substitua o seguinte:

  • MapRoute com MapControllerRoute
  • MapAreaRoute com MapAreaControllerRoute

Como o roteamento agora inclui suporte para mais do que apenas MVC, a terminologia foi alterada para fazer com que esses métodos indiquem claramente o que eles fazem. Rotas convencionais como MapControllerRoute/MapAreaControllerRoute/MapDefaultControllerRoute são aplicadas na ordem em que são adicionadas. Coloque rotas mais específicas (como rotas para uma área) primeiro.

No exemplo a seguir:

  • O MapControllers adiciona suporte para controladores roteado por atributo.
  • O MapAreaControllerRoute adiciona uma rota convencional para controladores em uma área.
  • O MapControllerRoute adiciona uma rota convencional para controladores.
public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapAreaControllerRoute(
            "admin",
            "admin",
            "Admin/{controller=Home}/{action=Index}/{id?}");
        endpoints.MapControllerRoute(
            "default", "{controller=Home}/{action=Index}/{id?}");
    });
}

Remoção do sufixo assíncrono dos nomes de ação do controlador

No ASP.NET Core 3.0, o ASP.NET Core MVC remove o sufixo Async dos nomes de ação do controlador. O roteamento e a geração de link são afetados por esse novo padrão. Por exemplo:

public class ProductsController : Controller
{
    public async Task<IActionResult> ListAsync()
    {
        var model = await _dbContext.Products.ToListAsync();
        return View(model);
    }
}

Antes do ASP.NET Core 3.0:

  • A ação anterior poderia ser acessada na rota Products/ListAsync.

  • A geração de link requer a especificação do sufixo Async. Por exemplo:

    <a asp-controller="Products" asp-action="ListAsync">List</a>
    

No ASP.NET Core 3.0:

  • A ação anterior pode ser acessada na rota Products/List.

  • A geração de link não requer a especificação do sufixo Async. Por exemplo:

    <a asp-controller="Products" asp-action="List">List</a>
    

Essa alteração não afeta os nomes especificados usando o atributo [ActionName]. O comportamento padrão pode ser desabilitado com o seguinte código em Startup.ConfigureServices:

services.AddMvc(options =>
    options.SuppressAsyncSuffixInActionNames = false);

Há algumas diferenças na geração de linka (usando Url.Link e APIs semelhantes, por exemplo). Estão incluídos:

  • Por padrão, ao usar o roteamento de ponto de extremidade, o uso de maiúsculas e minúsculas nos parâmetros de rota em URIs gerados não é necessariamente preservado. Esse comportamento pode ser controlado com a interface IOutboundParameterTransformer.
  • Gerar um URI para uma rota inválida (um controlador/ação ou página que não existe) produzirá uma cadeia de caracteres vazia no roteamento de ponto de extremidade em vez de produzir um URI inválido.
  • Os valores de ambiente (parâmetros de rota do contexto atual) não são usados automaticamente na geração de link com roteamento de ponto de extremidade. Anteriormente, ao gerar um link para outra ação (ou página), os valores de rota não especificados seriam inferidos dos valores de ambiente das rotas atuais . Ao usar o roteamento de ponto de extremidade, todos os parâmetros de rota devem ser especificados explicitamente durante a geração de link.

Razor Pages

O mapeamento de páginas Razor agora ocorre dentro de UseEndpoints.

Adicione MapRazorPages se o aplicativo usar páginas Razor. Como o Roteamento de Ponto de Extremidade inclui suporte para muitas estruturas, a adição de páginas Razor agora é opcional.

No método a seguir Startup.Configure, MapRazorPages adiciona suporte para as páginas Razor:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Usar MVC sem Roteamento de ponto de extremidade

O uso do MVC por meio de UseMvc ou UseMvcWithDefaultRoute no ASP.NET Core 3.0 requer uma aceitação explícita dentro de Startup.ConfigureServices. Isso é necessário porque o MVC deve saber se ele pode contar com a autorização e o middleware CORS durante a inicialização. É fornecido um analisador que avisa se o aplicativo tentar usar uma configuração não suportada.

Se o aplicativo exigir suporte IRouter herdado, desabilite EnableEndpointRoutingusando qualquer uma das seguintes abordagens em Startup.ConfigureServices:

services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddControllers(options => options.EnableEndpointRouting = false);
services.AddControllersWithViews(options => options.EnableEndpointRouting = false);
services.AddRazorPages().AddMvcOptions(options => options.EnableEndpointRouting = false);

Verificações de integridade

As verificações de integridade podem ser usadas como um roteador com o Roteamento de Ponto de Extremidade.

Adicione MapHealthChecks para usar verificações de integridade com o Roteamento de Ponto de Extremidade. O método MapHealthChecks aceita argumentos semelhantes a UseHealthChecks. A vantagem de usar MapHealthChecks em vez de UseHealthChecks é a capacidade de aplicar autorização e ter um controle mais refinado sobre a política de correspondência.

No exemplo a seguir, MapHealthChecks é chamado para um ponto de extremidade de verificação de integridade em /healthz:

public void Configure(IApplicationBuilder app)
{
    ...

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
    });
}

HostBuilder substitui WebHostBuilder

Os modelos do ASP.NET Core 3.0 usam o Host Genérico. As versões anteriores usavam o Host da Web. O código a seguir mostra a classe Program gerada pelo modelo ASP.NET Core 3.0:

// requires using Microsoft.AspNetCore.Hosting;
// requires using Microsoft.Extensions.Hosting;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

O código a seguir mostra a classe Program gerada pelo modelo ASP.NET Core 2.2:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

IWebHostBuilder permanece em 3.0 e é o tipo do webBuilder visto no exemplo de código anterior. WebHostBuilder será preterido em uma versão futura e substituído por HostBuilder.

A alteração mais significativa de WebHostBuilder para HostBuilder é na injeção de dependência (DI). Ao usar HostBuilder, você só pode injetar o seguinte no construtor do Startup:

As restrições de DI HostBuilder:

  • Habilite o contêiner de DI para ser criado apenas uma vez.
  • Evita os problemas resultantes de tempo de vida do objeto, como resolver várias instâncias de singletons.

Para obter mais informações, confira Evitando a injeção de serviço de inicialização no ASP.NET Core 3.

AddAuthorization movido para um assembly diferente

Os métodos AddAuthorization do ASP.NET Core 2.2 e inferiores no Microsoft.AspNetCore.Authorization.dll:

  • Foram renomeados AddAuthorizationCore.
  • Foram movidos para Microsoft.AspNetCore.Authorization.Policy.dll.

Os aplicativos que usam Microsoft.AspNetCore.Authorization.dll e Microsoft.AspNetCore.Authorization.Policy.dll não são afetados.

Os aplicativos que não usam Microsoft.AspNetCore.Authorization.Policy.dll devem seguir um dos seguintes procedimentos:

  • Adicione uma referência a Microsoft.AspNetCore.Authorization.Policy.dll. Essa abordagem funciona para a maioria dos aplicativos e é tudo o que é necessário.
  • Mudar para usar AddAuthorizationCore

Para obter mais informações, confira Alteração interruptiva na sobrecarga AddAuthorization(o =>) reside em um assembly diferente nº 386.

Identity IU

As atualizações de interface do usuário Identity para ASP.NET Core 3.0:

  • Adicione uma referência de pacote a Microsoft.AspNetCore.Identity.UI.
  • Os aplicativos que não usam as páginas Razor devem chamar MapRazorPages. Confira as páginas Razor neste documento.
  • O Bootstrap 4 é a estrutura de interface do usuário padrão. Defina uma propriedade de projeto IdentityUIFrameworkVersion para alterar o padrão. Para obter mais informações, confira este anúncio do GitHub.

SignalR

O cliente JavaScript SignalR foi alterado de @aspnet/signalr para @microsoft/signalr. Para reagir a essa alteração, altere as referências nos arquivos package.json, instruções require e instruções import de ECMAScript.

System.Text.Json é o protocolo padrão

System.Text.Json agora é o protocolo hub padrão usado pelo cliente e pelo servidor.

Em Startup.ConfigureServices, chame AddJsonProtocol para definir as opções do serializador.

Servidor:

services.AddSignalR(...)
        .AddJsonProtocol(options =>
        {
            options.PayloadSerializerOptions.WriteIndented = false;
        })

Cliente:

new HubConnectionBuilder()
    .WithUrl("/chathub")
    .AddJsonProtocol(options =>
    {
        options.PayloadSerializerOptions.WriteIndented = false;
    })
    .Build();

Alternar para Newtonsoft.Json

Se você estiver usando recursos do Newtonsoft.Json que não têm suporte no System.Text.Json, poderá voltar para Newtonsoft.Json. Confira Usar Newtonsoft.Json em um projeto SignalR do ASP.NET Core 3.0 anterior neste artigo.

Caches distribuídos do Redis

O pacote Microsoft.Extensions.Caching.Redis não está disponível para aplicativos do ASP.NET Core 3.0 ou posterior. Substitua a referência do pacote por Microsoft.Extensions.Caching.StackExchangeRedis. Para obter mais informações, confira Cache distribuído no ASP.NET Core.

Aceitar a compilação de runtime

Antes do ASP.NET Core 3.0, a compilação de runtime de exibições era um recurso implícito da estrutura. A compilação de runtime complementa a compilação de tempo de compilação das exibições. Ela permite que a estrutura compile exibições e páginas Razor (arquivos .cshtml) quando os arquivos forem modificados, sem precisar recompilar todo o aplicativo. Esse recurso é compatível com o cenário de fazer uma edição rápida no IDE e atualizar o navegador para exibir as alterações.

No ASP.NET Core 3.0, a compilação de runtime é um cenário opcional. A compilação de tempo de compilação é o único mecanismo para a compilação de exibição habilitada por padrão. O runtime depende do Visual Studio ou dotnet-watch em Visual Studio Code para recompilar o projeto quando detectar alterações nos arquivos .cshtml. No Visual Studio, as alterações nos arquivos .cs, .cshtml ou .razor no projeto que está sendo executado (Ctrl+F5), mas não depurados (F5), disparam a recompilação do projeto.

Para habilitar a compilação de runtime em seu projeto do ASP.NET Core 3.0:

  1. Instale o pacote NuGet Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.

  2. Atualize Startup.ConfigureServices para chamar AddRazorRuntimeCompilation:

    Para ASP.NET Core MVC, use o seguinte código:

    services.AddControllersWithViews()
        .AddRazorRuntimeCompilation(...);
    

    Para páginas Razor do ASP.NET Core, use o código a seguir:

    services.AddRazorPages()
        .AddRazorRuntimeCompilation(...);
    

O exemplo em https://github.com/aspnet/samples/tree/main/samples/aspnetcore/mvc/runtimecompilation mostra um exemplo de como habilitar a compilação de runtime condicionalmente em Ambientes de desenvolvimento.

Para obter mais informações sobre compilação de arquivo Razor, confira compilação do arquivo Razor no ASP.NET Core.

Migrar bibliotecas por meio de vários destinos

As bibliotecas geralmente ser compatíveis com várias versões do ASP.NET Core. A maioria das bibliotecas que foram compiladas em versões anteriores do ASP.NET Core deve continuar funcionando sem problemas. As seguintes condições exigem que o aplicativo seja compilado de forma cruzada:

  • A biblioteca depende de um recurso que tem uma alteração interruptiva binária.
  • A biblioteca deseja aproveitar os novos recursos do ASP.NET Core 3.0.

Por exemplo:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>netcoreapp3.0;netstandard2.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp3.0'">
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="Microsoft.AspNetCore" Version="2.1.0" />
  </ItemGroup>
</Project>

Use #ifdefs para habilitar APIs específicas do ASP.NET Core 3.0:

var webRootFileProvider =
#if NETCOREAPP3_0
    GetRequiredService<IWebHostEnvironment>().WebRootFileProvider;
#elif NETSTANDARD2_0
    GetRequiredService<IHostingEnvironment>().WebRootFileProvider;
#else
#error unknown target framework
#endif

Para obter mais informações sobre como usar APIs do ASP.NET Core em uma biblioteca de classes, confira Usar APIs do ASP.NET Core em uma biblioteca de classes.

Alterações diversas

O sistema de validação no .NET Core 3.0 e posterior trata parâmetros não anuláveis ou propriedades limitadas como se tivessem um atributo [Required]. Para obter mais informações, confira o Atributo [obrigatório].

Publicação

Exclua as pastas bin e obj no diretório do projeto.

TestServer

Para aplicativos que usam TestServer diretamente com o Host Genérico, crie o TestServer em um IWebHostBuilder no ConfigureWebHost:

[Fact]
public async Task GenericCreateAndStartHost_GetTestServer()
{
    using var host = await new HostBuilder()
        .ConfigureWebHost(webBuilder =>
        {
            webBuilder
                .UseTestServer()
                .Configure(app => { });
        })
    .StartAsync();

    var response = await host.GetTestServer().CreateClient().GetAsync("/");

    Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}

Alterações interruptivas na API

Examine as alterações interruptivas:

Roteamento de ponto de extremidade com parâmetro catch-all

Aviso

Um parâmetro catch-all pode corresponder às rotas incorretamente devido a um bug no roteamento. Os aplicativos afetados por esse bug têm as seguintes características:

  • Uma rota catch-all, por exemplo, {**slug}"
  • A rota catch-all não corresponde às solicitações que deveria corresponder.
  • Remover outras rotas faz com que a rota catch-all comece a funcionar.

Confira os bugs do GitHub 18677 e 16579, por exemplo, casos que atingiram esse bug.

Uma correção de aceitação para esse bug está contida no SDK do .NET Core 3.1.301 e posterior. O código a seguir define um comutador interno que corrige esse bug:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

.NET Core 3.0 no Serviço de Aplicativo do Azure

A distribuição do .NET Core para Serviço de Aplicativo do Azure foi concluída. O .NET Core 3.0 está disponível em todos os datacenters do Serviço de Aplicativo do Azure.

Módulo do ASP.NET Core (ANCM)

Se o Módulo do ASP.NET Core (ANCM) não foi um componente selecionado quando o Visual Studio foi instalado ou se uma versão anterior do ANCM foi instalada no sistema, baixe o Instalador de Pacote de Hospedagem do .NET Core (download direto) mais recente e execute o instalador. Para obter mais informações, confira Hospedagem de Pacote.