ASP.NET Core no .NET 11 Preview 7: análise técnica das novidades

O .NET 11 Preview 7 chegou como a última grande janela de mudanças antes do fechamento de API do ciclo, e o ASP.NET Core concentra boa parte do peso desta versão. São catorze áreas com novidades funcionais, dez mudanças que quebram compatibilidade e uma lista extensa de correções de segurança e desempenho no pipeline de servidor.

Este artigo percorre cada bloco relevante, com atenção especial ao que exige ação de quem já testa o preview em bases de código reais.

O contexto do .NET 11 Preview 7

Vale o enquadramento antes de entrar nos detalhes. O .NET 11 é uma versão de suporte padrão (STS), com lançamento previsto para 10 de novembro de 2026 e dois anos de manutenção.

Por outro lado, o .NET 10 permanece como a linha de suporte de longo prazo (LTS), ativa até novembro de 2028. Portanto, ele continua sendo a escolha correta para quem prioriza estabilidade em produção.

Se você acompanha a série, as novidades anteriores do ciclo estão no artigo sobre o ASP.NET no .NET 11 Preview 5. Assim, fica mais fácil entender quais recursos o Preview 7 apenas completa.

Pausa automática de circuitos Blazor no .NET 11 Preview 7

Circuitos Interactive Server agora conseguem se pausar sozinhos quando a aba do navegador fica oculta. Com isso, o servidor libera recursos até o usuário retornar.

O Preview 6 já havia introduzido Circuit.RequestCircuitPauseAsync para a pausa sob demanda. Agora, o .NET 11 Preview 7 completa o ciclo com um pacote opcional que detecta a inatividade e dispara a pausa automaticamente.

A ativação exige a referência ao pacote Microsoft.AspNetCore.Components.Server.AutoPause e uma configuração via AddAutoPause sobre BrowserOptions:

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode()
    .WithBrowserOptions(options =>
    {
        // Pausa o circuito 30 segundos depois que a aba fica oculta
        options.AddAutoPause(pause =>
        {
            pause.Enabled = true;
            pause.HiddenDelay = TimeSpan.FromSeconds(30);
        });
    });

Segundo as notas de release, o valor padrão do HiddenDelay é de dois minutos. No exemplo acima, o atraso foi reduzido para 30 segundos.

Quando a pausa é adiada

O ponto mais interessante do desenho é o conjunto de adiamentos automáticos. A pausa não ocorre quando existe um campo de texto modificado ou um elemento de áudio ou vídeo tocando sem mudo.

Da mesma forma, ela também espera quando há uma janela em Picture-in-Picture, um Web Lock retido ou qualquer atividade de circuito em andamento.

Além disso, aplicações podem registrar o próprio critério de adiamento. Para isso, basta criar no cliente um circuit handler que implemente onCircuitPausing, registrado por um inicializador JavaScript.

O Blazor aguarda todos os handlers registrados antes de pausar, tanto no caminho automático quanto na pausa iniciada pelo servidor.

Como consequência, Circuit.RequestCircuitPauseAsync passou a retornar Task<bool> e a aceitar um token de cancelamento. Dessa forma, é possível abortar o adiamento quando a conexão está sendo encerrada.

CacheView no .NET 11 Preview 7

O CacheView é um componente novo do .NET 11 Preview 7 que armazena o HTML de uma subárvore renderizada no servidor. Em caso de acerto no cache, os componentes filhos não são instanciados nem renderizados de novo.

Ou seja, o HTML capturado anteriormente volta direto para a resposta. Na prática, isso reduz CPU e alocação em fragmentos caros.

<CacheView ExpiresAfter="TimeSpan.FromMinutes(10)"
           VaryByRoute="productId"
           VaryByQuery="page,pageSize"
           VaryByCulture="true">
    <ExpensiveProductSummary ProductId="productId" />
</CacheView>

O componente aceita expiração absoluta, com ExpiresAfter e ExpiresOn, e deslizante, com ExpiresSliding. Também oferece variação por query string, rota, cabeçalho, cookie, usuário autenticado e cultura corrente.

O armazenamento padrão fica em memória, limitado por RazorComponentsServiceOptions.CacheViewSizeLimit, com padrão de 100 MB. Além disso, o cache é ignorado em requisições que não sejam GET e dentro de SSR com streaming.

Integração com HybridCache

A integração com HybridCache merece destaque operacional. Se a aplicação registrar HybridCache no contêiner de injeção de dependência, o CacheView o adota automaticamente.

Com isso, o cache local vira uma estrutura de dois níveis sem nenhuma outra alteração de código.

Regras de segurança do cache

O risco previsível de um mecanismo assim é congelar conteúdo que depende de estado por requisição. Por isso, a equipe criou os atributos [CacheBehavior] e [CacheCondition].

Componentes como AntiforgeryToken e HeadOutlet recebem a marcação Rerender e sempre renderizam de novo. Já o AuthorizeView exige VaryByUser, e o QuickGrid exige VaryByQuery.

O Virtualize, por sua vez, simplesmente não pode ficar dentro de um CacheView. Quando a regra é violada, a exceção nomeia o componente e descreve a correção esperada, o que reduz bastante o custo de diagnóstico.

Novos analisadores Blazor no .NET 11 Preview 7

O .NET 11 Preview 7 adiciona cinco analisadores, todos habilitados por padrão com severidade Warning.

  • BL0012: detecta chamadas desnecessárias a StateHasChanged() em métodos nos quais o framework já agenda a renderização, como OnInitializedAsync, e oferece correção automática.
  • BL0013: sinaliza chamadas a GetAuthenticationStateAsync() sem assinatura de AuthenticationStateChanged, o que deixa o componente com estado de autenticação obsoleto.
  • BL0014: aponta contadores de laço for capturados por closures ou RenderFragment, defeito clássico que amarra os callbacks ao valor da última iteração.
  • BL0015: identifica métodos [JSInvokable] não públicos, que compilam, mas nunca podem ser chamados pelo JavaScript.
  • BL0016: marca chamadas a InvokeAsync ou InvokeVoidAsync fora de um bloco try/catch.

Como todos nascem em nível de aviso, uma base que compilava limpa no Preview 6 passará a exibir avisos após a atualização.

Quando não seguir o analisador

Dois casos exigem leitura crítica. O BL0012 acusa o padrão comum de chamar StateHasChanged() no início de um manipulador assíncrono, antes do primeiro await.

A chamada realmente é redundante nesse ponto. Contudo, quem depende de atualizar a interface antes de um bloco síncrono longo deve manter o await Task.Yield().

Já o BL0016 dispara também em bibliotecas que propagam JSException ou JSDisconnectedException de propósito para o chamador. Nesse caso, o correto é suprimir o diagnóstico com justificativa, e jamais engolir a exceção.

Virtualize e QuickGrid no .NET 11 Preview 7

O Virtualize<TItem> deixou de exigir um ItemComparer explícito. Agora, ele detecta inserções no início e no fim da coleção usando EqualityComparer<TItem>.Default.

Isso funciona para tipos por valor e para tipos por referência cujo provedor devolva referências estáveis.

O QuickGrid<TGridItem> passou a encaminhar InitialItemIndex e ScrollToItemAsync para o Virtualize interno. Assim, você abre a grade em uma linha específica e rola até um item pelo código.

Ambas as APIs só têm efeito com Virtualize="true". Além disso, ScrollToItemAsync lança InvalidOperationException se a virtualização estiver desligada ou se a grade ainda não tiver renderizado.

Toolchain WebAssembly e unions no Razor

A workload wasm-tools do .NET 11 passou do Emscripten 5.0.6 para o 6.0.3, atualizando musl libc, llvm/clang e libunwind. Esse toolchain atende a compilação AOT para WebAssembly e as dependências nativas.

Nenhuma alteração de código é necessária para aproveitar o novo toolchain.

No lado da linguagem, o compilador Razor passou a aceitar valores literais em parâmetros cujo tipo é uma união do C#. Então, o padrão de expor um string para o caso comum e um RenderFragment para o resto pode dar lugar a um único tipo.

@* Preview 6 *@
<Toast Message="@("Saved successfully.")" />

@* Preview 7 *@
<Toast Message="Saved successfully." />

Com isso, o consumo do componente volta a parecer natural, como em qualquer atributo HTML.

Validação no .NET 11 Preview 7

A validação recebeu três frentes de mudança no .NET 11 Preview 7: o comportamento no cliente, a localização das mensagens e a saída de atributos do estágio experimental.

Validação no cliente em SSR estático

A validação no cliente em formulários de SSR estático, introduzida no Preview 5, ficou mais próxima da validação interativa. Agora, o motor no navegador aplica as mesmas classes CSS.

Os campos recebem valid e invalid, além de modified após a edição. As mensagens usam validation-message, e os sumários ganham as variações de erro correspondentes.

Mais importante, regras de cliente só saem para campos que a validação de servidor também valida. Dessa forma, o navegador deixa de sinalizar um campo que o servidor ignora.

Localização embutida das mensagens

A localização de mensagens de validação passou a fazer parte do Microsoft.Extensions.Validation. Por isso, o pacote de preview Microsoft.Extensions.Validation.Localization saiu, junto com a API AddValidationLocalization<TResource>().

A localização entra em ação automaticamente assim que existe um IStringLocalizerFactory registrado. Além disso, o gerador de código emite a busca de chaves para dentro do próprio assembly.

// A localização das mensagens é ativada automaticamente
builder.Services.AddLocalization();
builder.Services.AddValidation();

As chaves são resolvidas contra os recursos do próprio modelo, com fallback para a mensagem embutida no atributo. Se preferir um arquivo compartilhado, ValidationOptions.LocalizerProvider permite apontar para ele.

Atributos personalizados que precisam substituir valores no template podem implementar IValidationMessageFormatter. As mesmas regras valem para minimal APIs e para Blazor.

Por fim, ValidatableTypeAttribute e SkipValidationAttribute deixaram de ser experimentais. Então, quem suprimia ASP0029 pode remover a supressão.

SignalR, autorização e OpenAPI

No .NET 11 Preview 7, o cliente .NET do SignalR mantém a renovação de autenticação funcionando quando a negociação redireciona para outro servidor. Para isso, ele preserva o provedor de token da aplicação durante o redirecionamento.

Além disso, o cliente adota o token de transporte renovado da resposta e retém tokenLifetimeSeconds. Assim, a renovação automática continua agendada.

Na camada de autorização, metadados como IAuthorizeData, AuthorizationPolicy ou IAuthorizationRequirementData passaram a ter tratamento uniforme. Isso vale para filtros do MVC, métodos de hub do SignalR e os componentes AuthorizeView e AuthorizeRouteView.

A implementação compartilhada é uma nova sobrecarga de AuthorizationPolicy.CombineAsync. Com ela, um atributo que implemente duas dessas formas contribui uma única vez para a decisão.

No OpenAPI, endpoints que retornam SseItem<T> passaram a usar a forma itemSchema do OpenAPI 3.2 para respostas text/event-stream. Ou seja, o documento descreve a carga de cada evento em vez de um esquema string genérico.

Para isso funcionar, o retorno deve passar por TypedResults.ServerSentEvents. Afinal, um IAsyncEnumerable<SseItem<T>> devolvido diretamente vira JSON comum.

Channel binding token e endurecimento de TLS

Com o .NET 11 Preview 7, aplicações sobre TLS conseguem ler o channel binding token da conexão a partir de ITlsConnectionFeature. Esse recurso é uma defesa direta contra ataques de retransmissão.

app.Use(async (context, next) =>
{
    var tls = context.Features.Get<ITlsConnectionFeature>();
    if (tls is not null && tls.TryGetChannelBindingBytes(
            ChannelBindingKind.Endpoint, out ReadOnlyMemory<byte> cbt))
    {
        // Comparar cbt com o token apresentado pelo cliente.
    }

    await next(context);
});

O Kestrel obtém o vínculo de SslStream.TransportContext.GetChannelBinding, enquanto IIS e HTTP.sys o extraem da requisição.

No HTTP.sys, a propriedade HttpSysOptions.HttpAuthenticationHardeningLevel controla o comportamento. O nível Legacy desabilita a validação, e o Medium expõe e valida o token quando presente.

Já o nível Strict exige o token e falha a inicialização caso o sistema operacional não consiga aplicar a configuração.

Mudanças que quebram compatibilidade no .NET 11 Preview 7

O .NET 11 Preview 7 traz dez mudanças que quebram compatibilidade no ASP.NET Core. Algumas afetam muitos projetos, enquanto outras só atingem quem usava APIs muito específicas.

Escopo da proteção contra CSRF

A mudança de maior impacto prático é a reversão parcial da proteção automática contra CSRF introduzida no Preview 6. Agora, o middleware valida apenas endpoints com IAntiforgeryMetadata { RequiresValidation: true }, a mesma regra do AntiforgeryMiddleware clássico.

Na prática, endpoints MapPost simples e ações MVC com [HttpPost] sem metadados de antiforgery voltam a passar direto. Dessa forma, o comportamento se alinha ao do .NET 10 e aplicações funcionais não quebram na migração.

Formulários de SSR do Blazor, binding de formulários em Razor Pages e MVC e minimal APIs com binding de formulário continuam protegidos. Isso acontece porque todos recebem RequireAntiforgeryTokenAttribute automaticamente.

Renomeações em virtualização e validação

As APIs de virtualização do Preview 6 mudaram de nome: InitialIndex virou InitialItemIndex, ScrollToIndexAsync virou ScrollToItemAsync e VirtualizeAnchorMode.Beginning virou Start.

Na validação de cliente do SSR, DataAnnotationsValidator.EnableClientValidation deu lugar a DisableClientValidation, com padrão false. Além disso, IClientValidationAdapter passou a se chamar IClientValidationRuleProvider.

O tipo dos erros em ValidateContext.ValidationErrors mudou de IEnumerable<string> para IReadOnlyList<ValidationError>. A nova classe ValidationError carrega Name, Path, ErrorMessage e Container.

As classes ValidatableTypeInfo, ValidatableParameterInfo e ValidatablePropertyInfo saíram da API pública. Agora, o gerador de código as emite como classes file, o que só afeta quem as construía diretamente.

Remoções e itens obsoletos

APIs obsoletas do MVC finalmente saíram, incluindo CompatibilityVersion, SetCompatibilityVersion e MvcCompatibilityOptions. Também nesta versão, EditContext.Validate ganhou a marcação de obsoleto em favor de EditContext.ValidateAsync.

No lado de ferramentas, UseWebAssemblyDebugging tornou-se obsoleto. O pacote Microsoft.AspNetCore.Components.WebAssembly.DevServer também foi depreciado em favor do novo Blazor Gateway, distribuído como pacote e como ferramenta de linha de comando.

Completam a lista a renomeação de WebApplicationFactory.ConfigureHostApplicationBuilder para ConfigureWebApplicationBuilder e a remoção do pacote Microsoft.AspNetCore.Grpc.Swagger. Por fim, a sessão ausente agora tem tratamento uniforme e falha rápido em SSR estático sem middleware de sessão.

Correções de segurança no .NET 11 Preview 7

A lista de correções do .NET 11 Preview 7 revela uma preocupação consistente com o endurecimento do pipeline de servidor. Entre elas, está a rejeição de cabeçalhos específicos de conexão enviados por nomes indexados em HPACK e QPACK.

Além disso, o servidor agora rejeita Content-Length com sinal e trata de forma mais rígida as requisições em chunks no ASP.NET Core Module. A janela de descompressão Zstandard também ganhou um limite de 8 MB.

O middleware de rewrite passou a colapsar barras iniciais em alvos relativos ao esquema e a normalizar contrabarras. Da mesma forma, PathString.StartsWithSegments passou a tratar contrabarras como limite de segmento.

São ajustes que raramente aparecem em notas de destaque. Mesmo assim, eles fecham vetores reais de contorno de autorização baseada em caminho.

Estratégia de adoção do .NET 11 Preview 7

O .NET 11 Preview 7 é um bom momento para testar e um péssimo momento para ir para produção. Afinal, versões de preview não têm suporte da Microsoft.

Quem está no .NET 8 ou no .NET 9 tem um problema mais urgente, porque ambas as linhas encerram o suporte em novembro de 2026. Esse é exatamente o mês previsto para a chegada do .NET 11.

O caminho seguro para esses times é migrar para o .NET 10, que é LTS e tem manutenção até novembro de 2028. Depois, vale avaliar o .NET 11 com base em uma necessidade concreta de recurso.

Para quem já está no .NET 10 e atualiza uma vez por ano, o CacheView, a pausa automática de circuitos e a localização embutida de validação são argumentos legítimos para o salto no lançamento oficial. Os detalhes completos estão no anúncio .NET 11 Preview 7 is now available, no blog oficial da Microsoft.

Para entender o rumo do Blazor no restante do ciclo, o artigo sobre o futuro do Blazor no .NET 11 complementa esta leitura.

Conclusão

O ASP.NET Core do .NET 11 Preview 7 tem uma personalidade clara: reduzir o custo operacional de aplicações Blazor com renderização no servidor. A pausa automática de circuitos ataca o consumo de memória em abas esquecidas, e o CacheView ataca a CPU em fragmentos caros.

Os analisadores, por sua vez, atacam uma classe de defeitos que só aparece em produção. Ao mesmo tempo, a reversão do escopo do CSRF mostra maturidade, porque a equipe preferiu preservar a compatibilidade com o .NET 10.

Para quem acompanha o ciclo, a recomendação é testar o .NET 11 Preview 7 em uma cópia da base. Em seguida, trate os cinco novos avisos com julgamento e revise as renomeações antes que o congelamento de API torne a migração inevitável.

FAQ

O .NET 11 Preview 7 pode ser usado em produção?

Não, versões de preview não têm suporte da Microsoft e servem apenas para teste público. O lançamento final está previsto para 10 de novembro de 2026.

Devo migrar para o .NET 11 ou para o .NET 10?

Se a prioridade for estabilidade, o .NET 10 é a resposta, por ser LTS com manutenção até novembro de 2028. O .NET 11 é STS, com dois anos de suporte.

A pausa automática de circuitos funciona sem instalar nada?

Não, é preciso adicionar o pacote Microsoft.AspNetCore.Components.Server.AutoPause. Depois, basta configurar AddAutoPause sobre BrowserOptions.

O CacheView funciona com cache distribuído?

Sim, basta registrar HybridCache no contêiner de injeção de dependência. O CacheView passa a usá-lo automaticamente, criando um cache de dois níveis.

Posso colocar qualquer componente dentro de um CacheView?

Não, componentes que dependem de estado por requisição usam [CacheBehavior] para controlar o cache. Além disso, o Virtualize não pode ficar dentro de um CacheView.

Os novos analisadores vão quebrar meu build?

Não, porque os cinco são emitidos como aviso. Ainda assim, projetos que tratam avisos como erros passarão a falhar.

A mudança no CSRF deixa minha aplicação menos segura?

Não necessariamente, porque formulários do Blazor SSR, do MVC, de Razor Pages e minimal APIs com binding de formulário continuam protegidos. Apenas endpoints sem metadados de antiforgery voltam ao comportamento do .NET 10.

Preciso remover app.UseWebAssemblyDebugging() do meu Program.cs?

Sim, se a chamada tiver sido adicionada manualmente, porque o método está obsoleto. O Visual Studio e o VS Code anexam o depurador de WebAssembly automaticamente.