Novidades do ASP.NET Core 9.0
Este artigo destaca as alterações mais significativas no ASP.NET Core 9.0 com links para a documentação relevante.
Este artigo foi atualizado para o .NET 9 Preview 5.
Blazor
Esta seção descreve os novos recursos do Blazor.
.NET MAUIBlazor Hybrid e um modelo de solução de Aplicativo Web
Um novo modelo de solução facilita a criação de aplicativos de cliente Web do Blazor e nativos do .NET MAUI que compartilham a mesma interface do usuário. Esse modelo mostra como criar aplicativos cliente que maximizam a reutilização de código e opções para Android, iOS, Mac, Windows e Web.
Os principais recursos deste modelo incluem:
- A capacidade de escolher um modo de renderização interativo Blazor para o aplicativo Web.
- Criação automática dos projetos apropriados, incluindo um aplicativo Blazor para a web (renderização automática interativa global) e um aplicativo .NET MAUIBlazor Hybrid.
- Os projetos criados usam uma biblioteca de classes do Razor (RCL) compartilhada para manter os componentes Razor da interface do usuário.
- Está incluída uma amostra de código que demonstra como usar a injeção de dependências para fornecer diferentes implementações de interface para o aplicativo Blazor Hybrid e o Aplicativo Web do Blazor.
Para começar, instale o SDK do .NET 9 e instale a carga de trabalho do .NET MAUI que contém o modelo:
dotnet workload install maui
Crie uma solução a partir do modelo de projeto em um shell de comando usando o seguinte comando:
dotnet new maui-blazor-web
O modelo também está disponível no Visual Studio.
Observação
Atualmente, ocorrerá uma exceção se os modos de renderização do Blazor forem definidos no nível por página/componente. Para obter mais informações, confira BlazorO WebView precisa de uma maneira de habilitar a substituição de ResolveComponentForRenderMode (dotnet/aspnetcore
nº 51235).
Para obter mais informações, confira Criar um aplicativo .NET MAUIBlazor Hybrid com um aplicativo web do Blazor.
Otimização de entrega de ativos estáticos
MapStaticAssets
é um novo middleware que ajuda a otimizar a entrega de ativos estáticos em qualquer aplicativo do ASP.NET Core, incluindo aplicativos Blazor.
Para obter mais informações, consulte um dos seguintes recursos:
- A seção desse artigo Como otimizar a entrega de ativos web estáticos.
- Arquivos estáticos do Blazor no ASP.NET Core.
Detectar o local de renderização, a interatividade e o modo de renderização atribuído no runtime
Introduzimos uma nova API projetada para simplificar o processo de consulta de estados de componentes no runtime. Essa API fornece os seguintes recursos:
- Determinar o local de execução atual do componente, o que pode ser particularmente útil para depurar e otimizar o desempenho do componente.
- Verificar se o componente está em execução em um ambiente interativo, o pode ser útil para componentes que têm comportamentos diferentes com base na interatividade de seu ambiente.
- Recuperar o modo de renderização atribuído ao componente: entender o modo de renderização pode ajudar a otimizar o processo de renderização e aprimorar o desempenho de um componente de modo geral.
Experiência de reconexão aprimorada do lado do servidor:
Os seguintes aprimoramentos foram feitos na experiência de reconexão padrão do lado do servidor:
Quando o usuário navega de volta para um aplicativo com um circuito desconectado, a reconexão é tentada imediatamente, em vez de aguardar todo o intervalo de tempo até a próxima reconexão. Isso aprimora a experiência do usuário quando este navega até um aplicativo em uma guia do navegador que entrou no modo de suspensão.
Quando uma tentativa de reconexão chega ao servidor, mas o servidor já liberou o circuito, a página é atualizada automaticamente. Isso impede que o usuário precise atualizar a página manualmente se o provável resultado for uma reconexão bem-sucedida.
O tempo decorrido até a reconexão usa uma estratégia de espera calculada. Por padrão, as primeiras várias tentativas de reconexão ocorrem em rápida sucessão sem um intervalo de repetição, antes que os atrasos calculados sejam introduzidos entre as tentativas. Você pode personalizar o comportamento do intervalo de repetição especificando uma função para calcular o intervalo de repetição, como demonstra o exemplo de espera exponencial a seguir:
Blazor.start({ circuit: { reconnectionOptions: { retryIntervalMilliseconds: (previousAttempts, maxRetries) => previousAttempts >= maxRetries ? null : previousAttempts * 1000 }, }, });
O estilo da interface do usuário de reconexão padrão foi modernizado.
Para obter mais informações, confira as diretrizes BlazorSignalRdo ASP.NET Core.
Serialização de estado de autenticação simplificada para Aplicativos Web Blazor
Novas APIs facilitam o acréscimo de autenticação a um Aplicativo Web do Blazor existente. Quando você cria um novo Aplicativo Web do Blazor com autenticação usando Contas Individuais e habilita a interatividade baseada em WebAssembly, o projeto inclui um AuthenticationStateProvider personalizado tanto nos projetos do servidor quanto do cliente.
Esses provedores fazem com que o estado de autenticação do usuário flua para o navegador. A autenticação no servidor em vez de no cliente permite que o aplicativo acesse o estado de autenticação durante a pré-renderização e antes que o runtime Blazor WebAssembly seja inicializado.
As implementações de AuthenticationStateProvider personalizadas usam o Serviço do Estado de Componente Persistente (PersistentComponentState) para serializar o estado de autenticação em comentários HTML e, em seguida, lê-lo de volta a partir do WebAssembly para criar uma nova instância de AuthenticationState.
Isso funcionará bem se você tiver começado a partir do modelo de projeto do Aplicativo Web do Blazor e selecionado a opção Contas Individuais, mas envolve muito código para implementar por conta própria ou para copiar, se você estiver tentando adicionar autenticação a um projeto existente. Agora temos APIs, que já fazem parte do modelo de projeto do Aplicativo Web do Blazor e podem ser chamadas nos projetos do servidor e do cliente para adicionar essa funcionalidade:
AddAuthenticationStateSerialization
: adiciona os serviços necessários para serializar o estado de autenticação no servidor.AddAuthenticationStateDeserialization
: adiciona os serviços necessários para desserializar o estado de autenticação no navegador.
Por padrão, a API só serializa as declarações de nome e função do lado do servidor para acesso no navegador. Uma opção pode ser repassada para AddAuthenticationStateSerialization
de modo a incluir todas as declarações.
Para obter mais informações, confira as seguintes seções do artigo **:
- Interface do usuário de BlazorIdentity (Contas Individuais)
- Gerenciar o estado da autenticação em aplicativos Web Blazor
Adicionar páginas de SSR (renderização do lado do servidor) estático a um aplicativo Web Blazor globalmente interativo
Com o lançamento do .NET 9, agora é mais simples adicionar páginas SSR estáticas a aplicativos que adotam interatividade global.
Essa abordagem só é útil quando o aplicativo tem páginas específicas que não podem funcionar com a renderização interativa do Servidor ou WebAssembly. Por exemplo, adote essa abordagem para páginas que dependem da leitura/gravação de HTTP cookiee só podem funcionar em um ciclo de solicitação/resposta em vez de renderização interativa. Para páginas que funcionam com renderização interativa, você não deve forçá-las a usar a renderização SSR estática, pois ela é menos eficiente e menos responsiva para o usuário final.
Marque qualquer página de componente Razor com o novo atributo [ExcludeFromInteractiveRouting]
atribuído com a diretiva @attribute
Razor:
@attribute [ExcludeFromInteractiveRouting]
A aplicação do atributo faz com que a navegação na página saia do roteamento interativo. A navegação de entrada é forçada a executar um recarregamento de página inteira, resolvendo a página por meio de roteamento interativo. O recarregamento de página inteira força o componente raiz de nível superior, normalmente o componente App
(App.razor
), a gerar novamente do servidor, permitindo que o aplicativo mude para um modo de renderização de nível superior diferente.
O método de extensão HttpContext.AcceptsInteractiveRouting
permite que o componente detecte se [ExcludeFromInteractiveRouting]
é aplicado à página atual.
No componente App
, use o padrão no exemplo a seguir:
- Páginas que não são anotadas com
[ExcludeFromInteractiveRouting]
padrão para o modo de renderizaçãoInteractiveServer
com interatividade global. Você pode substituirInteractiveServer
porInteractiveWebAssembly
ouInteractiveAuto
para especificar um modo de renderização global padrão diferente. - Páginas anotadas com
[ExcludeFromInteractiveRouting]
adotar SSR estático (PageRenderMode
é atribuídonull
).
<!DOCTYPE html>
<html>
<head>
...
<HeadOutlet @rendermode="@PageRenderMode" />
</head>
<body>
<Routes @rendermode="@PageRenderMode" />
...
</body>
</html>
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? PageRenderMode
=> HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}
Uma alternativa ao uso do método de extensão HttpContext.AcceptsInteractiveRouting
é ler metadados de ponto de extremidade manualmente usando HttpContext.GetEndpoint()?.Metadata
.
Esse recurso é abordado pela documentação de referência nos Modos de renderização Blazor do ASP.NET Core .
Injeção de construção
Os componentes Razor dão suporte à injeção do construtor.
No exemplo a seguir, a classe parcial (code-behind) injeta o serviço NavigationManager
usando um construtor primário:
public partial class ConstructorInjection(NavigationManager navigation)
{
protected NavigationManager Navigation { get; } = navigation;
}
Para saber mais, confira Injeção de dependência do Blazor no ASP.NET Core.
Compactação de Websocket para componentes do Servidor Interativo
Por padrão, os componentes do Servidor Interativo habilitam a compactação para conexões WebSocket e definem uma diretiva frame-ancestors
Política de Segurança de Conteúdo (CSP) definida como 'self'
, que só permite a incorporação do aplicativo em uma origem <iframe>
da qual o aplicativo é servido quando a compactação está habilitada ou quando uma configuração para o contexto do WebSocket é fornecida.
A compactação pode ser desabilitada definindo ConfigureWebSocketOptions
como null
, o que reduz a vulnerabilidade do aplicativo a ataques, mas pode resultar em desempenho reduzido:
.AddInteractiveServerRenderMode(o => o.ConfigureWebSocketOptions = null)
Configure um CSP frame-ancestors
mais restrito com um valor de 'none'
(aspas simples obrigatórias), que permite a compactação do WebSocket mas impede que os navegadores incorporem o aplicativo em qualquer <iframe>
:
.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")
Para saber mais, consulte os recursos a seguir:
- Diretrizes BlazorSignalR do ASP.NET Core
- Diretrizes de mitigação de ameaças para a renderização interativa do ASP.NET Core Blazor do lado do servidor
Manipular eventos de composição de teclado no Blazor
A nova propriedade KeyboardEventArgs.IsComposing
indica se o evento de teclado faz parte de uma sessão de composição. Acompanhar o estado de composição de eventos de teclado é crucial para lidar com métodos de entrada de caracteres internacionais.
Parâmetro OverscanCount
adicionado a QuickGrid
O componente QuickGrid
agora expõe uma propriedade OverscanCount
que especifica quantas linhas adicionais são renderizadas antes e depois da região visível quando a virtualização está habilitada.
O OverscanCount
padrão é 3. O exemplo a seguir aumenta o OverscanCount
para 4:
<QuickGrid ItemsProvider="itemsProvider" Virtualize="true" OverscanCount="4">
...
</QuickGrid>
SignalR
Esta seção descreve os novos recursos do SignalR.
Suporte a tipos polimórficos em Hubs SignalR
Os métodos de hub agora podem aceitar uma classe base em vez da classe derivada para habilitar cenários polimórficos. O tipo base precisa ser anotado para permitir o polimorfismo.
public class MyHub : Hub
{
public void Method(JsonPerson person)
{
if (person is JsonPersonExtended)
{
}
else if (person is JsonPersonExtended2)
{
}
else
{
}
}
}
[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended), nameof(JsonPersonExtended))]
[JsonDerivedType(typeof(JsonPersonExtended2), nameof(JsonPersonExtended2))]
private class JsonPerson
{
public string Name { get; set; }
public Person Child { get; set; }
public Person Parent { get; set; }
}
private class JsonPersonExtended : JsonPerson
{
public int Age { get; set; }
}
private class JsonPersonExtended2 : JsonPerson
{
public string Location { get; set; }
}
APIs mínimas
Essa seção descreve novos recursos para APIs mínimas.
InternalServerError
e InternalServerError<TValue>
foram adicionados a TypedResults
A classe TypedResults é um veículo útil para retornar respostas baseadas em código de status HTTP fortemente tipado de uma API mínima. TypedResults
agora inclui métodos e tipos de fábrica para retornar respostas de "500 Erro Interno do Servidor" de pontos de extremidade. Este é um exemplo que retorna uma resposta 500:
var app = WebApplication.Create();
app.MapGet("/", () => TypedResults.InternalServerError("Something went wrong!"));
app.Run();
OpenAPI
Suporte interno para geração de documentos OpenAPI
A especificação OpenAPI é um padrão para descrever APIs HTTP. O padrão permite que os desenvolvedores definam a forma de APIs que podem ser conectadas a geradores de cliente, geradores de servidor, ferramentas de teste, documentação e muito mais. No .NET 9 Preview, o ASP.NET Core fornece suporte interno para gerar documentos OpenAPI que representam APIs baseadas em controlador ou mínimas por meio do pacote Microsoft.AspNetCore.OpenApi.
As seguintes chamadas de código realçadas:
AddOpenApi
para registrar as dependências necessárias no contêiner de DI do aplicativo.MapOpenApi
para registrar os pontos de extremidade OpenAPI necessários nas rotas do aplicativo.
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/hello/{name}", (string name) => $"Hello {name}"!);
app.Run();
Instale o pacote Microsoft.AspNetCore.OpenApi
no projeto usando o seguinte comando:
dotnet add package Microsoft.AspNetCore.OpenApi --prerelease
Execute o aplicativo e navegue até openapi/v1.json
para exibir o documento OpenAPI gerado:
Documentos OpenAPI também podem ser gerados no tempo de build adicionando o pacote Microsoft.Extensions.ApiDescription.Server
:
dotnet add package Microsoft.Extensions.ApiDescription.Server --prerelease
No arquivo de projeto do aplicativo, adicione o seguinte:
<PropertyGroup>
<OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
</PropertyGroup>
Execute dotnet build
e inspecione o arquivo JSON gerado no diretório do projeto.
A geração de documentos OpenAPI interna do ASP.NET Core oferece suporte para várias personalizações e opções. Ela fornece transformadores de documento e operação e tem a capacidade de gerenciar vários documentos OpenAPI para o mesmo aplicativo.
Para saber mais sobre os novos recursos de documento OpenAPI do ASP.NET Core, consulte os novos documentos Microsoft.AspNetCore.OpenApi.
Autenticação e autorização
Esta seção descreve os novos recursos de autenticação e autorização.
Personalização do parâmetro OIDC e OAuth
Os manipuladores de autenticação OAuth e OIDC agora têm uma opção AdditionalAuthorizationParameters
para facilitar a personalização dos parâmetros de mensagem de autorização que geralmente são incluídos como parte da cadeia de caracteres de consulta de redirecionamento. No .NET 8 e anterior, isso requer um retorno de chamada personalizado OnRedirectToIdentityProvider ou um método substituído BuildChallengeUrl em um manipulador personalizado. Aqui está um exemplo de código .NET 8:
builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("prompt", "login");
context.ProtocolMessage.SetParameter("audience", "https://api.example.com");
return Task.CompletedTask;
};
});
O exemplo anterior agora pode ser simplificado para o seguinte código:
builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
options.AdditionalAuthorizationParameters.Add("prompt", "login");
options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});
Configurar sinalizadores de autenticação estendida HTTP.sys
Agora você pode configurar os sinalizadores HTTP.sys HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING
e HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL
usando as novas propriedades EnableKerberosCredentialCaching
e CaptureCredentials
no HTTP.sys AuthenticationManager para otimizar o modo como a autenticação do Windows é tratada. Por exemplo:
webBuilder.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
options.Authentication.EnableKerberosCredentialCaching = true;
options.Authentication.CaptureCredentials = true;
});
Diversos
As seções a seguir descrevem diversos novos recursos.
Nova biblioteca de HybridCache
A API HybridCache
abre algumas lacunas nas APIs IDistributedCache e IMemoryCache existentes. Ele também adiciona novos recursos, como:
- Proteção "Stampede" para impedir buscas paralelas do mesmo trabalho.
- Serialização configurável.
HybridCache
foi projetado para ser uma substituição suspensa para uso de IDistributedCache
e IMemoryCache
existentes e fornece uma API simples para adicionar um novo código de cache. Ele fornece uma API unificada para cache em processo e fora do processo.
Para ver como a API HybridCache
é simplificada, compare-a com o código que usa IDistributedCache
. Aqui está um exemplo de como é usar IDistributedCache
:
public class SomeService(IDistributedCache cache)
{
public async Task<SomeInformation> GetSomeInformationAsync
(string name, int id, CancellationToken token = default)
{
var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
var bytes = await cache.GetAsync(key, token); // Try to get from cache.
SomeInformation info;
if (bytes is null)
{
// Cache miss; get the data from the real source.
info = await SomeExpensiveOperationAsync(name, id, token);
// Serialize and cache it.
bytes = SomeSerializer.Serialize(info);
await cache.SetAsync(key, bytes, token);
}
else
{
// Cache hit; deserialize it.
info = SomeSerializer.Deserialize<SomeInformation>(bytes);
}
return info;
}
// This is the work we're trying to cache.
private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
CancellationToken token = default)
{ /* ... */ }
}
Isso é muito trabalho para acertar a cada vez, incluindo coisas como serialização. E no cenário de falha de cache, você pode acabar com vários threads simultâneos, todos recebendo uma falha de cache, todos buscando os dados subjacentes, todos serializando-os e todos enviando esses dados para o cache.
Para simplificar e melhorar esse código com HybridCache
, primeiro precisamos adicionar a nova biblioteca Microsoft.Extensions.Caching.Hybrid
:
<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0" />
Registre o serviço HybridCache
, como você registraria uma implementação de IDistributedCache
:
services.AddHybridCache(); // Not shown: optional configuration API.
Agora, a maioria das preocupações de cache pode ser descarregada para HybridCache
:
public class SomeService(HybridCache cache)
{
public async Task<SomeInformation> GetSomeInformationAsync
(string name, int id, CancellationToken token = default)
{
return await cache.GetOrCreateAsync(
$"someinfo:{name}:{id}", // Unique key for this combination.
async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
token: token
);
}
}
Fornecemos uma implementação concreta da classe abstrata HybridCache
por meio da injeção de dependência, mas a intenção é que os desenvolvedores possam fornecer implementações personalizadas da API. A implementação HybridCache
lida com tudo relacionado ao cache, incluindo o tratamento de operações simultâneas. O token cancel
aqui representa o cancelamento combinado de todos os chamadores simultâneos - não apenas o cancelamento do chamador que podemos ver (ou seja, token
).
Cenários de alta taxa de transferência podem ser otimizados ainda mais usando o padrão TState
, para evitar alguma sobrecarga de variáveis capturadas e retornos de chamada por instância:
public class SomeService(HybridCache cache)
{
public async Task<SomeInformation> GetSomeInformationAsync(string name, int id, CancellationToken token = default)
{
return await cache.GetOrCreateAsync(
$"someinfo:{name}:{id}", // unique key for this combination
(name, id), // all of the state we need for the final call, if needed
static async (state, token) =>
await SomeExpensiveOperationAsync(state.name, state.id, token),
token: token
);
}
}
HybridCache
usa a implementação de IDistributedCache
configurada, se houver, para o cache fora de processo secundário, por exemplo, usando o Redis. Mas mesmo sem um IDistributedCache
, o serviço HybridCache
ainda fornecerá proteção contra cache e "debandada" em processo.
Uma anotação sobre a reutilização do objeto
No código existente típico que usa IDistributedCache
, cada recuperação de um objeto do cache resulta em desserialização. Esse comportamento significa que cada chamador simultâneo obtém uma instância separada do objeto, que não pode interagir com outras instâncias. O resultado é a segurança de thread, pois não há risco de modificações simultâneas na mesma instância de objeto.
Como muitos HybridCache
uso serão adaptados do código IDistributedCache
existente, HybridCache
preserva esse comportamento por padrão para evitar a introdução de bugs de simultaneidade. No entanto, um determinado caso de uso é inerentemente thread-safe:
- Se os tipos que estão sendo armazenados em cache forem imutáveis.
- Se o código não os modificar.
Nesses casos, informe HybridCache
que é seguro reutilizar instâncias:
- Marcando o tipo como
sealed
. A palavra-chavesealed
em C# significa que a classe não pode ser herdada. - Aplicando o atributo
[ImmutableObject(true)]
a ele. O atributo[ImmutableObject(true)]
indica que o estado do objeto não pode ser alterado depois de criado.
Ao reutilizar instâncias, HybridCache
pode reduzir a sobrecarga de alocações de CPU e objeto associadas à desserialização por chamada. Isso pode levar a melhorias de desempenho em cenários em que os objetos armazenados em cache são grandes ou acessados com frequência.
Outros recursos de HybridCache
Assim como IDistributedCache
, HybridCache
dá suporte à remoção por chave com um método RemoveKeyAsync
.
HybridCache
também fornece APIs opcionais para implementações de IDistributedCache
, para evitar alocações byte[]
. Esse recurso é implementado pelas versões prévias dos pacotes Microsoft.Extensions.Caching.StackExchangeRedis
e Microsoft.Extensions.Caching.SqlServer
.
A serialização é configurada como parte do registro do serviço, com suporte para serializadores específicos do tipo e generalizados por meio dos métodos WithSerializer
e .WithSerializerFactory
, encadeados da chamada AddHybridCache
. Por padrão, a biblioteca manipula string
e byte[]
internamente e usa System.Text.Json
para todo o resto, mas você pode usar protobuf, xml ou qualquer outra coisa.
HybridCache
dá suporte a runtimes mais antigos do .NET, até .NET Framework 4.7.2 e .NET Standard 2.0.
Para obter mais informações sobre HybridCache
, consulte Biblioteca HybridCache no ASP.NET Core
Melhorias na página de exceção do desenvolvedor
A página de exceção do desenvolvedor do ASP.NET Core é exibida quando um aplicativo lança uma exceção não tratada durante o desenvolvimento. A página de exceção do desenvolvedor fornece informações detalhadas sobre a exceção e a solicitação.
A versão prévia 3 adicionou metadados de ponto de extremidade à página de exceção do desenvolvedor. ASP.NET Core usa metadados de ponto de extremidade para controlar o comportamento do ponto de extremidade, como roteamento, cache de resposta, limitação de taxa, geração OpenAPI e muito mais. A imagem a seguir mostra as novas informações de metadados na seção Routing
da página de exceção do desenvolvedor:
Durante o teste da página de exceção do desenvolvedor, foram identificados pequenos aprimoramentos de qualidade de vida. Eles foram enviados na versão prévia 4:
- Melhor disposição de texto. Longos cookies, de cadeia de caracteres de consulta e de método não adicionam mais barras de rolagem horizontal do navegador.
- Texto maior que é encontrado em designs modernos.
- Tamanhos de tabela mais consistentes.
A imagem animada a seguir mostra a nova página de exceção do desenvolvedor:
Melhorias de depuração do dicionário
A exibição de depuração de dicionários e outras coleções de chave-valor tem um layout aprimorado. A chave é exibida na coluna de chave do depurador em vez de ser concatenada com o valor. As imagens a seguir mostram a exibição antiga e nova de um dicionário no depurador.
Antes:
Depois:
O ASP.NET Core tem muitas coleções de chave-valor. Essa experiência de depuração aprimorada se aplica a:
- Cabeçalhos HTTP
- Cadeias de consulta
- Formulários
- Cookies
- Exibir dados
- Rotear dados
- Recursos
Correção para 503 durante o ciclo de aplicativo no IIS
Por padrão, agora há um atraso de 1 segundo entre quando o IIS é notificado de um ciclo ou desligamento e quando o ANCM informa ao servidor gerenciado para começar a desligar. O atraso é configurável por meio da variável de ambiente ANCM_shutdownDelay
ou definindo a configuração do manipulador de shutdownDelay
. Ambos os valores estão em milissegundos. O atraso é principalmente para reduzir a probabilidade de uma corrida em que:
- O IIS não começou a enfileirar solicitações para ir para o novo aplicativo.
- O ANCM começa a rejeitar novas solicitações que entram no aplicativo antigo.
Computadores ou computadores mais lentos com uso mais pesado da CPU podem querer ajustar esse valor para reduzir a probabilidade de 503.
Exemplo de configuração shutdownDelay
:
<aspNetCore processPath="dotnet" arguments="myapp.dll" stdoutLogEnabled="false" stdoutLogFile=".logsstdout">
<handlerSettings>
<!-- Milliseconds to delay shutdown by.
this doesn't mean incoming requests will be delayed by this amount,
but the old app instance will start shutting down after this timeout occurs -->
<handlerSetting name="shutdownDelay" value="5000" />
</handlerSettings>
</aspNetCore>
A correção está no módulo ANCM globalmente instalado que vem do pacote de hospedagem.
Otimizando a entrega de ativos da Web estáticos
A criação de aplicativos Web com desempenho inclui a otimização da entrega de ativos para o navegador. Isso envolve muitos aspectos, como:
- Definir os cabeçalhos ETag e Last-Modified.
- Configurar cabeçalhos de cache adequados.
- Usar middleware de cache.
- Servir versões compactadas dos ativos quando possível.
- Usar uma CDN para atender os ativos mais próximos do usuário.
- Diminuir os ativos.
MapStaticAssets
é um novo middleware que ajuda a otimizar a entrega de ativos estáticos em um aplicativo. Ele foi projetado para funcionar com todas as estruturas de interface do usuário, incluindo Blazor, Razor Pages e MVC. Normalmente, é uma substituição direta (drop-in) para UseStaticFiles
.
MapStaticAssets
opera combinando processos de build e de tempo de publicação para coletar informações sobre todos os recursos estáticos em um aplicativo. Essas informações são então utilizadas pela biblioteca de runtime para servir esses arquivos ao navegador com eficiência.
MapStaticAssets
pode substituir UseStaticFiles
na maioria das situações; no entanto, ele é otimizado para atender aos ativos dos quais o aplicativo tem conhecimento no tempo de compilação e publicação. Se o aplicativo atender ativos de outros locais, como disco ou recursos inseridos, o UseStaticFiles
deverá ser usado.
MapStaticAssets
fornece os seguintes benefícios não encontrados com UseStaticFiles
:
- Compactação de tempo de build para todos os ativos no aplicativo:
gzip
durante o desenvolvimento egzip + brotli
durante a publicação.- Todos os ativos são compactados com a meta de reduzir o tamanho dos ativos ao mínimo.
ETags
baseado em conteúdo: asEtags
para cada recurso são a cadeia de caracteres codificada em Base64 do hash SHA-256 do conteúdo. Isso garante que o navegador só recarregue um arquivo se o conteúdo tiver sido alterado.
A tabela a seguir mostra os tamanhos originais e compactados do CSS e dos arquivos JS no modelo padrão do Razor Pages:
Arquivo | Original | Compressed | Redução de % |
---|---|---|---|
bootstrap.min.css | 163 | 17.5 | 89,26% |
jquery.js | 89,6 | 28 | 68,75% |
bootstrap.min.js | 78,5 | 20 | 74,52% |
Total | 331,1 | 65,5 | 80,20% |
A tabela a seguir mostra os tamanhos originais e compactados usando a Biblioteca de componentes Blazor da interface do usuário do Fluent:
Arquivo | Original | Compressed | Redução de % |
---|---|---|---|
fluent.js | 384 | 73 | 80.99% |
fluent.css | 94 | 11 | 88,30% |
Total | 478 | 84 | 82,43% |
Para um total de 478 KB descompactados a 84 KB compactados.
A tabela a seguir mostra os tamanhos originais e compactados usando a biblioteca de componentes MudBlazorBlazor:
Arquivo | Original | Compressed | Redução |
---|---|---|---|
MudBlazor.min.css | 541 | 37,5 | 93,07% |
MudBlazor.min.js | 47.4 | 9.2 | 80,59% |
Total | 588,4 | 46,7 | 92,07% |
A otimização ocorre automaticamente ao usar MapStaticAssets
. Quando uma biblioteca é adicionada ou atualizada, por exemplo, com o novo JavaScript ou CSS, os ativos são otimizados como parte do build. A otimização é especialmente benéfica para ambientes móveis que podem ter uma largura de banda menor ou conexões não confiáveis.
Habilitar a compactação dinâmica no servidor versus usar MapStaticAssets
MapStaticAssets
tem as seguintes vantagens em relação à compactação dinâmica no servidor:
- É mais simples porque não há nenhuma configuração específica do servidor.
- É mais eficaz porque os ativos são compactados no momento da compilação.
- Permite que o desenvolvedor gaste tempo extra durante o processo de build para garantir que os ativos sejam do tamanho mínimo.
Considere a tabela a seguir comparando a compactação MudBlazor com a compactação dinâmica do IIS e MapStaticAssets
:
Gzip do IIS | MapStaticAssets | Redução de MapStaticAssets |
---|---|---|
≅ 90 | 37,5 | 59% |
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários