Co nowego w ASP.NET Core w .NET 11

W tym artykule przedstawiono najważniejsze zmiany w ASP.NET Core w .NET 11 z linkami do odpowiedniej dokumentacji.

Ten artykuł zostanie zaktualizowany w miarę udostępniania nowych wersji zapoznawczych.

Blazor

W tej sekcji opisano nowe funkcje programu Blazor.

Nowy DisplayName składnik oraz obsługa atrybutów [Display] i [DisplayName]

Komponent DisplayName może być używany do wyświetlania nazw właściwości z atrybutów metadanych:

[Required, DisplayName("Production Date")]
public DateTime ProductionDate { get; set; }

Atrybut [Display] właściwości klasy modelu jest obsługiwany:

[Required, Display(Name = "Production Date")]
public DateTime ProductionDate { get; set; }

Z dwóch podejść [Display] jest zalecany atrybut, który udostępnia dodatkowe właściwości. Atrybut [Display] umożliwia również przypisywanie typu zasobu dla lokalizacji. Gdy oba atrybuty są obecne, [Display] ma pierwszeństwo przed [DisplayName]. Jeśli żaden atrybut nie jest obecny, składnik wraca do nazwy właściwości.

DisplayName Użyj składnika w etykietach lub nagłówkach tabeli:

<label>
    <DisplayName For="@(() => Model!.ProductionDate)" />
    <InputDate @bind-Value="Model!.ProductionDate" />
</label>

Blazor Format opcji startowych skryptów internetowych jest teraz obsługiwany dla skryptów Blazor Server i Blazor WebAssembly

Obiekt opcji Blazor Web App (blazor.web.js) przekazywany do Blazor.start() od wydania .NET 8 używa następującego formatu:

Blazor.start({
  ssr: { ... },
  circuit: { ... },
  webAssembly: { ... },
});

Blazor Server Teraz skrypty (blazor.server.js) i Blazor WebAssembly (blazor.webassembly.js) mogą używać tego samego formatu opcji.

W poniższym przykładzie przedstawiono poprzedni format opcji, który pozostaje obsługiwany:

Blazor.start({
  loadBootResource: function (...) {
      ...
    },
  });

Nowo obsługiwany format opcji dla poprzedniego przykładu:

Blazor.start({
  webAssembly: {
    loadBootResource: function (...) {
      ...
    },
  },
});

Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor startup.

Nowy BasePath składnik

Blazor Web Apps może użyć nowego BasePath składnika (<BasePath />) do automatycznego renderowania ścieżki podstawowej aplikacji (<base href>) tagu HTML. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor ścieżka podstawowa aplikacji.

JS Wbudowany program obsługi zdarzeń usunięty ze NavMenu składnika

Wbudowany JS program obsługi zdarzeń, który przełącza wyświetlanie linków nawigacji, nie jest już obecny w NavMenu składniku szablonu Blazor Web App projektu. Aplikacje wygenerowane na podstawie szablonu projektu korzystają teraz ze współlokowanego JS modułu w celu pokazania lub ukrycia paska nawigacyjnego na renderowanej stronie. Nowe podejście zwiększa zgodność z polityką zabezpieczeń zawartości (CSP), ponieważ nie wymaga, aby polityka CSP zawierała niebezpieczny skrót dla wbudowanego elementu JS.

Aby przeprowadzić migrację istniejącej aplikacji do .NET 11, w tym wdrożenie nowego podejścia modułu JS dla przełącznika paska nawigacyjnego, zobacz Migrate z ASP.NET Core w .NET 10 do ASP.NET Core w .NET 11.

Nowy parametr (wartość domyślna: ) dla oraz składnika umożliwia przechodzenie do identyfikatorów URI względem bieżącej ścieżki strony, a nie podstawowego identyfikatora URI aplikacji.

Rozważ następujące zagnieżdżone punkty końcowe:

  • /docs
    • /getting-started
      • /installation
      • /configuration

Gdy identyfikator URI przeglądarki to /docs/getting-started/installation i chcesz skierować użytkownika do /docs/getting-started/configuration, NavigateTo("/configuration") przekierowuje do /configuration w katalogu głównym aplikacji, zamiast ścieżki względnej pod adresem /docs/getting-started/configuration. Ustaw RelativeToCurrentUri za pomocą NavigateTo lub NavLink składnika, aby uzyskać żądaną nawigację.

Navigation.NavigateTo("/configuration", new NavigationOptions
{
    RelativeToCurrentUri = true
});
<NavLink href="configuration" RelativeToCurrentUri="true">Configuration</NavLink>

Utrwalanie danych tymczasowych między żądaniami HTTP podczas statycznego renderowania po stronie serwera (statyczne SSR)

Aby utrwalać dane tymczasowe między żądaniami HTTP podczas renderowania statycznego po stronie serwera (statyczne SSR), Blazor obsługuje funkcję TempData. TempData jest idealnym rozwiązaniem w scenariuszach, takich jak komunikaty flash po przesłaniu formularza, przekazywanie danych podczas przekierowań (wzorzec POST-Redirect-GET) i jednorazowe powiadomienia.

Właściwość TempData jest dostępna, gdy AddRazorComponents jest wywoływana w pliku Program aplikacji i jest przekazywana jako wartość kaskadowa za pomocą atrybutu [CascadingParameter].

[CascadingParameter]
public ITempData? TempData { get; set; }

W przypadku dostarczenia do parametru prostego odczytu/zapisu pojedynczej wartości użyj atrybutu [SupplyParameterFromTempData] :

[SupplyParameterFromTempData]
public string? Message { get; set; }

Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor zarządzanie stanem po stronie serwera.

Nowy Blazor szablon pracownika web (blazorwebworker)

Szablon projektu .NET Web Worker, który zawiera klienta Web Worker do przenoszenia długotrwałych zadań do wątku działającego w tle, został przemianowany na szablon projektu Blazor Web Worker (blazorwebworker). Zmiana nazwy wyraźniej wskazuje, że szablon jest częścią stosu technologicznego Blazor, przeznaczonego do użycia w aplikacjach internetowych Blazor WebAssembly i Blazor (do renderowania po stronie klienta, CSR).

Do wygenerowanego elementu WebWorkerClientdodano dwie często wymagane możliwości:

  • InvokeVoidAsync do wywołań workera typu „wyślij i zapomnij”, które nie zwracają wartości, odzwierciedlając strukturę w IJSRuntime
  • Obsługa anulowania i limitu czasu zarówno podczas tworzenia procesu roboczego, jak i jego wywołań, dzięki czemu wywołujący mogą przekazać CancellationToken i czysto zakończyć zawieszony proces roboczy.

Istniejące projekty utworzone przy użyciu starego szablonu nadal działają. Ta zmiana nazwy wpływa tylko na nazwę szablonu wyświetlaną w dotnet new list oraz na liście szablonów Utwórz nowy projekt w programie Visual Studio.

Aby uzyskać więcej informacji, zobacz następujące zasoby:

Ulepszenia wirtualizacji

  • Składnik Virtualize<TItem> nie zakłada już, że każdy element ma taką samą wysokość. Wcześniej komponent wyłączał natywne kotwiczenie przewijania w przeglądarce (aby uniknąć nieskończonej pętli renderowania), co oznaczało, że każda zmiana wysokości powyżej obszaru widocznego — rozwinięcie elementu, aktualizacje danych, zawartość ładowana z opóźnieniem — powodowała widoczne przeskakiwanie elementów na ekranie. Komponent Virtualize dostosowuje się teraz do zmierzonych rozmiarów elementów w czasie wykonywania, co ogranicza nieprawidłowe odstępy i problemy z przewijaniem, gdy wysokości elementów są różne.

    Te aktualizacje wykorzystują podejście hybrydowe: natywne kotwiczenie przewijania w CSS w przeglądarkach, które je obsługują, w układach innych niż <table>, oraz ręczny mechanizm kompensacji przewijania oparty na ResizeObserver jako rozwiązanie awaryjne dla układów <table> oraz w Safari, gdzie natywne kotwiczenie błędnie oblicza pozycje elementów <tr>.

    Aplikacje korzystające Virtualize ze składnika automatycznie otrzymują korzyści z tych aktualizacji. Nie są wymagane żadne zmiany interfejsu API dewelopera.

    Te aktualizacje obejmują aktualizację wartości domyślnej Virtualize<TItem>.OverscanCount, która była 3 w .NET 10 lub starszych, a teraz zmienia się na 15 w .NET 11 lub nowszym. Zmiana wartości domyślnej zwiększa dokładność obliczeń o średniej wysokości elementu.

    Aby uzyskać więcej informacji, zobacz następujące zasoby:

  • Użyj nowego AnchorMode parametru, aby kontrolować sposób działania widoku na krawędziach listy, gdy elementy są dynamicznie dodawane:

    • None: brak przypinania krawędzi. Obszar widoku pozostaje na bieżącej pozycji przewijania niezależnie od zmian elementów.
    • Beginning: przypina widok do początku listy. Na przykład to działanie przypinania jest przydatne w interfejsie kanału aktualności.
    • End: Przypina obszar widoku na końcu listy. Na przykład taki sposób przypinania jest przydatny w interfejsie czatu lub dziennika zdarzeń.

    W poniższym przykładzie zwirtualizowana zawartość jest przypięta na początku listy:

    <Virtualize AnchorMode="Beginning" ...>
        ...
    </Virtualize>
    

    Aby uzyskać więcej informacji, zobacz następujące zasoby:

Nowy szablon projektu biblioteki domyślnej usługi dla Blazor WebAssembly aplikacji

Szablon projektu blazor-wasm-servicedefaults tworzy bibliotekę domyślnych ustawień usługi dla aplikacji Blazor WebAssembly z integracją Aspire. Aby uzyskać więcej informacji, zobacz Tooling for ASP.NET Core Blazor.

Nowy serwer programistyczny dla aplikacji Blazor WebAssembly

Microsoft.AspNetCore.Components.Gateway jest uproszczonym hostem ASP.NET Core, który zastępuje Microsoft.AspNetCore.Components.WebAssembly.DevServer do obsługi autonomicznych aplikacji Blazor WebAssembly podczas programowania i produkcji.

Aby uzyskać więcej informacji, zobacz [Blazor] Zastąpienie DevServer przez BlazorGateway w samodzielnych aplikacjach WASM (dotnet/aspnetcore #65982) (Prosimy nie komentować zamkniętych zgłoszeń i pull requestów).

Wstrzymanie obwodu wywołane przez serwer

Ta funkcja ma zastosowanie do aplikacji po stronie Blazor serwera.

Blazor obsługuje już płynne wstrzymywanie i wznawianie wyłącznika za pomocą Blazor.pauseCircuit() i Blazor.resumeCircuit(). .NET 11 wprowadza symetryczną możliwość wstrzymywania i wznawiania po stronie serwera, dzięki której serwer może zażądać od podłączonych klientów rozpoczęcia procedury kontrolowanego wstrzymania obwodu.

Circuit.RequestCircuitPauseAsync(CancellationToken) Służy do wysłania żądania, aby połączony klient rozpoczął proces łagodnego wstrzymania obwodu. Element CancellationToken anuluje żądanie, zanim zostanie zaakceptowane przez platformę. Metoda zwraca true , czy żądanie zostało zaakceptowane, a klient został poproszony o wstrzymanie.

Ta funkcja jest przydatna w następujących scenariuszach:

  • Planowane wyłączenia i wdrożenia.
  • Opróżnianie instancji.
  • Okna obsługi aplikacji.

Aby uzyskać więcej informacji i przykład implementacji ponownego uruchamiania serwera, zobacz ASP.NET Core Blazor zarządzanie stanem po stronie serwera.

Mniejsze Blazor WebAssembly dane wyjściowe publikacji

Dwie zmiany w przycinaniu zmniejszają rozmiar opublikowanych aplikacji Blazor WebAssembly, które nie używają OpenTelemetry (OTEL) ani funkcji Przeładowywanie na gorąco:

  • Typy ComponentsMetrics i ComponentsActivitySource są teraz objęte atrybutem [FeatureSwitchDefinition], więc mechanizm przycinania może usunąć ścieżki wywołań metryk i śledzenia z Renderer i podobnych elementów, gdy System.Diagnostics.Metrics.Meter.IsSupported ma wartość false (jest to wartość domyślna dla przyciętych aplikacji) [browser][wasm] Implementacja przycinania IL dla OTEL (dotnet/aspnetcore #65901) (Prosimy nie komentować zamkniętych zgłoszeń i pull requestów).
  • HotReloadManager udostępnia teraz właściwość IsSupported, przełączaną flagą funkcji i powiązaną z System.Reflection.Metadata.MetadataUpdater.IsSupported, dzięki czemu trimmer może wyeliminować pamięci podręczne funkcji hot reload oraz rejestracje procedur obsługi aktualizacji metadanych w całym rendererze podczas publikowania [blazor][wasm] Naprawa przycinania IL dla funkcji hot reload (dotnet/aspnetcore #65903) (Prosimy nie komentować zamkniętych zgłoszeń i pull requestów).

Aplikacje korzystające z pakietu OTEL lub Przeładowywanie na gorąco nie mają wpływu na powyższe aktualizacje.

Blazor Hybrid

W tej sekcji opisano nowe funkcje programu Blazor Hybrid.

Informacje o wersji są wyświetlane w tej sekcji, gdy funkcje w wersji przeglądowej staną się dostępne.

SignalR

W tej sekcji opisano nowe funkcje programu SignalR.

Minimalne API

W tej sekcji opisano nowe funkcje minimalnych interfejsów API.

Filtry punktów końcowych obserwują błędy powiązania parametrów

Jeśli minimalny punkt końcowy interfejsu API ma skonfigurowane filtry lub fabryki filtrów, potok filtru jest teraz uruchamiany nawet wtedy, gdy powiązanie parametru zakończy się niepowodzeniem. Filtry mogą odczytać HttpContext.Response.StatusCode == 400 i zastąpić je własną treścią odpowiedzi.

W środowisku Development ustaw opcję RouteHandlerOptions.ThrowOnBadRequest = false, aby zwracany był kod 400, który filtr może przechwycić, zamiast zgłaszać BadHttpRequestException na stronie wyjątków deweloperskich. Jest to już ustawienie domyślne w środowiskach nie-Development.

Dziękujemy @marcominerva za ten wkład!

Interfejs OpenAPI

W tej sekcji opisano nowe funkcje interfejsu OpenAPI.

Opisywanie odpowiedzi na pliki binarne

ASP.NET Core 11 wprowadza obsługę generowania opisów interfejsu OpenAPI dla operacji, które zwracają odpowiedzi plików binarnych. Ta obsługa mapuje FileContentResult typ wyniku na schemat OpenAPI z elementami type: string i format: binary.

Użyj metody rozszerzenia Produces<T> z T i FileContentResult aby określić typ odpowiedzi i typ zawartości.

app.MapPost("/filecontentresult", () =>
{
    var content = "This endpoint returns a FileContentResult!"u8.ToArray();
    return TypedResults.File(content);
})
.Produces<FileContentResult>(contentType: MediaTypeNames.Application.Octet);

Wygenerowany dokument OpenAPI opisuje odpowiedź punktu końcowego jako:

responses:
  '200':
    description: OK
    content:
      application/octet-stream:
        schema:
          $ref: '#/components/schemas/FileContentResult'

Element FileContentResult jest zdefiniowany w components/schemas następujący sposób:

components:
  schemas:
    FileContentResult:
      type: string
      format: binary

Obsługa interfejsu OpenAPI 3.2.0 (zmiana powodująca niezgodność)

Microsoft.AspNetCore.OpenApi obsługuje teraz interfejs OpenAPI 3.2.0 za pośrednictwem zaktualizowanej zależności od Microsoft.OpenApi 3.3.1. Ta aktualizacja zawiera zmiany łamiące kompatybilność w bazowej bibliotece. Aby uzyskać więcej informacji, zobacz przewodnik aktualizacji Microsoft.OpenApi.

Aby wygenerować dokument OpenAPI 3.2.0, określ wersję podczas wywoływania polecenia AddOpenApi:

builder.Services.AddOpenApi(options =>
{
    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_2;
});

Kolejne aktualizacje korzystają z nowych funkcji w specyfikacji 3.2.0, takich jak obsługa schematu elementów dla zdarzeń przesyłania strumieniowego.

Dziękujemy @baywet za ten wkład!

ZAPYTANIE HTTP w wygenerowanych dokumentach OpenAPI

Generowanie dokumentów OpenAPI rozpoznaje teraz zapytanie HTTP jako znany typ operacji. QUERY to proponowana bezpieczna, idempotentna metoda, która umożliwia klientom wysyłanie treści żądania w celu opisania wyszukiwania, co jest przydatne, gdy zapytanie jest zbyt długie lub zbyt złożone, aby zmieścić się w adresie URL. Routing już akceptuje dowolne ciągi znaków czasowników za pośrednictwem MapMethods, a OpenAPI 3.2 dodaje pole query do obiektu Path Item, dzięki czemu można to opisać w dokumencie OpenAPI.

Należy pamiętać, że parametr query jest prawidłowy wyłącznie w dokumencie OpenAPI 3.2, dlatego ustaw parametr OpenApiVersion w elemencie OpenApiOptions. We wcześniejszych wersjach OpenAPI operacja query jest generowana w rozszerzeniu specyfikacji x-oai-additionalOperations w obiekcie Path Item.

using Microsoft.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi(options =>
{
    options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_2;
});

var app = builder.Build();

app.MapOpenApi();

app.MapMethods("/search", ["QUERY"], (SearchRequest request) =>
    SearchService.Run(request));

app.Run();

W dokumencie OpenAPI 3.2 operacja QUERY jest opisana bezpośrednio jako element na tym samym poziomie co get, post i inne standardowe operacje:

"paths": {
  "/search": {
    "query": {
      "requestBody": { ... },
      "responses": { "200": { ... } }
    }
  }
}

W dokumentach OpenAPI 3.0 i 3.1 ta sama operacja jest przedstawiona w rozszerzeniu x-oai-additionalOperations obiektu Path Item:

"paths": {
  "/search": {
    "x-oai-additionalOperations": {
      "QUERY": {
        "requestBody": { ... },
        "responses": { "200": { ... } }
      }
    }
  }
}

Dziękujemy @kilifu za ten wkład!

Typy wyników strumienia plików są wyświetlane w dokumentach OpenAPI

FileStreamResult, FileContentHttpResulti FileStreamHttpResult są teraz opisane jako schematy ciągów binarnych w wygenerowanych dokumentach OpenAPI, więc klienci widzą dokładne kształty odpowiedzi dla punktów końcowych, które przesyłają strumieniowo pliki. Dodaj adnotację do punktu końcowego za pomocą .Produces<FileContentHttpResult>(contentType: "application/pdf") (lub równoważnego FileStreamHttpResult/FileStreamResult typu), aby interfejs OpenAPI widział typ wyniku i emituje schemat binarny.

Dziękujemy @marcominerva za ten wkład!

Uwierzytelnianie i autoryzacja

W tej sekcji opisano nowe funkcje uwierzytelniania i autoryzacji.

obsługa TimeProvider w ASP.NET Core Identity

ASP.NET Core Identity teraz używa TimeProvider zamiast DateTime i DateTimeOffset dla wszystkich operacji związanych z czasem. Ta zmiana sprawia, że Identity składniki są bardziej testowalne i zapewniają lepszą kontrolę nad czasem w testach i wyspecjalizowanych scenariuszach.

W poniższym przykładzie pokazano, jak używać fałszywego TimeProvider do testowania funkcji Identity.

// In tests
var fakeTimeProvider = new FakeTimeProvider(
    new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero));

services.AddSingleton<TimeProvider>(fakeTimeProvider);
services.AddIdentity<IdentityUser, IdentityRole>();

// Identity will now use the fake time provider

Za pomocą programu TimeProvidermożna łatwiej pisać testy deterministyczne dla funkcji wrażliwych Identity na czas, takich jak wygaśnięcie tokenu, czasy trwania blokady i walidacja sygnatury zabezpieczeń.

Pobieranie nazwy wyświetlanej passkey z authenticatora

ASP.NET Core Identity teraz automatycznie przypisuje przyjazne nazwy wyświetlane dla kluczy uwierzytelnienia na podstawie ich identyfikatora AAGUID (Identyfikator GUID zaświadczania autentifikatora). Wbudowane mapowania są uwzględniane w przypadku najczęściej używanych wystawców uwierzytelnień typu passkey, w tym Google Password Manager, iCloud Keychain, Windows Hello, 1Password i Bitwarden.

W przypadku znanych uwierzytelniających nazwa jest przypisywana automatycznie bez powiadamiania użytkownika. W przypadku nieznanych wystawców uwierzytelnień użytkownik jest przekierowywany do strony zmiany nazwy. Rozszerz mapowania, dodając wpisy do słownika PasskeyAuthenticators w projekcie.

Miscellaneous

W tej sekcji opisano różne nowe funkcje w .NET 11.

interfejs IOutputCachePolicyProvider

ASP.NET Core w .NET 11 udostępnia interfejs IOutputCachePolicyProvider do implementowania niestandardowej logiki wyboru zasad buforowania danych wyjściowych. Korzystając z tego interfejsu, aplikacje mogą określać domyślne zasady buforowania podstawowego, sprawdzać istnienie nazwanych zasad i obsługiwać zaawansowane scenariusze, w których zasady muszą być rozwiązywane dynamicznie. Przykłady obejmują ładowanie zasad z zewnętrznych źródeł konfiguracji, baz danych lub stosowanie reguł buforowania specyficznych dla najemcy.

Poniższy kod przedstawia IOutputCachePolicyProvider interfejs:

public interface IOutputCachePolicyProvider
{
    IReadOnlyList<IOutputCachePolicy> GetBasePolicies();
    ValueTask<IOutputCachePolicy?> GetPolicyAsync(string policyName);
}

Dziękujemy @lqlive za ten wkład!

Certyfikaty programistyczne z automatycznym zaufaniem w programie WSL

Konfiguracja certyfikatu deweloperskiego automatycznie ufa certyfikatom w środowiskach WSL (Podsystem Windows dla systemu Linux). Po uruchomieniu dotnet dev-certs https --trust w programie WSL certyfikat jest automatycznie instalowany i uznawany za zaufany zarówno w środowisku WSL, jak i w systemie Windows, eliminując potrzebę ręcznej konfiguracji zaufania.

# Automatically trusts certificates in both WSL and Windows
dotnet dev-certs https --trust

To ulepszenie usprawnia środowisko programistyczne podczas korzystania z programu WSL, usuwając wspólny punkt tarć dla deweloperów pracujących w środowiskach systemu Linux w Windows.

Dziękujemy @StickFun za ten wkład!

Natywne śledzenie OpenTelemetry dla ASP.NET Core

ASP.NET Core teraz natywnie dodaje atrybuty semantycznej konwencji OpenTelemetry do aktywności serwera HTTP, zgodnie ze specyfikacją zakresu serwera HTTP OpenTelemetry. Wszystkie wymagane atrybuty są domyślnie dołączane, pasujące do metadanych, które były wcześniej dostępne tylko za pośrednictwem OpenTelemetry.Instrumentation.AspNetCore biblioteki.

Aby zebrać wbudowane dane śledzenia, zasubskrybuj źródło aktywności Microsoft.AspNetCore w konfiguracji OpenTelemetry.

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing => tracing
        .AddSource("Microsoft.AspNetCore")
        .AddConsoleExporter());

Dodatkowa biblioteka instrumentacji (na przykład OpenTelemetry.Instrumentation.AspNetCore) nie jest wymagana. Platforma wypełnia teraz bezpośrednio atrybuty konwencji semantycznej dla działania żądania, takie jak http.request.method, url.path, http.response.status_codei server.address.

Jeśli nie chcesz, aby atrybuty OpenTelemetry zostały dodane do działania, możesz ją wyłączyć, ustawiając przełącznik Microsoft.AspNetCore.Hosting.SuppressActivityOpenTelemetryData AppContext na wartość true.

Ulepszenia wydajności

KestrelAnalizator żądań HTTP/1.1 używa teraz ścieżki kodu, która nie zgłasza źle sformułowanych żądań. Zamiast zgłaszać BadHttpRequestException niepowodzenie analizy, analizator zwraca strukturę rezultatów wskazującą stany powodzenia, niekompletności lub błędu. W scenariuszach z wieloma źle sformułowanymi żądaniami — takimi jak skanowanie portów, złośliwy ruch lub błędnie skonfigurowany klienci — eliminuje to kosztowną obsługę wyjątków i zwiększa przepływność nawet o 20–40%. Nie ma wpływu na prawidłowe przetwarzanie żądań.

Oprogramowanie pośredniczące rejestrowania HTTP teraz zaczyna używać puli jego ResponseBufferingStream wystąpień, co zmniejsza alokacje na poszczególne żądania, gdy włączono rejestrowanie treści odpowiedzi lub przechwytywanie.

Kompresja danych odpowiedzi przy użyciu Zstandard i dekompresja danych żądań

ASP.NET Core obsługuje teraz Zstandard (zstd) zarówno w przypadku kompresji odpowiedzi, jak i dekompresji żądań. Dodaje to obsługę zstd do istniejącego oprogramowania pośredniczącego do kompresji odpowiedzi i dekompresji żądań oraz domyślnie włącza zstd.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddResponseCompression();
builder.Services.AddRequestDecompression();
builder.Services.Configure<ZstandardCompressionProviderOptions>(options =>
{
    options.CompressionOptions = new ZstandardCompressionOptions
    {
        Quality = 6 // 1-22, higher = better compression, slower
    };
});

Dziękujemy @manandre za ten wkład!

Protokół HTTP/3 rozpoczyna przetwarzanie żądań wcześniej

Kestrel teraz rozpoczyna przetwarzanie żądań HTTP/3 bez oczekiwania na strumień sterowania i ramkę SETTINGS, co zmniejsza opóźnienie pierwszego żądania w nowych połączeniach.

Szablon serwera MCP jest dostarczany z zestawem SDK .NET

Szablon projektu mcpserver, dostępny wcześniej tylko przez zainstalowanie Microsoft.McpServer.ProjectTemplates, teraz jest dostarczany jako szablon dołączony do zestawu SDK .NET:

dotnet new mcpserver -o MyMcpServer

Przeniesienie szablonu do ASP.NET Core sprawia, że można go odnaleźć z dotnet new list bez oddzielnego kroku instalacji i wyrównuje obsługę z resztą stosu internetowego.

Monitorowanie uzgadniania połączenia TLS w Kestrel

Dwie powiązane zmiany ułatwiają diagnozowanie i dostosowywanie połączeń TLS w programie Kestrel.

ITlsHandshakeFeature udostępnia teraz właściwość Exception zawierającą wyjątek wyrzucony podczas nieudanego uzgadniania TLS, dzięki czemu oprogramowanie pośredniczące i mechanizmy rejestrowania mogą zapisywać przyczynę niepowodzenia połączenia, zamiast napotykać jedynie IOException na wyższych poziomach stosu wywołań. Funkcja nadal działa po niepowodzeniu uzgadniania — Kestrel zachowuje migawki odpowiednich pól z bazowego SslStream przed jego zwolnieniem.

Opcja TlsClientHelloBytesCallback w HttpsConnectionAdapterOptions została przekształcona w warstwę pośrednią połączenia. Poprzednia postać wywołania zwrotnego jest teraz przestarzała; zamiast niej skonfiguruj inspekcję ClientHello za pomocą nowego rozszerzenia ListenOptions.UseTlsClientHelloListener. W poniższym przykładzie użyto obu funkcji — oprogramowanie pośredniczące połączenia odczytuje ITlsHandshakeFeature.Exception po uzgadnianiu i UseTlsClientHelloListener sprawdza wartość ClientHello przed protokołem TLS:

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5001, listenOptions =>
    {
        listenOptions.Use(next => async context =>
        {
            await next(context);

            var tlsHandshakeFeature = context.Features.Get<ITlsHandshakeFeature>();
            if (tlsHandshakeFeature?.Exception is { } ex)
            {
                Console.WriteLine($"[TLS Handshake Failed] ConnectionId={context.ConnectionId}, Exception={ex.GetType().Name}: {ex.Message}");
            }
        });

        // UseTlsClientHelloListener must be called before UseHttps()
        listenOptions.UseTlsClientHelloListener((connection, clientHelloBytes) =>
        {
            Console.WriteLine($"TLS Client Hello received on {connection.ConnectionId}, {clientHelloBytes.Length} bytes");
        });
        listenOptions.UseHttps();
    });
});

Kompresja odpowiedzi zawsze emituje Vary: Accept-Encoding

Oprogramowanie pośredniczące kompresji odpowiedzi dodaje Vary: Accept-Encoding teraz do każdej odpowiedzi, gdy kompresja jest włączona, nawet jeśli sama odpowiedź nie jest kompresowana. Zapobiega to serwowaniu przez współdzielone pamięci podręczne i sieci CDN skompresowanej odpowiedzi klientowi, który o nią nie prosił (lub odwrotnie).

Dziękujemy @pedrobsaila za ten wkład!

Włączono runtime-async dla bibliotek współdzielonej platformy

Biblioteki ASP.NET Core przeznaczone wyłącznie dla współdzielonej platformy są teraz kompilowane przy użyciu funkcji runtime-async w net11.0+. Runtime-async umożliwia środowisku uruchomieniowemu, a nie kompilatorowi języka C#, generowanie maszyny stanów dla async/await, co może zmniejszyć alokacje dla poszczególnych operacji await i poprawić diagnostykę. To wewnętrzna zmiana w generatorze kodu, która nie wpływa na publiczny interfejs API — aplikacje przeznaczone dla net11.0 automatycznie odnoszą korzyści, gdy wywołują biblioteki ASP.NET Core objęte tą zmianą.

Biblioteki dostarczane zarówno jako składniki współdzielonego frameworka, jak i jako samodzielne pakiety NuGet są wykluczone, ponieważ runtime-async nie jest zgodne z WebAssembly i w przeciwnym razie powodowałoby problemy u użytkowników Wasm korzystających z tych pakietów.

Ponieważ runtime-async zmienia sposób generowania async/await dla dużej części stosu ASP.NET Core, przetestuj swoje aplikacje z tą wersją zapoznawczą i zgłoś problem, jeśli napotkasz nieoczekiwane zachowanie, zwłaszcza w obszarze stosów wyjątków, przepływu ExecutionContext/AsyncLocal albo wszystkiego, co wygląda na regresję względem .NET 10.

Oprogramowanie pośredniczące ograniczające szybkość zwraca dokładne Retry-After nagłówki

Teraz FixedWindowRateLimiter zgłasza wartość metadanych RetryAfter, która dokładnie odzwierciedla następną granicę okna. Aplikacje, które przekazują te metadane do nagłówka odpowiedzi Retry-After w wywołaniu zwrotnym OnRejected, automatycznie ustawiają prawidłowe odstępy między ponownymi próbami bez konieczności wprowadzania zmian w kodzie.

Dodatkowe poprawki w System.Threading.RateLimiting rozwiązują problem, w którym TokenBucketRateLimiter nieprawidłowo obsługiwał częściowe uzupełnianie tokenów podczas pozyskiwania z zerową liczbą pozwoleń, a także usprawniają łańcuchowy ogranicznik szybkości zwracany przez CreateChained, aby prawidłowo przekazywał czas bezczynności i sposób uzupełniania z jego wewnętrznych ograniczników.

Aby zapoznać się z omówieniem oprogramowania pośredniczącego ograniczania liczby żądań, zobacz Oprogramowanie pośredniczące ograniczania liczby żądań w ASP.NET Core.

Dziękujemy @asbjornvad i @apoorvdarshan za te wkłady!

Zmiany przełomowe

Użyj artykułów w Breaking changes in .NET, aby znaleźć zmiany powodujące problemy ze zgodnością, które mogą mieć zastosowanie podczas uaktualniania aplikacji do nowszej wersji .NET.