Condividi tramite


Novità di ASP.NET Core 6.0

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

ASP.NET Core MVC e Razor miglioramenti

API minime

Le API minime sono progettata per creare API HTTP con dipendenze minime. Sono ideali per microservizi e app che vogliono includere solo i file, le funzionalità e le dipendenze minimi in ASP.NET Core. Per altre informazioni, vedi:

SignalR

Tag di attività a esecuzione prolungata per SignalR le connessioni

SignalR usa il nuovo Microsoft.AspNetCore.Http.Features.IHttpActivityFeature.Activity oggetto per aggiungere un http.long_running tag all'attività della richiesta. IHttpActivityFeature.Activity viene usato dai servizi APM come Application Insights di Monitoraggio di Azure per filtrare SignalR le richieste dalla creazione di avvisi di richiesta a esecuzione prolungata.

Miglioramenti delle prestazioni SignalR

  • Allocare HubCallerClients una sola volta per ogni connessione anziché ogni chiamata al metodo hub.
  • Evitare l'allocazione di chiusura in SignalRDefaultHubDispatcher.Invoke. Lo stato viene passato a una funzione statica locale tramite parametri per evitare un'allocazione di chiusura. Per altre informazioni, vedere questa richiesta pull di GitHub.
  • Allocare un singolo StreamItemMessage flusso invece di ogni elemento di flusso nel flusso da server a client. Per altre informazioni, vedere questa richiesta pull di GitHub.

Razor compilatore

Razor compilatore aggiornato per l'uso dei generatori di origine

Il Razor compilatore è ora basato su generatori di origine C#. I generatori di origine vengono eseguiti durante la compilazione e controllano cosa viene compilato per produrre file aggiuntivi compilati insieme al rest del progetto. L'uso dei generatori di origine semplifica il Razor compilatore e accelera notevolmente i tempi di compilazione.

Razor il compilatore non produce più un assembly di viste separato

Il Razor compilatore ha usato in precedenza un processo di compilazione in due passaggi che ha generato un assembly Views separato che conteneva le visualizzazioni e le pagine generate (.cshtml file) definite nell'app. I tipi generati erano pubblici e nello spazio dei AspNetCore nomi .

Il compilatore aggiornato Razor compila le visualizzazioni e i tipi di pagine nell'assembly di progetto principale. Questi tipi vengono ora generati per impostazione predefinita come sealed interno nello spazio dei AspNetCoreGeneratedDocument nomi. Questa modifica migliora le prestazioni di compilazione, consente la distribuzione di singoli file e consente a questi tipi di partecipare a Ricaricamento rapido.

Per altre informazioni su questa modifica, vedere il problema relativo all'annuncio in GitHub.

miglioramenti delle prestazioni e delle API principali ASP.NET

Sono state apportate molte modifiche per ridurre le allocazioni e migliorare le prestazioni nello stack:

Footprint di memoria ridotto per le connessioni TLS inattive

Per le connessioni TLS a esecuzione prolungata in cui i dati vengono inviati solo occasionalmente in avanti e indietro, è stato notevolmente ridotto il footprint di memoria delle app ASP.NET Core in .NET 6. Ciò dovrebbe contribuire a migliorare la scalabilità degli scenari, ad esempio i server WebSocket. Ciò è stato possibile a causa di numerosi miglioramenti in System.IO.Pipelines, SslStreame Kestrel. Le sezioni seguenti illustrano in dettaglio alcuni dei miglioramenti apportati al footprint di memoria ridotto:

Ridurre le dimensioni di System.IO.Pipelines.Pipe

Per ogni connessione stabilita, due pipe vengono allocate in Kestrel:

  • Livello di trasporto per l'app per la richiesta.
  • Livello applicazione per il trasporto per la risposta.

Riducendo le dimensioni di da 368 byte a 264 byte (circa una riduzione del System.IO.Pipelines.Pipe 28,2%), vengono salvati 208 byte per connessione (104 byte per pipe).

Pool SocketSender

SocketSender gli oggetti (che sottoclasse SocketAsyncEventArgs) sono circa 350 byte in fase di esecuzione. Anziché allocare un nuovo SocketSender oggetto per ogni connessione, è possibile eseguire il pooling. SocketSender gli oggetti possono essere inseriti in pool perché gli invii sono in genere molto veloci. Il pooling riduce il sovraccarico per connessione. Anziché allocare 350 byte per connessione, vengono allocati solo 350 byte per IOQueue ogni connessione. L'allocazione viene eseguita per coda per evitare conflitti. Il server WebSocket con 5000 connessioni inattive è passato dall'allocazione di ~1,75 MB (350 byte * 5000) all'allocazione di ~2,8 kb (350 byte * 8) per SocketSender gli oggetti.

Letture in byte zero con SslStream

Le letture senza buffer sono una tecnica usata in ASP.NET Core per evitare di noleggiare memoria dal pool di memoria se non sono disponibili dati nel socket. Prima di questa modifica, il server WebSocket con 5000 connessioni inattive richiedeva circa 200 MB senza TLS rispetto a ~800 MB con TLS. Alcune di queste allocazioni (4k per connessione) non devono Kestrel essere bloccate in un ArrayPool<T> buffer durante l'attesa del completamento delle letture SslStream . Dato che queste connessioni sono inattive, nessuna delle letture è stata completata e ha restituito i buffer a ArrayPool, forzando l'allocazione ArrayPool di più memoria. Le allocazioni rimanenti erano in SslStream sé: buffer 4k per handshake TLS e buffer di 32k per le letture normali. In .NET 6, quando l'utente esegue una lettura SslStream a zero byte e non dispone di dati disponibili, SslStream esegue internamente una lettura a zero byte nel flusso di cui è stato eseguito il wrapping sottostante. Nel caso migliore (connessione inattiva), queste modifiche comportano un risparmio di 40 KB per connessione, consentendo al consumer (Kestrel) di ricevere una notifica quando i dati sono disponibili senza tenere premuti alcun buffer inutilizzato.

Letture a byte zero con PipeReader

Con le letture senza buffer supportate in SslStream, è stata aggiunta un'opzione per eseguire letture di byte zero in StreamPipeReader, il tipo interno che si adatta a Stream in un oggetto PipeReader. In Kestrel, unStreamPipeReader oggetto viene usato per adattare l'oggetto sottostante SslStream in un oggetto PipeReader. Pertanto, è stato necessario esporre la semantica di lettura zero byte in PipeReader.

È ora possibile creare un PipeReader oggetto che supporta zero byte letti su qualsiasi elemento sottostante Stream che supporta la semantica di lettura zero byte (ad esempio SslStream, , e NetworkStreamcosì via) usando l'API seguente:

var reader = PipeReader.Create(stream, new StreamPipeReaderOptions(useZeroByteReads: true));

Rimuovere le lastre dall'oggetto SlabMemoryPool

Per ridurre la frammentazione dell'heap, Kestrel è stata usata una tecnica in cui sono stati allocati lastre di memoria di 128 KB come parte del relativo pool di memoria. Le lastre sono state poi ulteriormente suddivise in blocchi da 4 KB usati Kestrel internamente. Le lastre devono essere superiori a 85 KB per forzare l'allocazione nell'heap di oggetti di grandi dimensioni per tentare e impedire al GC di rilocare questa matrice. Tuttavia, con l'introduzione della nuova generazione GC, l'heap dell'oggetto aggiunto (POH), non ha più senso allocare blocchi sulla lastra. Kestrel ora alloca direttamente i blocchi nel POH, riducendo la complessità della gestione del pool di memoria. Questa modifica dovrebbe semplificare l'esecuzione di miglioramenti futuri, ad esempio semplificando la compattazione del pool di memoria usato da Kestrel.

IAsyncDisposable supportato

IAsyncDisposable è ora disponibile per controller, Razor pagine e componenti di visualizzazione. Le versioni asincrone sono state aggiunte alle interfacce pertinenti nelle factory e negli attivatori:

  • I nuovi metodi offrono un'implementazione di interfaccia predefinita che delega alla versione sincrona e chiama Dispose.
  • Le implementazioni sostituiscono l'implementazione predefinita e gestiscono l'eliminazione IAsyncDisposable delle implementazioni.
  • Le implementazioni prediligono IAsyncDisposable IDisposable quando vengono implementate entrambe le interfacce.
  • Gli extender devono eseguire l'override dei nuovi metodi inclusi per supportare IAsyncDisposable le istanze.

IAsyncDisposable è utile quando si lavora con:

  • Enumeratori asincroni, ad esempio, in flussi asincroni.
  • Risorse non gestite con operazioni di I/O a elevato utilizzo di risorse da rilasciare.

Quando si implementa questa interfaccia, usare il DisposeAsync metodo per rilasciare le risorse.

Si consideri un controller che crea e usa un oggetto Utf8JsonWriter. Utf8JsonWriter è una IAsyncDisposable risorsa:

public class HomeController : Controller, IAsyncDisposable
{
    private Utf8JsonWriter? _jsonWriter;
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
        _jsonWriter = new Utf8JsonWriter(new MemoryStream());
    }

IAsyncDisposable deve implementare DisposeAsync:

public async ValueTask DisposeAsync()
{
    if (_jsonWriter is not null)
    {
        await _jsonWriter.DisposeAsync();
    }

    _jsonWriter = null;
}

Porta Vcpkg per SignalR il client C++

Vcpkg è una gestione pacchetti da riga di comando multipiattaforma per le librerie C e C++. Di recente è stata aggiunta una porta per vcpkg aggiungere CMake il supporto nativo per il SignalR client C++. vcpkg funziona anche con MSBuild.

Il SignalR client può essere aggiunto a un progetto CMake con il frammento di codice seguente quando vcpkg è incluso nel file toolchain:

find_package(microsoft-signalr CONFIG REQUIRED)
link_libraries(microsoft-signalr::microsoft-signalr)

Con il frammento di codice precedente, il SignalR client C++ è pronto per l'uso e l'uso #include in un progetto senza alcuna configurazione aggiuntiva. Per un esempio completo di un'applicazione C++ che usa il SignalR client C++, vedere il repository halter73/SignalR-Client-Cpp-Sample .

Blazor

Modifiche al modello di progetto

Sono state apportate diverse modifiche al modello di progetto per Blazor le app, incluso l'uso del file per il Pages/_Layout.cshtml contenuto del layout visualizzato nel _Host.cshtml file per le app precedenti Blazor Server . Esaminare le modifiche creando un'app da un modello di progetto 6.0 o accedendo all'origine di riferimento ASP.NET Core per i modelli di progetto:

Blazor WebAssembly supporto delle dipendenze native

Blazor WebAssembly le app possono usare le dipendenze native create per l'esecuzione in WebAssembly. Per altre informazioni, vedere ASP.NET dipendenze native di CoreBlazor WebAssembly.

Compilazione e ricollegamento del runtime di WebAssembly Ahead-of-Time (AOT)

Blazor WebAssembly supporta la compilazione anticipata (AOT), in cui è possibile compilare il codice .NET direttamente in WebAssembly. La compilazione AOT comporta miglioramenti delle prestazioni di runtime a scapito di dimensioni maggiori dell'app. Il ricollegamento del runtime .NET WebAssembly riduce il codice di runtime inutilizzato e quindi migliora la velocità di download. Per altre informazioni, vedere Compilazione in anticipo (AOT) e Ricollegamento del runtime.

Mantenere lo stato prerenderato

Blazor supporta lo stato persistente in una pagina pre-risolto in modo che lo stato non debba essere ricreato quando l'app viene completamente caricata. Per altre informazioni, vedere Integrare ASP.NET componenti Core Razor con MVC o Razor Pages.

Limiti di errore

I limiti degli errori offrono un approccio pratico per la gestione delle eccezioni a livello di interfaccia utente. Per altre informazioni, vedere Gestire gli errori nelle app ASP.NET CoreBlazor.

Supporto SVG

L'elemento <foreignObject> elemento è supportato per visualizzare codice HTML arbitrario in un formato SVG. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Blazor Server supporto per il trasferimento di matrici di byte in JS Interoperabilità

Blazor supporta l'interoperabilità della matrice JS di byte ottimizzata che evita la codifica e la decodifica delle matrici di byte in Base64. Per ulteriori informazioni, vedi le seguenti risorse:

Miglioramenti delle stringhe di query

Il supporto per l'uso delle stringhe di query è stato migliorato. Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor.

Binding per selezionare più

L'associazione supporta la selezione di più opzioni con <input> elementi. Per ulteriori informazioni, vedi le seguenti risorse:

Controllo contenuto head (<head>)

Razor i componenti possono modificare il contenuto dell'elemento HTML <head> di una pagina, inclusa l'impostazione del titolo della pagina (<title> elemento) e la modifica dei metadati (<meta> elementi). Per altre informazioni, vedere Controllare il <head> contenuto nelle app ASP.NET CoreBlazor.

Generare componenti di Angular e React

Generare componenti JavaScript specifici del framework dai Razor componenti per framework Web, ad esempio Angular o React. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Eseguire il rendering dei componenti di da JavaScript

Eseguire il rendering Razor di componenti in modo dinamico da JavaScript per le app JavaScript esistenti. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Elementi personalizzati

Il supporto sperimentale è disponibile per la creazione di elementi personalizzati, che usano interfacce HTML standard. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Dedurre i tipi generici dei componenti dai componenti predecessori

Un componente predecessore può propagare a catena un parametro di tipo in base al nome ai discendenti usando il nuovo [CascadingTypeParameter] attributo. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Componenti di cui è stato eseguito il rendering dinamico

Usare il nuovo componente predefinito DynamicComponent per eseguire il rendering dei componenti in base al tipo. Per altre informazioni, vedere Componenti di base RazorASP.NET sottoposti a rendering dinamico.

Accessibilità migliorata Blazor

Usare il nuovo FocusOnNavigate componente per impostare lo stato attivo dell'interfaccia utente su un elemento basato su un selettore CSS dopo lo spostamento da una pagina a un'altra. Per altre informazioni, vedere ASP.NET routing e navigazione coreBlazor.

Supporto dell'argomento evento personalizzato

Blazor supporta argomenti di evento personalizzati, che consentono di passare dati arbitrari ai gestori eventi .NET con eventi personalizzati. Per altre informazioni, vedere ASP.NET Gestione degli eventi CoreBlazor.

Parametri obbligatori

Applicare il nuovo [EditorRequired] attributo per specificare un parametro del componente obbligatorio. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Collocazione di file JavaScript con pagine, visualizzazioni e componenti

Collocare i file JavaScript per pagine, visualizzazioni e Razor componenti come modo pratico per organizzare gli script in un'app. Per altre informazioni, vedere ASP.NET Core JavaScript interoperabilità (interoperabilità).For more information, see ASP.NET Core Blazor JavaScript interoperability (JS interop).

Inizializzatori JavaScript

Gli inizializzatori JavaScript eseguono la logica prima e dopo il caricamento di un'app Blazor . Per altre informazioni, vedere ASP.NET Core JavaScript interoperabilità (interoperabilità).For more information, see ASP.NET Core Blazor JavaScript interoperability (JS interop).

Interoperabilità JavaScript di streaming

Blazor supporta ora lo streaming dei dati direttamente tra .NET e JavaScript. Per ulteriori informazioni, vedi le seguenti risorse:

Vincoli di tipo generico

I parametri di tipo generico sono ora supportati. Per altre informazioni, vedere ASP.NET Componenti di baseRazor.

Layout di distribuzione di WebAssembly

Usare un layout di distribuzione per abilitare Blazor WebAssembly i download delle app in ambienti di sicurezza con restrizioni. Per altre informazioni, vedere Layout di distribuzione per le app ospitate Blazor WebAssembly ASP.NET Core.

Nuovi Blazor articoli

Oltre alle Blazor funzionalità descritte nelle sezioni precedenti, sono disponibili nuovi Blazor articoli sugli argomenti seguenti:

  • ASP.NET download di file coreBlazor: informazioni su come scaricare un file usando l'interoperabilità di streaming nativa byte[] per garantire un trasferimento efficiente al client.
  • Visualizzare immagini e documenti in ASP.NET Core Blazor: informazioni su come usare immagini e documenti nelle Blazor app, tra cui come trasmettere i dati di immagine e documento.

Creare Blazor Hybrid app con .NET MAUI, WPF e Windows Form

Usare Blazor Hybrid per combinare framework client nativi desktop e per dispositivi mobili con .NET e Blazor:

  • .NET Multi-platform App UI (.NET MAUI) è un framework multipiattaforma per la creazione di app native per dispositivi mobili e desktop con C# e XAML.
  • Blazor Hybridle app possono essere compilate con Windows Presentation Foundation (WPF) e Windows Form framework.

Importante

Blazor Hybrid è in anteprima e non deve essere usato nelle app di produzione fino alla versione finale.

Per ulteriori informazioni, vedi le seguenti risorse:

Kestrel

HTTP/3 è attualmente in fase di bozza e quindi soggetto a modifiche. Il supporto HTTP/3 in ASP.NET Core non viene rilasciato, è una funzionalità di anteprima inclusa in .NET 6.

Kestrel supporta ora HTTP/3. Per altre informazioni, vedere Usare HTTP/3 con il server Web ASP.NET Core Kestrel e il post di blog http/3 support in .NET 6.

Nuove Kestrel categorie di registrazione per la registrazione selezionata

Prima di questa modifica, l'abilitazione della registrazione dettagliata per Kestrel è stata eccessivamente costosa come tutti i nomi della categoria di Kestrel registrazione condivisa Microsoft.AspNetCore.Server.Kestrel . Microsoft.AspNetCore.Server.Kestrel è ancora disponibile, ma le nuove sottocategorie seguenti consentono un maggiore controllo della registrazione:

  • Microsoft.AspNetCore.Server.Kestrel(categoria corrente): ApplicationError, ConnectionHeadResponseBodyWriteApplicationNeverCompleted, , RequestBodyStartRequestBodyDone, RequestBodyNotEntirelyRead, RequestBodyDrainTimedOut, ResponseMinimumDataRateNotSatisfied, InvalidResponseHeaderRemovedHeartbeatSlow.
  • Microsoft.AspNetCore.Server.Kestrel.BadRequests: ConnectionBadRequest, RequestProcessingError, RequestBodyMinimumDataRateNotSatisfied.
  • Microsoft.AspNetCore.Server.Kestrel.Connections: ConnectionAccepted, ConnectionStart, ConnectionStop, ConnectionPauseConnectionResume, ConnectionKeepAlive, ConnectionRejectedConnectionDisconnect, , NotAllConnectionsClosedGracefully, NotAllConnectionsAborted. ApplicationAbortedConnection
  • Microsoft.AspNetCore.Server.Kestrel.Http2: Http2ConnectionError, Http2ConnectionClosing, Http2ConnectionClosed, Http2StreamErrorHttp2StreamResetAbort, HPackDecodingErrorHttp2FrameReceivedHPackEncodingError, . Http2FrameSendingHttp2MaxConcurrentStreamsReached
  • Microsoft.AspNetCore.Server.Kestrel.Http3: Http3ConnectionError, Http3ConnectionClosing, Http3ConnectionClosedHttp3StreamAbort, Http3FrameReceived, , . Http3FrameSending

Le regole esistenti continuano a funzionare, ma è ora possibile essere più selettive sulle regole abilitate. Ad esempio, l'overhead di osservabilità dell'abilitazione Debug della registrazione per richieste non valide è notevolmente ridotto e può essere abilitato con la configurazione seguente:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.Kestrel.BadRequests": "Debug"
    }
  }

Il filtro dei log applica regole con il prefisso della categoria corrispondente più lungo. Per altre informazioni, vedere Come vengono applicate le regole di filtro

Generare KestrelServerOptions tramite l'evento EventSource

KestrelEventSource genera un nuovo evento contenente il codice JSON serializzato KestrelServerOptions quando è abilitato con dettaglio EventLevel.LogAlways. Questo evento semplifica il motivo del comportamento del server durante l'analisi delle tracce raccolte. Il codice JSON seguente è un esempio del payload dell'evento:

{
  "AllowSynchronousIO": false,
  "AddServerHeader": true,
  "AllowAlternateSchemes": false,
  "AllowResponseHeaderCompression": true,
  "EnableAltSvc": false,
  "IsDevCertLoaded": true,
  "RequestHeaderEncodingSelector": "default",
  "ResponseHeaderEncodingSelector": "default",
  "Limits": {
    "KeepAliveTimeout": "00:02:10",
    "MaxConcurrentConnections": null,
    "MaxConcurrentUpgradedConnections": null,
    "MaxRequestBodySize": 30000000,
    "MaxRequestBufferSize": 1048576,
    "MaxRequestHeaderCount": 100,
    "MaxRequestHeadersTotalSize": 32768,
    "MaxRequestLineSize": 8192,
    "MaxResponseBufferSize": 65536,
    "MinRequestBodyDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
    "MinResponseDataRate": "Bytes per second: 240, Grace Period: 00:00:05",
    "RequestHeadersTimeout": "00:00:30",
    "Http2": {
      "MaxStreamsPerConnection": 100,
      "HeaderTableSize": 4096,
      "MaxFrameSize": 16384,
      "MaxRequestHeaderFieldSize": 16384,
      "InitialConnectionWindowSize": 131072,
      "InitialStreamWindowSize": 98304,
      "KeepAlivePingDelay": "10675199.02:48:05.4775807",
      "KeepAlivePingTimeout": "00:00:20"
    },
    "Http3": {
      "HeaderTableSize": 0,
      "MaxRequestHeaderFieldSize": 16384
    }
  },
  "ListenOptions": [
    {
      "Address": "https://127.0.0.1:7030",
      "IsTls": true,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "https://[::1]:7030",
      "IsTls": true,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "http://127.0.0.1:5030",
      "IsTls": false,
      "Protocols": "Http1AndHttp2"
    },
    {
      "Address": "http://[::1]:5030",
      "IsTls": false,
      "Protocols": "Http1AndHttp2"
    }
  ]
}

Nuovo evento DiagnosticSource per le richieste HTTP rifiutate

Kestrel ora genera un nuovo DiagnosticSource evento per le richieste HTTP rifiutate a livello di server. Prima di questa modifica, non è stato possibile osservare queste richieste rifiutate. Il nuovo DiagnosticSource evento Microsoft.AspNetCore.Server.Kestrel.BadRequest contiene un IBadRequestExceptionFeature oggetto che può essere utilizzato per introspettire il motivo per rifiutare la richiesta.

using Microsoft.AspNetCore.Http.Features;
using System.Diagnostics;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var diagnosticSource = app.Services.GetRequiredService<DiagnosticListener>();
using var badRequestListener = new BadRequestEventListener(diagnosticSource,
    (badRequestExceptionFeature) =>
{
    app.Logger.LogError(badRequestExceptionFeature.Error, "Bad request received");
});
app.MapGet("/", () => "Hello world");

app.Run();

class BadRequestEventListener : IObserver<KeyValuePair<string, object>>, IDisposable
{
    private readonly IDisposable _subscription;
    private readonly Action<IBadRequestExceptionFeature> _callback;

    public BadRequestEventListener(DiagnosticListener diagnosticListener,
                                   Action<IBadRequestExceptionFeature> callback)
    {
        _subscription = diagnosticListener.Subscribe(this!, IsEnabled);
        _callback = callback;
    }
    private static readonly Predicate<string> IsEnabled = (provider) => provider switch
    {
        "Microsoft.AspNetCore.Server.Kestrel.BadRequest" => true,
        _ => false
    };
    public void OnNext(KeyValuePair<string, object> pair)
    {
        if (pair.Value is IFeatureCollection featureCollection)
        {
            var badRequestFeature = featureCollection.Get<IBadRequestExceptionFeature>();

            if (badRequestFeature is not null)
            {
                _callback(badRequestFeature);
            }
        }
    }
    public void OnError(Exception error) { }
    public void OnCompleted() { }
    public virtual void Dispose() => _subscription.Dispose();
}

Per altre informazioni, vedere Registrazione e diagnostica in Kestrel.

Creare un connectionContext da un socket accept

Il nuovo SocketConnectionContextFactory rende possibile creare un oggetto ConnectionContext da un socket accettato. In questo modo è possibile creare un socket personalizzato senza IConnectionListenerFactory perdere tutte le prestazioni e il pooling in SocketConnection.

Vedere questo esempio di un oggetto IConnectionListenerFactory personalizzato che illustra come usare questo SocketConnectionContextFactoryoggetto .

Kestrel è il profilo di avvio predefinito per Visual Studio

Il profilo di avvio predefinito per tutti i nuovi progetti Web dotnet è Kestrel. L'avvio Kestrel è notevolmente più veloce e comporta un'esperienza più reattiva durante lo sviluppo di app.

IIS Express è ancora disponibile come profilo di avvio per scenari come l'autenticazione di Windows o la condivisione delle porte.

Le porte Localhost per Kestrel sono casuali

Per altre informazioni, vedere Porte generate dal modello per Kestrel in questo documento.

Autenticazione e autorizzazione

Server di autenticazione

.NET 3 a .NET 5 ha usato IdentityServer4 come parte del modello per supportare l'emissione di token JWT per spa e Blazor applicazioni. I modelli ora usano il server DuendeIdentity.

Se si estendono i identity modelli e si aggiornano i progetti esistenti, aggiornare gli spazi dei nomi nel codice da IdentityServer4.IdentityServer a Duende.IdentityServer e seguire le istruzioni di migrazione.

Il modello di licenza per Duende Identity Server è cambiato in una licenza reciproca, che può richiedere tariffe di licenza quando viene usato commercialmente nell'ambiente di produzione. Per altri dettagli, vedere la pagina delle licenze di Duende.

Negoziazione del certificato client ritardata

Gli sviluppatori possono ora acconsentire esplicitamente all'uso della negoziazione del certificato client ritardata specificando ClientCertificateMode.DelayCertificate in HttpsConnectionAdapterOptions. Questo funziona solo con le connessioni HTTP/1.1 perché HTTP/2 impedisce la rinegoziazione dei certificati ritardata. Il chiamante di questa API deve memorizzare il corpo della richiesta nel buffer prima di richiedere il certificato client:

using Microsoft.AspNetCore.Server.Kestrel.Https;
using Microsoft.AspNetCore.WebUtilities;

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel(options =>
{
    options.ConfigureHttpsDefaults(adapterOptions =>
    {
        adapterOptions.ClientCertificateMode = ClientCertificateMode.DelayCertificate;
    });
});

var app = builder.Build();
app.Use(async (context, next) =>
{
    bool desiredState = GetDesiredState();
    // Check if your desired criteria is met
    if (desiredState)
    {
        // Buffer the request body
        context.Request.EnableBuffering();
        var body = context.Request.Body;
        await body.DrainAsync(context.RequestAborted);
        body.Position = 0;

        // Request client certificate
        var cert = await context.Connection.GetClientCertificateAsync();

        //  Disable buffering on future requests if the client doesn't provide a cert
    }
    await next(context);
});


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

Cookie La scadenza scorrevole dell'autenticazione può ora essere personalizzata o eliminata usando il nuovo OnCheckSlidingExpirationoggetto . Ad esempio, questo evento può essere usato da un'app a pagina singola che deve effettuare periodicamente il ping del server senza influire sulla sessione di autenticazione.

Varie

Ricaricamento rapido

Apportare rapidamente aggiornamenti dell'interfaccia utente e del codice alle app in esecuzione senza perdere lo stato dell'app per un'esperienza di sviluppo più veloce e produttiva usando Ricaricamento rapido. Per altre informazioni, vedere Supporto di .NET Ricaricamento rapido per ASP.NET Core e aggiornamento in .NET Ricaricamento rapido avanzamento e Evidenziazioni di Visual Studio 2022.

Modelli di app a pagina singola migliorati

I modelli di progetto ASP.NET Core sono stati aggiornati per Angular e React per usare un modello migliorato per le app a pagina singola più flessibili e più strettamente allineate ai modelli comuni per lo sviluppo Web front-end moderno.

In precedenza, il modello ASP.NET Core per Angular e React usava middleware specializzato durante lo sviluppo per avviare il server di sviluppo per il framework front-end e quindi le richieste proxy da ASP.NET Core al server di sviluppo. La logica per l'avvio del server di sviluppo front-end era specifica dell'interfaccia della riga di comando per il framework front-end corrispondente. Il supporto di framework front-end aggiuntivi che usano questo modello significava aggiungere logica aggiuntiva a ASP.NET Core.

I modelli di ASP.NET Core aggiornati per Angular e React in .NET 6 capovolgono questa disposizione e sfruttano il supporto predefinito del proxy nei server di sviluppo dei framework front-end più moderni. Quando viene avviata l'app ASP.NET Core, il server di sviluppo front-end viene avviato esattamente come in precedenza, ma il server di sviluppo è configurato per il proxy delle richieste al processo back-end ASP.NET Core. Tutte le configurazioni specifiche del front-end per configurare il proxy fanno parte dell'app, non ASP.NET Core. La configurazione di ASP.NET progetti Core per l'uso con altri framework front-end è ora semplice: configurare il server di sviluppo front-end per il framework scelto per il proxy al back-end ASP.NET Core usando il modello stabilito nei modelli Angular e React.

Il codice di avvio per l'app ASP.NET Core non richiede più alcuna logica specifica dell'app a pagina singola. La logica per avviare il server di sviluppo front-end durante lo sviluppo viene inserita nell'app in fase di esecuzione dal nuovo pacchetto Microsoft.AspNetCore.SpaProxy . Il routing di fallback viene gestito usando il routing degli endpoint anziché il middleware specifico dell'applicazione a pagina singola.

I modelli che seguono questo modello possono comunque essere eseguiti come un singolo progetto in Visual Studio o usando dotnet run dalla riga di comando. Quando l'app viene pubblicata, il codice front-end nella cartella ClientApp viene compilato e raccolto come prima nella radice Web dell'app host ASP.NET Core e servito come file statici. Gli script inclusi nel modello configurano il server di sviluppo front-end per l'uso di HTTPS usando il certificato di sviluppo ASP.NET Core.

Supporto http/3 bozza in .NET 6

HTTP/3 è attualmente in fase di bozza e quindi soggetto a modifiche. Il supporto HTTP/3 in ASP.NET Core non viene rilasciato, è una funzionalità di anteprima inclusa in .NET 6.

Vedere la voce di blog supporto HTTP/3 in .NET 6.

Annotazioni del tipo riferimento nullable

Parti del codice sorgente di ASP.NET Core 6.0 hanno applicato annotazioni di nullità.

Usando la nuova funzionalità Nullable in C# 8, ASP.NET Core può fornire ulteriore sicurezza in fase di compilazione nella gestione dei tipi di riferimento. Ad esempio, la protezione da null eccezioni di riferimento. I progetti che hanno acconsento esplicitamente all'uso di annotazioni nullable possono visualizzare nuovi avvisi in fase di compilazione dalle API di base di ASP.NET.

Per abilitare i tipi riferimento nullable, aggiungere la proprietà seguente ai file di progetto:

<PropertyGroup>
    <Nullable>enable</Nullable>
</PropertyGroup>

Per altre informazioni, vedere Tipi di riferimento Nullable.

Analisi del codice sorgente

Sono stati aggiunti diversi analizzatori della piattaforma del compilatore .NET che esaminano il codice dell'applicazione per individuare problemi quali la configurazione o l'ordine del middleware non corretto, i conflitti di routing e così via. Per altre informazioni, vedere Analisi del codice nelle app ASP.NET Core.

Miglioramenti del modello di app Web

Modelli di app Web:

  • Usare il nuovo modello di hosting minimo.
  • Riduce significativamente il numero di file e righe di codice necessari per creare un'app. Ad esempio, l'app Web vuota ASP.NET Core crea un file C# con quattro righe di codice ed è un'app completa.
  • Unifica Startup.cs e Program.cs in un singolo Program.cs file.
  • Usa istruzioni di primo livello per ridurre al minimo il codice necessario per un'app.
  • Usa direttive globali using per eliminare o ridurre al minimo il numero di righe di using istruzioni necessarie.

Porte generate dal modello per Kestrel

Le porte casuali vengono assegnate durante la creazione del progetto per l'uso da parte del Kestrel server Web. Le porte casuali consentono di ridurre al minimo un conflitto di porte quando più progetti vengono eseguiti nello stesso computer.

Quando viene creato un progetto, nel file generato Properties/launchSettings.json viene specificata una porta HTTP casuale compresa tra 5000-5300 e una porta HTTPS casuale compresa tra 7000 e 7300. Le porte possono essere modificate nel Properties/launchSettings.json file. Se non viene specificata alcuna porta, Kestrel per impostazione predefinita le porte HTTP 5000 e HTTPS 5001. Per altre informazioni, vedere Configurare gli endpoint per il server Web ASP.NET CoreKestrel.

Nuove impostazioni predefinite di registrazione

Sono state apportate le modifiche seguenti a appsettings.json e appsettings.Development.json:

- "Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.AspNetCore": "Warning"

La modifica da "Microsoft": "Warning" a "Microsoft.AspNetCore": "Warning" comporta la registrazione di tutti i messaggi informativi dallo spazio dei Microsoft nomi ad eccezione Microsoft.AspNetCore di . Ad esempio, Microsoft.EntityFrameworkCore viene registrato a livello informativo.

Middleware per le eccezioni per sviluppatori aggiunto automaticamente

Nell'ambiente di sviluppo l'oggetto DeveloperExceptionPageMiddleware viene aggiunto per impostazione predefinita. Non è più necessario aggiungere il codice seguente alle app dell'interfaccia utente Web:

if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

Supporto per le intestazioni di richiesta con codifica Latin1 in HttpSysServer

HttpSysServer supporta ora la decodifica delle intestazioni Latin1 di richiesta codificate impostando la UseLatin1RequestHeaders proprietà su HttpSysOptions true:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys(o => o.UseLatin1RequestHeaders = true);

var app = builder.Build();

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

app.Run();

I log di ASP.NET Core Module includono timestamp e PID

I log di diagnostica avanzati di ASP.NET Core Module (ANCM) per IIS (ANCM) includono timestamp e PID del processo che genera i log. La registrazione di timestamp e PID semplifica la diagnosi dei problemi relativi ai riavvii di processi sovrapposti in IIS quando sono in esecuzione più processi di lavoro IIS.

I log risultanti sono ora simili all'output di esempio illustrato di seguito:

[2021-07-28T19:23:44.076Z, PID: 11020] [aspnetcorev2.dll] Initializing logs for 'C:\<path>\aspnetcorev2.dll'. Process Id: 11020. File Version: 16.0.21209.0. Description: IIS ASP.NET Core Module V2. Commit: 96475a2acdf50d7599ba8e96583fa73efbe27912.
[2021-07-28T19:23:44.079Z, PID: 11020] [aspnetcorev2.dll] Resolving hostfxr parameters for application: '.\InProcessWebSite.exe' arguments: '' path: 'C:\Temp\e86ac4e9ced24bb6bacf1a9415e70753\'
[2021-07-28T19:23:44.080Z, PID: 11020] [aspnetcorev2.dll] Known dotnet.exe location: ''

Configurabile le dimensioni del buffer in ingresso non consumate per IIS

Il server IIS in precedenza memorizzava nel buffer solo 64 KiB di corpi di richiesta non utilizzati. Il buffering di 64 KiB ha comportato un vincolo di lettura a tale dimensione massima, che influisce sulle prestazioni con corpi in ingresso di grandi dimensioni, ad esempio i caricamenti. In .NET 6 le dimensioni predefinite del buffer cambiano da 64 KiB a 1 MiB, che dovrebbe migliorare la velocità effettiva per caricamenti di grandi dimensioni. Nei test, un caricamento miB di 700 che richiedeva 9 secondi ora richiede solo 2,5 secondi.

Lo svantaggio di una dimensione del buffer maggiore è un aumento del consumo di memoria per richiesta quando l'app non legge rapidamente dal corpo della richiesta. Oltre a modificare le dimensioni predefinite del buffer, la dimensione del buffer configurabile, consentendo alle app di configurare le dimensioni del buffer in base al carico di lavoro.

Visualizzare gli helper tag dei componenti

Si consideri un componente di visualizzazione con un parametro facoltativo, come illustrato nel codice seguente:

class MyViewComponent
{
    IViewComponentResult Invoke(bool showSomething = false) { ... }
}

Con ASP.NET Core 6, l'helper tag può essere richiamato senza dover specificare un valore per il showSomething parametro :

<vc:my />

Modello Angular aggiornato a Angular 12

Il modello ASP.NET Core 6.0 per Angular usa ora Angular 12.

Il modello React è stato aggiornato a React 17.

Soglia del buffer configurabile prima della scrittura su disco in Json.NET formattatore di output

Nota: è consigliabile usare il System.Text.Json formattatore di output tranne quando il Newtonsoft.Json serializzatore è necessario per motivi di compatibilità. Il System.Text.Json serializzatore è completamente async e funziona in modo efficiente per payload più grandi.

Il Newtonsoft.Json formattatore di output per impostazione predefinita memorizza nel buffer le risposte fino a 32 KiB in memoria prima del buffering su disco. Ciò consiste nell'evitare di eseguire operazioni di I/O sincrone, che possono comportare altri effetti collaterali, ad esempio la fame di thread e i deadlock dell'applicazione. Tuttavia, se la risposta è superiore a 32 KiB, si verifica una notevole I/O su disco. La soglia di memoria è ora configurabile tramite la proprietà MvcNewtonsoftJsonOptions.OutputFormatterMemoryBufferThreshold prima del buffering su disco:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages()
            .AddNewtonsoftJson(options =>
            { 
                options.OutputFormatterMemoryBufferThreshold = 48 * 1024;
            });

var app = builder.Build();

Per altre informazioni, vedere questa richiesta pull di GitHub e il file NewtonsoftJsonOutputFormatterTest.cs .

Ottenere e impostare più velocemente per le intestazioni HTTP

Sono state aggiunte nuove API per esporre tutte le intestazioni comuni disponibili in Microsoft.Net.Http.Headers.HeaderNames come proprietà sul IHeaderDictionary risultato in un'API più semplice da usare. Ad esempio, il middleware inline nel codice seguente ottiene e imposta intestazioni di richiesta e risposta usando le nuove API:

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

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

app.Use(async (context, next) =>
{
    var hostHeader = context.Request.Headers.Host;
    app.Logger.LogInformation("Host header: {host}", hostHeader);
    context.Response.Headers.XPoweredBy = "ASP.NET Core 6.0";
    await next.Invoke(context);
    var dateHeader = context.Response.Headers.Date;
    app.Logger.LogInformation("Response date: {date}", dateHeader);
});

app.Run();

Per le intestazioni implementate, le funzioni di accesso get e set vengono implementate passando direttamente al campo e ignorando la ricerca. Per le intestazioni non implementate, le funzioni di accesso possono ignorare la ricerca iniziale rispetto alle intestazioni implementate ed eseguire direttamente la Dictionary<string, StringValues> ricerca. Evitare la ricerca comporta un accesso più rapido per entrambi gli scenari.

Streaming asincrono

ASP.NET Core supporta ora lo streaming asincrono dalle azioni e dalle risposte del controller dal formattatore JSON. La restituzione di un oggetto IAsyncEnumerable da un'azione non memorizza più nel buffer il contenuto della risposta in memoria prima dell'invio. La mancata memorizzazione nel buffer consente di ridurre l'utilizzo della memoria quando si restituiscono set di dati di grandi dimensioni che possono essere enumerati in modo asincrono.

Si noti che Entity Framework Core fornisce implementazioni di per l'esecuzione di IAsyncEnumerable query sul database. Il supporto migliorato per IAsyncEnumerable in ASP.NET Core in .NET 6 può essere usato EF Core con ASP.NET Core più efficiente. Ad esempio, il codice seguente non memorizza più nel buffer i dati del prodotto in memoria prima di inviare la risposta:

public IActionResult GetMovies()
{
    return Ok(_context.Movie);
}

Tuttavia, quando si usa il caricamento differita in EF Core, questo nuovo comportamento può causare errori a causa dell'esecuzione simultanea delle query durante l'enumerazione dei dati. Le app possono ripristinare il comportamento precedente memorizzando nel buffer i dati:

public async Task<IActionResult> GetMovies2()
{
    return Ok(await _context.Movie.ToListAsync());
}

Per altri dettagli su questa modifica nel comportamento, vedere l'annuncio correlato.

Middleware di registrazione HTTP

La registrazione HTTP è un nuovo middleware predefinito che registra le informazioni sulle richieste HTTP e le risposte HTTP, incluse le intestazioni e l'intero corpo:

var builder = WebApplication.CreateBuilder(args);

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

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

app.Run();

Passare a / con le informazioni di log del codice precedenti simili all'output seguente:

info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
      Request:
      Protocol: HTTP/2
      Method: GET
      Scheme: https
      PathBase: 
      Path: /
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
      Accept-Encoding: gzip, deflate, br
      Accept-Language: en-US,en;q=0.9
      Cache-Control: max-age=0
      Connection: close
      Cookie: [Redacted]
      Host: localhost:44372
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30
      sec-ch-ua: [Redacted]
      sec-ch-ua-mobile: [Redacted]
      sec-ch-ua-platform: [Redacted]
      upgrade-insecure-requests: [Redacted]
      sec-fetch-site: [Redacted]
      sec-fetch-mode: [Redacted]
      sec-fetch-user: [Redacted]
      sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
      Response:
      StatusCode: 200
      Content-Type: text/plain; charset=utf-8

L'output precedente è stato abilitato con il file seguente appsettings.Development.json :

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
    }
  }
}

La registrazione HTTP fornisce log per:

  • Informazioni sulla richiesta HTTP
  • Proprietà comuni
  • Intestazioni
  • Testo
  • Informazioni sulla risposta HTTP

Per configurare il middleware di registrazione HTTP, specificare HttpLoggingOptions:

using Microsoft.AspNetCore.HttpLogging;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
    // Customize HTTP logging.
    logging.LoggingFields = HttpLoggingFields.All;
    logging.RequestHeaders.Add("My-Request-Header");
    logging.ResponseHeaders.Add("My-Response-Header");
    logging.MediaTypeOptions.AddText("application/javascript");
    logging.RequestBodyLogLimit = 4096;
    logging.ResponseBodyLogLimit = 4096;
});

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

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

app.Run();

IConnectionSocketFeature

La IConnectionSocketFeature funzionalità di richiesta fornisce l'accesso al socket accept sottostante associato alla richiesta corrente. È possibile accedervi tramite su FeatureCollection HttpContext.

Ad esempio, l'app seguente imposta la LingerState proprietà sul socket accettato:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions => listenOptions.Use((connection, next) =>
    {
        var socketFeature = connection.Features.Get<IConnectionSocketFeature>();
        socketFeature.Socket.LingerState = new LingerOption(true, seconds: 10);
        return next();
    }));
});
var app = builder.Build();
app.MapGet("/", (Func<string>)(() => "Hello world"));
await app.RunAsync();

Vincoli di tipo generico in Razor

Quando si definiscono parametri di tipo generico in Razor usando la @typeparam direttiva , è ora possibile specificare vincoli di tipo generico usando la sintassi C# standard:

Script , Blazor Servere MessagePack più piccoli SignalR

Gli SignalRscript , MessagePack e Blazor Server sono ora notevolmente più piccoli, consentendo download più piccoli, meno analisi e compilazione JavaScript dal browser e avvio più rapido. Riduzione delle dimensioni:

  • signalr.js: 70%
  • blazor.server.js: 45%

Gli script più piccoli sono il risultato di un contributo della community di Ben Adams. Per altre informazioni sui dettagli della riduzione delle dimensioni, vedere La richiesta pull di GitHub di Ben.

Abilitare le sessioni di profilatura di Redis

Un contributo della community di Gabriel Lucaci abilita la sessione di profilatura di Redis con Microsoft.Extensions.Caching.StackExchangeRedis:

using StackExchange.Redis.Profiling;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.ProfilingSession = () => new ProfilingSession();
});

Per altre informazioni, vedere Profiling stackExchange.Redis.

Copia shadow in IIS

È stata aggiunta una funzionalità sperimentale all'ASP.NET Core Module (ANCM) per IIS per aggiungere il supporto per gli assembly dell'applicazione di copia shadow. Attualmente .NET blocca i file binari dell'applicazione durante l'esecuzione in Windows, rendendo impossibile sostituire i file binari quando l'app è in esecuzione. Anche se il consiglio rimane di usare un file offline dell'app, è possibile riconoscere che esistono alcuni scenari (ad esempio distribuzioni FTP) in cui non è possibile farlo.

In questi scenari, abilitare la copia shadow personalizzando le impostazioni del gestore del modulo core di ASP.NET. Nella maggior parte dei casi, ASP.NET le app Core non dispongono di un web.config controllo del codice sorgente che è possibile modificare. In ASP.NET Core, web.config viene in genere generato dall'SDK. Per iniziare, è possibile usare l'esempio web.config seguente:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- To customize the asp.net core module uncomment and edit the following section. 
  For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->

  <system.webServer>
    <handlers>
      <remove name="aspNetCore"/>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
      <handlerSettings>
        <handlerSetting name="experimentalEnableShadowCopy" value="true" />
        <handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
        <!-- Only enable handler logging if you encounter issues-->
        <!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />-->
        <!--<handlerSetting name="debugLevel" value="FILE,TRACE" />-->
      </handlerSettings>
    </aspNetCore>
  </system.webServer>
</configuration>

La copia shadow in IIS è una funzionalità sperimentale che non è garantita come parte di ASP.NET Core. Lasciare commenti e suggerimenti sulla copia shadow di IIS in questo problema di GitHub.

Risorse aggiuntive