Condividi tramite


Novità di ASP.NET Core 8.0

Questo articolo illustra le modifiche più significative in ASP.NET Core 8.0 con collegamenti alla documentazione pertinente.

Blazor

Interfaccia utente Web full-stack

Con il rilascio di .NET 8, Blazor è un framework dell'interfaccia utente Web full-stack per lo sviluppo di app che eseguono il rendering del contenuto a livello di componente o pagina con:

  • Rendering del server statico (detto anche rendering lato server statico, SSR statico) per generare codice HTML statico nel server.
  • Rendering di Interactive Server (detto anche rendering lato server interattivo, SSR interattivo) per generare componenti interattivi con prerendering sul server.
  • Rendering Interattivo WebAssembly (detto anche rendering lato client, CSR, che si presuppone sempre essere interattivo) per generare componenti interattivi nel client con prerendering sul server.
  • Rendering automatico interattivo (automatico) per usare inizialmente il runtime ASP.NET Core sul lato server per il rendering e l'interattività del contenuto. Il runtime .NET WebAssembly nel client viene usato per il rendering e l'interattività successivi dopo il download del bundle e l'attivazione Blazor del runtime WebAssembly. Il rendering automatico interattivo offre in genere l'esperienza di avvio più veloce dell'app.

Per impostazione predefinita, le modalità di rendering interattive prerendere anche il contenuto.

Per altre informazioni, vedere gli articoli seguenti:

Esempi in tutta la Blazor documentazione sono stati aggiornati per l'uso in Blazor App Web. Blazor Server gli esempi rimangono nel contenuto con versione per .NET 7 o versioni precedenti.

Nuovo articolo sulle librerie di classi con rendering statico lato server (SSR statico)

È stato aggiunto un nuovo articolo che illustra l'autorizzazione della libreria dei componenti nelle Razor librerie di classi (RCL) con il rendering statico lato server (SSR statico).

Per altre informazioni, vedere ASP.NET Librerie di classi core Razor con rendering statico lato server (SSR statico).

Nuovo articolo sui problemi di memorizzazione nella cache HTTP

È stato aggiunto un nuovo articolo che illustra alcuni dei problemi comuni di memorizzazione nella cache HTTP che possono verificarsi durante l'aggiornamento Blazor delle app tra le versioni principali e come risolvere i problemi di memorizzazione nella cache HTTP.

Per altre informazioni, vedere Evitare problemi di memorizzazione nella cache HTTP durante l'aggiornamento delle app ASP.NET CoreBlazor.

Nuovo Blazor modello di app Web

È stato introdotto un nuovo Blazor modello di progetto: il Blazor modello app Web. Il nuovo modello fornisce un singolo punto di partenza per l'uso Blazor dei componenti per compilare qualsiasi stile di interfaccia utente Web. Il modello combina i punti di forza dei modelli esistenti Blazor Server e Blazor WebAssembly di hosting con le nuove Blazor funzionalità aggiunte in .NET 8: rendering statico lato server (SSR statico), rendering in streaming, spostamento avanzato e gestione dei moduli e la possibilità di aggiungere interattività usando Blazor Server o Blazor WebAssembly per ogni componente.

Nell'ambito dell'unificazione dei vari Blazor modelli di hosting in un singolo modello in .NET 8, viene consolidato anche il numero di modelli di Blazor progetto. È stato rimosso il Blazor Server modello e l'opzione ASP.NET Core Hosted è stata rimossa dal Blazor WebAssembly modello. Entrambi questi scenari sono rappresentati dalle opzioni quando si usa il Blazor modello app Web.

Nota

Le app e Blazor WebAssembly esistenti Blazor Server rimangono supportate in .NET 8. Facoltativamente, queste app possono essere aggiornate per usare le nuove funzionalità dell'interfaccia utente Blazor Web dello stack completo.

Per altre informazioni sul nuovo Blazor modello di app Web, vedere gli articoli seguenti:

Nuovi JS inizializzatori per Blazor App Web

Per Blazor Serverle app , Blazor WebAssemblye Blazor Hybrid :

  • beforeStart viene usato per attività quali la personalizzazione del processo di caricamento, il livello di registrazione e altre opzioni.
  • afterStarted viene usato per attività quali la registrazione di Blazor listener di eventi e i tipi di evento personalizzati.

Gli inizializzatori legacy precedenti JS non vengono richiamati per impostazione predefinita in un'app Blazor Web. Per Blazor App Web, viene usato un nuovo set di JS inizializzatori: beforeWebStart, afterWebStarted, beforeServerStartafterServerStarted, beforeWebAssemblyStart, e afterWebAssemblyStarted.

Per altre informazioni, vedere ASP.NET avvio di CoreBlazor.

Suddivisione del prerendering e delle linee guida per l'integrazione

Per le versioni precedenti di .NET, sono stati illustrati i prerendering e l'integrazione in un singolo articolo. Per semplificare e concentrarsi sulla copertura, sono stati suddivisi gli argomenti nei nuovi articoli seguenti, che sono stati aggiornati per .NET 8:

Rendere persistente lo stato del componente in un'app Blazor Web

È possibile mantenere e leggere lo stato del componente in un'app Blazor Web usando il servizio esistente PersistentComponentState . Ciò è utile per rendere persistente lo stato del componente durante la pre-esecuzione del servizio.

BlazorApp Web rendere persistente automaticamente qualsiasi stato a livello di app registrato creato durante la pre-esecuzione del servizio, rimuovendo la necessità di Rendere persistente l'helper tag di stato del componente.

Gestione dei moduli e associazione di modelli

Blazor i componenti possono ora gestire le richieste di modulo inviate, tra cui l'associazione di modelli e la convalida dei dati della richiesta. I componenti possono implementare moduli con gestori di moduli separati usando il tag HTML <form> standard o usando il componente esistente EditForm .

L'associazione Blazor di modelli di modulo rispetta gli attributi del contratto dati (ad esempio, [DataMember] e [IgnoreDataMember]) per personalizzare il modo in cui i dati del modulo sono associati al modello.

Il nuovo supporto antiforgery è incluso in .NET 8. Un nuovo AntiforgeryToken componente esegue il rendering di un token antiforgery come campo nascosto e il nuovo [RequireAntiforgeryToken] attributo abilita la protezione antiforgeria. Se un controllo antiforgery non riesce, viene restituita una risposta 400 (richiesta non valida) senza elaborazione moduli. Le nuove funzionalità antiforgery sono abilitate per impostazione predefinita per i moduli basati su Editform e possono essere applicate manualmente ai moduli HTML standard.

Per altre informazioni, vedere ASP.NET Panoramica dei moduli principaliBlazor.

Spostamento avanzato e gestione dei moduli

Il rendering statico lato server (SSR statico) esegue in genere un aggiornamento a pagina intera ogni volta che l'utente passa a una nuova pagina o invia un modulo. In .NET 8 è Blazor possibile migliorare la gestione degli spostamenti delle pagine e dei moduli intercettando la richiesta ed eseguendo invece una richiesta di recupero. Blazor gestisce quindi il contenuto della risposta di cui è stato eseguito il rendering eseguendo l'applicazione di patch nel DOM del browser. La gestione avanzata degli spostamenti e dei moduli evita la necessità di un aggiornamento a pagina completa e mantiene più lo stato della pagina, in modo che le pagine vengano caricate più velocemente e senza problemi. La navigazione avanzata è abilitata per impostazione predefinita quando viene caricato lo Blazor script (blazor.web.js). La gestione avanzata dei moduli può essere abilitata facoltativamente per moduli specifici.

La nuova API di spostamento avanzata consente di aggiornare la pagina corrente chiamando NavigationManager.Refresh(bool forceLoad = false).

Per altre informazioni, vedere le sezioni seguenti dell'articolo BlazorRouting :

Nuovo articolo sul rendering statico con spostamento avanzato per JS l'interoperabilità

Alcune app dipendono dall'interoperabilità JS per eseguire attività di inizializzazione specifiche di ogni pagina. Quando si usa Blazorla funzionalità di spostamento avanzata con pagine sottoposte a rendering statico che eseguono JS attività di inizializzazione di interoperabilità, è possibile che non JS venga eseguito di nuovo come previsto ogni volta che si verifica un spostamento pagina avanzato. Un nuovo articolo illustra come risolvere questo scenario in Blazor App Web:

ASP.NET Core Blazor JavaScript con rendering statico lato server (SSR statico)

Rendering in streaming

È ora possibile trasmettere gli aggiornamenti del contenuto nel flusso di risposta quando si usa il rendering statico lato server (SSR statico) con Blazor. Il rendering in streaming può migliorare l'esperienza utente per le pagine che eseguono attività asincrone a esecuzione prolungata per il rendering completo del contenuto non appena è disponibile.

Ad esempio, per eseguire il rendering di una pagina potrebbe essere necessario eseguire una query di database a esecuzione prolungata o una chiamata API. In genere, le attività asincrone eseguite come parte del rendering di una pagina devono essere completate prima dell'invio della risposta sottoposta a rendering, che può ritardare il caricamento della pagina. Il rendering dello streaming esegue inizialmente il rendering dell'intera pagina con contenuto segnaposto durante l'esecuzione delle operazioni asincrone. Al termine delle operazioni asincrone, il contenuto aggiornato viene inviato al client nella stessa connessione di risposta e con patch nel DOM. Il vantaggio di questo approccio è che il layout principale dell'app viene eseguito il rendering il più rapidamente possibile e la pagina viene aggiornata non appena il contenuto è pronto.

Per altre informazioni, vedere Rendering dei componenti di ASP.NET CoreRazor.

Inserire i servizi con chiave nei componenti

Blazor supporta ora l'inserimento di servizi con chiave usando l'attributo [Inject] . Le chiavi consentono di definire l'ambito della registrazione e dell'utilizzo dei servizi quando si usa l'inserimento delle dipendenze. Usare la nuova InjectAttribute.Key proprietà per specificare la chiave per il servizio da inserire:

[Inject(Key = "my-service")]
public IMyService MyService { get; set; }

La @injectRazor direttiva non supporta i servizi con chiave per questa versione, ma il lavoro viene rilevato da Update @inject per supportare i servizi con chiave (dotnet/razor #9286) per una versione futura di .NET.

Per altre informazioni, vedere ASP.NET Core Blazor dependency injection.

Accesso HttpContext come parametro a catena

È ora possibile accedere all'oggetto corrente HttpContext come parametro a catena da un componente server statico:

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

L'accesso HttpContext a da un componente server statico può essere utile per esaminare e modificare intestazioni o altre proprietà.

Per un esempio che passa HttpContext lo stato, l'accesso e l'aggiornamento dei token, ai componenti, vedere Scenari di sicurezza aggiuntivi sul lato server ASP.NET CoreBlazor.

Eseguire il rendering Razor dei componenti all'esterno di ASP.NET Core

È ora possibile eseguire il rendering Razor dei componenti all'esterno del contesto di una richiesta HTTP. È possibile eseguire il rendering Razor dei componenti come HTML direttamente in una stringa o in un flusso indipendentemente dall'ambiente di hosting ASP.NET Core. Ciò è utile per gli scenari in cui si vogliono generare frammenti HTML, ad esempio per la generazione di messaggi di posta elettronica o contenuto del sito statico.

Per altre informazioni, vedere Eseguire il rendering Razor dei componenti all'esterno di ASP.NET Core.

Supporto delle sezioni

I nuovi SectionOutlet componenti e SectionContent in Blazor aggiungono il supporto per specificare punti di vendita per il contenuto che possono essere compilati in un secondo momento. Le sezioni vengono spesso usate per definire segnaposto nei layout che vengono quindi compilati da pagine specifiche. Le sezioni vengono a cui viene fatto riferimento tramite un nome univoco o un ID oggetto univoco.

Per altre informazioni, vedere le sezioni ASP.NET CoreBlazor.

Supporto della pagina degli errori

BlazorApp Web possibile definire una pagina di errore personalizzata da usare con il middleware di gestione delle eccezioni di base ASP.NET. Il Blazor modello di progetto App Web include una pagina di errore predefinita (Components/Pages/Error.razor) con contenuto simile a quello usato nelle app MVC e Razor Pages. Quando viene eseguito il rendering della pagina di errore in risposta a una richiesta dal middleware di gestione delle eccezioni, la pagina di errore viene sempre visualizzata come componente server statico, anche se l'interattività è abilitata in caso contrario.

Error.razor nell'origine di riferimento 8.0

QuickGrid

Il Blazor componente QuickGrid non è più sperimentale ed è ora parte del Blazor framework in .NET 8.

QuickGrid è un componente griglia ad alte prestazioni per la visualizzazione dei dati in formato tabulare. QuickGrid è progettato per essere un modo semplice e pratico per visualizzare i dati, offrendo al tempo stesso funzionalità avanzate, ad esempio l'ordinamento, il filtro, il paging e la virtualizzazione.

Per altre informazioni, vedere ASP.NET componente Core Blazor QuickGrid.

Indirizzare agli elementi denominati

Blazor supporta ora l'uso del routing lato client per passare a un elemento HTML specifico in una pagina usando frammenti URL standard. Se si specifica un identificatore per un elemento HTML usando l'attributo standard id , Blazor scorre correttamente fino a tale elemento quando il frammento URL corrisponde all'identificatore dell'elemento.

Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor.

Valori a cascata a livello radice

I valori a catena a livello radice possono essere registrati per l'intera gerarchia dei componenti. Sono supportati valori e sottoscrizioni denominati a catena per le notifiche di aggiornamento.

Per altre informazioni, vedere ASP.NET Valori e parametri a catena di baseBlazor.

Virtualizzare il contenuto vuoto

Usare il nuovo EmptyContent parametro nel Virtualize componente per fornire il contenuto quando il componente è stato caricato ed Items è vuoto o ItemsProviderResult<T>.TotalItemCount è zero.

Per altre informazioni, vedere ASP.NET Virtualizzazione dei componenti coreRazor.

Chiudere i circuiti quando non sono presenti componenti server interattivi rimanenti

I componenti server interattivi gestiscono gli eventi dell'interfaccia utente Web usando una connessione in tempo reale con il browser denominato circuito. Un circuito e lo stato associato vengono configurati quando viene eseguito il rendering di un componente server interattivo radice. Il circuito viene chiuso quando non sono presenti componenti server interattivi rimanenti nella pagina, che libera risorse server.

Monitorare l'attività SignalR del circuito

È ora possibile monitorare l'attività del circuito in ingresso nelle app sul lato server usando il nuovo CreateInboundActivityHandler metodo in CircuitHandler. L'attività del circuito in ingresso è qualsiasi attività inviata dal browser al server, ad esempio eventi dell'interfaccia utente o JavaScript-to-.NET chiamate di interoperabilità.

Per altre informazioni, vedere ASP.NET Linee guida di baseBlazorSignalR.

Prestazioni di runtime più veloci con Jiterpreter

Jiterpreter è una nuova funzionalità di runtime in .NET 8 che consente il supporto parziale della compilazione JIT (Just-in-Time) durante l'esecuzione in WebAssembly per ottenere prestazioni di runtime migliorate.

Per altre informazioni, vedere Ospitare e distribuire ASP.NET Core Blazor WebAssembly.

SIMD e gestione delle eccezioni in anticipo (AOT)

Blazor WebAssembly La compilazione ahead-of-time (AOT) usa ora SIMD a larghezza fissa WebAssembly e gestione delle eccezioni WebAssembly per impostazione predefinita per migliorare le prestazioni di runtime.

Per altre informazioni, vedere gli articoli seguenti:

Creazione di pacchetti Webcil web-friendly

Webcil è un pacchetto web-friendly di assembly .NET che rimuove il contenuto specifico per l'esecuzione nativa di Windows per evitare problemi durante la distribuzione in ambienti che bloccano il download o l'uso di .dll file. Webcil è abilitato per impostazione predefinita per Blazor WebAssembly le app.

Per altre informazioni, vedere Ospitare e distribuire ASP.NET Core Blazor WebAssembly.

Nota

Prima del rilascio di .NET 8, linee guida in Layout di distribuzione per le app ospitate Blazor WebAssembly di ASP.NET Core indirizzano gli ambienti che impediscono ai client di scaricare ed eseguire DLL con un approccio di bundle multipart. In .NET 8 o versioni successive Blazor usa il formato di file Webcil per risolvere il problema. La creazione di bundle in più parti con il pacchetto NuGet sperimentale descritto dall'articolo layout di distribuzione WebAssembly non è supportata per Blazor le app in .NET 8 o versioni successive. Per altre informazioni, vedere Migliorare il Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle pacchetto per definire un formato di bundle personalizzato (dotnet/aspnetcore #36978). Se si vuole continuare a usare il pacchetto bundle multipart nelle app .NET 8 o successive, è possibile usare le indicazioni contenute nell'articolo per creare un pacchetto NuGet multipart bundling, ma non sarà supportato da Microsoft.

Blazor WebAssembly miglioramenti al debug

Quando si esegue il debug di .NET in WebAssembly, il debugger scarica ora i dati dei simboli dalle posizioni dei simboli configurate nelle preferenze di Visual Studio. Ciò migliora l'esperienza di debug per le app che usano pacchetti NuGet.

È ora possibile eseguire il debug Blazor WebAssembly delle app usando Firefox. Blazor WebAssembly Per eseguire il debug delle app è necessario configurare il browser per il debug remoto e quindi connettersi al browser usando gli strumenti di sviluppo del browser tramite il proxy di debug WebAssembly .NET. Il debug di Firefox da Visual Studio non è attualmente supportato.

Per altre informazioni, vedere Eseguire il debug di app ASP.NET CoreBlazor.

Compatibilità dei criteri di sicurezza dei contenuti (CSP)

Blazor WebAssembly non richiede più l'abilitazione dell'origine unsafe-eval script quando si specifica un CSP (Content Security Policy).

Per altre informazioni, vedere Applicare criteri di sicurezza del contenuto per ASP.NET Core Blazor.

Gestire le eccezioni rilevate al di fuori del ciclo di vita di un Razor componente

Usare ComponentBase.DispatchExceptionAsync in un Razor componente per elaborare le eccezioni generate all'esterno dello stack di chiamate del ciclo di vita del componente. In questo modo il codice del componente può trattare le eccezioni come se fossero eccezioni del metodo del ciclo di vita. Successivamente, Blazori meccanismi di gestione degli errori, ad esempio i limiti degli errori, possono elaborare le eccezioni.

Per altre informazioni, vedere Gestire gli errori nelle app ASP.NET CoreBlazor.

Configurare il runtime .NET WebAssembly

Il runtime .NET WebAssembly può ora essere configurato per Blazor l'avvio.

Per altre informazioni, vedere ASP.NET avvio di CoreBlazor.

Configurazione dei timeout di connessione in HubConnectionBuilder

Le soluzioni alternative precedenti per la configurazione dei timeout della connessione hub possono essere sostituite con la configurazione del timeout del generatore di connessioni hub formale SignalR .

Per altre informazioni, vedere gli argomenti seguenti:

Modelli di progetto getta Open Iconic

I modelli di Blazor progetto non dipendono più da Open Iconic per le icone.

Supporto per gli eventi di annullamento e chiusura della finestra di dialogo

Blazor supporta ora gli cancel eventi e close nell'elemento dialog HTML.

Nell'esempio seguente :

  • OnClose viene chiamato quando la my-dialog finestra di dialogo viene chiusa con il pulsante Chiudi .
  • OnCancel viene chiamato quando il dialogo viene annullato con il tasto ESC . Quando una finestra di dialogo HTML viene chiusa con la chiave ESC , vengono attivati entrambi gli cancel eventi e close .
<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, ";
}

BlazorIdentity UI

Blazor supporta la generazione di un'interfaccia utente completa Blazorbasata su Identity quando si sceglie l'opzione di autenticazione per singoli account. È possibile selezionare l'opzione Account singoli nella finestra di dialogo nuovo progetto per Blazor App Web da Visual Studio oppure passare l'opzione -au|--auth impostata su Individual dalla riga di comando quando si crea un nuovo progetto.

Per ulteriori informazioni, vedi le seguenti risorse:

Proteggere Blazor WebAssembly con ASP.NET Core Identity

La Blazor documentazione ospita un nuovo articolo e un'app di esempio per la protezione di un'app autonoma Blazor WebAssembly con ASP.NET Core Identity.

Per ulteriori informazioni, vedi le seguenti risorse:

Blazor Server con il routing yarp

Il routing e il deep linking per Blazor Server con Yarp funzionano correttamente in .NET 8.

Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 7.0 a 8.0.

Blazor Hybrid

Gli articoli seguenti illustrano le modifiche apportate a Blazor Hybrid in .NET 8:

[Parameter] l'attributo non è più necessario quando viene specificato dalla stringa di query

L'attributo [Parameter] non è più necessario quando si specifica un parametro dalla stringa di query:

- [Parameter]
  [SupplyParameterFromQuery]

SignalR

Nuovo approccio per impostare il timeout del server e l'intervallo Keep-Alive

ServerTimeout (impostazione predefinita: 30 secondi) e KeepAliveInterval (impostazione predefinita: 15 secondi) possono essere impostati direttamente su HubConnectionBuilder.

Approccio precedente per i client JavaScript

L'esempio seguente mostra l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 7.0 o versioni precedenti:

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .build();

connection.serverTimeoutInMilliseconds = 60000;
connection.keepAliveIntervalInMilliseconds = 30000;

Nuovo approccio per i client JavaScript

L'esempio seguente illustra il nuovo approccio per l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 8.0 o versione successiva:

var connection = new signalR.HubConnectionBuilder()
  .withUrl("/chatHub")
  .withServerTimeout(60000)
  .withKeepAlive(30000)
  .build();

Approccio precedente per il client JavaScript di un'app Blazor Server

L'esempio seguente mostra l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 7.0 o versioni precedenti:

Blazor.start({
  configureSignalR: function (builder) {
    let c = builder.build();
    c.serverTimeoutInMilliseconds = 60000;
    c.keepAliveIntervalInMilliseconds = 30000;
    builder.build = () => {
      return c;
    };
  }
});

Nuovo approccio per il client JavaScript dell'app lato Blazor server

L'esempio seguente illustra il nuovo approccio per l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 8.0 o versione successiva per Blazor App Web e Blazor Server.

Blazor App Web:

Blazor.start({
  circuit: {
    configureSignalR: function (builder) {
      builder.withServerTimeout(60000).withKeepAliveInterval(30000);
    }
  }
});

Blazor Server:

Blazor.start({
  configureSignalR: function (builder) {
    builder.withServerTimeout(60000).withKeepAliveInterval(30000);
  }
});

Approccio precedente per i client .NET

L'esempio seguente mostra l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 7.0 o versioni precedenti:

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();

Nuovo approccio per i client .NET

L'esempio seguente illustra il nuovo approccio per l'assegnazione di valori che corrispondono al doppio dei valori predefiniti in ASP.NET Core 8.0 o versione successiva:

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 riconnessione con stato

SignalR la riconnessione con stato riduce il tempo di inattività percepito dei client che hanno una disconnessione temporanea nella connessione di rete, ad esempio quando si cambiano connessioni di rete o si verifica una breve perdita temporanea nell'accesso.

La riconnessione con stato consente di ottenere questo risultato:

  • Memorizzazione temporaneamente nel buffer dei dati nel server e nel client.
  • Riconoscimento dei messaggi ricevuti (ACK-ing) sia dal server che dal client.
  • Riconoscimento quando una connessione restituisce e riproduce messaggi che potrebbero essere stati inviati mentre la connessione è inattiva.

La riconnessione con stato è disponibile in ASP.NET Core 8.0 e versioni successive.

Acconsentire esplicitamente alla riconnessione con stato sia all'endpoint dell'hub server che al client:

  • Aggiornare la configurazione dell'endpoint dell'hub server per abilitare l'opzione AllowStatefulReconnects :

    app.MapHub<MyHub>("/hubName", options =>
    {
        options.AllowStatefulReconnects = true;
    });
    

    Facoltativamente, le dimensioni massime del buffer in byte consentite dal server possono essere impostate a livello globale o per un hub specifico con l'opzione StatefulReconnectBufferSize :

    L'opzione StatefulReconnectBufferSize impostata a livello globale:

    builder.AddSignalR(o => o.StatefulReconnectBufferSize = 1000);
    

    L'opzione StatefulReconnectBufferSize impostata per un hub specifico:

    builder.AddSignalR().AddHubOptions<MyHub>(o => o.StatefulReconnectBufferSize = 1000);
    

    L'opzione StatefulReconnectBufferSize è facoltativa con un valore predefinito di 100.000 byte.

  • Aggiornare il codice client JavaScript o TypeScript per abilitare l'opzione withStatefulReconnect :

    const builder = new signalR.HubConnectionBuilder()
      .withUrl("/hubname")
      .withStatefulReconnect({ bufferSize: 1000 });  // Optional, defaults to 100,000
    const connection = builder.build();
    

    L'opzione bufferSize è facoltativa con un valore predefinito di 100.000 byte.

  • Aggiornare il codice client .NET per abilitare l'opzione WithStatefulReconnect :

      var builder = new HubConnectionBuilder()
          .WithUrl("<hub url>")
          .WithStatefulReconnect();
      builder.Services.Configure<HubConnectionOptions>(o => o.StatefulReconnectBufferSize = 1000);
      var hubConnection = builder.Build();
    

    L'opzione StatefulReconnectBufferSize è facoltativa con un valore predefinito di 100.000 byte.

Per altre informazioni, vedere Configurare la riconnessione con stato.

API minime

Questa sezione descrive le nuove funzionalità per le API minime. Per altre informazioni relative alle API minime, vedere anche la sezione relativa all'AOT nativo.

Impostazioni cultura di override utente

A partire da ASP.NET Core 8.0, la proprietà RequestLocalizationOptions.CultureInfoUseUserOverride consente all'applicazione di decidere se usare o meno le impostazioni di Windows non predefinite per le CultureInfo DateTimeFormat proprietà e NumberFormat . Questo non ha alcun impatto su Linux. Corrisponde direttamente a UseUserOverride.

    app.UseRequestLocalization(options =>
    {
        options.CultureInfoUseUserOverride = false;
    });

Associazione a moduli

È ora supportata l'associazione esplicita ai valori del modulo usando l'attributo [FromForm]. I parametri associati alla richiesta con [FromForm] includono un token anti-falsità. Il token anti-falsità viene convalidato quando la richiesta viene elaborata.

È supportata anche l'associazione dedotta ai moduli che usano i IFormCollectiontipi , IFormFilee IFormFileCollection . I metadati OpenAPI vengono dedotti per i parametri del modulo per supportare l'integrazione con l'interfaccia utente di Swagger.

Per altre informazioni, vedi:

L'associazione dai moduli è ora supportata per:

  • Raccolte, ad esempio List e Dictionary
  • Tipi complessi, ad esempio o TodoProject

Per altre informazioni, vedere Associare a raccolte e tipi complessi dai moduli.

Antiforgery con API minime

Questa versione aggiunge un middleware per convalidare i token antiforgery, che vengono usati per attenuare gli attacchi di richiesta intersito falsi. Chiama AddAntiforgery per registrare i servizi antiforgery in DI. WebApplicationBuilder aggiunge automaticamente il middleware quando i servizi antiforgery sono stati registrati nel contenitore di inserimento delle dipendenze. I token antiforgery vengono usati per attenuare gli attacchi falsi di richiesta intersito.

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

app.MapGet("/", () => "Hello World!");

app.Run();

Middleware antiforgery:

  • Non esegue il corto circuito dell'esecuzione del resto della pipeline di richiesta.
  • Imposta IAntiforgeryValidationFeature in HttpContext.Features della richiesta corrente.

Il token antiforgery viene convalidato solo se:

  • L'endpoint contiene metadati che implementano IAntiforgeryMetadata dove RequiresValidation=true.
  • Il metodo HTTP associato all'endpoint è un metodo HTTP pertinente. I metodi pertinenti sono tutti metodi HTTP ad eccezione di TRACE, OPTIONS, HEAD e GET.
  • La richiesta è associata a un endpoint valido.

Per altre informazioni, vedere Antiforgery con API minime.

Nuova IResettable interfaccia in ObjectPool

Microsoft.Extensions.ObjectPool fornisce il supporto per il pool di istanze di oggetti in memoria. Le app possono usare un pool di oggetti se i valori sono costosi da allocare o inizializzare.

In questa versione il pool di oggetti è stato reso più semplice da usare aggiungendo l'interfaccia IResettable . I tipi riutilizzabili spesso devono essere reimpostati su uno stato predefinito tra gli usi. IResettable I tipi vengono reimpostati automaticamente quando vengono restituiti a un pool di oggetti.

Per altre informazioni, vedere l'esempio ObjectPool.

AOT nativo

È stato aggiunto il supporto per .NET native in anticipo (AOT). Le app pubblicate con AOT possono avere prestazioni notevolmente migliori: dimensioni delle app più piccole, meno utilizzo della memoria e tempi di avvio più veloci. AOT nativo è attualmente supportato dalle app gRPC, API minime e del servizio di lavoro. Per altre informazioni, vedere supporto di ASP.NET Core per AOT nativo ed Esercitazione: Pubblicare un'app ASP.NET Core con AOT nativo. Per informazioni sui problemi noti relativi alla compatibilità ASP.NET Core e native AOT, vedere Problema di GitHub dotnet/core #8288.

Librerie e AOT nativo

Molte delle librerie più diffuse usate nei progetti ASP.NET Core presentano attualmente alcuni problemi di compatibilità quando vengono usati in un progetto destinato a AOT nativo, ad esempio:

  • Uso della reflection per esaminare e individuare i tipi.
  • Caricamento condizionale delle librerie in fase di esecuzione.
  • Generazione di codice in tempo reale per implementare la funzionalità.

Le librerie che usano queste funzionalità dinamiche devono essere aggiornate per lavorare con AOT nativo. Possono essere aggiornati usando strumenti come generatori di origine Roslyn.

Gli autori di librerie che sperano di supportare native AOT sono invitati a:

Nuovo modello di progetto

Il nuovo modello webapiaotdi progetto api Web principale (AOT nativo) ASP.NET crea un progetto con pubblicazione AOT abilitata. Per altre informazioni, vedere Il modello api Web (AOT nativo).

Nuovo CreateSlimBuilder metodo

Il CreateSlimBuilder() metodo usato nel modello api Web (AOT nativo) inizializza WebApplicationBuilder con le funzionalità minime ASP.NET Core necessarie per eseguire un'app. Il CreateSlimBuilder metodo include le funzionalità seguenti, in genere necessarie per un'esperienza di sviluppo efficiente:

  • JSConfigurazione del file ON per appsettings.json e appsettings.{EnvironmentName}.json.
  • Configurazione dei segreti utente.
  • Registrazione della console.
  • Configurazione della registrazione.

Per altre informazioni, vedere Il CreateSlimBuilder metodo .

Nuovo CreateEmptyBuilder metodo

Esiste un altro nuovo WebApplicationBuilder metodo factory per la creazione di app di piccole dimensioni che contengono solo le funzionalità necessarie: WebApplication.CreateEmptyBuilder(WebApplicationOptions options). Questa WebApplicationBuilder operazione viene creata senza alcun comportamento predefinito. L'app compilata contiene solo i servizi e il middleware configurati in modo esplicito.

Ecco un esempio di uso di questa API per creare una piccola applicazione 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();

La pubblicazione di questo codice con AOT nativo con .NET 8 Preview 7 in un computer linux-x64 comporta un eseguibile nativo autonomo di circa 8,5 MB.

Riduzione delle dimensioni delle app con supporto HTTPS configurabile

Sono stati ulteriormente ridotte le dimensioni binarie native AOT per le app che non necessitano del supporto HTTPS o HTTP/3. L'uso di HTTPS o HTTP/3 è comune per le app che vengono eseguite dietro un proxy di terminazione TLS ( ad esempio, ospitate in Azure). Il nuovo WebApplication.CreateSlimBuilder metodo omette questa funzionalità per impostazione predefinita. Può essere aggiunto chiamando builder.WebHost.UseKestrelHttpsConfiguration() HTTPS o builder.WebHost.UseQuic() per HTTP/3. Per altre informazioni, vedere Il CreateSlimBuilder metodo .

JSSerializzazione ON dei tipi generati dal IAsyncEnumerable<T> compilatore

Sono state aggiunte nuove funzionalità per supportare System.Text.Json meglio native AOT. Queste nuove funzionalità aggiungono funzionalità per la modalità di generazione di origine di System.Text.Json, perché la reflection non è supportata da AOT.

Una delle nuove funzionalità è il supporto per JSla serializzazione ON delle IAsyncEnumerable<T> implementazioni implementate dal compilatore C#. Questo supporto apre l'uso nei progetti ASP.NET Core configurati per pubblicare AOT nativo.

Questa API è utile negli scenari in cui un gestore di route usa yield return per restituire in modo asincrono un'enumerazione. Ad esempio, per materializzare le righe da una query di database. Per altre informazioni, vedere Supporto dei tipi indicibili nell'annuncio .NET 8 Preview 4.

Per informazioni sugli altri miglioramenti apportati alla System.Text.Json generazione di origine, vedere Miglioramenti della serializzazione in .NET 8.

API di primo livello annotate per gli avvisi di taglio

I punti di ingresso principali ai sottosistemi che non funzionano in modo affidabile con AOT nativo sono ora annotati. Quando questi metodi vengono chiamati da un'applicazione con AOT nativo abilitato, viene visualizzato un avviso. Ad esempio, il codice seguente genera un avviso alla chiamata di AddControllers perché questa API non è trim-safe e non è supportata da AOT nativo.

Finestra di Visual Studio che mostra il messaggio di avviso IL2026 nel metodo AddControllers che indica che MVC non supporta attualmente Native AOT.

Generatore di delegati della richiesta

Per rendere compatibili le API minime con AOT nativo, viene introdotto il generatore di delegati di richiesta (RDG). RdG è un generatore di origine che esegue le RequestDelegateFactory operazioni di (RDF). Vale a dire, trasforma i vari MapGet(), MapPost()e chiama come tali istanze in RequestDelegate istanze associate alle route specificate. Invece di eseguire questa operazione in memoria in un'applicazione all'avvio, rdg lo esegue in fase di compilazione e genera codice C# direttamente nel progetto. The RDG:

  • Rimuove la generazione di runtime di questo codice.
  • Garantisce che i tipi usati nelle API siano analizzabili in modo statico dalla catena di strumenti AOT nativa.
  • Assicura che il codice necessario non sia eliminato.

Microsoft sta lavorando per assicurarsi che il maggior numero possibile di funzionalità API minime sia supportato dal set di dati RDG e quindi compatibile con Native AOT.

Il set di dati RDG viene abilitato automaticamente in un progetto quando la pubblicazione con AOT nativo è abilitata. RdG può essere abilitato manualmente anche quando non si usa AOT nativo impostando <EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator> nel file di progetto. Ciò può essere utile quando si valuta inizialmente l'idoneità di un progetto per AOT nativo o per ridurre il tempo di avvio di un'app.

Miglioramento delle prestazioni tramite intercettori

Il generatore di delegati di richiesta usa la nuova funzionalità del compilatore di intercettori C# 12 per supportare l'intercettazione delle chiamate a metodi di mapping API minimi con varianti generate in modo statico in fase di esecuzione. L'uso di intercettori comporta un aumento delle prestazioni di avvio per le app compilate con PublishAot.

Registrazione e gestione delle eccezioni nelle API minime generate in fase di compilazione

Le API minime generate in fase di esecuzione supportano la registrazione automatica (o la generazione di eccezioni negli ambienti di sviluppo) quando l'associazione di parametri ha esito negativo. .NET 8 introduce lo stesso supporto per le API generate in fase di compilazione tramite il generatore di delegati di richiesta (RDG). Per altre informazioni, vedere Registrazione e gestione delle eccezioni nelle API minime generate in fase di compilazione.

AOT e System.Text.Json

Le API minime sono ottimizzate per la ricezione e la restituzione di JSpayload ON usando System.Text.Json, quindi si applicano anche i requisiti di compatibilità per JSON e Native AOT. La compatibilità AOT nativa richiede l'uso del System.Text.Json generatore di origine. Tutti i tipi accettati come parametri o restituiti dai delegati di richiesta nelle API minime devono essere configurati in un oggetto JsonSerializerContext registrato tramite l'inserimento delle dipendenze di ASP.NET Core, ad esempio:

// 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
{

}

Per altre informazioni sull'API TypeInfoResolverChain , vedere le risorse seguenti:

Librerie e AOT nativo

Molte delle librerie comuni disponibili per i progetti ASP.NET Core presentano attualmente alcuni problemi di compatibilità se usati in un progetto destinato a AOT nativo. Le librerie più diffuse spesso si basano sulle funzionalità dinamiche della reflection .NET per esaminare e individuare i tipi, caricare in modo condizionale le librerie in fase di esecuzione e generare codice in tempo reale per implementare le funzionalità. Queste librerie devono essere aggiornate per poter usare Native AOT usando strumenti come i generatori di origine Roslyn.

Gli autori di librerie che vogliono saperne di più sulla preparazione delle librerie per Native AOT sono invitati a iniziare preparando la libreria per tagliare e ottenere altre informazioni sui requisiti di compatibilità AOT nativi.

Kestrel e HTTP.sys server

Sono disponibili diverse nuove funzionalità per Kestrel e HTTP.sys.

Supporto per named pipe in Kestrel

Named pipe è una tecnologia popolare per la creazione di comunicazioni tra processi (IPC) tra app di Windows. È ora possibile compilare un server IPC usando .NET, Kestrele named pipe.

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenNamedPipe("MyPipeName");
});

Per altre informazioni su questa funzionalità e su come usare .NET e gRPC per creare un server e un client IPC, vedere Comunicazione tra processi con gRPC.

Miglioramenti delle prestazioni per il trasporto named pipe

Sono stati migliorate le prestazioni di connessione named pipe. KestrelIl trasporto named pipe accetta ora le connessioni in parallelo e riutilizza NamedPipeServerStream le istanze.

Tempo necessario per creare 100.000 connessioni:

  • Prima di : 5,916 secondi
  • Dopo : 2,374 secondi

Supporto HTTP/2 su TLS (HTTPS) in macOS in Kestrel

.NET 8 aggiunge il supporto per application-layer Protocol Negotiation (ALPN) a macOS. ALPN è una funzionalità TLS usata per negoziare il protocollo HTTP che verrà usato da una connessione. Ad esempio, ALPN consente ai browser e ad altri client HTTP di richiedere una connessione HTTP/2. Questa funzionalità è particolarmente utile per le app gRPC, che richiedono HTTP/2. Per altre informazioni, vedere Usare HTTP/2 con il server Web ASP.NET CoreKestrel.

Controllo del file di certificato in Kestrel

I certificati TLS configurati dal percorso vengono ora monitorati per le modifiche quando reloadOnChange vengono passati a KestrelServerOptions.Configure(). Una modifica al file di certificato viene considerata come una modifica al percorso configurato, ovvero gli endpoint vengono ricaricati.

Si noti che le eliminazioni di file non vengono rilevate in modo specifico perché si verificano temporaneamente e arrestano in modo anomalo il server se non sono temporanei.

Avviso quando non verranno usati i protocolli HTTP specificati

Se TLS è disabilitato e HTTP/1.x è disponibile, HTTP/2 e HTTP/3 verranno disabilitati, anche se sono stati specificati. Questo può causare alcune brutte sorprese, quindi è stato aggiunto l'output dell'avviso per informare l'utente quando si verifica.

HTTP_PORTS e HTTPS_PORTS chiavi di configurazione

Le applicazioni e i contenitori vengono spesso assegnati solo a una porta in ascolto, ad esempio 80, senza vincoli aggiuntivi come host o percorso. HTTP_PORTS e HTTPS_PORTS sono nuove chiavi di configurazione che consentono di specificare le porte di ascolto per i Kestrel server e HTTP.sys. Questi valori possono essere definiti con i prefissi delle DOTNET_ variabili di ambiente o ASPNETCORE_ specificati direttamente tramite qualsiasi altro input di configurazione, ad esempio appsettings.json. Ogni è un elenco delimitato da punto e virgola di valori di porta. Ad esempio:

ASPNETCORE_HTTP_PORTS=80;8080
ASPNETCORE_HTTPS_PORTS=443;8081

Si tratta di una sintassi abbreviata per quanto segue, che specifica lo schema (HTTP o HTTPS) e qualsiasi host o IP:

ASPNETCORE_URLS=http://*:80/;http://*:8080/;https://*:443/;https://*:8081/

Per altre informazioni, vedere Configurare gli endpoint per il server Web ASP.NET Core Kestrel e HTTP.sys'implementazione del server Web in ASP.NET Core.

Nome host SNI in ITlsHandshakeFeature

Il nome host SNI (Server Name Indication) è ora esposto nella proprietà HostName dell'interfaccia ITlsHandshakeFeature .

SNI fa parte del processo di handshake TLS. Consente ai client di specificare il nome host a cui sta tentando di connettersi quando il server ospita più host virtuali o domini. Per presentare il certificato di sicurezza corretto durante il processo di handshake, il server deve conoscere il nome host selezionato per ogni richiesta.

In genere il nome host viene gestito solo all'interno dello stack TLS e viene usato per selezionare il certificato corrispondente. Ma esponendolo, altri componenti in un'app possono usare tali informazioni a scopo di diagnostica, limitazione della velocità, routing e fatturazione.

L'esposizione del nome host è utile per i servizi su larga scala che gestiscono migliaia di associazioni SNI. Questa funzionalità può migliorare significativamente l'efficienza del debug durante le escalation dei clienti. L'aumento della trasparenza consente una risoluzione più rapida dei problemi e un'affidabilità avanzata del servizio.

Per altre informazioni, vedere ITlsHandshakeFeature.HostName.

IHttpSysRequestTimingFeature

IHttpSysRequestTimingFeature fornisce informazioni dettagliate sulla tempistica per le richieste quando si usa il server HTTP.sys e l'hosting in-process con IIS:

IHttpSysRequestTimingFeature.TryGetTimestamp recupera il timestamp per il tipo di intervallo specificato:

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();

Per altre informazioni, vedere Ottenere informazioni dettagliate sulla tempistica con IHttpSysRequestTimingFeature e Informazioni sull'intervallo e sull'hosting in-process con IIS.

HTTP.sys: supporto esplicito per il buffer delle risposte in modalità kernel

In alcuni scenari, volumi elevati di scritture di piccole dimensioni con latenza elevata possono causare un impatto significativo sulle prestazioni di HTTP.sys. Questo impatto è dovuto alla mancanza di un Pipe buffer nell'implementazione HTTP.sys . Per migliorare le prestazioni in questi scenari, è stato aggiunto il supporto per il buffer delle risposte a HTTP.sys. Abilitare il buffering impostando HttpSysOptions.EnableKernelResponseBuffering su true.

Il buffer delle risposte deve essere abilitato da un'app che esegue operazioni di I/O sincrone o I/O asincrone senza più di una scrittura in sospeso alla volta. In questi scenari, il buffer delle risposte può migliorare significativamente la velocità effettiva rispetto alle connessioni a latenza elevata.

Le app che usano operazioni di I/O asincrone e che possono avere più di una scrittura in sospeso alla volta non devono usare questo flag. L'abilitazione di questo flag può comportare un utilizzo di CPU e memoria superiore da HTTP.Sys.

Autenticazione e autorizzazione

ASP.NET Core 8 aggiunge nuove funzionalità all'autenticazione e all'autorizzazione.

Identity Endpoint API

MapIdentityApi<TUser> è un nuovo metodo di estensione che aggiunge due endpoint API (/register e /login). L'obiettivo MapIdentityApi principale di è semplificare per gli sviluppatori l'uso di ASP.NET Core Identity per l'autenticazione nelle app a pagina singola (SPA) o Blazor basate su JavaScript. Invece di usare l'interfaccia utente predefinita fornita da ASP.NET Core Identity, basata su Razor Pages, l'API mapIdentityaggiunge JSendpoint API ON più adatti per le app SPA e le app nonbrowser. Per altre informazioni, vedere Identity Endpoint API.

IAuthorizationRequirementData

Prima di ASP.NET Core 8, l'aggiunta di un criterio di autorizzazione con parametri a un endpoint richiede l'implementazione di :

  • AuthorizeAttribute per ogni criterio.
  • AuthorizationPolicyProvider per elaborare un criterio personalizzato da un contratto basato su stringa.
  • AuthorizationRequirement per i criteri.
  • AuthorizationHandler per ogni requisito.

Si consideri ad esempio l'esempio seguente scritto per 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;
    }
}

L'esempio completo è disponibile nel repository AspNetCore.Docs.Samples .

ASP.NET Core 8 introduce l'interfaccia IAuthorizationRequirementData . L'interfaccia IAuthorizationRequirementData consente alla definizione dell'attributo di specificare i requisiti associati ai criteri di autorizzazione. Usando IAuthorizationRequirementData, il codice dei criteri di autorizzazione personalizzato precedente può essere scritto con un minor numero di righe di codice. File aggiornato Program.cs :

  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();

Oggetto aggiornato MinimumAgeAuthorizationHandler:

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.

L'esempio aggiornato completo è disponibile qui.

Per un esame dettagliato del nuovo esempio, vedere Criteri di autorizzazione personalizzati con IAuthorizationRequirementData .

Protezione degli endpoint dell'interfaccia utente di Swagger

Gli endpoint dell'interfaccia utente di Swagger possono ora essere protetti negli ambienti di produzione chiamando MapSwagger().RequireAuthorization. Per altre informazioni, vedere Protezione degli endpoint dell'interfaccia utente di Swagger

Varie

Le sezioni seguenti descrivono varie nuove funzionalità in ASP.NET Core 8.

Supporto dei servizi con chiave nell'inserimento delle dipendenze

I servizi con chiave fanno riferimento a un meccanismo per la registrazione e il recupero di servizi di inserimento delle dipendenze tramite chiavi. Un servizio è associato a una chiave chiamando AddKeyedSingleton (o AddKeyedScoped ) AddKeyedTransientper registrarlo. Accedere a un servizio registrato specificando la chiave con l'attributo [FromKeyedServices] . Il codice seguente illustra come usare i servizi con chiave:

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"));
    }
}

Modelli di progetto di Visual Studio per app spa con back-end ASP.NET Core

I modelli di progetto di Visual Studio sono ora il modo consigliato per creare app a pagina singola con un back-end ASP.NET Core. Vengono forniti modelli che creano app basate sui framework JavaScript Angular, React e Vue. Questi modelli:

  • Creare una soluzione di Visual Studio con un progetto front-end e un progetto back-end.
  • Usare il tipo di progetto di Visual Studio per JavaScript e TypeScript (con estensione esproj) per il front-end.
  • Usare un progetto ASP.NET Core per il back-end.

Per altre informazioni sui modelli di Visual Studio e su come accedere ai modelli legacy, vedere Panoramica delle app a pagina singola in ASP.NET Core

Supporto per attributi generici

Gli attributi che in precedenza richiedevano un Type parametro sono ora disponibili in varianti generiche più pulite. Ciò è reso possibile dal supporto per gli attributi generici in C# 11. Ad esempio, la sintassi per annotare il tipo di risposta di un'azione può essere modificata nel modo seguente:

[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);
}

Le varianti generiche sono supportate per gli attributi seguenti:

  • [ProducesResponseType<T>]
  • [Produces<T>]
  • [MiddlewareFilter<T>]
  • [ModelBinder<T>]
  • [ModelMetadataType<T>]
  • [ServiceFilter<T>]
  • [TypeFilter<T>]

Analisi del codice nelle app ASP.NET Core

I nuovi analizzatori illustrati nella tabella seguente sono disponibili in ASP.NET Core 8.0.

ID di diagnostica Causa o non causa un'interruzione Descrizione
ASP0016 Non causa un'interruzione Non restituire un valore da RequestDelegate
ASP0019 Non causa un'interruzione Suggerire di usare IHeaderDictionary.Append o l'indicizzatore
ASP0020 Non causa un'interruzione I tipi complessi a cui fanno riferimento i parametri di route devono essere analizzabili
ASP0021 Non causa un'interruzione Il tipo restituito del metodo BindAsync deve essere ValueTask<T>
ASP0022 Non causa un'interruzione Conflitto di route rilevato tra gestori di route
ASP0023 Non causa un'interruzione MVC: è stato rilevato un conflitto di route tra i gestori di route
ASP0024 Non causa un'interruzione Il gestore di route ha più parametri con l'attributo [FromBody]
ASP0025 Non causa un'interruzione Usare AddAuthorizationBuilder

Strumenti di route

ASP.NET Core è basato sul routing. API minime, API Web, Razor Pagine e Blazor tutte le route usano per personalizzare il mapping delle richieste HTTP al codice.

In .NET 8 abbiamo investito in una suite di nuove funzionalità per semplificare l'apprendimento e l'uso del routing. Queste nuove funzionalità includono:

Per altre informazioni, vedere Strumenti di route in .NET 8.

Metriche di ASP.NET Core

Le metriche sono misurazioni segnalate nel tempo e vengono usate più spesso per monitorare l'integrità di un'app e generare avvisi. Ad esempio, un contatore che segnala richieste HTTP non riuscite può essere visualizzato nei dashboard o generare avvisi quando gli errori superano una soglia.

Questa anteprima aggiunge nuove metriche in ASP.NET Core usando System.Diagnostics.Metrics. Metrics è un'API moderna per la creazione di report e la raccolta di informazioni sulle app.

Le metriche offrono molti miglioramenti rispetto ai contatori eventi esistenti:

  • Nuovi tipi di misurazioni con contatori, misuratori e istogrammi.
  • Creazione di report avanzati con valori multidimensionali.
  • Integrazione nell'ecosistema nativo del cloud più ampio allineandosi agli standard OpenTelemetry.

Sono state aggiunte metriche per ASP.NET Hosting core, Kestrele SignalR. Per altre informazioni, vedere System.Diagnostics.Metrics.

IExceptionHandler

IExceptionHandler è una nuova interfaccia che offre allo sviluppatore un callback per la gestione delle eccezioni note in una posizione centrale.

IExceptionHandler le implementazioni vengono registrate chiamando IServiceCollection.AddExceptionHandler<T>. È possibile aggiungere più implementazioni e vengono chiamate nell'ordine registrato. Se un gestore eccezioni gestisce una richiesta, può tornare true a interrompere l'elaborazione. Se un'eccezione non viene gestita da alcun gestore eccezioni, il controllo esegue il fallback al comportamento predefinito e alle opzioni del middleware.

Per altre informazioni, vedere IExceptionHandler.

Esperienza di debug migliorata

Gli attributi di personalizzazione del debug sono stati aggiunti a tipi come HttpContext, HttpRequestHttpResponse, ClaimsPrincipal, e WebApplication. Il debugger avanzato visualizza per questi tipi semplifica la ricerca di informazioni importanti nel debugger di un IDE. Gli screenshot seguenti mostrano la differenza che questi attributi fanno nella visualizzazione del debugger di HttpContext.

.NET 7:

Visualizzazione non utile del debugger di tipo HttpContext in .NET 7.

.NET 8:

Visualizzazione utile del debugger del tipo HttpContext in .NET 8.

La visualizzazione del debugger per WebApplication evidenzia informazioni importanti, ad esempio endpoint configurati, middleware e IConfiguration valori.

.NET 7:

Visualizzazione non utile del debugger di tipo WebApplication in .NET 7.

.NET 8:

Visualizzazione utile del debugger del tipo WebApplication in .NET 8.

Per altre informazioni sui miglioramenti del debug in .NET 8, vedere:

IPNetwork.Parse e TryParse

I nuovi Parse metodi e TryParse per IPNetwork aggiungere il supporto per la creazione di un oggetto IPNetwork usando una stringa di input nella notazione CIDR o nella notazione "barra".

Di seguito sono riportati esempi 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);

Ecco alcuni esempi per 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);

Memorizzazione nella cache dell'output basata su Redis

ASP.NET Core 8 aggiunge il supporto per l'uso di Redis come cache distribuita per la memorizzazione nella cache dell'output. La memorizzazione nella cache dell'output è una funzionalità che consente a un'app di memorizzare nella cache l'output di un endpoint API minimo, un'azione del controller o Razor una pagina. Per altre informazioni, vedere Memorizzazione nella cache dell'output.

Middleware a corto circuito dopo il routing

Quando il routing corrisponde a un endpoint, in genere consente l'esecuzione del resto della pipeline middleware prima di richiamare la logica dell'endpoint. I servizi possono ridurre l'utilizzo delle risorse filtrando le richieste note nelle prime fasi della pipeline. Usare il metodo di estensione per causare il ShortCircuit routing per richiamare immediatamente la logica dell'endpoint e quindi terminare la richiesta. Ad esempio, una determinata route potrebbe non dover passare attraverso l'autenticazione o il middleware CORS. Nell'esempio seguente vengono richieste di corto circuito che corrispondono alla /short-circuit route:

app.MapGet("/short-circuit", () => "Short circuiting!").ShortCircuit();

Usare il MapShortCircuit metodo per configurare il corto circuito per più route contemporaneamente, passando a essa una matrice params di prefissi URL. Ad esempio, browser e bot spesso probe server per percorsi noti come robots.txt e favicon.ico. Se l'app non dispone di tali file, una riga di codice può configurare entrambe le route:

app.MapShortCircuit(404, "robots.txt", "favicon.ico");

Per altre informazioni, vedere Middleware a corto circuito dopo il routing.

Estendibilità del middleware di registrazione HTTP

Il middleware di registrazione HTTP offre diverse nuove funzionalità:

  • HttpLoggingFields.Duration: se abilitato, il middleware genera un nuovo log alla fine della richiesta e della risposta che misura il tempo totale impiegato per l'elaborazione. Questo nuovo campo è stato aggiunto al HttpLoggingFields.All set.
  • HttpLoggingOptions.CombineLogs: se abilitato, il middleware consolida tutti i log abilitati per una richiesta e una risposta in un unico log alla fine. Un singolo messaggio di log include la richiesta, il corpo della richiesta, la risposta, il corpo della risposta e la durata.
  • IHttpLoggingInterceptor: nuova interfaccia per un servizio che può essere implementata e registrata (usando AddHttpLoggingInterceptor) per ricevere callback per richiesta e per risposta per personalizzare i dettagli registrati. Tutte le impostazioni di log specifiche dell'endpoint vengono applicate per prime e possono quindi essere sottoposte a override in questi callback. Un'implementazione può:
    • Esaminare una richiesta e una risposta.
    • Abilitare o disabilitare qualsiasi oggetto HttpLoggingFields.
    • Regolare la quantità di corpo della richiesta o della risposta registrata.
    • Aggiungere campi personalizzati ai log.

Per altre informazioni, vedere Registrazione HTTP in .NET Core e ASP.NET Core.

Nuove API in ProblemDetails per supportare integrazioni più resilienti

In .NET 7 è stato introdotto il servizio ProblemDetails per migliorare l'esperienza per la generazione di risposte di errore conformi alla specifica ProblemDetails. In .NET 8 è stata aggiunta una nuova API per semplificare l'implementazione del comportamento di fallback se IProblemDetailsService non è in grado di generare ProblemDetails. L'esempio seguente illustra l'uso della nuova TryWriteAsync API:

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();

Per altre informazioni, vedere Fallback IProblemDetailsService

Risorse aggiuntive