O que há de novo no ASP.NET Core 8.0
Este artigo destaca as alterações mais significativas no ASP.NET Core 8.0 com links para documentação relevante.
Blazor
Interface do usuário da Web de pilha completa
Com o lançamento do .NET 8, o Blazor é uma estrutura full stack de interface do usuário para a web, ideal para o desenvolvimento de aplicativos que processam conteúdo ao nível do componente ou da página com:
- Renderização estática em servidor (também chamada renderização estática em servidor, SSR estático) para gerar HTML estático no servidor.
- Renderização interativa do servidor (também chamada de renderização interativa do lado do servidor , SSR interativo) para gerar componentes interativos com pré-renderização no servidor.
- Renderização interativa de WebAssembly (também chamada de renderização do lado do cliente, CSR, que sempre é assumida como interativa) para gerar componentes interativos no cliente com pré-renderização no servidor.
- Renderização Interativa Automática para usar inicialmente o tempo de execução do ASP.NET Core no lado do servidor para renderização e interatividade de conteúdo. O tempo de execução do .NET WebAssembly no cliente é usado para renderização e interatividade subsequentes depois que o pacote de Blazor é baixado e o tempo de execução do WebAssembly é ativado. A renderização automática interativa geralmente fornece a experiência de inicialização de aplicativo mais rápida.
Os modos de renderização interativos também pré-renderizam o conteúdo por padrão.
Para obter mais informações, consulte os seguintes artigos:
- ASP.NET Core Blazor Fundamentos: Novas seções sobre renderização e conceitos estáticos/interativos aparecem na parte superior do artigo.
- ASP.NET Core Blazor modos de renderização
- Cobertura de migração: Migrar do ASP.NET Core 7.0 para o 8.0
Os exemplos ao longo da documentação Blazor foram atualizados para uso em Blazor Web Apps. Os exemplos Blazor Server ainda permanecem em versões de conteúdo para .NET 7 ou anterior.
Novo artigo sobre bibliotecas de classes com renderização estática do lado do servidor (SSR estático)
Adicionámos um novo artigo que discute a autoria de bibliotecas de componentes em bibliotecas de classes Razor (RCLs) com renderização estática do lado do servidor (SSR).
Para obter mais informações, consulte ASP.NET Core Razor class libraries (RCLs) com renderização estática do lado do servidor (SSR estático).
Novo artigo sobre problemas de cache HTTP
Adicionamos um novo artigo que discute alguns dos problemas comuns de cache HTTP que podem ocorrer ao atualizar aplicativos Blazor nas principais versões e como resolver problemas de cache HTTP.
Para obter mais informações, consulte Evitar problemas de cache HTTP ao atualizar aplicativos ASP.NET Core Blazor.
Novo modelo de Blazor Web App
Introduzimos um novo modelo de projeto Blazor: o modelo Blazor Web App. O novo modelo fornece um único ponto de partida para usar componentes Blazor para criar qualquer estilo de interface do usuário da Web. O modelo combina os pontos fortes dos modelos de hospedagem de Blazor Server e Blazor WebAssembly existentes com os novos recursos de Blazor adicionados no .NET 8: renderização estática do lado do servidor (SSR estático), renderização de streaming, navegação aprimorada e manipulação de formulários e a capacidade de adicionar interatividade usando Blazor Server ou Blazor WebAssembly por componente.
Como parte da unificação dos vários modelos de hospedagem Blazor em um único modelo no .NET 8, também estamos consolidando o número de modelos de projeto Blazor. Removemos o modelo Blazor Server e a opção ASP.NET Core Hosted foi removida do modelo Blazor WebAssembly. Ambos os cenários são representados por opções ao usar o modelo Blazor Web App.
Observação
Os aplicativos Blazor Server e Blazor WebAssembly existentes permanecem com suporte no .NET 8. Opcionalmente, estas aplicações podem ser atualizadas para usar os novos recursos integrais da interface web do utilizador Blazor.
Para obter mais informações sobre o novo modelo de Blazor Web App, consulte os seguintes artigos:
Novos inicializadores de JS para Blazor Web Apps
Para as aplicações Blazor Server, Blazor WebAssemblye Blazor Hybrid:
-
beforeStart
é usado para tarefas como personalizar o processo de carregamento, nível de registro e outras opções. -
afterStarted
é usado para tarefas como registrar ouvintes de eventos Blazor e tipos de eventos personalizados.
Os inicializadores de JS herdados anteriores não são invocados por padrão em um Blazor Web App. Para Blazor Web Apps, um novo conjunto de inicializadores de JS são usados: beforeWebStart
, afterWebStarted
, beforeServerStart
, afterServerStarted
, beforeWebAssemblyStart
e afterWebAssemblyStarted
.
Para obter mais informações, consulte ASP.NET Core Blazor startup.
Divisão das diretrizes de pré-renderização e integração
Para versões anteriores do .NET, abordamos a pré-renderização e a integração em um único artigo. Para simplificar e focar nossa cobertura, dividimos os assuntos nos seguintes novos artigos, que foram atualizados para o .NET 8:
- Pré-renderizar componentes do ASP.NET Core Razor
- Integre ASP.NET componentes principais do Razor com o MVC ou o Razor Pages
Persistir o estado do componente num Blazor Web App
Você pode persistir e ler o estado do componente em um Blazor Web App usando o serviço de PersistentComponentState existente. Isso é útil para estado do componente persistente durante a pré-renderização.
Blazor Web Apps persistem automaticamente qualquer estado registrado no nível do aplicativo criado durante a pré-renderização, removendo a necessidade do Persist Component State Tag Helper.
Tratamento de formulários e vinculação de modelos
Blazor componentes agora podem lidar com solicitações de formulário enviadas, incluindo vinculação de modelo e validação dos dados da solicitação. Os componentes podem implementar formulários com manipuladores de formulário separados usando a marca HTML <form>
padrão ou usando o componente EditForm
existente.
A associação do modelo de formulário no Blazor respeita os atributos do contrato de dados (por exemplo, [DataMember]
e [IgnoreDataMember]
) para personalizar a forma como os dados do formulário são associados ao modelo.
Novo suporte antifalsificação está incluído no .NET 8. Um novo componente AntiforgeryToken
renderiza um token antifalsificação como um campo oculto e o novo atributo [RequireAntiforgeryToken]
habilita a proteção antifalsificação. Se uma verificação antifalsificação falhar, uma resposta 400 (Solicitação incorreta) será retornada sem processamento de formulário. Os novos recursos antifalsificação são habilitados por padrão para formulários baseados em Editform
e podem ser aplicados manualmente a formulários HTML padrão.
Para obter mais informações, consulte visão geral dos formulários do ASP.NET Core Blazor.
Navegação e manipulação de formulários aprimoradas
A renderização estática do lado do servidor (SSR estático) normalmente executa uma atualização de página inteira sempre que o usuário navega para uma nova página ou envia um formulário. No .NET 8, Blazor pode aprimorar a navegação de página e o tratamento de formulários intercetando a solicitação e executando uma solicitação de busca.
Blazor em seguida, lida com o conteúdo de resposta renderizado corrigindo-o no DOM do navegador. A navegação aprimorada e o tratamento de formulários evitam a necessidade de uma atualização de página inteira e preservam mais do estado da página, para que as páginas sejam carregadas mais rapidamente e sem problemas. A navegação avançada é ativada por padrão quando o script Blazor (blazor.web.js
) é carregado. A manipulação aprimorada de formulários pode ser habilitada opcionalmente para formulários específicos.
A nova API de navegação aprimorada permite que você atualize a página atual chamando NavigationManager.Refresh(bool forceLoad = false)
.
Para obter mais informações, consulte as seguintes seções do artigo de Roteamento Blazor:
Novo artigo sobre renderização estática com navegação melhorada para a interoperabilidade JS
Algumas aplicações dependem da interoperabilidade de JS para realizar tarefas de inicialização específicas de cada página. Ao utilizar a funcionalidade de navegação avançada do Blazorcom páginas renderizadas estaticamente que realizam tarefas de inicialização de interoperabilidade JS, as funções JS específicas da página podem não ser executadas novamente como esperado cada vez que ocorre uma navegação melhorada na página. Um novo artigo explica como lidar com esse cenário em Blazor Web Apps:
ASP.NET Core Blazor JavaScript com renderização estática do lado do servidor (SSR estático)
Renderização em streaming
Agora você pode transmitir atualizações de conteúdo no fluxo de resposta ao usar a renderização estática do lado do servidor (SSR estático) com Blazor. A renderização de streaming pode melhorar a experiência do usuário para páginas que executam tarefas assíncronas de longa execução para renderizar totalmente o conteúdo assim que estiver disponível.
Por exemplo, para renderizar uma página, talvez seja necessário fazer uma consulta de banco de dados de longa duração ou uma chamada de API. Normalmente, as tarefas assíncronas executadas como parte da renderização de uma página devem ser concluídas antes que a resposta renderizada seja enviada, o que pode atrasar o carregamento da página. A renderização de streaming inicialmente renderiza toda a página com conteúdo de espaço reservado enquanto operações assíncronas são executadas. Após a conclusão das operações assíncronas, o conteúdo atualizado é enviado para o cliente na mesma conexão de resposta e integrado no DOM. O benefício dessa abordagem é que o layout principal do aplicativo é renderizado o mais rápido possível e a página é atualizada assim que o conteúdo estiver pronto.
Para obter mais informações, consulte Razordo ASP.NET Core .
Injetar serviços chaveados em componentes
Blazor agora oferece suporte à injeção de serviços com chave usando o atributo [Inject]
. As chaves permitem definir o âmbito para o registo e o consumo de serviços ao usar a injeção de dependência. Use a nova propriedade InjectAttribute.Key
para especificar a chave que o serviço deve injetar:
[Inject(Key = "my-service")]
public IMyService MyService { get; set; }
A diretiva @inject
Razor não suporta serviços com chave para esta versão, mas o trabalho é rastreado pelo Update @inject
para oferecer suporte a serviços com chave (dotnet/razor #9286) para uma versão futura do .NET.
Para obter mais informações, consulte ASP.NET Core Blazor de injeção de dependência.
Aceder a HttpContext
como parâmetro em cascata
Agora você pode acessar o HttpContext atual como um parâmetro em cascata de um componente de servidor estático:
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
Acessar o HttpContext a partir de um componente de servidor estático pode ser útil para inspecionar e modificar cabeçalhos ou outras propriedades.
Para obter um exemplo que passe o estado HttpContext, com acesso e atualização de tokens para componentes, consulte o ASP.NET Core no lado do servidor e os cenários de segurança adicionais e Blazor Web App.
Renderizar Razor componentes fora do ASP.NET Core
Agora você pode renderizar Razor componentes fora do contexto de uma solicitação HTTP. Você pode renderizar componentes Razor como HTML diretamente para um texto ou fluxo, independentemente do ambiente de hospedagem do ASP.NET Core. Isso é conveniente para cenários em que você deseja gerar fragmentos HTML, como para gerar e-mail ou conteúdo estático do site.
Para obter mais informações, consulte Renderizar componentes Razor fora do ASP.NET Core.
Suporte de seções
Os novos componentes SectionOutlet
e SectionContent
em Blazor adicionam suporte para a especificação de pontos de saída para conteúdo que pode ser preenchido posteriormente. As seções geralmente são usadas para definir espaços reservados em layouts que são preenchidos por páginas específicas. As seções são referenciadas por um nome exclusivo ou usando uma ID de objeto exclusiva.
Para obter mais informações, consulte as seções ASP.NET Core Blazor.
Suporte para páginas de erro
Blazor Web Apps pode definir uma página de erro personalizada para uso com o middleware de tratamento de exceções ASP.NET Core. O modelo de projeto Blazor Web App inclui uma página de erro padrão (Components/Pages/Error.razor
) com conteúdo semelhante ao usado nos aplicativos MVC e Razor Pages. Quando a página de erro é processada em resposta a uma solicitação do Exception Handling Middleware, a página de erro sempre é renderizada como um componente de servidor estático, mesmo que a interatividade esteja habilitada de outra forma.
Error.razor
na fonte de referência 8.0
QuickGrid
O componente BlazorQuickGrid não é mais experimental e agora faz parte da estrutura Blazor no .NET 8.
QuickGrid é um componente de grade de alto desempenho para exibir dados em forma de tabela. QuickGrid foi criado para ser uma maneira simples e conveniente de exibir seus dados, ao mesmo tempo em que fornece recursos poderosos, como classificação, filtragem, paginação e virtualização.
Para obter mais informações, consulte ASP.NET componente Core Blazor 'QuickGrid'.
Rota para elementos nomeados
Blazor agora oferece suporte ao uso do roteamento do lado do cliente para navegar até um elemento HTML específico em uma página usando fragmentos de URL padrão. Se você especificar um identificador para um elemento HTML usando o atributo id
padrão, Blazor rolará corretamente para esse elemento quando o fragmento de URL corresponder ao identificador do elemento.
Para obter mais informações, consulte ASP.NET Core Blazor roteamento e navegação.
Valores em cascata no nível raiz
Os valores em cascata no nível raiz podem ser registrados para toda a hierarquia de componentes. Há suporte para valores em cascata nomeados e assinaturas para notificações de atualização.
Para obter mais informações, consulte ASP.NET Core Blazor valores e parâmetros em cascata.
Virtualizar conteúdo vazio
Use o novo parâmetro EmptyContent
no componente Virtualize
para disponibilizar conteúdo quando o componente estiver carregado e Items
estiver vazio ou ItemsProviderResult<T>.TotalItemCount
for zero.
Para obter mais informações, consulte ASP.NET Core Razor component virtualization.
Feche circuitos quando não houver componentes de servidor interativos restantes
Os componentes de servidor interativos lidam com eventos da interface do usuário da Web usando uma conexão em tempo real com o navegador chamada circuito. Um circuito e seu estado associado são configurados quando um componente de servidor interativo raiz é renderizado. O circuito é fechado quando não há componentes de servidor interativos restantes na página, o que libera recursos do servidor.
Monitore a atividade do circuito SignalR
Agora você pode monitorar a atividade do circuito de entrada em aplicativos do lado do servidor usando o novo método CreateInboundActivityHandler
no CircuitHandler
. Atividade de circuito de entrada é qualquer atividade enviada do navegador para o servidor, como eventos de interface do usuário ou chamadas de interoperabilidade JavaScript-to-.NET.
Para obter mais informações, consulte ASP.NET Core BlazorSignalR guidance.
Desempenho de tempo de execução mais rápido com o Jiterpreter
O Jiterpreter é um novo recurso de tempo de execução no .NET 8 que permite o suporte parcial à compilação Just-in-Time (JIT) quando executado no WebAssembly para obter melhor desempenho de tempo de execução.
Para obter mais informações, consulte Host e implantar ASP.NET Core Blazor WebAssembly.
SIMD antecipado (AOT) e tratamento de exceções
Blazor WebAssembly compilação ahead-of-time (AOT) agora usa SIMD de largura fixa WebAssembly e tratamento de exceção WebAssembly por padrão para melhorar o desempenho do tempo de execução.
Para obter mais informações, consulte os seguintes artigos:
Embalagem Webcil otimizada para a Web
O Webcil é um pacote amigável para a Web de assemblies .NET que remove conteúdo específico da execução nativa do Windows para evitar problemas ao implantar em ambientes que bloqueiam o download ou o uso de arquivos .dll
. O Webcil está habilitado por padrão para Blazor WebAssembly aplicativos.
Para obter mais informações, consulte Host e implantar ASP.NET Core Blazor WebAssembly.
Observação
Antes do lançamento do .NET 8, as diretrizes na configuração de implantação para aplicativos Blazor WebAssembly hospedados em ASP.NET Core tratam de ambientes que impedem os clientes de baixar e executar DLLs com uma abordagem de agregação de várias partes. No .NET 8 ou posterior, Blazor usa o formato de arquivo Webcil para resolver esse problema. O agrupamento multipartes usando o pacote NuGet experimental descrito no artigo sobre o layout de implantação do WebAssembly Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle
pacote para definir um formato de pacote personalizado (dotnet/aspnetcore #36978). Se desejar continuar a usar o pacote de agrupamento de várias partes em aplicações .NET 8 ou posteriores, pode seguir as orientações no artigo para criar o seu próprio pacote NuGet de agrupamento de várias partes, mas não terá suporte da Microsoft.
Blazor WebAssembly melhorias na depuração
Ao depurar .NET no WebAssembly, o depurador agora baixa dados de símbolos a partir das localizações de símbolos configuradas nas preferências do Visual Studio. Isso melhora a experiência de depuração para aplicativos que usam pacotes NuGet.
Agora você pode depurar aplicativos Blazor WebAssembly usando o Firefox. A depuração de aplicativos Blazor WebAssembly requer configurar o navegador para depuração remota e, em seguida, conectar-se ao navegador usando as ferramentas de desenvolvedor do navegador por meio do proxy de depuração .NET WebAssembly. Não é possível depurar o Firefox a partir do Visual Studio neste momento.
Para obter mais informações, consulte Depurar aplicativos ASP.NET Core Blazor.
Compatibilidade com a Política de Segurança de Conteúdo (CSP)
Blazor WebAssembly mais necessário habilitar a fonte de script unsafe-eval
ao especificar uma CSP (Política de Segurança de Conteúdo).
Para obter mais informações, consulte Impor uma política de segurança de conteúdo para o ASP.NET Core Blazor.
Lidar com exceções detetadas fora do ciclo de vida de um componente Razor
Use ComponentBase.DispatchExceptionAsync
em um componente Razor para processar exceções lançadas fora da pilha de chamadas do ciclo de vida do componente. Isso permite que o código do componente trate exceções como se fossem exceções do método de ciclo de vida. Depois disso, os mecanismos de tratamento de erros do Blazor, como limites de erro, podem processar exceções.
Para obter mais informações, consulte Tratar erros em aplicações do ASP.NET Core Blazor.
Configurar o tempo de execução do .NET WebAssembly
O ambiente de execução do .NET WebAssembly agora pode ser configurado para inicialização Blazor.
Para obter mais informações, consulte ASP.NET Core Blazor startup.
Configuração de tempos limite de conexão em HubConnectionBuilder
As soluções alternativas anteriores para configurar os tempos de espera de conexão do hub podem ser substituídas pela configuração formal do tempo limite no construtor de conexões de hub SignalR.
Para obter mais informações, consulte o seguinte:
- Orientação Blazorsobre o ASP.NET CoreSignalR
- alojar e implantar ASP.NET Core Blazor WebAssembly
- Hospede e implante aplicativos Blazor do lado do servidor ASP.NET Core
Modelos de projeto removem Open Iconic
Os modelos de projeto Blazor não dependem mais do Open Iconic para ícones.
Suporte para cancelar e fechar eventos de caixa de diálogo
Blazor agora suporta os eventos cancel
e close
no elemento HTML dialog
.
No exemplo a seguir:
-
OnClose
é chamado quando o diálogomy-dialog
é fechado com o botão Fechar. -
OnCancel
é chamado quando o diálogo é cancelado com a tecla Esc. Quando uma caixa de diálogo HTML é descartada com a tecla Esc, os eventoscancel
eclose
são acionados.
<div>
<p>Output: @message</p>
<button onclick="document.getElementById('my-dialog').showModal()">
Show modal dialog
</button>
<dialog id="my-dialog" @onclose="OnClose" @oncancel="OnCancel">
<p>Hi there!</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
</div>
@code {
private string? message;
private void OnClose(EventArgs e) => message += "onclose, ";
private void OnCancel(EventArgs e) => message += "oncancel, ";
}
Blazor Identity UI
Blazor oferece suporte à geração de uma interface do usuário Blazor baseada em Identitycompleta quando você escolhe a opção de autenticação para Contas Individuais. Você pode selecionar a opção "Contas Individuais" na caixa de diálogo de novo projeto para Blazor Web Apps no Visual Studio ou passar a opção -au|--auth
definida como Individual
na linha de comando ao criar um novo projeto.
Para obter mais informações, consulte os seguintes recursos:
- ASP.NET Core Blazor autenticação e autorização
- O que há de novo na identidade no .NET 8 (postagem de blog)
Proteja Blazor WebAssembly com o ASP.NET Core Identity
A documentação do Blazor hospeda um novo artigo e um aplicativo de exemplo para cobrir a proteção de um aplicativo Blazor WebAssembly autônomo com ASP.NET Core Identity.
Para obter mais informações, consulte os seguintes recursos:
- Proteja ASP.NET Core Blazor WebAssembly com ASP.NET Core Identity
- O que há de novo na identidade no .NET 8 (postagem de blog)
Blazor Server com roteamento Yarp
O roteamento e as ligações profundas para Blazor Server com Yarp funcionam corretamente no .NET 8.
Para obter mais informações, consulte Migrar do ASP.NET Core 7.0 para 8.0.
Vários Blazor Web Apps por projeto de servidor
O suporte para múltiplos Blazor Web Apps em cada projeto de servidor será considerado no .NET 10 (novembro de 2025).
Para obter mais informações, consulte Suporte para várias aplicações Web Blazor por cada projeto de servidor (dotnet/aspnetcore
#52216).
Blazor Hybrid
Os seguintes artigos documentam alterações para Blazor Hybrid no .NET 8:
- pt-PT: Solucionar problemas do ASP.NET Core Blazor Hybrid: Um novo artigo explica como usar o registo de logs BlazorWebView.
- Criar um aplicativo .NET MAUIBlazor Hybrid: O nome do modelo de projeto .NET MAUI Blazor foi alterado para .NET MAUI Blazor Hybrid.
-
ASP.NET Core Blazor Hybrid:
BlazorWebView
obtém um métodoTryDispatchAsync
que chama umAction<ServiceProvider>
especificado de forma assíncrona e passa os serviços com escopo disponíveis em Razor componentes. Isso permite que o código da interface do usuário nativa aceda a serviços com escopo, comoNavigationManager
. -
ASP.NET Core Blazor Hybrid de roteamento e navegação: use a propriedade
BlazorWebView.StartPath
para obter ou definir o caminho para a navegação inicial dentro do contexto de navegação Blazor quando o componente Razor terminar de carregar.
[Parameter]
atributo não é mais necessário quando fornecido a partir da cadeia de caracteres de consulta
O atributo [Parameter]
não é mais necessário ao fornecer um parâmetro da cadeia de caracteres de consulta:
- [Parameter]
[SupplyParameterFromQuery]
SignalR
Nova abordagem para definir o tempo limite do servidor e o intervalo de Keep-Alive
ServerTimeout (padrão: 30 segundos) e KeepAliveInterval (padrão: 15 segundos) podem ser definidos diretamente no HubConnectionBuilder.
Abordagem anterior para clientes JavaScript
O exemplo a seguir mostra a atribuição de valores que são o dobro dos valores padrão no ASP.NET Core 7.0 ou anterior:
var connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.build();
connection.serverTimeoutInMilliseconds = 60000;
connection.keepAliveIntervalInMilliseconds = 30000;
Nova abordagem para clientes JavaScript
O exemplo a seguir mostra a nova abordagem para atribuir valores que são o dobro dos valores padrão no ASP.NET Core 8.0 ou posterior:
var connection = new signalR.HubConnectionBuilder()
.withUrl("/chatHub")
.withServerTimeout(60000)
.withKeepAlive(30000)
.build();
Abordagem anterior para o cliente JavaScript de um aplicativo Blazor Server
O exemplo a seguir mostra a atribuição de valores que são o dobro dos valores padrão no ASP.NET Core 7.0 ou anterior:
Blazor.start({
configureSignalR: function (builder) {
let c = builder.build();
c.serverTimeoutInMilliseconds = 60000;
c.keepAliveIntervalInMilliseconds = 30000;
builder.build = () => {
return c;
};
}
});
Nova abordagem para o cliente JavaScript do aplicativo Blazor do lado do servidor
O exemplo a seguir mostra a nova abordagem para atribuir valores que são o dobro dos valores padrão no ASP.NET Core 8.0 ou posterior para Blazor Web Apps e Blazor Server.
Blazor Web App:
Blazor.start({
circuit: {
configureSignalR: function (builder) {
builder.withServerTimeout(60000).withKeepAliveInterval(30000);
}
}
});
Blazor Server:
Blazor.start({
configureSignalR: function (builder) {
builder.withServerTimeout(60000).withKeepAliveInterval(30000);
}
});
Abordagem anterior para clientes .NET
O exemplo a seguir mostra a atribuição de valores que são o dobro dos valores padrão no ASP.NET Core 7.0 ou anterior:
var builder = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.Build();
builder.ServerTimeout = TimeSpan.FromSeconds(60);
builder.KeepAliveInterval = TimeSpan.FromSeconds(30);
builder.On<string, string>("ReceiveMessage", (user, message) => ...
await builder.StartAsync();
Nova abordagem para clientes .NET
O exemplo a seguir mostra a nova abordagem para atribuir valores que são o dobro dos valores padrão no ASP.NET Core 8.0 ou posterior:
var builder = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"))
.WithServerTimeout(TimeSpan.FromSeconds(60))
.WithKeepAliveInterval(TimeSpan.FromSeconds(30))
.Build();
builder.On<string, string>("ReceiveMessage", (user, message) => ...
await builder.StartAsync();
SignalR reconexão com monitoração de estado
SignalR A reconexão com estado reduz o tempo de inatividade percebido dos clientes que têm uma desconexão temporária na sua conexão de rede, como ao alternar conexões de rede ou durante uma breve perda de acesso.
A reconexão com estado alcança isso ao:
- Armazenamento temporário de dados em buffer no servidor e no cliente.
- Confirmação de mensagens recebidas (ACK-ing) pelo servidor e pelo cliente.
- Reconhecer quando uma conexão está retornando e reproduzir mensagens que podem ter sido enviadas enquanto a conexão estava inativa.
A reconexão com estado está disponível no ASP.NET Core 8.0 e posterior.
Opte pela reconexão com monitoração de estado no ponto de extremidade do hub do servidor e no cliente:
Atualize a configuração do ponto de extremidade do hub do servidor para habilitar a opção
AllowStatefulReconnects
:app.MapHub<MyHub>("/hubName", options => { options.AllowStatefulReconnects = true; });
Opcionalmente, o tamanho máximo do buffer em bytes permitido pelo servidor pode ser definido globalmente ou para um hub específico com a opção
StatefulReconnectBufferSize
:As opções
StatefulReconnectBufferSize
definidas globalmente:builder.AddSignalR(o => o.StatefulReconnectBufferSize = 1000);
A opção
StatefulReconnectBufferSize
definida para um hub específico:builder.AddSignalR().AddHubOptions<MyHub>(o => o.StatefulReconnectBufferSize = 1000);
A opção
StatefulReconnectBufferSize
é opcional com um padrão de 100.000 bytes.Atualize o código do cliente JavaScript ou TypeScript para ativar a opção
withStatefulReconnect
:const builder = new signalR.HubConnectionBuilder() .withUrl("/hubname") .withStatefulReconnect({ bufferSize: 1000 }); // Optional, defaults to 100,000 const connection = builder.build();
A opção
bufferSize
é opcional com um padrão de 100.000 bytes.Atualize o código do cliente .NET para habilitar a opção
WithStatefulReconnect
:var builder = new HubConnectionBuilder() .WithUrl("<hub url>") .WithStatefulReconnect(); builder.Services.Configure<HubConnectionOptions>(o => o.StatefulReconnectBufferSize = 1000); var hubConnection = builder.Build();
A opção
StatefulReconnectBufferSize
é opcional com um padrão de 100.000 bytes.
Para obter mais informações, consulte Configurar a reconexão com monitoração de estado.
APIs mínimas
Esta seção descreve os novos recursos para APIs mínimas. Consulte também a secção sobre AOT Nativo para mais informações sobre APIs mínimas.
Cultura de prevalência do utilizador
A partir do ASP.NET Core 8.0, a propriedade RequestLocalizationOptions.CultureInfoUseUserOverride permite que o aplicativo decida se deseja ou não usar configurações não padrão do Windows para as propriedades CultureInfoDateTimeFormat e NumberFormat. Isso não tem impacto no Linux. Isso corresponde diretamente a UseUserOverride.
app.UseRequestLocalization(options =>
{
options.CultureInfoUseUserOverride = false;
});
Vinculação a formulários
A associação explícita a valores de formulário usando o atributo [FromForm] agora é suportada. Os parâmetros vinculados à solicitação com [FromForm]
incluem um token antifalsificação . O token antifalsificação é validado quando a solicitação é processada.
A vinculação inferida a formulários usando os tipos IFormCollection, IFormFilee IFormFileCollection também é suportada. metadados de OpenAPI são inferidos para parâmetros de formulário para oferecer suporte à integração com Swagger UI.
Para mais informações, consulte:
- Ligação explícita dos valores do formulário.
- Vinculação a formulários com IFormCollection, IFormFile e IFormFileCollection.
- Associação de formulário em APIs minimalistas
A vinculação de formulários agora é suportada para:
- Coleções, por exemplo, Lista e Dicionário
- Tipos complexos, por exemplo,
Todo
ouProject
Para obter mais informações, consulte Vincular a coleções e tipos complexos de formulários.
Antifalsificação com APIs mínimas
Esta versão adiciona um middleware para validar tokens antifalsificação, que são usados para mitigar ataques de falsificação de solicitação entre sites. Ligue para AddAntiforgery para registrar serviços antifalsificação na DI.
WebApplicationBuilder
adiciona automaticamente o middleware quando os serviços antifalsificação são registrados no contêiner DI. Os tokens anti-falsificação são usados para mitigar ataques de falsificação de solicitação entre sites .
var builder = WebApplication.CreateBuilder();
builder.Services.AddAntiforgery();
var app = builder.Build();
app.UseAntiforgery();
app.MapGet("/", () => "Hello World!");
app.Run();
O middleware antifalsificação:
- A execução do restante do pipeline de solicitação não é curto-circuitada pelo ?
- Define o
IAntiforgeryValidationFeature no HttpContext.Features da solicitação atual.
O token antifalsificação só é validado se:
- O ponto de extremidade contém metadados que implementam IAntiforgeryMetadata, onde
RequiresValidation=true
. - O método HTTP relevante associado ao endpoint é um método HTTP . Os métodos relevantes são todos os métodos HTTP exceto TRACE, OPTIONS, HEAD e GET.
- A solicitação está associada a um ponto de extremidade válido.
Para obter mais informações, consulte Antifalsificação with Minimal APIs.
Interface nova IResettable
em ObjectPool
Microsoft.Extensions.ObjectPool fornece suporte para agrupar instâncias de objeto na memória. Os aplicativos podem usar um pool de objetos se os valores forem caros para alocar ou inicializar.
Nesta versão, tornamos o pool de objetos mais fácil de usar adicionando a interface IResettable. Os tipos reutilizáveis geralmente precisam ser redefinidos para um estado padrão entre os usos. Os tipos IResettable
são automaticamente redefinidos quando devolvidos a uma pool de objetos.
Para obter mais informações, consulte o exemplo ObjectPool.
AOT nativo
Foi adicionado suporte para de antecipação do tempo (AOT) nativo do .NET. Os aplicativos que são publicados usando AOT podem ter um desempenho substancialmente melhor: tamanho menor do aplicativo, menor uso de memória e tempo de inicialização mais rápido. Atualmente, a AOT nativa é suportada por gRPC, API mínima e aplicativos de serviço de trabalho. Para obter mais informações, consulte Suporte do ASP.NET Core para AOT Nativo e Tutorial: Publicar uma aplicação ASP.NET Core usando AOT Nativo. Para obter informações sobre problemas conhecidos com a compatibilidade do ASP.NET Core e do AOT nativo, veja a questão no GitHub dotnet/core #8288.
Bibliotecas e AOT nativo
Muitas das bibliotecas populares usadas em projetos ASP.NET Core atualmente têm alguns problemas de compatibilidade quando usadas em um projeto direcionado à AOT nativa, como:
- Uso da reflexão para inspecionar e descobrir tipos.
- Carregamento condicional de bibliotecas em tempo de execução.
- Geração de código em tempo real para implementar funcionalidades.
As bibliotecas que usam esses recursos dinâmicos precisam ser atualizadas para trabalhar com AOT nativo. Eles podem ser atualizados usando ferramentas como geradores de fontes Roslyn.
Os autores de bibliotecas que desejam apoiar o AOT nativo são encorajados a:
Novo modelo de projeto
O novo modelo de projeto
Novo método CreateSlimBuilder
O método CreateSlimBuilder() usado no modelo Web API (Native AOT) inicializa o WebApplicationBuilder com o mínimo de recursos ASP.NET Core necessários para executar um aplicativo. O método CreateSlimBuilder
inclui os seguintes recursos que normalmente são necessários para uma experiência de desenvolvimento eficiente:
- Configuração do arquivo JSON para
appsettings.json
eappsettings.{EnvironmentName}.json
. - Configuração de segredos do usuário.
- Registo de consola.
- Configuração de registo.
Para obter mais informações, consulte O método CreateSlimBuilder
.
Novo método CreateEmptyBuilder
Há outro novo método de fábrica WebApplicationBuilder para criar pequenos aplicativos que contêm apenas os recursos necessários: WebApplication.CreateEmptyBuilder(WebApplicationOptions options)
. Este WebApplicationBuilder
é criado sem comportamento incorporado. O aplicativo que ele cria contém apenas os serviços e middleware que estão explicitamente configurados.
Aqui está um exemplo de como usar essa API para criar um pequeno aplicativo Web:
var builder = WebApplication.CreateEmptyBuilder(new WebApplicationOptions());
builder.WebHost.UseKestrelCore();
var app = builder.Build();
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello, World!");
await next(context);
});
Console.WriteLine("Running...");
app.Run();
A publicação desse código com AOT nativo usando o .NET 8 Preview 7 em uma máquina linux-x64 resulta em um executável nativo autônomo de cerca de 8,5 MB.
Tamanho reduzido do aplicativo com suporte a HTTPS configurável
Reduzimos ainda mais o tamanho binário do AOT nativo para aplicativos que não precisam de suporte a HTTPS ou HTTP/3. Não usar HTTPS ou HTTP/3 é comum para aplicativos que são executados atrás de um proxy de terminação TLS (por exemplo, hospedado no Azure). O novo método WebApplication.CreateSlimBuilder
omite essa funcionalidade por padrão. Ele pode ser adicionado chamando builder.WebHost.UseKestrelHttpsConfiguration()
para HTTPS ou builder.WebHost.UseQuic()
para HTTP/3. Para obter mais informações, consulte O método CreateSlimBuilder
.
Serialização JSON de tipos de IAsyncEnumerable<T>
gerados pelo compilador
Novos recursos foram adicionados ao System.Text.Json para oferecer melhor suporte ao AOT nativo. Essas novas funcionalidades adicionam capacidades ao modo de geração de código-fonte do System.Text.Json
, porque a reflexão não é suportada pela AOT.
Um dos novos recursos é o suporte para serialização JSON de implementações IAsyncEnumerable<T> implementadas pelo compilador C#. Esse suporte abre seu uso em projetos ASP.NET Core configurados para publicar AOT nativa.
Essa API é útil em cenários em que um manipulador de rotas usa yield return
para retornar uma enumeração de forma assíncrona. Por exemplo, para materializar linhas de uma consulta de banco de dados. Para obter mais informações, consulte de suporte a tipos indescritíveis no anúncio do .NET 8 Preview 4.
Para obter informações sobre outros aprimoramentos na geração de origem System.Text.Json
, consulte Serialization improvements in .NET 8.
APIs de nível superior anotadas para avisos de corte
Os principais pontos de entrada para subsistemas que não funcionam de forma confiável com AOT nativo agora são anotados. Quando esses métodos são chamados de um aplicativo com AOT nativo habilitado, um aviso é fornecido. Por exemplo, o código a seguir produz um aviso na invocação de AddControllers
porque essa API não é compatível com trim e não é suportada pela Native AOT.
Solicitar gerador de delegados
Para tornar as APIs mínimas compatíveis com o AOT nativo, estamos introduzindo o Request Delegate Generator (RDG). O RDG é um gerador de fonte que faz o que o RequestDelegateFactory (RDF) faz. Ou seja, ele transforma os vários MapGet()
, MapPost()
e chamadas como eles em instâncias RequestDelegate associadas às rotas especificadas. Mas em vez de fazê-lo na memória em um aplicativo quando ele é iniciado, o RDG faz isso em tempo de compilação e gera código C# diretamente no projeto. O RDG:
- Remove a geração de tempo de execução desse código.
- Garante que os tipos usados em APIs sejam analisáveis estaticamente pela cadeia de ferramentas AOT nativa.
- Garanta que o código necessário não seja removido.
Estamos trabalhando para garantir que o maior número possível de recursos mínimos da API sejam suportados pelo RDG e, portanto, compatíveis com a AOT nativa.
O RDG é ativado automaticamente em um projeto quando a publicação com AOT nativo está habilitada. O RDG pode ser ativado manualmente mesmo quando não estiver usando AOT nativo, definindo <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
no arquivo de projeto. Isso pode ser útil ao avaliar inicialmente a preparação de um projeto para AOT nativo ou para reduzir o tempo de inicialização de um aplicativo.
Melhor desempenho usando intercetores
O Request Delegate Generator usa o novo recurso de compilador de intercetadores C# 12 para oferecer suporte à intercetação de chamadas para métodos mínimos de API Map com variantes geradas estaticamente em tempo de execução. O uso de intercetadores resulta em maior desempenho de inicialização para aplicativos compilados com PublishAot
.
Registro em log e tratamento de exceções em APIs mínimas geradas em tempo de compilação
APIs mínimas geradas em tempo de execução suportam o registro automático (ou o lançamento de exceções em ambientes de desenvolvimento) quando a vinculação de parâmetros falha. O .NET 8 introduz o mesmo suporte para APIs geradas em tempo de compilação por meio do Request Delegate Generator (RDG). Para obter mais informações, consulte Registo de logs e tratamento de exceções em APIs mínimas geradas durante o tempo de compilação.
AOT e System.Text.Json
APIs mínimas são otimizadas para receber e retornar cargas úteis JSON usando System.Text.Json
, portanto, os requisitos de compatibilidade para JSON e AOT nativo também se aplicam. A compatibilidade AOT nativa requer o uso do gerador de código-fonte System.Text.Json
. Todos os tipos aceitos como parâmetros ou retornados de delegados de solicitação em APIs mínimas devem ser configurados em um JsonSerializerContext
registrado por meio da injeção de dependência do ASP.NET Core, por exemplo:
// Register the JSON serializer context with DI
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
...
// Add types used in the minimal API app to source generated JSON serializer content
[JsonSerializable(typeof(Todo[]))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}
Para obter mais informações sobre a API TypeInfoResolverChain, consulte os seguintes recursos:
- JsonSerializerOptions.TypeInfoResolverChain
- Geradores de fonte de cadeia
- Alterações para suportar a geração de código-fonte
Bibliotecas e AOT nativo
Muitas das bibliotecas comuns disponíveis para projetos ASP.NET Core atualmente têm alguns problemas de compatibilidade se usadas em um projeto direcionado à AOT nativa. As bibliotecas populares geralmente dependem dos recursos dinâmicos do .NET reflection para inspecionar e descobrir tipos, carregar condicionalmente bibliotecas em tempo de execução e gerar código rapidamente para implementar sua funcionalidade. Essas bibliotecas precisam ser atualizadas para trabalhar com AOT nativo usando ferramentas como geradores de código-fonte Roslyn.
Os autores de bibliotecas que desejam aprender mais sobre como preparar suas bibliotecas para AOT nativo são incentivados a começar por preparando sua biblioteca para cortar e aprender mais sobre os requisitos de compatibilidade de AOT nativo .
Servidores Kestrel e HTTP.sys
Existem várias novas funcionalidades para Kestrel e HTTP.sys.
Suporte para pipes nomeados no Kestrel
Named pipes é uma tecnologia popular para estabelecer comunicação entre processos (IPC) entre aplicações Windows. Agora você pode criar um servidor IPC usando .NET, Kestrele pipes nomeados.
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.ListenNamedPipe("MyPipeName");
});
Para obter mais informações sobre esse recurso e como usar o .NET e o gRPC para criar um servidor e um cliente IPC, consulte Comunicação entre processos com o gRPC.
Melhorias de desempenho no transporte de tubos nomeados
Melhorámos o desempenho da ligação do tubo nomeado. O transporte por pipe nomeado do Kestrelagora aceita conexões simultâneas e reutiliza instâncias de NamedPipeServerStream.
Tempo para criar 100.000 conexões:
- Antes : 5.916 segundos
- Após : 2.374 segundos
Suporte a HTTP/2 sobre TLS (HTTPS) no macOS em Kestrel
O .NET 8 adiciona suporte para Application-Layer Protocol Negotiation (ALPN) ao macOS. ALPN é um recurso TLS usado para negociar qual protocolo HTTP uma conexão usará. Por exemplo, o ALPN permite que navegadores e outros clientes HTTP solicitem uma conexão HTTP/2. Esse recurso é especialmente útil para aplicativos gRPC, que exigem HTTP/2. Para obter mais informações, consulte Usar HTTP/2 com o servidor Web ASP.NET Core Kestrel.
Monitorização de ficheiros de certificados em Kestrel
Os certificados TLS configurados por caminho agora são monitorados quanto a alterações quando reloadOnChange
é passado para KestrelServerOptions.Configure(). Uma alteração no ficheiro de certificado é tratada da mesma forma que uma alteração no caminho configurado (ou seja, as endpoints são recarregadas).
Observe que as exclusões de arquivos não são rastreadas, pois surgem de forma transitória e travariam o servidor se não fossem transitórias.
Aviso quando os protocolos HTTP especificados não serão usados
Se o TLS estiver desativado e o HTTP/1.x estiver disponível, HTTP/2 e HTTP/3 serão desativados, mesmo que tenham sido especificados. Isso pode causar algumas surpresas desagradáveis, por isso adicionamos saída de aviso para que você saiba quando isso acontecer.
HTTP_PORTS
e HTTPS_PORTS
teclas de configuração
Aplicações e contentores geralmente recebem apenas uma porta para escutar, como 80, sem restrições adicionais, como host ou caminho.
HTTP_PORTS
e HTTPS_PORTS
são novas chaves de configuração que permitem especificar as portas de escuta para os servidores Kestrel e HTTP.sys. Estes podem ser definidos com os prefixos de variáveis de ambiente DOTNET_
ou ASPNETCORE_
, ou especificados diretamente através de qualquer outra entrada de configuração, como appsettings.json. Cada um é uma lista delimitada por ponto-e-vírgula de valores de portas. Por exemplo:
ASPNETCORE_HTTP_PORTS=80;8080
ASPNETCORE_HTTPS_PORTS=443;8081
Esta é a abreviação do seguinte, que especifica o esquema (HTTP ou HTTPS) e qualquer host ou IP:
ASPNETCORE_URLS=http://*:80/;http://*:8080/;https://*:443/;https://*:8081/
Para obter mais informações, consulte Kestrel e a implementação do servidor Web no ASP.NET CoreHTTP.sys.
Nome SNI do host em ITlsHandshakeFeature
O nome de host SNI (Server Name Indication) agora está exposto na propriedade HostName da interface ITlsHandshakeFeature.
O SNI faz parte do processo de handshake TLS
Normalmente, o nome do host é tratado apenas dentro da pilha TLS e é usado para selecionar o certificado correspondente. Mas, ao expô-lo, outros componentes em um aplicativo podem usar essas informações para fins como diagnóstico, limitação de taxa, roteamento e cobrança.
Expor o nome do host é útil para serviços de grande escala gerenciando milhares de associações SNI. Esta funcionalidade pode melhorar significativamente a eficiência de depuração durante os escalonamentos por parte dos clientes. A maior transparência permite uma resolução de problemas mais rápida e maior confiabilidade do serviço.
Para obter mais informações, consulte ITlsHandshakeFeature.HostName.
IHttpSysRequestTimingFeature
[IHttpSysRequestTimingFeature](https://source.dot.net/#Microsoft.AspNetCore.Server.HttpSys/IHttpSysRequestTimingFeature.cs,3c5dc86dc837b1f4) fornece informações detalhadas de tempo para solicitações ao usar o [HTTP.sys server](xref:fundamentals/servers/httpsys) e [In-process hosting with IIS](xref:host-and-deploy/iis/in-process-hosting?view=aspnetcore-8.0&preserve-view=true#ihsrtf8):- Os carimbos de data/hora são obtidos utilizando o QueryPerformanceCounter.
- A frequência de carimbo de data/hora pode ser obtida através QueryPerformanceFrequency.
- O índice do tempo pode ser convertido para HttpSysRequestTimingType para saber o que o tempo representa.
- O valor pode ser 0 se o tempo não estiver disponível para a solicitação atual.
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.HttpSys;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys();
var app = builder.Build();
app.Use((context, next) =>
{
var feature = context.Features.GetRequiredFeature<IHttpSysRequestTimingFeature>();
var loggerFactory = context.RequestServices.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger("Sample");
var timingType = HttpSysRequestTimingType.RequestRoutingEnd;
if (feature.TryGetTimestamp(timingType, out var timestamp))
{
logger.LogInformation("Timestamp {timingType}: {timestamp}",
timingType, timestamp);
}
else
{
logger.LogInformation("Timestamp {timingType}: not available for the "
+ "current request", timingType);
}
return next(context);
});
app.MapGet("/", () => Results.Ok());
app.Run();
Para obter mais informações, consulte Obter informações detalhadas de temporização com IHttpSysRequestTimingFeature e Informações de temporização e Hospedagem em processo com o IIS.
HTTP.sys: Suporte opt-in para bufferização de resposta em modo núcleo
Em alguns cenários, altos volumes de pequenas gravações com alta latência podem causar um impacto significativo no desempenho de HTTP.sys
. Este impacto deve-se à falta de um buffer de Pipe na implementação HTTP.sys
. Para melhorar o desempenho nesses cenários, o suporte para buffer de resposta foi adicionado ao HTTP.sys
. Habilite o buffer definindo HttpSysOptions.EnableKernelResponseBuffering como true
.
O buffer de resposta deve ser ativado por uma aplicação que faça E/S síncrona ou E/S assíncrona, com não mais de uma gravação pendente de cada vez. Nesses cenários, o buffer de resposta pode melhorar significativamente a taxa de transferência em conexões de alta latência.
Os aplicativos que usam E/S assíncrona e que podem ter mais de uma gravação pendente por vez não devem usar esse sinalizador. Ativar esse sinalizador pode resultar em maior uso de CPU e memória por HTTP.Sys.
Autenticação e autorização
ASP.NET Core 8 adiciona novos recursos à autenticação e autorização.
Identity pontos de extremidade da API
MapIdentityApi<TUser>
é um novo método de extensão que adiciona dois pontos de extremidade de API (/register
e /login
). O principal objetivo do MapIdentityApi
é tornar mais fácil para os desenvolvedores usarem ASP.NET Core Identity para autenticação em aplicativos de página única (SPA) baseados em JavaScript ou aplicativos Blazor. Em vez de usar a UI padrão fornecida pelo ASP.NET Core Identity, que se baseia em Páginas Razor, o MapIdentityApi adiciona endpoints de API JSON que são mais adequados para aplicações SPA e aplicações não baseadas em navegador. Para obter mais informações, consulte Identity endpoints da API.
IAuthorizationRequirementData
Até ao ASP.NET Core 8, adicionar uma política de autorização parametrizada a um ponto de extremidade exigia a implementação de:
-
AuthorizeAttribute
para cada política. -
AuthorizationPolicyProvider
processar uma política personalizada a partir de um contrato baseado em texto. -
AuthorizationRequirement
para a política. -
AuthorizationHandler
para cada requisito.
Por exemplo, considere o seguinte exemplo escrito para o ASP.NET Core 7.0:
using AuthRequirementsData.Authorization;
using Microsoft.AspNetCore.Authorization;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();
var app = builder.Build();
app.MapControllers();
app.Run();
using Microsoft.AspNetCore.Mvc;
namespace AuthRequirementsData.Controllers;
[ApiController]
[Route("api/[controller]")]
public class GreetingsController : Controller
{
[MinimumAgeAuthorize(16)]
[HttpGet("hello")]
public string Hello() => $"Hello {(HttpContext.User.Identity?.Name ?? "world")}!";
}
using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;
namespace AuthRequirementsData.Authorization;
class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
{
private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;
public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
{
_logger = logger;
}
// Check whether a given MinimumAgeRequirement is satisfied or not for a particular
// context.
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
// Log as a warning so that it's very clear in sample output which authorization
// policies(and requirements/handlers) are in use.
_logger.LogWarning("Evaluating authorization requirement for age >= {age}",
requirement.Age);
// Check the user's age
var dateOfBirthClaim = context.User.FindFirst(c => c.Type ==
ClaimTypes.DateOfBirth);
if (dateOfBirthClaim != null)
{
// If the user has a date of birth claim, check their age
var dateOfBirth = Convert.ToDateTime(dateOfBirthClaim.Value, CultureInfo.InvariantCulture);
var age = DateTime.Now.Year - dateOfBirth.Year;
if (dateOfBirth > DateTime.Now.AddYears(-age))
{
// Adjust age if the user hasn't had a birthday yet this year.
age--;
}
// If the user meets the age criterion, mark the authorization requirement
// succeeded.
if (age >= requirement.Age)
{
_logger.LogInformation("Minimum age authorization requirement {age} satisfied",
requirement.Age);
context.Succeed(requirement);
}
else
{
_logger.LogInformation("Current user's DateOfBirth claim ({dateOfBirth})" +
" does not satisfy the minimum age authorization requirement {age}",
dateOfBirthClaim.Value,
requirement.Age);
}
}
else
{
_logger.LogInformation("No DateOfBirth claim present");
}
return Task.CompletedTask;
}
}
O exemplo completo está
ASP.NET Core 8 apresenta a interface IAuthorizationRequirementData. A interface IAuthorizationRequirementData
permite que a definição de atributo especifique os requisitos associados à política de autorização. Usando IAuthorizationRequirementData
, o código de política de autorização personalizado anterior pode ser escrito com menos linhas de código. O arquivo de Program.cs
atualizado:
using AuthRequirementsData.Authorization;
using Microsoft.AspNetCore.Authorization;
var builder = WebApplication.CreateBuilder();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
builder.Services.AddControllers();
- builder.Services.AddSingleton<IAuthorizationPolicyProvider, MinimumAgePolicyProvider>();
builder.Services.AddSingleton<IAuthorizationHandler, MinimumAgeAuthorizationHandler>();
var app = builder.Build();
app.MapControllers();
app.Run();
A MinimumAgeAuthorizationHandler
atualizada :
using Microsoft.AspNetCore.Authorization;
using System.Globalization;
using System.Security.Claims;
namespace AuthRequirementsData.Authorization;
- class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeRequirement>
+ class MinimumAgeAuthorizationHandler : AuthorizationHandler<MinimumAgeAuthorizeAttribute>
{
private readonly ILogger<MinimumAgeAuthorizationHandler> _logger;
public MinimumAgeAuthorizationHandler(ILogger<MinimumAgeAuthorizationHandler> logger)
{
_logger = logger;
}
// Check whether a given MinimumAgeRequirement is satisfied or not for a particular
// context
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
- MinimumAgeRequirement requirement)
+ MinimumAgeAuthorizeAttribute requirement)
{
// Remaining code omitted for brevity.
A amostra atualizada completa pode ser encontrada aqui.
Consulte Políticas de autorização personalizadas com IAuthorizationRequirementData para uma análise detalhada do novo exemplo.
Protegendo pontos de extremidade da interface do usuário do Swagger
Os endpoints do Swagger UI agora podem ser protegidos em ambientes de produção chamando MapSwagger().RequireAuthorization
. Para obter mais informações, consulte Protegendo endpoints do Swagger UI
Diversos
As seções a seguir descrevem diversos novos recursos no ASP.NET Core 8.
Suporte para serviços chaveados na injeção de dependências
Serviços chaveados refere-se a um mecanismo para o registo e recuperação de serviços de injeção de dependências (DI) usando chaves. Um serviço é associado a uma chave chamando AddKeyedSingleton (ou AddKeyedScoped
ou AddKeyedTransient
) para registrá-lo. Acesse um serviço registrado especificando a chave com o atributo [FromKeyedServices]
. O código a seguir mostra como usar serviços com chave:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddControllers();
var app = builder.Build();
app.MapGet("/big", ([FromKeyedServices("big")] ICache bigCache) => bigCache.Get("date"));
app.MapGet("/small", ([FromKeyedServices("small")] ICache smallCache) =>
smallCache.Get("date"));
app.MapControllers();
app.Run();
public interface ICache
{
object Get(string key);
}
public class BigCache : ICache
{
public object Get(string key) => $"Resolving {key} from big cache.";
}
public class SmallCache : ICache
{
public object Get(string key) => $"Resolving {key} from small cache.";
}
[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
[HttpGet("big-cache")]
public ActionResult<object> GetOk([FromKeyedServices("big")] ICache cache)
{
return cache.Get("data-mvc");
}
}
public class MyHub : Hub
{
public void Method([FromKeyedServices("small")] ICache cache)
{
Console.WriteLine(cache.Get("signalr"));
}
}
Modelos de projeto do Visual Studio para aplicativos SPA com back-end ASP.NET Core
Os modelos de projeto do Visual Studio agora são a maneira recomendada de criar aplicativos de página única (SPAs) que têm um back-end ASP.NET Core. São fornecidos modelos que criam aplicações baseadas nas estruturas JavaScript Angular, Reacte Vue. Estes modelos:
- Crie uma solução do Visual Studio com um projeto de frontend e um projeto de back-end.
- Use o tipo de projeto Visual Studio para JavaScript e TypeScript (.esproj) para o frontend.
- Use um projeto ASP.NET Core para o back-end.
Para obter mais informações sobre os modelos do Visual Studio e como acessar os modelos herdados, consulte Visão geral de aplicativos de página única (SPAs) no ASP.NET Core
Suporte para atributos genéricos
Atributos que antes exigiam um parâmetro Type agora estão disponíveis em variantes genéricas mais limpas. Isso é possível graças ao suporte para atributos genéricos em C# 11. Por exemplo, a sintaxe para anotar o tipo de resposta de uma ação pode ser modificada da seguinte maneira:
[ApiController]
[Route("api/[controller]")]
public class TodosController : Controller
{
[HttpGet("/")]
- [ProducesResponseType(typeof(Todo), StatusCodes.Status200OK)]
+ [ProducesResponseType<Todo>(StatusCodes.Status200OK)]
public Todo Get() => new Todo(1, "Write a sample", DateTime.Now, false);
}
Variantes genéricas são suportadas para os seguintes atributos:
[ProducesResponseType<T>]
[Produces<T>]
[MiddlewareFilter<T>]
[ModelBinder<T>]
[ModelMetadataType<T>]
[ServiceFilter<T>]
[TypeFilter<T>]
Análise de código em aplicativos ASP.NET Core
Os novos analisadores mostrados na tabela a seguir estão disponíveis no ASP.NET Core 8.0.
ID de diagnóstico | Quebrável ou não quebrável | Descrição |
---|---|---|
ASP0016 | Sem quebra | Não retorne um valor de RequestDelegate |
ASP0019 | Sem quebra | Sugira o uso de IHeaderDictionary.Append ou o indexador |
ASP0020 | Sem quebra | Tipos complexos referenciados por parâmetros de rota devem ser analisáveis |
ASP0021 | Sem quebra | O tipo de retorno do método BindAsync deve ser ValueTask<T> |
ASP0022 | Sem quebra | Conflito de rota detetado entre manipuladores de rota |
ASP0023 | Sem quebra | MVC: Conflito de rota detetado entre manipuladores de rota |
ASP0024 | Sem quebra | O manipulador de rotas tem vários parâmetros com o atributo [FromBody] |
ASP0025 | Sem quebra | Utilizar AddAuthorizationBuilder |
Ferramentas de rota
ASP.NET Core é construído sobre roteamento. APIs mínimas, APIs da Web, Razor Páginas e Blazor todos usam rotas para personalizar como as solicitações HTTP são mapeadas para o código.
No .NET 8, investimos em um conjunto de novos recursos para tornar o roteamento mais fácil de aprender e usar. Esses novos recursos incluem:
- Realce de sintaxe da rota
- Preenchimento automático de nomes de parâmetros e rotas
- Preenchimento automático de restrições de rota
- Analisadores e ajustadores de rota
- Suporte para APIs mínimas, APIs da Web e Blazor
Para obter mais informações, consulte ferramentas de roteamento no .NET 8.
ASP.NET Core métricas
As métricas são medições relatadas ao longo do tempo e são usadas com mais frequência para monitorar a integridade de um aplicativo e gerar alertas. Por exemplo, um contador que relata solicitações HTTP com falha pode ser exibido em painéis ou gerar alertas quando as falhas ultrapassarem um limite.
Esta pré-visualização introduz novas métricas ao longo de todo o ASP.NET Core usando System.Diagnostics.Metrics.
Metrics
é uma API moderna para relatórios e coleta de informações sobre aplicativos.
As métricas oferecem muitas melhorias em comparação com os contadores de eventos existentes:
- Novos tipos de medições com contadores, medidores e histogramas.
- Relatórios robustos com valores multidimensionais.
- Integração no ecossistema nativo da nuvem mais amplo, alinhando-se com os padrões OpenTelemetry .
Foram adicionadas métricas para hospedagem ASP.NET Core, Kestrele SignalR. Para obter mais informações, consulte System.Diagnostics.Metrics.
IExceptionHandler
IExceptionHandler é uma nova interface que dá ao desenvolvedor um callback para lidar com exceções conhecidas em um ponto central.
IExceptionHandler
implementações são registradas chamando IServiceCollection.AddExceptionHandler<T>
. Várias implementações podem ser adicionadas e são chamadas na ordem registrada. Se um manipulador de exceção lida com uma solicitação, ele pode retornar true
para interromper o processamento. Se uma exceção não for manipulada por nenhum manipulador de exceções, o controle retornará ao comportamento padrão e às opções do middleware.
Para obter mais informações, consulte IExceptionHandler.
Experiência de depuração melhorada
Os atributos de personalização de depuração foram adicionados a tipos como HttpContext
, HttpRequest
, HttpResponse
, ClaimsPrincipal
e WebApplication
. As exibições aprimoradas do depurador para esses tipos facilitam a localização de informações importantes no depurador de um IDE. As capturas de ecrã a seguir mostram a diferença que os atributos fazem na exibição no depurador de HttpContext
.
.NET 7:
.NET 8:
A exibição do depurador para WebApplication
destaca informações importantes, como pontos de extremidade configurados, camadas de intermediação, e valores IConfiguration
.
.NET 7:
.NET 8:
Para obter mais informações sobre melhorias de depuração no .NET 8, consulte:
- Aprimoramentos de depuração no .NET 8
- Problema do GitHub dotnet/aspnetcore 48205
IPNetwork.Parse
e TryParse
Os novos métodos Parse e TryParse no IPNetwork adicionar suporte para a criação de um IPNetwork
usando uma cadeia de caracteres de entrada em de notação CIDR ou "notação de barra".
Aqui estão exemplos de IPv4:
// Using Parse
var network = IPNetwork.Parse("192.168.0.1/32");
// Using TryParse
bool success = IPNetwork.TryParse("192.168.0.1/32", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("192.168.0.1"), 32);
E aqui estão exemplos de IPv6:
// Using Parse
var network = IPNetwork.Parse("2001:db8:3c4d::1/128");
// Using TryParse
bool success = IPNetwork.TryParse("2001:db8:3c4d::1/128", out var network);
// Constructor equivalent
var network = new IPNetwork(IPAddress.Parse("2001:db8:3c4d::1"), 128);
Cache de saída baseado em Redis
ASP.NET Core 8 adiciona suporte para usar o Redis como um cache distribuído para cache de saída. O cache de saída é uma funcionalidade que permite a uma aplicação armazenar em cache a saída de um endpoint de API mínimo, uma ação do controlador ou uma Página Razor. Para obter mais informações, consulte Cache de saída.
Middleware de curto-circuito após o encaminhamento
Quando o encaminhamento corresponde a um ponto final, geralmente permite que o restante do pipeline de middleware seja executado antes de invocar a lógica do ponto final. Os serviços podem reduzir o uso de recursos filtrando solicitações conhecidas logo no início do pipeline. Use o método de extensão ShortCircuit para fazer com que o roteamento invoque a lógica do ponto de extremidade imediatamente e, em seguida, encerre a solicitação. Por exemplo, uma determinada rota pode não precisar passar por autenticação ou middleware CORS. O exemplo a seguir curto-circuita solicitações que correspondem à rota /short-circuit
:
app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();
Use o método MapShortCircuit para configurar curto-circuito para várias rotas ao mesmo tempo, passando para ele uma matriz de parâmetros de prefixos de URL. Por exemplo, navegadores e bots geralmente sondam servidores em busca de caminhos bem conhecidos, como robots.txt
e favicon.ico
. Se o aplicativo não tiver esses arquivos, uma linha de código poderá configurar ambas as rotas:
app.MapShortCircuit(404, "robots.txt", "favicon.ico");
Para mais informações, consulte o middleware de curto-circuito após o roteamento .
Extensibilidade do middleware de log HTTP
O middleware de log HTTP tem vários recursos novos:
- HttpLoggingFields.Duration: Quando ativado, o middleware emite um novo log no final da solicitação e da resposta que mede o tempo total necessário para o processamento. Este novo campo foi adicionado ao conjunto de HttpLoggingFields.All.
- HttpLoggingOptions.CombineLogs: Quando ativado, o middleware consolida todos os logs que estão ativados para uma solicitação e resposta num único log no final. Uma única mensagem de log inclui a solicitação, o corpo da solicitação, a resposta, o corpo da resposta e a duração.
-
IHttpLoggingInterceptor: Uma nova interface para um serviço que pode ser implementado e registado (usando AddHttpLoggingInterceptor) para receber retornos de chamada por requisição e por resposta para personalizar quais detalhes são registados. Todas as configurações de log específicas do ponto de extremidade são aplicadas primeiro e, em seguida, podem ser alteradas nestes callbacks. Uma implementação pode:
- Inspecione a solicitação e a resposta.
- É possível ativar ou desativar qualquer HttpLoggingFields.
- Ajuste a quantidade do corpo da solicitação ou resposta que é registrada.
- Adicione campos personalizados aos logs.
Para obter mais informações, consulte log HTTP no .NET Core e no ASP.NET Core.
Novas APIs no ProblemDetails para suportar integrações mais resilientes
No .NET 7, o serviço ProblemDetails foi introduzido para melhorar a experiência de geração de respostas de erro que estejam em conformidade com a especificação ProblemDetails. No .NET 8, uma nova API foi adicionada para facilitar a implementação do comportamento de fallback se IProblemDetailsService não for capaz de gerar ProblemDetails. O exemplo a seguir ilustra o uso da nova API TryWriteAsync:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async httpContext =>
{
var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (pds == null
|| !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
{
// Fallback behavior
await httpContext.Response.WriteAsync("Fallback: An error occurred.");
}
});
});
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
Para obter mais informações, consulte fallback de IProblemDetailsService