Udostępnij za pośrednictwem


Co nowego w programie ASP.NET Core 9.0

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

Ten artykuł został zaktualizowany dla platformy .NET 9 (wersja zapoznawcza 5).

Blazor

W tej sekcji opisano nowe funkcje programu Blazor.

.NET MAUIBlazor Hybrid szablon rozwiązania i aplikacja internetowa

Nowy szablon rozwiązania ułatwia tworzenie .NET MAUI natywnych i Blazor internetowych aplikacji klienckich korzystających z tego samego interfejsu użytkownika. W tym szablonie pokazano, jak tworzyć aplikacje klienckie, które maksymalizują ponowne użycie kodu oraz docelowe systemy Android, iOS, Mac, Windows i Web.

Najważniejsze funkcje tego szablonu obejmują:

  • Możliwość wybrania interaktywnego Blazor trybu renderowania dla aplikacji internetowej.
  • Automatyczne tworzenie odpowiednich projektów, w tym Blazor aplikacji internetowej (globalne renderowanie interakcyjne) i .NET MAUIBlazor Hybrid aplikacji.
  • Utworzone projekty używają biblioteki klas udostępnionych Razor (RCL) do obsługi składników interfejsu Razor użytkownika.
  • Dołączono przykładowy kod, który pokazuje, jak używać wstrzykiwania zależności w celu zapewnienia różnych implementacji interfejsu dla Blazor Hybrid aplikacji i Blazor aplikacji internetowej.

Aby rozpocząć, zainstaluj zestaw SDK platformy .NET 9 i zainstaluj .NET MAUI obciążenie, które zawiera szablon:

dotnet workload install maui

Utwórz rozwiązanie na podstawie szablonu projektu w powłoce poleceń przy użyciu następującego polecenia:

dotnet new maui-blazor-web

Szablon jest również dostępny w programie Visual Studio.

Uwaga

Obecnie wyjątek występuje, jeśli Blazor tryby renderowania są definiowane na poziomie poszczególnych stron/składników. Aby uzyskać więcej informacji, zobacz BlazorWebView wymaga sposobu włączenia zastępowania ResolveComponentForRenderMode (dotnet/aspnetcore #51235).

Aby uzyskać więcej informacji, zobacz Tworzenie .NET MAUIBlazor Hybrid aplikacji za pomocą Blazor aplikacji internetowej.

Optymalizacja dostarczania zasobów statycznych

MapStaticAssets to nowe oprogramowanie pośredniczące, które pomaga zoptymalizować dostarczanie zasobów statycznych w dowolnej aplikacji ASP.NET Core, w tym Blazor aplikacji.

Aby uzyskać więcej informacji, zobacz jeden z następujących zasobów:

Wykrywanie lokalizacji renderowania, interakcyjności i przypisanego trybu renderowania w czasie wykonywania

Wprowadziliśmy nowy interfejs API zaprojektowany w celu uproszczenia procesu wykonywania zapytań dotyczących stanów składników w czasie wykonywania. Ten interfejs API zapewnia następujące możliwości:

  • Określ bieżącą lokalizację wykonywania składnika: może to być szczególnie przydatne podczas debugowania i optymalizowania wydajności składników.
  • Sprawdź, czy składnik jest uruchomiony w środowisku interaktywnym: może to być przydatne w przypadku składników, które mają różne zachowania w oparciu o interakcyjność ich środowiska.
  • Pobieranie przypisanego trybu renderowania dla składnika: Zrozumienie trybu renderowania może pomóc w optymalizacji procesu renderowania i poprawie ogólnej wydajności składnika.

Ulepszone środowisko ponownego łączenia po stronie serwera:

Następujące ulepszenia zostały wprowadzone do domyślnego środowiska ponownego nawiązywania połączenia po stronie serwera:

  • Gdy użytkownik przechodzi z powrotem do aplikacji z odłączonym obwodem, następuje natychmiastowe ponowne nawiązanie połączenia, a nie oczekiwanie na czas trwania następnego interwału ponownego połączenia. Poprawia to środowisko użytkownika podczas przechodzenia do aplikacji na karcie przeglądarki, która przeszła w stan uśpienia.

  • Gdy próba ponownego nawiązania połączenia osiągnie serwer, ale serwer już zwolnił obwód, nastąpi automatyczne odświeżenie strony. Uniemożliwia to użytkownikowi ręczne odświeżenie strony, jeśli prawdopodobnie spowoduje to pomyślne ponowne nawiązanie połączenia.

  • Czas ponownego nawiązywania połączenia używa obliczonej strategii wycofywania. Domyślnie pierwsze kilka ponownych prób nawiązania połączenia odbywa się w krótkim odstępie czasu bez interwału ponawiania prób przed wprowadzeniem obliczonych opóźnień między próbami. Zachowanie interwału ponawiania prób można dostosować, określając funkcję w celu obliczenia interwału ponawiania, jak pokazano w poniższym przykładzie wykładniczego wycofywania:

    Blazor.start({
      circuit: {
        reconnectionOptions: {
          retryIntervalMilliseconds: (previousAttempts, maxRetries) => 
            previousAttempts >= maxRetries ? null : previousAttempts * 1000
        },
      },
    });
    
  • Styl domyślnego interfejsu użytkownika ponownego łączenia został zmodernizowany.

Aby uzyskać więcej informacji, zobacz wskazówki dotyczące platformy ASP.NET CoreBlazorSignalR.

Uproszczona serializacji stanu uwierzytelniania dla Blazor usługi Web Apps

Nowe interfejsy API ułatwiają dodawanie uwierzytelniania do istniejącej Blazor aplikacji internetowej. Po utworzeniu nowej Blazor aplikacji internetowej z uwierzytelnianiem przy użyciu indywidualnych kont i włączeniu interakcyjności opartej na zestawie WebAssembly projekt zawiera niestandardowy AuthenticationStateProvider zarówno w projektach serwera, jak i klienta.

Ci dostawcy przepływają stan uwierzytelniania użytkownika do przeglądarki. Uwierzytelnianie na serwerze, a nie na kliencie, umożliwia aplikacji dostęp do stanu uwierzytelniania podczas prerenderingu i przed Blazor WebAssembly zainicjowanie środowiska uruchomieniowego.

Implementacje niestandardowe AuthenticationStateProvider używają usługi stanu trwałego składnika (PersistentComponentState), aby serializować stan uwierzytelniania w komentarzach HTML i odczytywać go z powrotem z zestawu WebAssembly w celu utworzenia nowego AuthenticationState wystąpienia.

Działa to dobrze, jeśli rozpoczęto pracę z Blazor szablonu projektu Aplikacja internetowa i wybrano opcję Indywidualne konta , ale jest to dużo kodu do zaimplementowania siebie lub skopiowania, jeśli próbujesz dodać uwierzytelnianie do istniejącego projektu. Teraz istnieją interfejsy API, które są teraz częścią Blazor szablonu projektu aplikacji internetowej, które można wywoływać w projektach serwera i klienta w celu dodania tej funkcji:

  • AddAuthenticationStateSerialization: dodaje niezbędne usługi do serializacji stanu uwierzytelniania na serwerze.
  • AddAuthenticationStateDeserialization: dodaje niezbędne usługi do deserializacji stanu uwierzytelniania w przeglądarce.

Domyślnie interfejs API serializuje tylko nazwę po stronie serwera i oświadczenia roli w celu uzyskania dostępu w przeglądarce. Można przekazać opcję w celu AddAuthenticationStateSerialization uwzględnienia wszystkich oświadczeń.

Aby uzyskać więcej informacji, zobacz następujące sekcje artykułu ** :

Dodawanie statycznych stron renderowania po stronie serwera (SSR) do globalnie interakcyjnej Blazor aplikacji internetowej

W wersji platformy .NET 9 jest teraz prostsze dodawanie statycznych stron SSR do aplikacji, które przyjmują globalną interakcyjność.

Takie podejście jest przydatne tylko wtedy, gdy aplikacja ma określone strony, które nie mogą pracować z interaktywnym serwerem lub renderowaniem zestawu WebAssembly. Na przykład zastosuj to podejście dla stron, które zależą od odczytu/zapisu http cookies i mogą działać tylko w cyklu żądania/odpowiedzi zamiast renderowania interakcyjnego. W przypadku stron, które działają z renderowaniem interaktywnym, nie należy wymuszać używania statycznego renderowania SSR, ponieważ jest mniej wydajne i mniej elastyczne dla użytkownika końcowego.

Oznacz dowolną Razor stronę składnika przy użyciu nowego [ExcludeFromInteractiveRouting] atrybutu przypisanego @attributeRazor do dyrektywy:

@attribute [ExcludeFromInteractiveRouting]

Zastosowanie atrybutu powoduje przejście do strony w celu zakończenia routingu interakcyjnego. Nawigacja przychodząca jest zmuszona do ponownego załadowania pełnej strony zamiast tego rozpoznawania strony za pośrednictwem routingu interakcyjnego. Ponowne ładowanie pełnej strony wymusza składnik główny najwyższego poziomu, zazwyczaj App składnik (App.razor), aby rerender z serwera, dzięki czemu aplikacja może przełączyć się do innego trybu renderowania najwyższego poziomu.

HttpContext.AcceptsInteractiveRouting Metoda rozszerzenia umożliwia składnikowi wykrywanie, czy [ExcludeFromInteractiveRouting] jest stosowane do bieżącej strony.

W składniku App użyj wzorca w poniższym przykładzie:

  • Strony, które nie są oznaczone adnotacją domyślną [ExcludeFromInteractiveRouting] do trybu renderowania InteractiveServer z globalną interakcyjnością. Możesz zastąpić InteractiveServer ciąg ciągiem InteractiveWebAssembly lub InteractiveAuto określić inny domyślny tryb renderowania globalnego.
  • Strony oznaczone adnotacjami przy [ExcludeFromInteractiveRouting] użyciu statycznego przewodnika SSR (PageRenderMode jest przypisywane ).null
<!DOCTYPE html>
<html>
<head>
    ...
    <HeadOutlet @rendermode="@PageRenderMode" />
</head>
<body>
    <Routes @rendermode="@PageRenderMode" />
    ...
</body>
</html>

@code {
    [CascadingParameter]
    private HttpContext HttpContext { get; set; } = default!;

    private IComponentRenderMode? PageRenderMode
        => HttpContext.AcceptsInteractiveRouting() ? InteractiveServer : null;
}

Alternatywą dla metody HttpContext.AcceptsInteractiveRouting rozszerzenia jest ręczne odczytywanie metadanych punktu końcowego przy użyciu polecenia HttpContext.GetEndpoint()?.Metadata.

Ta funkcja jest objęta dokumentacją referencyjną w trybach renderowania ASP.NET CoreBlazor.

Wstrzykiwanie konstruktora

Razor składniki obsługują wstrzykiwanie konstruktora.

W poniższym przykładzie klasa częściowa (code-behind) wprowadza usługę NavigationManager przy użyciu podstawowego konstruktora:

public partial class ConstructorInjection(NavigationManager navigation)
{
    protected NavigationManager Navigation { get; } = navigation;
}

Aby uzyskać więcej informacji, zobacz ASP.NET Core dependency injection (Wstrzykiwanie zależności ASP.NET CoreBlazor).

Kompresja protokołu Websocket dla składników interactive server

Domyślnie składniki interaktywnego serwera umożliwiają kompresję dla połączeń protokołu WebSocket i ustawiają frame-ancestors dyrektywę zasad zabezpieczeń zawartości (CSP) ustawioną na 'self', która zezwala tylko na osadzanie aplikacji w miejscu <iframe> pochodzenia, z którego aplikacja jest obsługiwana, gdy kompresja jest włączona lub gdy jest udostępniana konfiguracja kontekstu protokołu WebSocket.

Kompresję można wyłączyć, ustawiając wartość ConfigureWebSocketOptions null, co zmniejsza lukę w zabezpieczeniach aplikacji do ataku , ale może spowodować zmniejszenie wydajności:

.AddInteractiveServerRenderMode(o => o.ConfigureWebSocketOptions = null)

Skonfiguruj bardziej frame-ancestors rygorystyczny dostawca CSP z wartością 'none' (wymagany pojedynczy cudzysłów), który umożliwia kompresję protokołu WebSocket, ale uniemożliwia przeglądarkom osadzanie aplikacji w dowolnym elemencie <iframe>:

.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

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

Obsługa zdarzeń kompozycji klawiatury w programie Blazor

Nowa KeyboardEventArgs.IsComposing właściwość wskazuje, czy zdarzenie klawiatury jest częścią sesji kompozycji. Śledzenie stanu kompozycji zdarzeń klawiatury ma kluczowe znaczenie dla obsługi metod wprowadzania znaków międzynarodowych.

Dodano parametr OverscanCount do elementu QuickGrid

Składnik QuickGrid uwidacznia teraz właściwość określającą OverscanCount , ile dodatkowych wierszy jest renderowanych przed i po widocznym regionie po włączeniu wirtualizacji.

Wartość domyślna OverscanCount to 3. Poniższy przykład zwiększa OverscanCount wartość do 4:

<QuickGrid ItemsProvider="itemsProvider" Virtualize="true" OverscanCount="4">
    ...
</QuickGrid>

SignalR

W tej sekcji opisano nowe funkcje programu SignalR.

Obsługa typu polimorficznego w centrach SignalR

Metody koncentratora mogą teraz akceptować klasę bazową zamiast klasy pochodnej w celu włączenia scenariuszy polimorficznych. Typ podstawowy musi być adnotacjami, aby umożliwić polimorfizm.

public class MyHub : Hub
{
    public void Method(JsonPerson person)
    {
        if (person is JsonPersonExtended)
        {
        }
        else if (person is JsonPersonExtended2)
        {
        }
        else
        {
        }
    }
}

[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended), nameof(JsonPersonExtended))]
[JsonDerivedType(typeof(JsonPersonExtended2), nameof(JsonPersonExtended2))]
private class JsonPerson
{
    public string Name { get; set; }
    public Person Child { get; set; }
    public Person Parent { get; set; }
}

private class JsonPersonExtended : JsonPerson
{
    public int Age { get; set; }
}

private class JsonPersonExtended2 : JsonPerson
{
    public string Location { get; set; }
}

Minimalne interfejsy API

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

Dodano InternalServerError polecenie i InternalServerError<TValue> do TypedResults

Klasa TypedResults jest przydatnym pojazdem do zwracania silnie typiowanych odpowiedzi opartych na kodzie stanu HTTP z minimalnego interfejsu API. TypedResults Teraz zawiera metody fabryczne i typy zwracania odpowiedzi "500 Wewnętrzny błąd serwera" z punktów końcowych. Oto przykład, który zwraca odpowiedź 500:

var app = WebApplication.Create();

app.MapGet("/", () => TypedResults.InternalServerError("Something went wrong!"));

app.Run();

OpenAPI

Wbudowana obsługa generowania dokumentów OpenAPI

Specyfikacja interfejsu OpenAPI jest standardem opisującym interfejsy API HTTP. Standard umożliwia deweloperom definiowanie kształtu interfejsów API, które mogą być podłączone do generatorów klientów, generatorów serwerów, narzędzi do testowania, dokumentacji i nie tylko. W wersji zapoznawczej platformy .NET 9 program ASP.NET Core zapewnia wbudowaną obsługę generowania dokumentów OpenAPI reprezentujących interfejsy API oparte na kontrolerach lub minimalnych interfejsach API za pośrednictwem pakietu Microsoft.AspNetCore.OpenApi .

Następujące wyróżnione wywołania kodu:

  • AddOpenApi aby zarejestrować wymagane zależności w kontenerze di aplikacji.
  • MapOpenApi aby zarejestrować wymagane punkty końcowe interfejsu OpenAPI w trasach aplikacji.
var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

app.MapGet("/hello/{name}", (string name) => $"Hello {name}"!);

app.Run();

Microsoft.AspNetCore.OpenApi Zainstaluj pakiet w projekcie przy użyciu następującego polecenia:

dotnet add package Microsoft.AspNetCore.OpenApi --prerelease

Uruchom aplikację i przejdź do openapi/v1.json strony , aby wyświetlić wygenerowany dokument OpenAPI:

Dokument OpenAPI

Dokumenty OpenAPI można również wygenerować w czasie kompilacji Microsoft.Extensions.ApiDescription.Server , dodając pakiet:

dotnet add package Microsoft.Extensions.ApiDescription.Server --prerelease

W pliku projektu aplikacji dodaj następujące elementy:

<PropertyGroup>
  <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
  <OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
</PropertyGroup>

Uruchom dotnet build i sprawdź wygenerowany JSplik ON w katalogu projektu.

Generowanie dokumentu OpenAPI w czasie kompilacji

Wbudowana generacja dokumentów OpenAPI platformy ASP.NET Core zapewnia obsługę różnych dostosowań i opcji. Zapewnia ona przekształcanie dokumentów i operacji oraz umożliwia zarządzanie wieloma dokumentami OpenAPI dla tej samej aplikacji.

Aby dowiedzieć się więcej o nowych możliwościach dokumentów openAPI w programie ASP.NET Core, zobacz nowe dokumenty Microsoft.AspNetCore.OpenApi.

Uwierzytelnianie i autoryzacja

W tej sekcji opisano nowe funkcje uwierzytelniania i autoryzacji.

Dostosowywanie parametrów OIDC i OAuth

Programy obsługi uwierzytelniania OAuth i OIDC mają AdditionalAuthorizationParameters teraz możliwość ułatwienia dostosowywania parametrów komunikatów autoryzacji, które są zwykle uwzględniane jako część ciągu zapytania przekierowania. W programie .NET 8 i starszych wersjach wymaga to niestandardowego OnRedirectToIdentityProvider wywołania zwrotnego lub zastąpienia BuildChallengeUrl metody w niestandardowej procedurze obsługi. Oto przykład kodu platformy .NET 8:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.Events.OnRedirectToIdentityProvider = context =>
    {
        context.ProtocolMessage.SetParameter("prompt", "login");
        context.ProtocolMessage.SetParameter("audience", "https://api.example.com");
        return Task.CompletedTask;
    };
});

Powyższy przykład można teraz uprościć do następującego kodu:

builder.Services.AddAuthentication().AddOpenIdConnect(options =>
{
    options.AdditionalAuthorizationParameters.Add("prompt", "login");
    options.AdditionalAuthorizationParameters.Add("audience", "https://api.example.com");
});

Konfigurowanie flag uwierzytelniania rozszerzonego HTTP.sys

Teraz można skonfigurować HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING flagi i HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL HTTP.sys przy użyciu nowych EnableKerberosCredentialCaching właściwości i CaptureCredentials w HTTP.sys AuthenticationManager , aby zoptymalizować sposób obsługi uwierzytelniania systemu Windows. Na przykład:

webBuilder.UseHttpSys(options =>
{
    options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
    options.Authentication.EnableKerberosCredentialCaching = true;
    options.Authentication.CaptureCredentials = true;
});

Różne

W poniższych sekcjach opisano różne nowe funkcje.

Nowa HybridCache biblioteka

Interfejs HybridCache API łączy pewne luki w istniejących IDistributedCache interfejsach API i IMemoryCache . Dodaje również nowe funkcje, takie jak:

  • Ochrona "Stampede", aby zapobiec równoległym pobieraniu tych samych zadań.
  • Konfigurowalna serializacji.

HybridCache jest przeznaczony do zastąpienia upuszczania dla istniejących IDistributedCache i IMemoryCache użycia, a także udostępnia prosty interfejs API do dodawania nowego kodu buforowania. Zapewnia ujednolicony interfejs API zarówno w przypadku buforowania w procesie, jak i poza procesem.

Aby zobaczyć, jak HybridCache interfejs API jest uproszczony, porównaj go z kodem, który używa metody IDistributedCache. Oto przykład użycia IDistributedCache :

public class SomeService(IDistributedCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        var key = $"someinfo:{name}:{id}"; // Unique key for this combination.
        var bytes = await cache.GetAsync(key, token); // Try to get from cache.
        SomeInformation info;
        if (bytes is null)
        {
            // Cache miss; get the data from the real source.
            info = await SomeExpensiveOperationAsync(name, id, token);

            // Serialize and cache it.
            bytes = SomeSerializer.Serialize(info);
            await cache.SetAsync(key, bytes, token);
        }
        else
        {
            // Cache hit; deserialize it.
            info = SomeSerializer.Deserialize<SomeInformation>(bytes);
        }
        return info;
    }

    // This is the work we're trying to cache.
    private async Task<SomeInformation> SomeExpensiveOperationAsync(string name, int id,
        CancellationToken token = default)
    { /* ... */ }
}

To dużo pracy, aby uzyskać rację za każdym razem, w tym takie rzeczy jak serializacja. W scenariuszu miss pamięci podręcznej można znaleźć wiele współbieżnych wątków, wszystkie chybienie pamięci podręcznej, wszystkie pobieranie danych bazowych, wszystkie serializacji i wszystkie wysyłanie tych danych do pamięci podręcznej.

Aby uprościć i ulepszyć ten kod za pomocą HybridCachepolecenia , najpierw musimy dodać nową bibliotekę Microsoft.Extensions.Caching.Hybrid:

<PackageReference Include="Microsoft.Extensions.Caching.Hybrid" Version="9.0.0" />

Zarejestruj usługę HybridCache , aby zarejestrować implementację IDistributedCache :

services.AddHybridCache(); // Not shown: optional configuration API.

Teraz większość problemów z buforowaniem można odciążyć do :HybridCache

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync
        (string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // Unique key for this combination.
            async cancel => await SomeExpensiveOperationAsync(name, id, cancel),
            token: token
        );
    }
}

Udostępniamy konkretną implementację klasy abstrakcyjnej HybridCache za pośrednictwem wstrzykiwania zależności, ale deweloperzy mogą udostępniać niestandardowe implementacje interfejsu API. Implementacja HybridCache dotyczy wszystkich elementów związanych z buforowaniem, w tym obsługą operacji współbieżnych. Token cancel w tym miejscu reprezentuje połączone anulowanie wszystkich współbieżnych wywołań — nie tylko anulowanie obiektu wywołującego, które widzimy (czyli token).

Scenariusze o wysokiej przepływności można dodatkowo zoptymalizować przy użyciu TState wzorca, aby uniknąć narzutów z przechwyconych zmiennych i wywołań zwrotnych dla poszczególnych wystąpień:

public class SomeService(HybridCache cache)
{
    public async Task<SomeInformation> GetSomeInformationAsync(string name, int id, CancellationToken token = default)
    {
        return await cache.GetOrCreateAsync(
            $"someinfo:{name}:{id}", // unique key for this combination
            (name, id), // all of the state we need for the final call, if needed
            static async (state, token) =>
                await SomeExpensiveOperationAsync(state.name, state.id, token),
            token: token
        );
    }
}

HybridCache używa skonfigurowanej IDistributedCache implementacji, jeśli istnieje, na potrzeby pomocniczego buforowania poza procesem, na przykład przy użyciu usługi Redis. Ale nawet bez IDistributedCache, HybridCache usługa nadal zapewnia buforowanie w procesie i "stampede" ochrony.

Uwaga dotycząca ponownego użycia obiektu

W typowym istniejącym kodzie, który używa IDistributedCachemetody , każde pobieranie obiektu z pamięci podręcznej powoduje deserializacji. To zachowanie oznacza, że każdy współbieżny obiekt wywołujący otrzymuje oddzielne wystąpienie obiektu, które nie może wchodzić w interakcje z innymi wystąpieniami. Wynikiem jest bezpieczeństwo wątków, ponieważ nie ma ryzyka współbieżnych modyfikacji w tym samym wystąpieniu obiektu.

Ponieważ wiele użycia zostanie dostosowanych z istniejącego HybridCache IDistributedCache kodu, zachowuje to zachowanie domyślnie, HybridCache aby uniknąć wprowadzania usterek współbieżności. Jednak dany przypadek użycia jest z natury bezpieczny wątkowo:

  • Jeśli buforowane typy są niezmienne.
  • Jeśli kod nie zmodyfikuje ich.

W takich przypadkach należy poinformować HybridCache , że ponowne użycie wystąpień jest bezpieczne przez:

  • Oznaczanie typu jako sealed. Słowo sealed kluczowe w języku C# oznacza, że nie można dziedziczyć klasy.
  • Zastosowanie do niego atrybutu [ImmutableObject(true)] . Atrybut [ImmutableObject(true)] wskazuje, że nie można zmienić stanu obiektu po jego utworzeniu.

Przez ponowne użycie wystąpień HybridCache może zmniejszyć obciążenie związane z alokacją procesora CPU i obiektu skojarzonymi z deserializacji poszczególnych wywołań. Może to prowadzić do poprawy wydajności w scenariuszach, w których buforowane obiekty są duże lub często używane.

Inne HybridCache funkcje

Podobnie jak IDistributedCache, HybridCache obsługuje usuwanie według klucza za pomocą RemoveKeyAsync metody .

HybridCache Udostępnia również opcjonalne interfejsy API dla IDistributedCache implementacji, aby uniknąć byte[] alokacji. Ta funkcja jest implementowana przez wersje Microsoft.Extensions.Caching.StackExchangeRedis zapoznawcza pakietów i Microsoft.Extensions.Caching.SqlServer .

Serializacja jest konfigurowana w ramach rejestrowania usługi z obsługą serializatorów specyficznych dla typu i uogólnionych za pośrednictwem WithSerializer metod i .WithSerializerFactory , w łańcuchu od wywołania AddHybridCache . Domyślnie biblioteka obsługuje string i byte[] wewnętrznie używa System.Text.Json wszystkich innych elementów, ale możesz użyć narzędzia protobuf, xml lub innego elementu.

HybridCache obsługuje starsze środowiska uruchomieniowe platformy .NET w dół do programów .NET Framework 4.7.2 i .NET Standard 2.0.

Aby uzyskać więcej informacji na temat HybridCacheusługi , zobacz biblioteka HybridCache w programie ASP.NET Core

Ulepszenia strony wyjątków dla deweloperów

Strona wyjątku dewelopera platformy ASP.NET Core jest wyświetlana, gdy aplikacja zgłasza nieobsługiwany wyjątek podczas programowania. Strona wyjątku dla deweloperów zawiera szczegółowe informacje o wyjątku i żądaniu.

Wersja zapoznawcza 3 dodała metadane punktu końcowego do strony wyjątku dewelopera. ASP.NET Core używa metadanych punktu końcowego do kontrolowania zachowania punktu końcowego, takich jak routing, buforowanie odpowiedzi, ograniczanie szybkości, generowanie interfejsu OpenAPI i nie tylko. Na poniższej ilustracji przedstawiono nowe informacje o metadanych w Routing sekcji strony wyjątku dewelopera:

Nowe informacje o metadanych na stronie wyjątku dewelopera

Podczas testowania strony wyjątku dla deweloperów zidentyfikowano niewielką jakość życia. Zostały one wysłane w wersji zapoznawczej 4:

  • Lepsze zawijanie tekstu. Długie cookiewartości ciągów zapytania i nazwy metod nie dodają już poziomych pasków przewijania przeglądarki.
  • Większy tekst, który znajduje się w nowoczesnych projektach.
  • Bardziej spójne rozmiary tabel.

Na poniższej animowanej ilustracji przedstawiono nową stronę wyjątku dla deweloperów:

Nowa strona wyjątku dla deweloperów

Ulepszenia debugowania słownika

Debugowanie wyświetlania słowników i innych kolekcji klucz-wartość ma ulepszony układ. Klucz jest wyświetlany w kolumnie klucza debugera zamiast łączyć się z wartością. Na poniższych obrazach przedstawiono stary i nowy ekran słownika w debugerze.

Przed:

Poprzednie środowisko debugera

Po:

Nowe środowisko debugera

ASP.NET Core ma wiele kolekcji klucz-wartość. To ulepszone środowisko debugowania ma zastosowanie do:

  • Nagłówki HTTP
  • Ciągi zapytań
  • Formularze
  • Cookies
  • Wyświetlanie danych
  • Dane trasy
  • Funkcje

Poprawka dotycząca funkcji 503 podczas recyklingu aplikacji w usługach IIS

Domyślnie występuje 1-sekundowe opóźnienie między powiadomieniem usług IIS o koszu lub zamknięciu, a gdy usługa ANCM informuje serwer zarządzany o rozpoczęciu zamykania. Opóźnienie można skonfigurować za pomocą zmiennej środowiskowej ANCM_shutdownDelay lub przez ustawienie shutdownDelay ustawienia programu obsługi. Obie wartości znajdują się w milisekundach. Opóźnienie polega głównie na zmniejszeniu prawdopodobieństwa wyścigu, w którym:

  • Usługi IIS nie uruchomiły kolejkowania żądań, aby przejść do nowej aplikacji.
  • Usługa ANCM rozpoczyna odrzucanie nowych żądań, które wchodzą do starej aplikacji.

Wolniejsze maszyny lub maszyny z większym użyciem procesora CPU mogą chcieć dostosować tę wartość, aby zmniejszyć prawdopodobieństwo 503.

Przykład ustawienia shutdownDelay:

<aspNetCore processPath="dotnet" arguments="myapp.dll" stdoutLogEnabled="false" stdoutLogFile=".logsstdout">
  <handlerSettings>
    <!-- Milliseconds to delay shutdown by.
    this doesn't mean incoming requests will be delayed by this amount,
    but the old app instance will start shutting down after this timeout occurs -->
    <handlerSetting name="shutdownDelay" value="5000" />
  </handlerSettings>
</aspNetCore>

Poprawka znajduje się w globalnie zainstalowanym module ANCM pochodzącym z pakietu hostingu.

Optymalizowanie statycznego dostarczania zasobów internetowych

Tworzenie wydajnych aplikacji internetowych obejmuje optymalizację dostarczania zasobów do przeglądarki. Obejmuje to wiele aspektów, takich jak:

MapStaticAssets to nowe oprogramowanie pośredniczące, które pomaga zoptymalizować dostarczanie zasobów statycznych w aplikacji. Jest ona przeznaczona do pracy ze wszystkimi strukturami interfejsu użytkownika, w tym Blazorz elementami , Razor Pages i MVC. Zazwyczaj jest to zamiana typu drop-in dla elementu UseStaticFiles.

MapStaticAssets działa przez połączenie procesów kompilowania i publikowania w celu zbierania informacji o wszystkich zasobach statycznych w aplikacji. Te informacje są następnie wykorzystywane przez bibliotekę środowiska uruchomieniowego do wydajnego udostępniania tych plików w przeglądarce.

MapStaticAssets program może zastąpić UseStaticFiles w większości sytuacji, jednak jest zoptymalizowany pod kątem obsługi zasobów, o których aplikacja ma wiedzę w czasie kompilacji i publikowania. Jeśli aplikacja obsługuje zasoby z innych lokalizacji, takich jak dyski lub zasoby osadzone, UseStaticFiles powinny być używane.

MapStaticAssets zapewnia następujące korzyści, których nie znaleziono w programie UseStaticFiles:

  • Kompresja czasu kompilacji dla wszystkich zasobów w aplikacji:
    • gzip podczas opracowywania i gzip + brotli publikowania.
    • Wszystkie zasoby są kompresowane w celu zmniejszenia rozmiaru zasobów do minimum.
  • Oparte na ETagszawartości: dla Etags każdego zasobu są ciągiem zakodowanym w formacie Base64 skrótu SHA-256 zawartości. Dzięki temu przeglądarka ponownie pobierze plik tylko wtedy, gdy jego zawartość uległa zmianie.

W poniższej tabeli przedstawiono oryginalne i skompresowane rozmiary plików CSS i JS plików w domyślnym Razor szablonie stron:

Plik Oryginalne Skompresowane % redukcji
bootstrap.min.css 163 17.5 89.26%
jquery.js 89.6 28 68.75%
bootstrap.min.js 78.5 20 74.52%
Łącznie 331.1 65.5 80.20%

W poniższej tabeli przedstawiono oryginalne i skompresowane rozmiary przy użyciu biblioteki składników interfejsu użytkownika Blazor Fluent:

Plik Oryginalne Skompresowane % redukcji
fluent.js 384 73 80.99%
fluent.css 94 11 88.30%
Łącznie 478 84 82.43%

W sumie 478 KB nieskompresowane do 84 KB skompresowane.

W poniższej tabeli przedstawiono oryginalne i skompresowane rozmiary przy użyciu biblioteki Składników BłotaBlazorBlazor:

Plik Oryginalne Skompresowane Redukcja
BłotoBlazor.min.css 541 37.5 93.07%
BłotoBlazor.min.js 47.4 9,2 80.59%
Łącznie 588.4 46,7 92.07%

Optymalizacja odbywa się automatycznie w przypadku korzystania z programu MapStaticAssets. Po dodaniu lub zaktualizowaniu biblioteki, na przykład przy użyciu nowego kodu JavaScript lub CSS, zasoby są optymalizowane w ramach kompilacji. Optymalizacja jest szczególnie korzystna dla środowisk mobilnych, które mogą mieć niższą przepustowość lub zawodne połączenia.

Włączanie kompresji dynamicznej na serwerze a przy użyciu MapStaticAssets

MapStaticAssets ma następujące zalety niż kompresja dynamiczna na serwerze:

  • Jest prostsze, ponieważ nie ma określonej konfiguracji serwera.
  • Jest bardziej wydajne, ponieważ zasoby są kompresowane w czasie kompilacji.
  • Umożliwia deweloperowi spędzenie dodatkowego czasu podczas procesu kompilacji, aby upewnić się, że zasoby są minimalnym rozmiarem.

Rozważmy poniższą tabelę porównującą kompresję mudBlazor z kompresją dynamiczną usług IIS i MapStaticAssets:

Program IIS gzip MapStaticAssets Redukcja zasobów mapstatycznych
≅ 90 37.5 59%