Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo destaca as alterações mais significativas no ASP.NET Core 3.0 com links para documentação relevante.
Blazor
Blazor é um novo framework no ASP.NET Core para construir interfaces de utilizador web interativas no lado do cliente com o .NET:
- Crie interfaces de usuário interativas avançadas usando C#.
- Partilhe a lógica da aplicação do lado do servidor e do lado do cliente escrita em .NET.
- Renderize a interface do usuário como HTML e CSS para amplo suporte a navegadores, incluindo navegadores móveis.
Blazor Cenários suportados pela Framework:
- Componentes reutilizáveis da interface do usuário (Razor componentes)
- Roteamento do lado do cliente
- Layouts de componentes
- Suporte para injeção de dependência
- Formulários e validação
- Fornecer Razor componentes em Razor bibliotecas de classes
- Interoperabilidade JavaScript
Para obter mais informações, consulte ASP.NET Core Blazor.
Blazor Server
Blazor desacopla a lógica de renderização de componentes de como as atualizações da interface do usuário são aplicadas. Blazor Server fornece suporte para hospedar componentes Razor no servidor em um aplicativo ASP.NET Core. As atualizações da interface do usuário são tratadas em uma conexão SignalR. Blazor Server é suportado no ASP.NET Core 3.0.
Blazor WebAssembly (Pré-visualização)
Blazor as aplicações também podem ser executadas diretamente no navegador usando um ambiente de execução .NET baseado em WebAssembly. Blazor WebAssembly está em versão de pré-visualização e não é suportado no ASP.NET Core 3.0. Blazor WebAssembly será suportado em uma versão futura do ASP.NET Core.
Componentes Razor
Blazor Os aplicativos são criados a partir de componentes. Os componentes são partes independentes da interface do usuário (UI), como uma página, caixa de diálogo ou formulário. Os componentes são classes .NET normais que definem a lógica de renderização da interface do usuário e manipuladores de eventos do lado do cliente. Você pode criar aplicativos Web interativos avançados sem JavaScript.
Os componentes em Blazor são normalmente criados usando Razor sintaxe, uma mistura natural de HTML e C#. Razor componentes são semelhantes às Páginas e vistas MVC, pois ambos usam Razor. Ao contrário de páginas e exibições, que se baseiam em um modelo de solicitação-resposta, os componentes são usados especificamente para lidar com a composição da interface do usuário.
gRPC
gRPC:
É uma estrutura RPC (chamada de procedimento remoto) popular e de alto desempenho.
Oferece uma abordagem opinativa de contrato primeiro para o desenvolvimento de API.
Utiliza tecnologias modernas, tais como:
- HTTP/2 para transporte.
- Protocol Buffers como a linguagem de descrição da interface.
- Formato de serialização binária.
Fornece recursos como:
- Autenticação
- Streaming bidirecional e controle de fluxo.
- Cancelamento e limites de tempo.
A funcionalidade gRPC no ASP.NET Core 3.0 inclui:
- Grpc.AspNetCore: Uma estrutura ASP.NET Core para hospedar serviços gRPC. O gRPC no ASP.NET Core integra-se com recursos padrão do ASP.NET Core, como registro, injeção de dependência (DI), autenticação e autorização.
-
Grpc.Net.Client: Um cliente gRPC para .NET Core que é construído sobre o familiar
HttpClient. -
Grpc.Net.ClientFactory: integração com cliente gRPC
HttpClientFactory.
Para obter mais informações, consulte Visão geral do gRPC no .NET.
SignalR
Consulte Atualizar SignalR código para obter instruções de migração.
SignalR agora usa System.Text.Json para serializar/desserializar mensagens JSON. Consulte Mudar para Newtonsoft.Json para obter instruções sobre como restaurar o serializador baseado em Newtonsoft.Json.
Nos Clientes JavaScript e .NET para SignalR, foi adicionado suporte para reconexão automática. Por padrão, o cliente tenta se reconectar imediatamente e tentar novamente após 2, 10 e 30 segundos, se necessário. Se o cliente se reconectar com êxito, ele receberá uma nova ID de conexão. A reconexão automática é ativada por escolha:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Os intervalos de reconexão podem ser especificados passando uma matriz de durações baseadas em milissegundos:
.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
//.withAutomaticReconnect([0, 2000, 10000, 30000]) The default intervals.
Uma implementação personalizada pode ser passada para controle total dos intervalos de reconexão.
Se a reconexão falhar após o último intervalo de reconexão:
- O cliente considera que a conexão está offline.
- O cliente para de tentar se reconectar.
Durante as tentativas de reconexão, atualize a interface do usuário do aplicativo para notificar o usuário de que a reconexão está sendo tentada.
Para fornecer comentários da interface do usuário quando a conexão é interrompida, a API do SignalR cliente foi expandida para incluir os seguintes manipuladores de eventos:
-
onreconnecting: Dá aos desenvolvedores a oportunidade de desabilitar a interface do usuário ou informar aos usuários que o aplicativo está offline. -
onreconnected: Dá aos desenvolvedores a oportunidade de atualizar a interface do usuário assim que a conexão for restabelecida.
O código a seguir usa onreconnecting para atualizar a interface do usuário ao tentar se conectar:
connection.onreconnecting((error) => {
const status = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageInput").disabled = true;
document.getElementById("sendButton").disabled = true;
document.getElementById("connectionStatus").innerText = status;
});
O código a seguir usa onreconnected para atualizar a interface do usuário na conexão:
connection.onreconnected((connectionId) => {
const status = `Connection reestablished. Connected.`;
document.getElementById("messageInput").disabled = false;
document.getElementById("sendButton").disabled = false;
document.getElementById("connectionStatus").innerText = status;
});
SignalR 3.0 ou posterior fornece um recurso personalizado para manipuladores de autorização quando um método de hub requer autorização. O recurso é uma instância do HubInvocationContext. O HubInvocationContext inclui o:
HubCallerContext- Nome do método hub que está sendo invocado.
- Argumentos para o método hub.
Considere o exemplo a seguir de um aplicativo de sala de chat que permite a entrada em várias organizações por meio do Azure Ative Directory. Qualquer pessoa com uma conta Microsoft pode iniciar sessão no chat, mas apenas os membros da organização proprietária podem banir utilizadores ou ver os históricos de chat dos utilizadores. O aplicativo pode restringir determinadas funcionalidades de usuários específicos.
public class DomainRestrictedRequirement :
AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
IAuthorizationRequirement
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
DomainRestrictedRequirement requirement,
HubInvocationContext resource)
{
if (context.User?.Identity?.Name == null)
{
return Task.CompletedTask;
}
if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name))
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
private bool IsUserAllowedToDoThis(string hubMethodName, string currentUsername)
{
if (hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase))
{
return currentUsername.Equals("bob42@jabbr.net", StringComparison.OrdinalIgnoreCase);
}
return currentUsername.EndsWith("@jabbr.net", StringComparison.OrdinalIgnoreCase));
}
}
No código anterior, DomainRestrictedRequirement serve como um personalizado IAuthorizationRequirement. Como o HubInvocationContext parâmetro resource está sendo passado, a lógica interna pode:
- Inspecione o contexto no qual o Hub está sendo chamado.
- Tome decisões sobre como permitir que o usuário execute métodos Hub individuais.
Os métodos individuais do Hub podem ser marcados com o nome da política que o código verifica em tempo de execução. À medida que os clientes tentam chamar métodos Hub individuais, o DomainRestrictedRequirement manipulador executa e controla o acesso aos métodos. Com base na forma como os DomainRestrictedRequirement controlam o acesso:
- Todos os usuários conectados podem chamar o
SendMessagemétodo. - Apenas os utilizadores que iniciaram sessão com um endereço de
@jabbr.nete-mail podem ver os históricos dos utilizadores. - Só
bob42@jabbr.netpode banir usuários da sala de chat.
[Authorize]
public class ChatHub : Hub
{
public void SendMessage(string message)
{
}
[Authorize("DomainRestricted")]
public void BanUser(string username)
{
}
[Authorize("DomainRestricted")]
public void ViewUserHistory(string username)
{
}
}
Criar a política DomainRestricted pode envolver:
- Em
Startup.cs, adicionando a nova política. - Forneça o requisito personalizado
DomainRestrictedRequirementcomo um parâmetro. - Registrando-se
DomainRestrictedcom o middleware de autorização.
services
.AddAuthorization(options =>
{
options.AddPolicy("DomainRestricted", policy =>
{
policy.Requirements.Add(new DomainRestrictedRequirement());
});
});
SignalR hubs usam o Roteamento de Pontos Finais. SignalR A conexão de hub era feita anteriormente explicitamente:
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
Na versão anterior, os desenvolvedores precisavam conectar controladores, Razor páginas e hubs em vários lugares. A conexão explícita resulta em uma série de segmentos de roteamento quase idênticos:
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("hubs/chat");
});
app.UseRouting(routes =>
{
routes.MapRazorPages();
});
SignalR Os hubs 3.0 podem ser roteados por meio do roteamento de pontos finais. Com o roteamento de ponto final, normalmente todo o roteamento pode ser configurado em UseRouting:
app.UseRouting(routes =>
{
routes.MapRazorPages();
routes.MapHub<ChatHub>("hubs/chat");
});
ASP.NET Core 3.0 SignalR adicionou:
Streaming de cliente para servidor. Com streaming de cliente para servidor, os métodos do lado do servidor podem receber instâncias de um IAsyncEnumerable<T> ou ChannelReader<T>. No exemplo de C# a seguir, o UploadStream método no Hub receberá um fluxo de cadeias de caracteres do cliente:
public async Task UploadStream(IAsyncEnumerable<string> stream)
{
await foreach (var item in stream)
{
// process content
}
}
Os aplicativos cliente .NET podem passar uma instância IAsyncEnumerable<T> ou ChannelReader<T> como argumento stream do método UploadStream Hub acima.
Depois que o for loop for concluído e a função local for encerrada, a conclusão do fluxo será enviada:
async IAsyncEnumerable<string> clientStreamData()
{
for (var i = 0; i < 5; i++)
{
var data = await FetchSomeData();
yield return data;
}
}
await connection.SendAsync("UploadStream", clientStreamData());
Os aplicativos cliente JavaScript usam o SignalRSubject (ou um RxJS Subject) para o stream argumento do UploadStream método Hub acima.
let subject = new signalR.Subject();
await connection.send("StartStream", "MyAsciiArtStream", subject);
O código JavaScript pode usar o subject.next método para manipular cadeias de caracteres à medida que elas são capturadas e prontas para serem enviadas ao servidor.
subject.next("example");
subject.complete();
Usando códigos como os dois trechos anteriores, experiências de streaming em tempo real podem ser criadas.
Nova serialização JSON
ASP.NET Core 3.0 agora usa System.Text.Json por padrão para serialização JSON:
- Lê e grava JSON de forma assíncrona.
- É otimizado para texto UTF-8.
- Normalmente maior desempenho do que
Newtonsoft.Json.
Para adicionar Json.NET ao ASP.NET Core 3.0, consulte Adicionar suporte ao formato JSON baseado em Newtonsoft.Json.
Novas Razor diretivas
A lista seguinte contém novas Razor diretivas:
-
@attribute: A@attributediretiva aplica o atributo dado à classe da página ou exibição gerada. Por exemplo,@attribute [Authorize]. -
@implements: A@implementsdiretiva implementa uma interface para a classe gerada. Por exemplo,@implements IDisposable.
O IdentityServer4 suporta autenticação e autorização para APIs da Web e SPAs
ASP.NET Core 3.0 oferece autenticação em SPAs (Single Page Apps) usando o suporte para autorização de API da Web. ASP.NET Core Identity para autenticar e armazenar usuários é combinado com o IdentityServer4 para implementar o OpenID Connect.
IdentityServer4 é uma estrutura OpenID Connect e OAuth 2.0 para ASP.NET Core 3.0. Permite os seguintes elementos de segurança:
- Autenticação como serviço (AaaS)
- Logon único/desligamento (SSO) em vários tipos de aplicativos
- Controle de acesso para APIs
- Gateway de Federação
Para obter mais informações, consulte a documentação do IdentityServer4 ou Autenticação e autorização para SPAs.
Certificado e autenticação Kerberos
A autenticação do certificado requer:
- Configurar o servidor para aceitar certificados.
- Adicionando o middleware de autenticação no
Startup.Configure. - Adicionando o serviço de autenticação de certificado no
Startup.ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
As opções para autenticação de certificado incluem a capacidade de:
- Aceite certificados autoassinados.
- Verifique se há revogação do certificado.
- Verifique se o certificado oferecido tem os sinalizadores de uso corretos.
Um principal de utilizador predefinido é construído a partir das propriedades do certificado. O principal do utilizador contém um evento que permite complementar ou substituir o principal. Para obter mais informações, consulte Configurar autenticação de certificado no ASP.NET Core.
A Autenticação do Windows foi estendida para Linux e macOS. Nas versões anteriores, a Autenticação do Windows era limitada ao IIS e ao HTTP.sys. No ASP.NET Core 3.0, Kestrel tem a capacidade de usar Negotiate, Kerberos e NTLM no Windows, Linux e macOS em hosts unidos a domínios do Windows. Kestrel o suporte a esses esquemas de autenticação é fornecido pelo pacote NuGet Microsoft.AspNetCore.Authentication.Negotiate . Tal como acontece com os outros serviços de autenticação, configure a autenticação em toda a aplicação e, em seguida, configure o serviço:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
// Other service configuration removed.
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
// Other app configuration removed.
}
Requisitos do anfitrião:
- Os hosts Windows devem ter Nomes de Entidade de Serviço (SPNs) adicionados à conta de utilizador que hospeda a aplicação.
- As máquinas Linux e macOS devem estar associadas ao domínio.
- SPNs devem ser criados para o processo web.
- Os arquivos Keytab devem ser gerados e configurados na máquina host.
Para obter mais informações, consulte Configurar a autenticação do Windows no ASP.NET Core.
Alterações de modelo
Os modelos de interface do usuário da Web (Razor Pages, MVC com controlador e vistas) têm os seguintes elementos removidos:
- A cookie interface do usuário de consentimento não está mais incluída. Para habilitar o cookie recurso de consentimento em um aplicativo gerado por modelo do ASP.NET Core 3.0, consulte Suporte do Regulamento Geral de Proteção de Dados (GDPR) no ASP.NET Core.
- Scripts e ativos estáticos relacionados agora são referenciados como arquivos locais em vez de usar CDNs. Para obter mais informações, consulte Scripts e ativos estáticos relacionados agora são referenciados como arquivos locais em vez de usar CDNs com base no ambiente atual (dotnet/AspNetCore.Docs #14350).
O modelo Angular foi atualizado para usar o Angular 8.
O modelo de biblioteca de classes Razor (RCL) define como padrão o desenvolvimento de componentes Razor. Uma nova opção de modelo no Visual Studio fornece suporte de modelo para páginas e modos de exibição. Ao criar um RCL a partir do modelo numa shell de comando, passe a --support-pages-and-views opção (dotnet new razorclasslib --support-pages-and-views).
Anfitrião Genérico
Os modelos do ASP.NET Core 3.0 usam o .NET Generic Host no ASP.NET Core. Versões anteriores utilizadas WebHostBuilder. O uso do Host Genérico do .NET Core (HostBuilder) fornece uma melhor integração dos aplicativos ASP.NET Core com outros cenários de servidor que não são específicos da Web. Para obter mais informações, consulte HostBuilder substitui WebHostBuilder.
Configuração do host
Antes do lançamento do ASP.NET Core 3.0, as variáveis de ambiente prefixadas com ASPNETCORE_ foram carregadas para a configuração do host da Web. Na versão 3.0, AddEnvironmentVariables é usado para carregar variáveis de ambiente prefixadas com DOTNET_ para configuração de host com CreateDefaultBuilder.
Alterações na injeção do construtor Startup
O Host Genérico suporta apenas os seguintes tipos para injeção no construtor Startup.
- IHostEnvironment
IWebHostEnvironment- IConfiguration
Todos os serviços ainda podem ser injetados diretamente como argumentos para o Startup.Configure método. Para obter mais informações, consulte Generic Host restringe a injeção do construtor de inicialização (aspnet/Announcements #353).
Kestrel
- A configuração Kestrel foi atualizada para a migração para o Host Genérico. Na versão 3.0, Kestrel é configurado no construtor de host da Web fornecido pelo
ConfigureWebHostDefaults. - Os Adaptadores de Conexão de Kestrel foram removidos e substituídos por Middleware de Conexão, que é semelhante ao Middleware HTTP no pipeline ASP.NET Core, mas para conexões de nível inferior.
- A Kestrel camada de transporte foi exposta como uma interface pública no
Connections.Abstractions. - A ambiguidade entre cabeçalhos e cabeçalhos de conclusão foi resolvida movendo os cabeçalhos de conclusão para uma nova coleção.
- As APIs de E/S síncronas, como
HttpRequest.Body.Read, são uma fonte comum de esgotamento de threads que leva a falhas de aplicações. Na versão 3.0,AllowSynchronousIOestá desativado por padrão.
Para obter mais informações, consulte Migrar do ASP.NET Core 2.2 para o 3.0.
HTTP/2 ativado por padrão
HTTP/2 está ativado por defeito em Kestrel para endpoints HTTPS. O suporte HTTP/2 para IIS ou HTTP.sys é ativado quando suportado pelo sistema operacional.
Contadores de eventos por solicitação
O Hosting EventSource, Microsoft.AspNetCore.Hosting, emite os seguintes novos EventCounter tipos relacionados a solicitações de entrada:
requests-per-secondtotal-requestscurrent-requestsfailed-requests
Roteamento de endereço de destino
O Roteamento de Pontos Finais, que permite que as estruturas (por exemplo, MVC) funcionem bem com middleware, é aprimorado:
- A ordem do middleware e dos endpoints é configurável no pipeline de processamento de solicitações do
Startup.Configure. - Os endpoints e o middleware combinam bem com outras tecnologias baseadas em ASP.NET Core, como verificações de saúde.
- Os endpoints podem implementar uma política, como CORS ou autorização, em middleware e MVC.
- Filtros e atributos podem ser colocados em métodos em controladores.
Para obter mais informações, consulte Roteamento no ASP.NET Core.
Verificações de Saúde
As Verificações de Integridade usam o roteamento de ponto de extremidade com o Host Genérico. No Startup.Configure, chame MapHealthChecks o construtor de pontos de extremidade com a URL do ponto de extremidade ou o caminho relativo:
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
Os Endpoints das Verificações de Integridade podem:
- Especifique um ou mais hosts/portas permitidos.
- Requer autorização.
- Exigir CORS.
Para obter mais informações, consulte os seguintes artigos:
Pipes em HttpContext
Agora é possível ler o corpo da solicitação e escrever o corpo da resposta usando a System.IO.Pipelines API. A HttpRequest.BodyReader propriedade fornece um PipeReader que pode ser usado para ler o corpo da solicitação. A HttpResponse.BodyWriter propriedade fornece um PipeWriter que pode ser usado para escrever o corpo da resposta.
HttpRequest.BodyReader é um análogo do HttpRequest.Body fluxo.
HttpResponse.BodyWriter é um análogo do HttpResponse.Body fluxo.
Relatório de erros melhorado no IIS
Os erros de inicialização ao hospedar aplicativos ASP.NET Core no IIS agora produzem dados de diagnóstico mais ricos. Esses erros são reportados ao Log de Eventos do Windows com rastreamentos de pilha quando aplicável. Além disso, todos os avisos, erros e exceções não tratadas são registrados no Log de Eventos do Windows.
Serviço de Trabalho e SDK do Trabalhador
O .NET Core 3.0 apresenta o novo modelo de aplicativo do Serviço de Trabalho. Este modelo fornece um ponto de partida para escrever serviços de longa execução no .NET Core.
Para obter mais informações, consulte:
- Trabalhadores do .NET Core como Serviços do Windows
- Tarefas em segundo plano com serviços hospedados no ASP.NET Core
- Host ASP.NET Core em um serviço do Windows
Melhorias no middleware para cabeçalhos encaminhados
Em versões anteriores do ASP.NET Core, chamavam UseHsts e UseHttpsRedirection eram problemáticos quando implantados em um Linux do Azure ou atrás de qualquer proxy reverso diferente do IIS. A correção para versões anteriores está documentada em Encaminhar o esquema para Linux e proxies inversos não-IIS.
Esse cenário é corrigido no ASP.NET Core 3.0. O host habilita o middleware de cabeçalhos encaminhados quando a ASPNETCORE_FORWARDEDHEADERS_ENABLED variável de ambiente é definida como true.
ASPNETCORE_FORWARDEDHEADERS_ENABLED está definido como true em nossas imagens de contêiner.
Melhorias de desempenho
ASP.NET Core 3.0 inclui muitas melhorias que reduzem o uso de memória e melhoram a taxa de transferência:
- Redução no uso de memória ao usar o contêiner de injeção de dependência interno para serviços com escopo.
- Redução nas alocações em toda a estrutura, incluindo cenários de middleware e roteamento.
- Redução no uso de memória para conexões WebSocket.
- Redução de memória e melhorias de taxa de transferência para conexões HTTPS.
- Novo serializador JSON otimizado e totalmente assíncrono.
- Redução no uso de memória e melhorias na taxa de transferência na análise de formulários.
ASP.NET Core 3.0 só é executado no .NET Core 3.0
A partir do ASP.NET Core 3.0, o .NET Framework não é mais uma estrutura de destino suportada. Os projetos destinados ao .NET Framework podem continuar de forma totalmente suportada usando a versão .NET Core 2.1 LTS. A maioria dos pacotes relacionados ao ASP.NET Core 2.1.x serão suportados indefinidamente, além do período LTS de três anos para o .NET Core 2.1.
Para obter informações sobre migração, consulte Portar seu código do .NET Framework para o .NET Core.
Usar a estrutura compartilhada ASP.NET Core
A estrutura compartilhada do ASP.NET Core 3.0, contida no metapacote Microsoft.AspNetCore.App, não requer mais um elemento explícito <PackageReference /> no arquivo de projeto. A estrutura compartilhada é referenciada automaticamente ao usar o Microsoft.NET.Sdk.Web SDK no arquivo de projeto:
<Project Sdk="Microsoft.NET.Sdk.Web">
Assemblies removidos da estrutura compartilhada do ASP.NET Core
Os assemblies mais notáveis removidos do framework partilhado do ASP.NET Core 3.0 são:
-
Newtonsoft.Json (Json.NET). Para adicionar Json.NET ao ASP.NET Core 3.0, consulte Adicionar suporte ao formato JSON baseado em Newtonsoft.Json. ASP.NET Core 3.0 introduz
System.Text.Jsonpara leitura e escrita JSON. Para obter mais informações, consulte Nova serialização JSON neste documento. - Núcleo do Entity Framework
Para obter uma lista completa de assemblies removidos da estrutura partilhada, consulte Assemblies que estão a ser removidos do Microsoft.AspNetCore.App 3.0. Para obter mais informações sobre a motivação para essa mudança, consulte Quebrando alterações no Microsoft.AspNetCore.App na versão 3.0 e Uma primeira olhada nas alterações que chegam no ASP.NET Core 3.0.
Alterações de grande impacto
Use os artigos em Alterações significativas no .NET para encontrar alterações significativas que podem ser aplicadas ao atualizar um aplicativo para uma versão mais recente do .NET.