ASP.NET no .NET 11 Preview 5: novidades e melhorias

O ASP.NET no .NET 11 ganhou um pacote robusto de novidades com o Preview 5, lançado em junho de 2026, e a maior parte delas mira o Blazor. Além disso, a versão traz ajustes no Kestrel, na geração de documentos OpenAPI e uma série de correções reportadas pela comunidade.

Neste artigo, você vai ver cada novidade com exemplos de código e o impacto prático de cada mudança. Por isso, vale ler com o editor aberto e testar os trechos em um projeto de estudo.

O que muda no ASP.NET no .NET 11 Preview 5

O Preview 5 concentra suas entregas em quatro frentes: formulários, gerenciamento de estado, interoperabilidade entre modos de renderização e infraestrutura para aplicações WebAssembly. Em outras palavras, o time da Microsoft atacou pontos que incomodavam quem trabalha com renderização mista.

Na prática, o ASP.NET no .NET 11 caminha para reduzir as diferenças entre o Blazor estático e o Blazor interativo. Assim, recursos que antes exigiam um circuito SignalR ou o runtime WebAssembly passam a funcionar também em páginas renderizadas no servidor.

Vale lembrar que se trata de uma versão preview. Portanto, nomes de APIs e comportamentos ainda podem mudar até o lançamento final, como de fato aconteceu com algumas APIs citadas aqui.

A documentação oficial reúne tudo em What's new in ASP.NET Core in .NET 11, que a Microsoft atualiza a cada preview.

Validação de formulários no Blazor

A validação de formulários recebeu três melhorias no ASP.NET no .NET 11 Preview 5. Primeiro, a validação no cliente para SSR, em seguida a validação assíncrona e, por fim, a localização das mensagens de erro.

Validação client-side no Blazor SSR

Uma das adições mais esperadas para formulários Blazor em modo SSR (Static Server-Side Rendering) é a validação nativa no lado do cliente. Com isso, o usuário recebe retorno sem precisar de um round-trip ao servidor.

Antes, formulários renderizados de forma estática só validavam os dados depois do envio. Dessa forma, a experiência ficava inferior à do MVC com unobtrusive validation ou à dos componentes Blazor interativos.

Agora, formulários SSR que usam o componente DataAnnotationsValidator fornecem feedback instantâneo no navegador. O servidor renderiza os metadados das regras, e o JavaScript do Blazor aplica essas regras no cliente.

Assim, o modelo .NET continua como a única fonte de verdade para as regras de negócio. O recurso vem ativo por padrão em todos os formulários SSR com DataAnnotationsValidator, tanto enhanced quanto não enhanced.

<EditForm Model="Model" Enhance FormName="registration" OnValidSubmit="HandleValidSubmit">
    <DataAnnotationsValidator />

    <div>
        <label for="Email">Email</label>
        <InputText @bind-Value="Model!.Email" id="Email" />
        <ValidationMessage For="@(() => Model!.Email)" />
    </div>

    <div>
        <label for="Password">Password</label>
        <InputText @bind-Value="Model!.Password" id="Password" type="password" />
        <ValidationMessage For="@(() => Model!.Password)" />
    </div>

    <button type="submit" id="submit-btn">Register</button>
</EditForm>

O modelo de dados permanece idêntico ao do modo interativo, com Data Annotations convencionais. Ou seja, você não precisa duplicar regras em JavaScript para ter validação imediata.

Contudo, a validação no cliente não substitui a validação no servidor. Ela melhora a experiência, enquanto o servidor continua responsável pela segurança dos dados.

Validação assíncrona no ASP.NET do .NET 11

O Preview 5 também introduz suporte a validações assíncronas em formulários Blazor. Por exemplo, você pode consultar o banco de dados ou chamar uma API externa para verificar se um nome de usuário está disponível.

Em qualquer modo de renderização, a validação no submit do EditForm agora aguarda a conclusão dos validadores assíncronos. Já nos modos interativos, componentes validadores registram tarefas assíncronas por campo via EditContext.AddValidationTask.

O framework rastreia essas tarefas e cancela execuções que ficaram obsoletas. Além disso, ele expõe o progresso com IsValidationPending(field) e IsValidationFaulted(field).

<EditForm EditContext="editContext" OnSubmit="HandleSubmit">
    <InputText @bind-Value="model.Username" />
    @if (editContext.IsValidationPending(() => model.Username))
    {
        <span>Checking availability...</span>
    }
    <ValidationMessage For="() => model.Username" />
    <button type="submit">Register</button>
</EditForm>

Vale destacar que o Preview 5 entrega apenas os blocos de construção da validação assíncrona. A experiência completa com DataAnnotationsValidator depende das novas APIs assíncronas de DataAnnotations, previstas para um preview posterior.

De fato, a documentação atual mostra que essas APIs chegaram depois como AsyncValidationAttribute e IAsyncValidatableObject. Em versões mais recentes, o registro por campo também passou a usar EditContext.RegisterAsyncFieldValidator, então confira o nome da API na versão que você instalou.

Localização de erros de validação

No ASP.NET no .NET 11, formulários Blazor e endpoints de Minimal API agora contam com suporte de primeira classe para localizar mensagens de erro e nomes de propriedades. Por padrão, a localização usa arquivos RESX por idioma, implantados junto com o assembly da aplicação.

builder.Services.AddValidation()
    .AddValidationLocalization<ValidationMessages>();
    // Resolve para ValidationMessages.en.resx, ValidationMessages.pt-BR.resx, ...

Os valores de ErrorMessage nos atributos de validação funcionam como chaves de localização. Assim, o texto exibido vem do arquivo de recursos do idioma ativo.

[ValidatableType]
public class ContactModel
{
    [Required(ErrorMessage = "RequiredField")]
    [EmailAddress(ErrorMessage = "InvalidEmail")]
    [Display(Name = "ContactEmail")]
    public string? Email { get; set; }
}

A plataforma também aceita implementações customizadas de IStringLocalizerFactory. Dessa forma, você pode ler as mensagens de um banco de dados ou de arquivos JSON, e a implementação registrada pelo usuário tem precedência sobre o RESX padrão.

Também dá para definir uma estratégia programática, sem repetir chaves em cada atributo:

builder.Services.AddValidation()
    .AddValidationLocalization<ValidationMessages>(options =>
    {
        // Usa o ErrorMessage como chave ou gera uma chave pelo nome do atributo
        options.ErrorMessageKeyProvider = ctx =>
            ctx.Attribute.ErrorMessage ?? $"{ctx.Attribute.GetType().Name}_Error";
    });

Essa abordagem ajuda em projetos com dezenas de modelos, porque centraliza as chaves e facilita a inclusão de novos idiomas. Ainda assim, a documentação atual indica que versões posteriores tornaram a localização nativa, ativada com AddLocalization seguido de AddValidation.

QuickGrid sem interatividade no ASP.NET do .NET 11

O componente QuickGrid recebeu uma atualização importante no ASP.NET no .NET 11: ordenação e paginação agora funcionam em páginas Blazor SSR estáticas. Antes, esses recursos exigiam um modo interativo.

Quando o grid não está em modo interativo, os controles de ordenação e o paginador viram links que atualizam o estado pela query string da URL. Portanto, o componente deixa de depender de handlers @onclick.

@page "/orders"
@using Microsoft.AspNetCore.Components.QuickGrid

<QuickGrid Items="orders.AsQueryable()" Pagination="pagination">
    <PropertyColumn Property="@(o => o.Id)" Sortable="true" />
    <PropertyColumn Property="@(o => o.Customer)" Sortable="true" />
    <PropertyColumn Property="@(o => o.Total)" Sortable="true" />
</QuickGrid>

<Paginator State="pagination" />

@code {
    private readonly PaginationState pagination = new() { ItemsPerPage = 20 };
    private readonly List<Order> orders = OrderRepository.GetOrders();
}

O comportamento baseado em URL vem ativo por padrão. Segundo a documentação, a URL passa a carregar parâmetros como page, sort e direction, o que permite compartilhar links e usar os botões de voltar e avançar do navegador.

Para restaurar o comportamento anterior baseado em <button>, basta definir o switch Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting como false.

// Volta a renderizar <button> com @onclick (exige modo interativo)
AppContext.SetSwitch(
    "Microsoft.AspNetCore.Components.QuickGrid.EnableUrlBasedQuickGridNavigationAndSorting",
    false);

Atenção ao CSS, porque o elemento renderizado muda de <button> para <a>. Nesse caso, seletores como button.col-title também precisam cobrir a.col-title.

Cultura e estado de sessão no Blazor

No ASP.NET no .NET 11, duas novidades tratam de estado: uma preserva a cultura entre servidor e cliente, enquanto a outra leva a sessão HTTP para dentro dos componentes.

Blazor WebAssembly preserva a cultura do servidor

Aplicações Blazor WebAssembly com pré-renderização no servidor agora persistem o CurrentCulture e o CurrentUICulture no estado do componente. Em seguida, o cliente aplica esses valores antes de carregar os assemblies satélite.

O recurso vem ativo por padrão para componentes WebAssembly interativos. Com isso, a página pré-renderizada e a versão hidratada no cliente usam a mesma cultura.

Se a sua aplicação precisa que o cliente escolha a cultura de forma independente, basta desativar o comportamento:

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents(options =>
    {
        // O cliente passa a escolher a própria cultura
        options.UseCultureFromServer = false;
    });

Essa mudança elimina um problema visual comum. Antes, a página aparecia com a formatação do servidor e depois mudava para a do cliente, afetando datas, moedas e outros dados regionais.

SupplyParameterFromSession para Blazor SSR

O atributo [SupplyParameterFromSession] chega ao Blazor SSR com o mesmo padrão declarativo de [SupplyParameterFromQuery] e [SupplyParameterFromForm]. Assim, propriedades de componentes leem e gravam valores da sessão HTTP diretamente.

Na prática, você mantém estado de sessão, como o ID de um carrinho ou o progresso de um formulário em etapas, perto do componente que o usa. O framework serializa os valores com System.Text.Json e grava tudo de volta antes de enviar a resposta.

@page "/checkout"

<p>Current step: @CurrentStep</p>

<EditForm Model="Input" FormName="checkout" OnSubmit="NextStep">
    <button type="submit">Next</button>
</EditForm>

@code {
    // Valor lido e gravado na sessão HTTP com a chave "checkout-step"
    [SupplyParameterFromSession(Name = "checkout-step")]
    public int CurrentStep { get; set; }

    private object Input { get; } = new();

    private void NextStep() => CurrentStep++;
}

Para habilitar o recurso, registre os serviços no Program.cs e inclua o middleware de sessão no pipeline:

builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
builder.Services.AddRazorComponents();

var app = builder.Build();
app.UseSession();

Diferente do TempData, os valores de sessão não somem depois da leitura. Eles permanecem disponíveis durante todo o tempo de vida da sessão.

Blazor WebAssembly Gateway no ASP.NET do .NET 11

Aplicações Blazor WebAssembly standalone ganharam um novo servidor de desenvolvimento no ASP.NET no .NET 11. O Microsoft.AspNetCore.Components.Gateway é um host ASP.NET Core leve que substitui o pacote Microsoft.AspNetCore.Components.WebAssembly.DevServer.

Segundo a Microsoft, o Gateway serve aplicações tanto em desenvolvimento quanto em produção. Além disso, ele oferece uma infraestrutura mais robusta e integrada do que a ferramenta anterior.

Como se trata de um host ASP.NET Core completo, o fallback SPA para rotas client-side é nativo. Ou seja, requisições que não correspondem a um arquivo estático caem no index.html.

Por isso, rotas como /orders/42 funcionam no refresh do navegador e na navegação direta. Antes, esse cenário exigia configuração extra no servidor que hospedava os arquivos.

Para adotar o Gateway em um projeto existente, a mudança no arquivo de projeto é mínima:

<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="11.0.0-preview.5.26302.115" />
  <PackageReference Include="Microsoft.AspNetCore.Components.Gateway" Version="11.0.0-preview.5.26302.115" PrivateAssets="all" />
</ItemGroup>

Novos projetos criados com o template atualizado já incluem o Gateway por padrão. Além disso, a documentação explica que a propriedade inspectUri do launchSettings.json deixa de ser necessária com o novo servidor.

ChildContent entre limites de render mode

Componentes renderizados com @rendermode agora aceitam ChildContent e outros parâmetros RenderFragment não genéricos vindos de outro modo de renderização. Antes, essa combinação lançava uma InvalidOperationException.

O erro acontecia porque RenderFragment é um delegate e não atravessava a fronteira entre SSR e interativo. Agora, o Blazor pré-renderiza o fragmento no servidor, captura a árvore resultante e a reidrata dentro do componente filho interativo.

<MyComponent @rendermode="InteractiveServer">
    <p>This content is rendered as SSR and projected into the interactive component.</p>
</MyComponent>

Essa melhoria do ASP.NET no .NET 11 amplia a flexibilidade de aplicações com modos de renderização mistos. Por outro lado, fragmentos genéricos ainda têm limitações de serialização neste preview.

Kestrel e OpenAPI no ASP.NET do .NET 11

Fora do Blazor, o ASP.NET no .NET 11 Preview 5 também traz ajustes de segurança no Kestrel e correções na geração de documentos OpenAPI.

Timeout para trailer headers no Kestrel

O Kestrel agora aplica o RequestHeadersTimeout a trailer headers fragmentados de HTTP/2 e HTTP/3 que não concluem o envio do bloco. Assim, o mesmo timeout que protege os headers iniciais passa a cobrir também os frames HEADERS de trailer.

builder.WebHost.ConfigureKestrel(options =>
{
    // Também vale para trailer headers incompletos em HTTP/2 e HTTP/3
    options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(10);
});

Essa melhoria importa em ambientes de alta concorrência. Afinal, conexões abertas de forma maliciosa ou por bugs em clientes poderiam consumir recursos do servidor indefinidamente.

Melhorias nos schemas OpenAPI

A geração de documentos OpenAPI do ASP.NET no .NET 11 recebeu duas correções importantes. Primeiro, parâmetros enum que não vêm do corpo mantêm os nomes originais dos membros C#, mesmo com uma política de nomenclatura no JsonStringEnumConverter.

Isso acontece porque a vinculação de query, route, header e form usa Enum.TryParse, e não a serialização JSON. Em segundo lugar, os identificadores de schemas de arrays agora usam nomes válidos, como stringArray e TodoArray.

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.Converters.Add(
        new JsonStringEnumConverter(JsonNamingPolicy.KebabCaseLower));
});

app.MapGet("/orders", (OrderStatus status) => Results.Ok(status));

Com essa configuração, o schema do corpo descreve OrderStatus.PendingReview como pending-review. Enquanto isso, o schema do parâmetro de query descreve o valor aceito como PendingReview.

Endpoints de Minimal API também passam a suportar múltiplos Produces<T>() para o mesmo status code. Por exemplo, uma resposta 200 pode chegar como application/json ou text/plain, cada uma com seu schema.

O mesmo suporte vale para controllers MVC com múltiplos atributos [ProducesResponseType]. Antes, o framework mantinha um único tipo por status code e descartava os demais em silêncio.

Correções de bugs no ASP.NET do .NET 11

O ASP.NET no .NET 11 Preview 5 inclui correções que merecem destaque. No Blazor, o time corrigiu uma falha ao renderizar um componente interativo a partir de um layout durante a navegação enhanced.

Também entraram anotações StringSyntaxAttribute.DateTimeFormat que faltavam nos overloads de formato DateTimeOffset do BindConverter. Assim, o editor passa a reconhecer essas strings como formatos de data.

Em Data Protection e antiforgery, a equipe resolveu a starvation do thread pool durante a inicialização a frio no KeyRingProvider. O problema surgia quando muitos chamadores pediam chaves antes de o key ring estar em cache.

No Kestrel, mensagens HTTP/2 e HTTP/3 com campos de header específicos de conexão agora contam como malformadas, conforme os RFCs 9113 e 9114. Além disso, o servidor fecha a conexão depois de processar uma requisição com Content-Length e Transfer-Encoding juntos, como exige o RFC 9112.

Em Minimal APIs, parâmetros de query do tipo struct opcional não anulável com = default deixaram de lançar exceção. Por fim, application/problem+json e application/problem+xml continuam como tipos preferidos quando o ProducesAttribute também define um tipo de conteúdo.

Se você quer entender melhor esse formato de erro, o artigo sobre ProblemDetails e a RFC 9457 explica o contrato em detalhes.

Como testar o ASP.NET no .NET 11 Preview 5

Para experimentar o ASP.NET no .NET 11 Preview 5, instale o SDK de preview correspondente e crie um projeto separado. Dessa forma, você evita misturar a versão preview com aplicações que rodam em produção.

Uma boa prática é fixar a versão do SDK com um arquivo global.json na pasta do projeto de testes. Assim, os outros projetos da máquina continuam usando a versão estável.

# Confere quais SDKs estão instalados
dotnet --list-sdks

# Cria um Blazor Web App para testar as novidades
dotnet new blazor -o PreviewLab

Em seguida, teste um recurso por vez, como a validação client-side ou o QuickGrid em SSR. Com isso, fica mais fácil identificar o que mudou e reportar problemas no repositório dotnet/aspnetcore.

Para acompanhar a evolução das próximas versões, vale ler também a análise do ASP.NET Core no .NET 11 Preview 7. Lá você vê como várias dessas APIs amadureceram.

Conclusão

O ASP.NET no .NET 11 Preview 5 mostra que a Microsoft segue investindo em um desenvolvimento web mais produtivo, seguro e expressivo. As melhorias no Blazor pesam especialmente para equipes que combinam componentes SSR e interativos na mesma aplicação.

No ASP.NET no .NET 11, a validação client-side em SSR elimina uma diferença notável entre os modos de renderização. Enquanto isso, a validação assíncrona e a localização de erros atendem demandas antigas da comunidade.

O novo Gateway e a passagem de ChildContent entre render modes mostram a maturidade crescente da plataforma. Também preparam o terreno para os recursos finais que chegam nas próximas previews.

Para quem usa ASP.NET Core em produção, acompanhar essas previews ajuda no planejamento de migrações. Portanto, teste cedo, registre o que quebra e adote os novos padrões com calma.

FAQ

O que é o Blazor SSR e como ele difere do Blazor interativo?

O Blazor SSR renderiza os componentes no servidor e entrega HTML pronto, sem conexão SignalR ou runtime WebAssembly. Já o modo interativo mantém um canal de comunicação ou executa código no cliente, o que permite reatividade sem recarregar a página.

A validação client-side no SSR elimina a validação no servidor?

Não. A validação no cliente melhora a experiência, enquanto a validação no servidor continua como fonte de verdade para a segurança.

O [SupplyParameterFromSession] funciona com todos os modos de renderização?

O atributo é específico do Blazor SSR e segue o mesmo escopo de [SupplyParameterFromQuery] e [SupplyParameterFromForm].

O Blazor WebAssembly Gateway pode ser usado em produção?

Sim. O Gateway substitui o DevServer em desenvolvimento e em produção, porque é um host ASP.NET Core completo com fallback SPA nativo.

As melhorias do QuickGrid exigem mudanças no código existente?

Não, porque o comportamento baseado em URL vem ativo por padrão. Quem quiser o comportamento anterior só precisa configurar o switch de contexto correspondente.

A passagem de ChildContent entre render modes funciona com qualquer RenderFragment?

No Preview 5, o suporte cobre ChildContent e outros RenderFragment não genéricos. Fragmentos genéricos ainda têm limitações de serialização.

As melhorias de OpenAPI afetam produção ou só desenvolvimento?

Elas afetam a geração do documento OpenAPI em qualquer ambiente onde ela esteja habilitada, embora seja mais comum usá-la em desenvolvimento e staging.