Compartilhar via


Novidades do ASP.NET Core 5.0

Este artigo destaca as alterações mais significativas no ASP.NET Core 5.0, com links para a documentação relevante.

Melhorias do ASP.NET Core MVC e do Razor

Model binding DateTime como UTC

O model binding agora dá suporte à associação de cadeias de caracteres de tempo UTC para DateTime. Se a solicitação contiver uma cadeia de caracteres de tempo UTC, a associação de modelo a associará a um UTC DateTime. Por exemplo, a cadeia de caracteres de tempo a seguir está associada ao UTC DateTime: https://example.com/mycontroller/myaction?time=2019-06-14T02%3A30%3A04.0576719Z

Model binding e validação com tipos de registro C# 9

Os tipos de registro C# 9 podem ser usados com model binding em um controlador MVC ou um Razor Page. Os tipos de registro são uma boa maneira de modelar os dados que estão sendo transmitidos pela rede.

Por exemplo, o PersonController a seguir usa o tipo de registro Person com model binding e validação de formulário:

public record Person([Required] string Name, [Range(0, 150)] int Age);

public class PersonController
{
   public IActionResult Index() => View();

   [HttpPost]
   public IActionResult Index(Person person)
   {
          // ...
   }
}

O arquivo Person/Index.cshtml:

@model Person

<label>Name: <input asp-for="Model.Name" /></label>
<span asp-validation-for="Model.Name" />

<label>Age: <input asp-for="Model.Age" /></label>
<span asp-validation-for="Model.Age" />

Melhorias no DynamicRouteValueTransformer

O ASP.NET Core 3.1 introduziu DynamicRouteValueTransformer como uma maneira de usar o ponto de extremidade personalizado para selecionar dinamicamente uma ação do controlador MVC ou uma página Razor. Os aplicativos ASP.NET Core 5.0 podem passar o estado para um DynamicRouteValueTransformer e filtrar o conjunto de pontos de extremidade escolhidos.

Diversos

  • O atributo [Compare] pode ser aplicado a propriedades em um modelo de Razor Page.
  • Parâmetros e propriedades associadas do corpo são considerados exigidos por padrão.

API Web

Especificação de OpenAPI ativada por padrão

A Especificação de OpenAPI é um padrão do setor para descrever APIs HTTP e integrá-las em processos de negócios complexos ou com terceiros. O OpenAPI é amplamente compatível com todos os provedores de nuvem e muitos registros de API. Os aplicativos que emitem documentos OpenAPI de APIs Web têm diversas novas oportunidades nas quais essas APIs podem ser usadas. Em parceria com os mantenedores do projeto de software livre Swashbuckle.AspNetCore, o modelo de API do ASP.NET Core contém uma dependência do NuGet no Swashbuckle. O Swashbuckle é um pacote NuGet de software livre popular que emite documentos OpenAPI dinamicamente. O Swashbuckle faz isso analisando os controladores de API e gerando o documento OpenAPI em tempo de execução ou em tempo de build usando a CLI do Swashbuckle.

No ASP.NET Core 5.0, os modelos de API Web habilitam o suporte a OpenAPI por padrão. Para desabilitar o OpenAPI:

  • Na linha de comando:

      dotnet new webapi --no-openapi true
    
  • No Visual Studio: desmarque Habilitar suporte ao OpenAPI.

Todos os arquivos .csproj criados para projetos de API Web contêm a referência de pacote NuGet Swashbuckle.AspNetCore.

<ItemGroup>
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
</ItemGroup>

O código gerado pelo modelo contém código no Startup.ConfigureServices que ativa a geração de documentos OpenAPI:

public void ConfigureServices(IServiceCollection services)
{

    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApp1", Version = "v1" });
    });
}

O método Startup.Configure adiciona o middleware Swashbuckle, que habilita o:

  • Processo de geração de documentos.
  • Página de interface do usuário do Swagger por padrão no modo de desenvolvimento.

O código gerado pelo modelo não exporá acidentalmente a descrição da API ao publicar em produção.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseSwagger();  // UseSwaggerUI Protected by if (env.IsDevelopment())
        app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
                         "WebApp1 v1"));
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

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

Importação do Gerenciamento de API do Azure

Quando os projetos de API da ASP.NET Core habilitam o OpenAPI, a publicação do Visual Studio 2019 versão 16.8 e posterior oferece automaticamente uma etapa adicional no fluxo de publicação. Os desenvolvedores que usam o Gerenciamento de API do Azure têm a oportunidade de importar automaticamente as APIs para o Gerenciamento de API do Azure durante o fluxo de publicação:

Importação vs. publicação do Gerenciamento de API do Azure

Melhor experiência de inicialização para projetos de API Web

Com o OpenAPI habilitado por padrão, a experiência de inicialização do aplicativo (F5) para desenvolvedores de API Web melhora significativamente. Com o ASP.NET Core 5.0, o modelo de API Web vem pré-configurado para carregar a página da interface do usuário do Swagger. A página da interface do usuário do Swagger fornece a documentação adicionada para a API publicada e permite testar as APIs com um único clique.

exibição swagger/index.html

Blazor

Melhorias de desempenho

Para o .NET 5, fizemos melhorias significativas no desempenho do runtime do WebAssembly .NET com um foco específico na renderização complexa da interface do usuário e na serialização JSON. Em nossos testes de desempenho, Blazor WebAssembly no .NET 5 é duas a três vezes mais rápido para a maioria dos cenários. Para obter mais informações, consulte Blog do ASP.NET: atualizações do ASP.NET Core no .NET 5 versão Release Candidate 1.

Isolamento de CSS

Blazor agora dá suporte à definição de estilos CSS com escopo para um determinado componente. Estilos CSS específicos do componente facilitam o raciocínio sobre os estilos em um aplicativo e evitam efeitos colaterais não intencionais de estilos globais. Para obter mais informações, confira Isolamento de CSS Blazordo ASP.NET Core.

Novo componente InputFile

O componente InputFile permite a leitura de um ou mais arquivos selecionados por um usuário para upload. Para obter mais informações, confira Carregamento de arquivos do ASP.NET CoreBlazor.

Novos componentes InputRadio e InputRadioGroup

Blazor tem componentes InputRadio e InputRadioGroup internos que simplificam a associação de dados a grupos de botões de opção com validação integrada. Para obter mais informações, consulte Componentes de entrada Blazor do ASP.NET Core.

Virtualização de componente

Melhore o desempenho percebido da renderização de componentes usando o suporte interno de virtualização da estrutura Blazor. Para obter mais informações, confira Virtualização de componentes Razor do ASP.NET Core.

Suporte a eventos ontoggle

Os eventos Blazor agora dão suporte ao evento DOM ontoggle. Para obter mais informações, consulte Tratamento de eventos do Blazor no ASP.NET Core.

Definir o foco da interface do usuário em aplicativos Blazor

Use o método de conveniência FocusAsync em referências de elemento para definir o foco da interface do usuário para esse elemento. Para obter mais informações, consulte Tratamento de eventos do Blazor no ASP.NET Core.

Atributos de classe CSS de validação personalizada

Os atributos de classe CSS de validação personalizada são úteis na integração com estruturas CSS, por exemplo, o Bootstrap. Para obter mais informações, consulte Validação de formulários Blazor do ASP.NET Core.

Suporte a IAsyncDisposable

Os componentes Razoragora dão suporte à interface IAsyncDisposable para a versão assíncrona de recursos alocados.

Referências de objeto e isolamento do JavaScript

Blazor habilita o isolamento de JavaScript em módulos JavaScript padrão. Para obter mais informações, consulte Chamar funções JavaScript de métodos .NET no ASP.NET Core Blazor.

Os componentes de formulário dão suporte ao nome de exibição

Os componentes internos a seguir dão suporte a nomes de exibição com o parâmetro DisplayName:

  • InputDate
  • InputNumber
  • InputSelect

Para obter mais informações, consulte ASP.NET CoreBlazor Visão geral dos formulários.

Parâmetros de rota catch-all

Os parâmetros de rota catch-all, que capturam caminhos entre vários limites de pasta, têm suporte nos componentes. Para obter mais informações, consulte Roteamento e navegação do Blazor no ASP.NET Core.

Melhorias na depuração

Os aplicativos de depuração Blazor WebAssembly são aprimorados no ASP.NET Core 5.0. Além disso, agora há suporte para depuração no Visual Studio para Mac. Para obter mais informações, consulte Depuração de aplicativos ASP.NET Core Blazor.

Microsoft Identity v2.0 e MSAL v2.0

A segurança Blazor agora usa o Microsoft Identity v2.0 (Microsoft.Identity.Web e Microsoft.Identity.Web.UI) e MSAL v2.0. Para obter mais informações, consulte os tópicos em BlazorSegurança e nó Identity.

Armazenamento de Navegador Protegido para Blazor Server

Agora, os aplicativos Blazor Server podem usar suporte interno para armazenar o estado do aplicativo no navegador que foi protegido contra adulterações usando a proteção de dados do ASP.NET Core. Os dados podem ser armazenados no armazenamento do navegador local ou no armazenamento de sessão. Para obter mais informações, confira Gerenciamento de estado Blazor do ASP.NET Core.

Pré-renderização Blazor WebAssembly

A integração de componentes é aprimorada em modelos de hospedagem, e os aplicativos Blazor WebAssembly agora podem pré-renderizar a saída no servidor.

Aprimoramentos de corte/vinculação

Blazor WebAssembly executa o corte/vinculação de IL (linguagem intermediária) durante um build para cortar a IL desnecessária dos assemblies de saída do aplicativo. Com o lançamento do ASP.NET Core 5.0, Blazor WebAssembly executa o corte aprimorado com opções de configuração adicionais. Para obter mais informações, confira Configurar a Unidade de Corte para o ASP.NET Core Blazor e Opções de corte.

Analisador de compatibilidade de navegador

Os aplicativos Blazor WebAssembly têm como destino a área de superfície completa da API do .NET, mas nem todas as APIs do .NET têm suporte no WebAssembly devido a restrições de área restrita do navegador. APIs sem suporte geram PlatformNotSupportedException durante a execução no WebAssembly. Um analisador de compatibilidade de plataforma avisa o desenvolvedor quando o aplicativo usa APIs que não têm suporte nas plataformas de destino do aplicativo. Para obter mais informações, consulte Consumir componentes Razor do ASP.NET Core de uma RCL (biblioteca de classes) Razor.

Assemblies de carga lentos

O desempenho de inicialização do aplicativo Blazor WebAssembly pode ser melhorado adiando o carregamento de alguns assemblies de aplicativo até que eles sejam necessários. Para obter mais informações, confira Assemblies de carregamento lentos no Blazor WebAssembly do ASP.NET Core.

Suporte à globalização atualizado

O suporte à globalização está disponível para Blazor WebAssembly com base em Componentes Internacionais para Unicode (ICU). Para obter mais informações, confira Globalização e localização Blazor do ASP.NET Core.

gRPC

Muitas melhorias de desempenho foram feitas no gRPC. Para obter mais informações, confira Melhorias de desempenho do gRPC no .NET 5.

Para obter mais informações sobre o gRPC, confira Visão geral do gRPC no .NET.

SignalR

Filtros de hub SignalR

Os filtros de hub SignalR, chamados pipelines de hub no ASP.NET SignalR, são um recurso que permite que o código seja executado antes e depois que os métodos hub são chamados. A execução de código antes e depois que os métodos hub são chamados é semelhante a como o middleware tem a capacidade de executar código antes e depois de uma solicitação HTTP. Os usos comuns incluem registro em log, tratamento de erros e validação de argumento.

Para obter mais informações, consulte Usar filtros de hub no ASP.NET Core SignalR.

Invocações de hub paralelo SignalR

O ASP.NET Core SignalR agora é capaz de lidar com invocações de hub paralelo. O comportamento padrão pode ser alterado para permitir que os clientes invoquem mais de um método de hub por vez:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR(options =>
    {
        options.MaximumParallelInvocationsPerClient = 5;
    });
}

Suporte adicionado ao Messagepack no cliente Java SignalR

Um novo pacote, com.microsoft.signalr.messagepack, adiciona suporte ao MessagePack no cliente Java SignalR. Para usar o protocolo do hub MessagePack, adicione .withHubProtocol(new MessagePackHubProtocol()) ao construtor de conexões:

HubConnection hubConnection = HubConnectionBuilder.create(
                           "http://localhost:53353/MyHub")
               .withHubProtocol(new MessagePackHubProtocol())
               .build();

Kestrel

  • Pontos de extremidade recarregáveis por meio da configuração: Kestrel pode detectar alterações na configuração passadas para KestrelServerOptions.Configure, desassociar de pontos de extremidade existentes e associar a novos pontos de extremidade sem exigir uma reinicialização do aplicativo quando o parâmetro reloadOnChange está definido como true. Por padrão, ao usar ConfigureWebHostDefaults ou CreateDefaultBuilder, Kestrel associa-se à subseção de configuração "Kestrel" com reloadOnChange habilitado. Os aplicativos devem passar reloadOnChange: true ao chamar KestrelServerOptions.Configure manualmente para obter pontos de extremidade recarregáveis.

  • Melhorias nos cabeçalhos de resposta HTTP/2. Para obter mais informações, confira Melhorias de desempenho na próxima seção.

  • Suporte para tipos de pontos de extremidade adicionais no transporte de soquetes: adicionar à nova API introduzida no System.Net.Sockets, o transporte padrão de soquetes no Kestrel permite a associação a identificadores de arquivo existentes e soquetes de domínio Unix. O suporte para associação a identificadores de arquivo existentes permite usar a integração Systemd existente sem exigir o transporte libuv.

  • Decodificação de cabeçalho personalizada em Kestrel: os aplicativos podem especificar quais Encoding usar para interpretar cabeçalhos de entrada com base no nome do cabeçalho em vez do padrão para UTF-8. Defina a propriedade Microsoft.AspNetCore.Server.Kestrel.KestrelServerOptions.RequestHeaderEncodingSelector para especificar qual codificação deve ser usada:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
          .ConfigureWebHostDefaults(webBuilder =>
          {
              webBuilder.ConfigureKestrel(options =>
              {
                  options.RequestHeaderEncodingSelector = encoding =>
                  {
                        return encoding switch
                        {
                            "Host" => System.Text.Encoding.Latin1,
                            _ => System.Text.Encoding.UTF8,
                        };
                  };
              });
              webBuilder.UseStartup<Startup>();
          });
    

Opções específicas do ponto de extremidade Kestrel por meio da configuração

O suporte foi adicionado para configurar as opções específicas do ponto de extremidade de Kestrel por meio da configuração. As configurações específicas do ponto de extremidade incluem:

  • Protocolos HTTP usados
  • Protocolos TLS usados
  • Certificado selecionado
  • Modo de certificado do cliente

A configuração permite especificar qual certificado é selecionado com base no nome do servidor especificado. O nome do servidor faz parte da extensão SNI (Indicação de Nome de Servidor) para o protocolo TLS, conforme indicado pelo cliente. A configuração do Kestrel também dá suporte a um prefixo curinga no nome do host.

O exemplo a seguir mostra como especificar o ponto de extremidade usando um arquivo de configuração:

{
  "Kestrel": {
    "Endpoints": {
      "EndpointName": {
        "Url": "https://*",
        "Sni": {
          "a.example.org": {
            "Protocols": "Http1AndHttp2",
            "SslProtocols": [ "Tls11", "Tls12"],
            "Certificate": {
              "Path": "testCert.pfx",
              "Password": "testPassword"
            },
            "ClientCertificateMode" : "NoCertificate"
          },
          "*.example.org": {
            "Certificate": {
              "Path": "testCert2.pfx",
              "Password": "testPassword"
            }
          },
          "*": {
            // At least one sub-property needs to exist per
            // SNI section or it cannot be discovered via
            // IConfiguration
            "Protocols": "Http1",
          }
        }
      }
    }
  }
}

A SNI (Indicação de Nome de Servidor) é uma extensão TLS para incluir um domínio virtual como parte da negociação SSL. O que isso significa efetivamente é que o nome de domínio virtual ou um nome de host pode ser usado para identificar o ponto de extremidade de rede.

Melhorias de desempenho

HTTP/2

  • Reduções significativas nas alocações no caminho do código HTTP/2.

  • Suporte para Compactação dinâmica HPack de cabeçalhos de resposta HTTP/2 no Kestrel. Para obter mais informações, consulte Tamanho da tabela de cabeçalho e HPACK: o (recurso de) encerramento silencioso de HTTP/2.

  • Enviando quadros PING HTTP/2: HTTP/2 tem um mecanismo para enviar quadros PING para garantir que uma conexão ociosa ainda esteja funcional. Garantir uma conexão viável é especialmente útil ao trabalhar com fluxos de longa duração que geralmente são ociosos, mas que só veem atividade intermitentemente, por exemplo, fluxos gRPC. Os aplicativos podem enviar quadros PING periódicos no Kestrel definindo limites em KestrelServerOptions:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
      Host.CreateDefaultBuilder(args)
          .ConfigureWebHostDefaults(webBuilder =>
          {
              webBuilder.ConfigureKestrel(options =>
              {
                  options.Limits.Http2.KeepAlivePingInterval =
                                                 TimeSpan.FromSeconds(10);
                  options.Limits.Http2.KeepAlivePingTimeout =
                                                 TimeSpan.FromSeconds(1);
              });
              webBuilder.UseStartup<Startup>();
          });
    

Contêineres

Antes do .NET 5.0, a criação e publicação de um Dockerfile para um aplicativo ASP.NET Core exigia a extração de todo o SDK do .NET Core e da imagem ASP.NET Core. Com essa versão, a extração dos bytes de imagens do SDK é reduzida e os bytes puxados para a imagem ASP.NET Core são amplamente eliminados. Saiba mais neste o comentário do problema desse GitHub.

Autenticação e autorização

Autenticação do Microsoft Entra ID com a Microsoft.Identity. Web

Os modelos de projeto ASP.NET Core agora se integram com Microsoft.Identity.Web para lidar com a autenticação com o Microsoft Entra ID (Azure AD). O pacote Microsoft.Identity.Web fornece:

  • Uma experiência melhor para autenticação por meio do Microsoft Entra ID.
  • Uma maneira mais fácil de acessar recursos do Azure em nome de seus usuários, incluindo o Microsoft Graph. Consulte o exemplo do Microsoft.Identity.Web, que começa com um logon básico e avança por meio de várias locações, usando APIs do Azure, usando o Microsoft Graph e protegendo suas próprias APIs. Microsoft.Identity.Web está disponível junto com o .NET 5.

Permitir acesso anônimo a um ponto de extremidade

O método de extensão AllowAnonymous permite acesso anônimo a um ponto de extremidade:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World!");
        })
        .AllowAnonymous();
    });
}

Tratamento personalizado de falhas de autorização

O tratamento personalizado de falhas de autorização agora é mais fácil com a nova interface IAuthorizationMiddlewareResultHandler invocada pelo Middleware de autorização. A implementação padrão permanece a mesma, mas um manipulador personalizado pode ser registrado em [Injeção de dependência, que permite respostas HTTP personalizadas com base no motivo pelo qual a autorização falhou. Confira este exemplo que demonstra o uso do IAuthorizationMiddlewareResultHandler.

Autorização ao usar o roteamento de ponto de extremidade

A autorização ao usar o roteamento de ponto de extremidade agora recebe o HttpContext em vez da instância do ponto de extremidade. Isso permite que o middleware de autorização acesse o RouteData e outras propriedades do HttpContext que não estavam acessíveis por meio da classe Endpoint. O ponto de extremidade pode ser buscado no contexto usando context.GetEndpoint.

Controle de acesso baseado em função com autenticação Kerberos e LDAP no Linux

Consulte RBAC (autenticação Kerberos e controle de acesso baseado em função)

Melhorias na API

Métodos de extensão JSON para HttpRequest e HttpResponse

Os dados JSON podem ser lidos e gravados em um HttpRequest e HttpResponse usando os métodos novos de extensão ReadFromJsonAsync e WriteAsJsonAsync. Esses métodos de extensão usam o serializador System.Text.Json para lidar com os dados JSON. O novo método de extensão HasJsonContentType também pode marcar se uma solicitação tiver um tipo de conteúdo JSON.

Os métodos de extensão JSON podem ser combinados com o roteamento de pontos de extremidade para criar APIs JSON em um estilo de programação que chamamos de rota para o código. É uma nova opção para desenvolvedores que desejam criar APIs JSON básicas de maneira leve. Por exemplo, um aplicativo Web que tem apenas alguns pontos de extremidade pode optar por usar a rota para o código em vez da funcionalidade completa de ASP.NET Core MVC:

endpoints.MapGet("/weather/{city:alpha}", async context =>
{
    var city = (string)context.Request.RouteValues["city"];
    var weather = GetFromDatabase(city);

    await context.Response.WriteAsJsonAsync(weather);
});

System.Diagnostics.Activity

O formato padrão de System.Diagnostics.Activity agora usa como padrão o formato W3C. Isso torna o suporte ao rastreamento distribuído em ASP.NET Core interoperável com mais estruturas por padrão.

FromBodyAttribute

FromBodyAttribute agora dá suporte à configuração de uma opção que permite que esses parâmetros ou propriedades sejam considerados opcionais:

public IActionResult Post([FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)]
                          MyModel model)
{
    ...
}

Melhorias diversas

Começamos a aplicar anotações anuláveis a assemblies do ASP.NET Core. Planejamos anotar a maior parte da superfície de API pública comum da estrutura do .NET 5.

Controlar a ativação da classe de inicialização

Foi adicionada uma sobrecarga de UseStartup adicional que permite que um aplicativo forneça um método de fábrica para controlar a ativação de classe Startup. O controle da ativação de classe Startup é útil para passar parâmetros adicionais para Startup os quais são inicializados junto com o host:

public class Program
{
    public static async Task Main(string[] args)
    {
        var logger = CreateLogger();
        var host = Host.CreateDefaultBuilder()
            .ConfigureWebHost(builder =>
            {
                builder.UseStartup(context => new Startup(logger));
            })
            .Build();

        await host.RunAsync();
    }
}

Atualização automática com dotnet watch

No .NET 5, a execução do dotnet watch em um projeto ASP.NET Core inicia o navegador padrão e atualiza automaticamente o navegador à medida que as alterações são feitas no código. Isso significa que você pode:

  • Abrir um projeto do ASP.NET Core em um editor de texto.
  • Execute dotnet watch.
  • Se concentrar nas alterações de código enquanto as ferramentas manipulam a recompilação, a reinicialização e o recarregamento do aplicativo.

Formatador do Agente de Console

Foram feitas melhorias no provedor de log do console na biblioteca Microsoft.Extensions.Logging. Os desenvolvedores agora podem implementar um ConsoleFormatter personalizado para exercer controle completo sobre formatação e colorização da saída do console. As APIs de formatador permitem formatação avançada implementando um subconjunto das sequências de escape VT-100. O VT-100 é compatível com a maioria dos terminais modernos. O agente do console pode analisar sequências de escape em terminais sem suporte, permitindo que os desenvolvedores criem um único formatador para todos os terminais.

Agente de Console do JSON

Além do suporte para formatadores personalizados, também adicionamos um formatador JSON interno que emite logs JSON estruturados para o console. O código a seguir mostra como alternar do agente padrão para JSON:

public static IHostBuilder CreateHostBuilder(string[] args) =>
           Host.CreateDefaultBuilder(args)
  .ConfigureLogging(logging =>
  {
     logging.AddJsonConsole(options =>
     {
         options.JsonWriterOptions = new JsonWriterOptions()
         { Indented = true };
     });
  })
  .ConfigureWebHostDefaults(webBuilder =>
  {
    webBuilder.UseStartup<Startup>();
  });

As mensagens de log emitidas para o console são formatadas para JSON:

{
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Microsoft.Hosting.Lifetime",
  "Message": "Now listening on: https://localhost:5001",
  "State": {
    "Message": "Now listening on: https://localhost:5001",
    "address": "https://localhost:5001",
    "{OriginalFormat}": "Now listening on: {address}"
  }
}