Megosztás a következőn keresztül:


A ASP.NET Core 9.0 újdonságai

Ez a cikk a ASP.NET Core 9.0 legfontosabb változásait emeli ki a vonatkozó dokumentációra mutató hivatkozásokkal.

Statikus eszközkézbesítés optimalizálása

MapStaticAssets az útválasztási végpontok konvenciói egy új funkció, amely optimalizálja a statikus eszközök kézbesítését az ASP.NET Core alkalmazásokban.

Az Blazor-alkalmazások statikus eszközkézbesítésére vonatkozó információkért lásd a ASP.NET Core Blazor statikus fájlokat.

A statikus eszközök kiszolgálásához ajánlott gyártási eljárások követése jelentős mennyiségű munkát és műszaki szakértelmet igényel. Optimalizálások, például tömörítés, gyorsítótárazás és ujjlenyomatok nélkül:

  • A böngészőnek további kéréseket kell küldenie minden oldalbetöltéshez.
  • A szükségesnél több bájt kerül átvitelre a hálózaton keresztül.
  • Néha elavult verziók kerülnek kiszolgálásra az ügyfelek számára.

A teljesítményalapú webalkalmazások létrehozásához optimalizálni kell az eszközök böngészőbe történő kézbesítését. A lehetséges optimalizálások a következők:

  • Egy adott objektumot egyszer kell kiszolgálni, amíg a fájl nem változik, vagy a böngésző nem törli a gyorsítótárát. Állítsa be a ETag fejlécet.
  • Megakadályozza, hogy a böngésző régi vagy elavult objektumokat használ az alkalmazás frissítése után. Állítsa be a utoljára módosított fejlécet.
  • Állítsa be a megfelelő gyorsítótárazási fejléceket.
  • Használja a gyorsítótárazó köztes szoftvert.
  • tömörített-verziókat szolgáljanak ki, ha lehetséges.
  • Használjon egy CDN- az eszközök felhasználóhoz közelebbi kiszolgálásához.
  • A böngészőnek kiszolgált objektumok méretének minimalizálása. Ez az optimalizálás nem tartalmazza a minifikációt.

MapStaticAssets egy új funkció, amely optimalizálja a statikus eszközök kézbesítését egy alkalmazásban. Úgy tervezték, hogy minden felhasználói felületi keretrendszerrel működjön, beleértve a Blazor, a Razor Pages és az MVC-t. Ez általában egy könnyen beilleszthető helyettesítő a UseStaticFilesszámára.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

+app.MapStaticAssets();
-app.UseStaticFiles();
app.MapRazorPages();

app.Run();

MapStaticAssets a buildelési és közzétételi idő folyamatok kombinálásával gyűjti össze az alkalmazás összes statikus erőforrásával kapcsolatos információkat. Ezt az információt a futtatókörnyezeti kódtár használja fel, hogy hatékonyan kiszolgálja ezeket a fájlokat a böngészőben.

MapStaticAssets a legtöbb helyzetben lecserélheti a UseStaticFiles-et, azonban az alkalmazás által a buildelés és a közzététel ideje alatt megismert eszközök kiszolgálására van optimalizálva. Ha az alkalmazás más helyekről, például lemezről vagy beágyazott erőforrásokból származó eszközöket szolgál ki, UseStaticFiles kell használni.

MapStaticAssets a következő, a UseStaticFiles-nél nem található előnyöket nyújtja:

  • Időtömörítés létrehozása az alkalmazás összes eszközéhez:
    • gzip a fejlesztés alatt és gzip + brotli a közzététel alatt.
    • Minden eszköz tömörítve van azzal a céllal, hogy az eszközök méretét a lehető legkisebbre csökkentse.
  • Tartalomalapú : Az egyes erőforrásokhoz tartozó a SHA-256 kivonat tartalmának Base64 formátumban kódolt sztringje. Ez biztosítja, hogy a böngésző csak akkor töltse újra újra a fájlt, ha a tartalma megváltozott.

Az alábbi táblázat a CSS és JS fájlok eredeti és tömörített méretét mutatja az alapértelmezett Razor Pages-sablonban:

Fájl Eredeti Tömörített % csökkentés
bootstrap.min.css 163 17.5 89.26%
jquery.js 89.6 28 68.75%
bootstrap.min.js 78.5 20 74.52%
Összes 331.1 65.5 80.20%

Az alábbi táblázat az eredeti és a tömörített méreteket mutatja be a Fluent felhasználói felületi Blazor összetevőtárhasználatával:

Fájl Eredeti Tömörített % csökkentés
fluent.js 384 73 80,99%
fluent.css 94 11 88.30%
Összes 478 84 82.43%

A 478 KB tömörítetlenből 84 KB tömörített lett.

Az alábbi táblázat az eredeti és a tömörített méreteket mutatja be a MudBlazorBlazor összetevőtár használatával:

Fájl Eredeti Tömörített Csökkentés
MudBlazor.min.css 541 37.5 93.07%
MudBlazor.min.js 47.4 9.2 80,59%
Összes 588.4 46.7 92.07%

Az optimalizálás automatikusan történik MapStaticAssetshasználatakor. Ha hozzáad vagy frissít egy kódtárat, például új JavaScript vagy CSS használatával, az eszközök a build részeként lesznek optimalizálva. Az optimalizálás különösen előnyös az alacsonyabb sávszélességű vagy megbízhatatlan kapcsolatokkal rendelkező mobilkörnyezetek számára.

Az új fájlkézbesítési funkciókról az alábbi forrásokból tájékozódhat:

Dinamikus tömörítés engedélyezése a kiszolgálón vs MapStaticAssets használata.

MapStaticAssets a következő előnyökkel rendelkezik a kiszolgáló dinamikus tömörítésével szemben:

  • Egyszerűbb, mert nincs kiszolgálóspecifikus konfiguráció.
  • Nagyobb teljesítményű, mert az objektumok tömörítése a létrehozáskor történik.
  • Lehetővé teszi a fejlesztő számára, hogy a buildelési folyamat során több időt töltsön annak érdekében, hogy az eszközök a minimális méretűek legyenek.

Vegye figyelembe az alábbi táblázatot, amely összehasonlítja a MudBlazor tömörítést az IIS dinamikus tömörítésével és MapStaticAssets:

IIS gzip MapStaticAssets MapStaticAssets csökkentése
≅ 90 37.5 59%

Blazor

Ez a szakasz a Blazorúj funkcióit ismerteti.

.NET MAUI Blazor Hybrid és Web App-megoldássablon

Egy új megoldássablon megkönnyíti .NET MAUI natív és Blazor azonos felhasználói felülettel rendelkező webes ügyfélalkalmazások létrehozását. Ez a sablon bemutatja, hogyan hozhat létre olyan ügyfélalkalmazásokat, amelyek maximalizálják a kód újrafelhasználását és célként az Android, iOS, Mac, Windows és Web rendszert.

A sablon főbb funkciói a következők:

  • A Blazor interaktív renderelési mód kiválasztásának lehetősége a webalkalmazáshoz.
  • A megfelelő projektek automatikus létrehozása, beleértve egy Blazor Web App (globális interaktív automatikus renderelés) és egy .NET MAUIBlazor Hybrid alkalmazás létrehozását.
  • A létrehozott projektek megosztott Razor osztálytárat (RCL) használnak a felhasználói felület Razor összetevőinek karbantartásához.
  • A mintakód bemutatja, hogyan használható függőséginjektálás az Blazor Hybrid alkalmazás és a Blazor Web Appkülönböző felületi implementációinak biztosítására.

Első lépésként telepítse a .NET 9 SDK és telepítse a sablont tartalmazó .NET MAUI számítási feladatot:

dotnet workload install maui

Hozzon létre egy megoldást a projektsablonból egy parancshéjban a következő paranccsal:

dotnet new maui-blazor-web

A sablon a Visual Studióban is elérhető.

Jegyzet

Jelenleg kivétel történik, ha Blazor renderelési módok az oldal/összetevő szintjén vannak definiálva. További információért lásd: a BlazorWebView-nak engedélyeznie kell a ResolveComponentForRenderMode (dotnet/aspnetcore #51235)felülbírálását.

További információért lásd: .NET MAUIBlazor Hybrid alkalmazás létrehozása Blazor Web App.

A renderelési hely, az interaktivitás és a hozzárendelt renderelési mód észlelése futásidőben

Bevezettünk egy új API-t, amely leegyszerűsíti az összetevők állapotainak futásidőben történő lekérdezését. Ez az API a következő képességeket biztosítja:

  • Az összetevő aktuális végrehajtási helyének meghatározása: Ez hasznos lehet az összetevők teljesítményének hibakereséséhez és optimalizálásához.
  • Ellenőrizze, hogy az összetevő interaktív környezetben fut-e: Ez hasznos lehet azoknak az összetevőknek, amelyek a környezetük interaktivitása alapján eltérő viselkedéssel rendelkeznek.
  • Az összetevőhöz rendelt renderelési mód lekérése: A renderelési mód megismerése segíthet a renderelési folyamat optimalizálásában és az összetevők általános teljesítményének javításában.

További információ: ASP.NET Core Blazor renderelési módok.

Továbbfejlesztett kiszolgálóoldali újracsatlakozási élmény:

A következő fejlesztések történtek az alapértelmezett kiszolgálóoldali újracsatlakozási felületen:

  • Amikor a felhasználó egy leválasztott kapcsolatcsoporttal rendelkező alkalmazásra lép vissza, a rendszer azonnal megkísérli az újracsatlakozást ahelyett, hogy a következő újracsatlakozási időköz időtartamára várna. Ez javítja a felhasználói élményt, amikor egy olyan alkalmazásra navigál egy böngészőlapon, amely alvó állapotba került.

  • Amikor egy újracsatlakozási kísérlet eléri a kiszolgálót, de a kiszolgáló már kiadta a kapcsolatot, a lap automatikusan frissül. Ez megakadályozza, hogy a felhasználó manuálisan frissítse a lapot, ha az valószínűleg sikeres újracsatlakozást eredményez.

  • Az újracsatlakozás időzítése egy kiszámított hátrálási stratégiát használ. Alapértelmezés szerint az első több újracsatlakozási kísérlet gyors egymásutánban történik újrapróbálkozási időköz nélkül, mielőtt a kísérletek között kiszámított késések lépnek fel. Az újrapróbálkozási időköz viselkedését úgy szabhatja testre, hogy megad egy függvényt az újrapróbálkozási időköz kiszámításához, ahogy az alábbi exponenciális visszalépési példa is mutatja:

    Blazor.start({
      circuit: {
        reconnectionOptions: {
          retryIntervalMilliseconds: (previousAttempts, maxRetries) => 
            previousAttempts >= maxRetries ? null : previousAttempts * 1000
        },
      },
    });
    
  • Az alapértelmezett újrakapcsolódási felhasználói felület stílusa modernizálva lett.

További információ: ASP.NET Core BlazorSignalR útmutató.

Egyszerűsített hitelesítési állapot szerializálása Blazor Web Apps-hez

Az új API-k megkönnyítik a hitelesítés hozzáadását egy meglévő Blazor Web App. Amikor új Blazor Web App-t hoz létre, hitelesítéssel egyéni fiókok használatával, és engedélyezi a WebAssembly-alapú interaktivitást, a projekt mind a kiszolgáló-, mind az ügyfélprojektek tartalmaz egy egyéni AuthenticationStateProvider-at.

Ezek a szolgáltatók továbbítják a felhasználó hitelesítési állapotát a böngészőbe. Az ügyfél helyett a kiszolgálón történő hitelesítés lehetővé teszi az alkalmazás számára a hitelesítési állapot elérését az előrendelés során és a .NET WebAssembly futtatókörnyezet inicializálása előtt.

Az egyéni AuthenticationStateProvider-implementációk az Állandó összetevő állapota szolgáltatás (PersistentComponentState) használatával szerializálják a hitelesítési állapotot HTML-megjegyzésekké, és a WebAssemblyből olvassák vissza egy új AuthenticationState-példány létrehozásához.

Ez akkor működik jól, ha a Blazor Web App projektsablonból indult, és kiválasztotta az Egyéni fiókok lehetőséget, de sok kóddal valósíthatja meg saját magát, vagy másolhatja, ha hitelesítést próbál hozzáadni egy meglévő projekthez. A Blazor Web App projektsablon részét képező API-k mostantól meghívhatók a kiszolgálói és ügyfélprojektekben a funkció hozzáadásához:

Alapértelmezés szerint az API csak a böngészőben való hozzáférés kiszolgálóoldali nevét és szerepkör-jogcímeit szerializálja. Az összes jogcím belefoglalásához a AddAuthenticationStateSerialization számára megadható egy lehetőség.

További információt a ASP.NET Core Blazor hitelesítés és engedélyezésalábbi szakaszaiban talál:

Statikus kiszolgálóoldali renderelési (SSR-) oldalak hozzáadása egy globálisan interaktívvá váló Blazor Web App-hoz.

A .NET 9 kiadásával mostantól egyszerűbb statikus SSR-oldalakat hozzáadni a globális interaktivitást alkalmazó alkalmazásokhoz.

Ez a módszer csak akkor hasznos, ha az alkalmazás olyan lapokkal rendelkezik, amelyek nem használhatók interaktív kiszolgáló- vagy WebAssembly-rendereléssel. Ez a megközelítés például olyan oldalak esetében alkalmazható, amelyek HTTP-cookie-k olvasásától/írásától függenek, és interaktív renderelés helyett csak kérés-válasz ciklusban működnek. Az interaktív rendereléssel dolgozó lapok esetében nem szabad statikus SSR-renderelésre kényszeríteni őket, mivel az kevésbé hatékony és kevésbé rugalmas a végfelhasználó számára.

Jelölje meg az Razor összetevőlapokat az [ExcludeFromInteractiveRouting] irányelvhez hozzárendelt új @attribute:

@attribute [ExcludeFromInteractiveRouting]

Az attribútum alkalmazása esetén a lapra való navigálás kilép az interaktív útválasztásból. A bejövő navigációnál egy teljes oldalt újra kell tölteni, ahelyett, hogy interaktív útválasztással megoldják az oldalt. A teljes oldal újrabetöltése kényszeríti a legfelső szintű gyökérösszetevőt, általában a App összetevőt (App.razor) a kiszolgálóról való újrarendelésre, lehetővé téve az alkalmazás számára, hogy másik legfelső szintű renderelési módra váltson.

A RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting bővítménymetódus lehetővé teszi, hogy az összetevő észlelje, hogy a [ExcludeFromInteractiveRouting] attribútum van-e alkalmazva az aktuális lapra.

Az App összetevőben használja a következő példában szereplő mintát:

<!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;
}

A RazorComponentsEndpointHttpContextExtensions.AcceptsInteractiveRouting bővítménymetódus használatának alternatívája a végpont metaadatainak manuális olvasása a HttpContext.GetEndpoint()?.Metadatahasználatával.

Ezt a funkciót a ASP.NET Core Blazor renderelési módjának referenciadokumentációjatartalmazza.

Konstruktor injektálás

Razor összetevők támogatják a konstruktorinjektálást.

Az alábbi példában a részleges (kód mögötti) osztály egy NavigationManagerhasználatával injektálja a szolgáltatást:

public partial class ConstructorInjection(NavigationManager navigation)
{
    private void HandleClick()
    {
        navigation.NavigateTo("/counter");
    }
}

További információért lásd a ASP.NET Core Blazor függőség-injektálás.

Websocket-tömörítés interaktív kiszolgáló-összetevőkhöz

Az interaktív kiszolgáló összetevői alapértelmezés szerint lehetővé teszik WebSocket-kapcsolatok tömörítését, és beállítanak egy frame-ancestorstartalombiztonsági szabályzatot (CSP) irányelv 'self', amely csak az alkalmazásnak az alkalmazás forrásának <iframe> való beágyazását teszi lehetővé a tömörítés engedélyezésekor vagy a WebSocket-környezet konfigurációjának megadásakor.

A tömörítés letiltható úgy, hogy ConfigureWebSocketOptionsnullértékre állítja, ami csökkenti az alkalmazás biztonsági rését a támadásához, de csökkentheti a teljesítményt:

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

Konfiguráljon egy szigorúbb frame-ancestors CSP-t 'none' értékkel (egyetlen idézőjel szükséges), amely lehetővé teszi a WebSocket tömörítést, de megakadályozza, hogy a böngészők bármely <iframe>-be ágyazzák az alkalmazást.

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

További információ:

Billentyűzetösszeállítási események kezelése a Blazor

Az új KeyboardEventArgs.IsComposing tulajdonság azt jelzi, hogy a billentyűzetesemény egy összeállítási munkamenet része-e. A billentyűzetesemények összetételének nyomon követése elengedhetetlen a nemzetközi karakterbeviteli módszerek kezeléséhez.

Hozzáadta OverscanCount paramétert a QuickGrid

A QuickGrid összetevő mostantól egy OverscanCount tulajdonságot tesz elérhetővé, amely meghatározza, hogy hány további sor jelenik meg a látható régió előtt és után, amikor engedélyezve van a virtualizálás.

Az alapértelmezett OverscanCount 3. A következő példa a OverscanCount-t 4-re növeli.

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

InputNumber összetevő támogatja a type="range" attribútumot

A InputNumber<TValue> összetevő mostantól támogatja a type="range" attribútumot, amely egy olyan tartománybemenetet hoz létre, amely támogatja a modellkötést és az űrlapérvényesítést, amely általában csúszkaként vagy tárcsázóként jelenik meg szövegdoboz helyett:

<EditForm Model="Model" OnSubmit="Submit" FormName="EngineForm">
    <div>
        <label>
            Nacelle Count (2-6): 
            <InputNumber @bind-Value="Model!.NacelleCount" max="6" min="2" 
                step="1" type="range" />
        </label>
    </div>
    <div>
        <button type="submit">Submit</button>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private EngineSpecifications? Model { get; set; }

    protected override void OnInitialized() => Model ??= new();

    private void Submit() {}

    public class EngineSpecifications
    {
        [Required, Range(minimum: 2, maximum: 6)]
        public int NacelleCount { get; set; }
    }
}

Új továbbfejlesztett navigációs események

JavaScript-visszahívások aktiválása a továbbfejlesztett navigáció előtt vagy után az új eseményfigyelőkkel:

  • blazor.addEventListener("enhancednavigationstart", {CALLBACK})
  • blazor.addEventListener("enhancednavigationend", {CALLBACK})

További információ: ASP.NET Core Blazor JavaScript statikus kiszolgálóoldali rendereléssel (statikus SSR).

SignalR

Ez a szakasz a SignalRúj funkcióit ismerteti.

Polimorf típus támogatás a SignalR csomópontokban

A központi metódusok mostantól elfogadnak egy alaposztályt a származtatott osztály helyett a polimorf forgatókönyvek engedélyezéséhez. Az alaptípust a polimorfizmusengedélyezéséhez jegyzetekkel kell.

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

Továbbfejlesztett tevékenységek SignalR

SignalR most már rendelkezik activitySource-rel a központi kiszolgálóhoz és az ügyfélhez is.

.NET SignalR kiszolgálói ActivitySource

A SignalR ActivitySource nevű Microsoft.AspNetCore.SignalR.Server központi metódushívások eseményeit bocsátja ki:

  • Minden metódus saját tevékenység, így minden, ami a hub metódushívása során tevékenységet bocsát ki, a hub metódus tevékenységéhez tartozik.
  • A központi metódustevékenységek nem rendelkeznek szülővel. Ez azt jelenti, hogy nincsenek csomagolva a hosszútávú SignalR kapcsolat alá.

Az alábbi példa az .NET Aspire irányítópult és a OpenTelemetry csomagokat használja:

<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />

Adja hozzá a következő indítási kódot a Program.cs fájlhoz:

using OpenTelemetry.Trace;
using SignalRChat.Hubs;

// Set OTEL_EXPORTER_OTLP_ENDPOINT environment variable depending on where your OTEL endpoint is.
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddSignalR();

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        if (builder.Environment.IsDevelopment())
        {
            // View all traces only in development environment.
            tracing.SetSampler(new AlwaysOnSampler());
        }

        tracing.AddAspNetCoreInstrumentation();
        tracing.AddSource("Microsoft.AspNetCore.SignalR.Server");
    });

builder.Services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());

var app = builder.Build();

A következő példakimenet az Aspire irányítópultról származik:

SignalR Hub metódushívási eseményeinek tevékenységlistája

.NET SignalR ügyfél tevékenységforrása

A SignalR nevű Microsoft.AspNetCore.SignalR.Client ActivitySource eseményeket bocsát ki egy SignalR-ügyfél számára:

  • A .NET SignalR-ügyfél neve ActivitySourceMicrosoft.AspNetCore.SignalR.Client. A központi meghívások mostantól létrehoznak egy ügyféltartományt. Vegye figyelembe, hogy más SignalR ügyfelek, például a JavaScript-ügyfél nem támogatják a nyomkövetést. Ez a funkció a jövőbeni kiadásokban több ügyfélhez lesz hozzáadva.
  • Az ügyfél és a kiszolgáló központi hívásai támogatják környezetpropagálási. A nyomkövetési környezet propagálása lehetővé teszi a valódi elosztott nyomkövetést. Mostantól megtekintheti az ügyféltől a kiszolgálóig és vissza érkező hívásokat.

Az alábbi módon jelennek meg ezek az új tevékenységek az .NET Aspire irányítópult:

SignalR elosztott nyomkövetés az Aspire vezérlőpulton

SignalR támogatja a vágást és a natív AOT-t

A .NET 8-ban megkezdett natív AOT- folytatásával engedélyeztük a vágást és a natív előzetes (AOT) fordítási támogatást ügyfél- és kiszolgálóforgatókönyvekben is. Most már kihasználhatja a natív AOT használatának teljesítménybeli előnyeit a valós idejű webes kommunikációhoz SignalR használó alkalmazásokban.

Kezdés

Telepítse a legújabb .NET 9 SDK.

Hozzon létre egy megoldást a webapiaot sablonból egy parancshéjban a következő paranccsal:

dotnet new webapiaot -o SignalRChatAOTExample

Cserélje le a Program.cs fájl tartalmát a következő SignalR kódra:

using Microsoft.AspNetCore.SignalR;
using System.Text.Json.Serialization;

var builder = WebApplication.CreateSlimBuilder(args);

builder.Services.AddSignalR();
builder.Services.Configure<JsonHubProtocolOptions>(o =>
{
    o.PayloadSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});

var app = builder.Build();

app.MapHub<ChatHub>("/chatHub");
app.MapGet("/", () => Results.Content("""
<!DOCTYPE html>
<html>
<head>
    <title>SignalR Chat</title>
</head>
<body>
    <input id="userInput" placeholder="Enter your name" />
    <input id="messageInput" placeholder="Type a message" />
    <button onclick="sendMessage()">Send</button>
    <ul id="messages"></ul>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.min.js"></script>
    <script>
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/chatHub")
            .build();

        connection.on("ReceiveMessage", (user, message) => {
            const li = document.createElement("li");
            li.textContent = `${user}: ${message}`;
            document.getElementById("messages").appendChild(li);
        });

        async function sendMessage() {
            const user = document.getElementById("userInput").value;
            const message = document.getElementById("messageInput").value;
            await connection.invoke("SendMessage", user, message);
        }

        connection.start().catch(err => console.error(err));
    </script>
</body>
</html>
""", "text/html"));

app.Run();

[JsonSerializable(typeof(string))]
internal partial class AppJsonSerializerContext : JsonSerializerContext { }

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

Az előző példa egy 10 MB-os natív Windows-futtatást és egy 10,9 MB-os Linux-futtatást eredményez.

Korlátozások

  • Jelenleg csak a JSON protokoll támogatott:
    • Az előző kódban látható módon a JSON szerializálást és natív AOT-t használó alkalmazásoknak a System.Text.Json Forrásgenerátort kell használniuk.
    • Ez ugyanazt a megközelítést követi, mint a minimális API-k.
  • A SignalR kiszolgálón nem támogatottak az olyan IAsyncEnumerable<T> és ChannelReader<T> típusú hubmetódus-paraméterek, ahol a T ValueType (struct) típusú. Az ilyen típusok használata futásidejű kivételt eredményez a fejlesztés indításakor és a közzétett alkalmazásban. További információért, nézze meg: SignalR: Az IAsyncEnumerable<T> és a ChannelReader<T> használata natív AOT-beli értéktípusokkal (dotnet/aspnetcore #56179).
  • Az erősen gépelt hubok nem támogatottak a natív AOT (PublishAot) használatával. Az erősen gépelt célhelyek natív AOT-val való használata figyelmeztetéseket eredményez a buildelés és a közzététel során, valamint futásidejű kivételt okozhat. Az erősen típusos hubok használata trimmeléssel (PublishedTrimmed) támogatott.
  • Az aszinkron visszatérési típusok csak Task, Task<T>, ValueTaskvagy ValueTask<T> támogatottak.

Minimális API-k

Ez a szakasz a minimális API-k új funkcióit ismerteti.

Hozzáadtuk InternalServerError-t és InternalServerError<TValue>-t a TypedResults-höz

A TypedResults osztály egy hasznos eszköz, amely egy minimális API-ból származó, erősen gépelt HTTP-állapotkódon alapuló válaszokat ad vissza. TypedResults mostantól gyári metódusokat és típusokat is tartalmaz az "500 belső kiszolgálóhiba" válaszok végpontokról való visszaadására. Íme egy példa, amely 500 választ ad vissza:

var app = WebApplication.Create();

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

app.Run();

Hívás ProducesProblem és ProducesValidationProblem útvonalcsoportokon

A ProducesProblem és ProducesValidationProblem kiterjesztési módszereket frissítették azon való használatuk támogatására az útvonalcsoportokon. Ezek a módszerek azt jelzik, hogy egy útvonalcsoport összes végpontja ProblemDetails vagy ValidationProblemDetails válaszokat adhat vissza OpenAPI-metaadatok céljából.

var app = WebApplication.Create();

var todos = app.MapGroup("/todos")
    .ProducesProblem();

todos.MapGet("/", () => new Todo(1, "Create sample app", false));
todos.MapPost("/", (Todo todo) => Results.Ok(todo));

app.Run();

record Todo(int Id, string Title, boolean IsCompleted);

Problem és ValidationProblem eredménytípusok támogatják az IEnumerable<KeyValuePair<string, object?>> értékekkel való építkezést

A .NET 9 előtt a probléma és ValidationProblem eredménytípusok minimális API-kban történő létrehozásához a errors és extensions tulajdonságok inicializálása szükséges a IDictionary<string, object?>implementációjával. Ebben a kiadásban ezek az építési API-k támogatják a IEnumerable<KeyValuePair<string, object?>>-t használó túlterheléseket is.

var app = WebApplication.Create();

app.MapGet("/", () =>
{
    var extensions = new List<KeyValuePair<string, object?>> { new("test", "value") };
    return TypedResults.Problem("This is an error with extensions",
                                                       extensions: extensions);
});

Köszönet a GitHub felhasználói joegoldman2 a hozzájárulásért!

OpenAPI

Ez a szakasz az OpenAPI új funkcióit ismerteti

Az OpenAPI-dokumentumlétrehozás beépített támogatása

A OpenAPI-specifikáció a HTTP API-k leírásának szabványa. A szabvány lehetővé teszi a fejlesztők számára, hogy meghatározzák az ügyfélgenerátorokhoz, kiszolgálógenerátorokhoz, tesztelési eszközökhöz, dokumentációhoz stb. csatlakoztatható API-k alakját. A .NET 9-ben a ASP.NET Core beépített támogatást nyújt a vezérlőalapú vagy minimális API-kat képviselő OpenAPI-dokumentumok létrehozásához a Microsoft.AspNetCore.OpenApi csomagon keresztül.

A következő kiemelt kódhívások:

  • AddOpenApi regisztrálni a szükséges függőségeket az alkalmazás DI-tárolójában.
  • MapOpenApi regisztrálni a szükséges OpenAPI-végpontokat az alkalmazás útvonalai között.
var builder = WebApplication.CreateBuilder();

builder.Services.AddOpenApi();

var app = builder.Build();

app.MapOpenApi();

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

app.Run();

Telepítse a Microsoft.AspNetCore.OpenApi csomagot a projektben az alábbi paranccsal:

dotnet add package Microsoft.AspNetCore.OpenApi

Futtassa az alkalmazást, és lépjen a(z) openapi/v1.json-ra, a létrehozott OpenAPI-dokumentum megtekintéséhez.

OpenAPI-dokumentum

Az OpenAPI-dokumentumok buildeléskor is létrehozhatók a Microsoft.Extensions.ApiDescription.Server csomag hozzáadásával:

dotnet add package Microsoft.Extensions.ApiDescription.Server

A kibocsátott OpenAPI-dokumentumok helyének módosításához állítsa be a cél elérési utat az alkalmazás projektfájljában lévő OpenApiDocumentsDirectory tulajdonságban:

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

Futtassa dotnet build, és vizsgálja meg a létrehozott JSON-fájlt a projektkönyvtárban.

OpenAPI-dokumentum létrehozása buildelési időben

ASP.NET Core beépített OpenAPI-dokumentumgenerációja számos testreszabási és beállítási lehetőséget támogat. Dokumentum-, művelet- és sématranszformátorokat biztosít, és több OpenAPI-dokumentumot is kezelhet ugyanahhoz az alkalmazáshoz.

Ha többet szeretne megtudni ASP.NET Core új OpenAPI-dokumentum képességeiről, tekintse meg az új Microsoft.AspNetCore.OpenApi dokumentumokat.

A Microsoft.AspNetCore.OpenApi támogatja a vágást és a natív AOT-t

Az OpenAPI a ASP.NET Core-ban támogatja a vágást és a natív AOT-t. Az alábbi lépések egy OpenAPI-alkalmazást hoznak létre és tesznek közzé kódtrimmeléssel és natív AOT használatával:

Hozzon létre egy új ASP.NET Core Web API-projektet (natív AOT-projektet).

dotnet new webapiaot

Adja hozzá a Microsoft.AspNetCore.OpenAPI csomagot.

dotnet add package Microsoft.AspNetCore.OpenApi

Frissítse a(z) Program.cs elemet az OpenAPI-dokumentumok létrehozásának engedélyezéséhez.

+ builder.Services.AddOpenApi();

var app = builder.Build();

+ app.MapOpenApi();

Tegye közzé az alkalmazást.

dotnet publish

Hitelesítés és engedélyezés

Ez a szakasz a hitelesítés és az engedélyezés új funkcióit ismerteti.

Az OpenIdConnectHandler támogatja a leküldéses engedélyezési kérelmeket (PAR)

Szeretnénk köszönetet mondani Joe DeCockDuende Software-tól, amiért továbbított engedélykérelmeket (PAR) adott hozzá az ASP.NET Core OpenIdConnectHandler-hez. Joe a API-javaslatában a PAR engedélyezésének hátterét és motivációját az alábbiak szerint írta le:

A leküldéses engedélyezési kérelmek (PAR) egy viszonylag új OAuth szabvány, amely javítja az OAuth- és OIDC-folyamatok biztonságát azáltal, hogy az engedélyezési paramétereket az első csatornáról a hátsó csatornára helyezi át. Vagyis az engedélyezési paraméterek áthelyezése a böngészőben lévő átirányítási URL-címekről a háttérrendszeren történő közvetlen gép-gép közötti HTTP-kapcsolatokra.

Ez megakadályozza, hogy egy kibertámadó a böngészőben a következőket tegye:

  • Engedélyezési paramétereket lát, amelyek kiszivároghatnak a PII-ből.
  • A paraméterek illetéktelen módosítása. A kibertámadás például megváltoztathatja a kért hozzáférés hatókörét.

Az engedélyezési paraméterek átvitele a kérelem URL-címeinek rövidségét is biztosítja. Az engedélyezési paraméterek nagyon hosszú ideig tarthatnak, ha összetettebb OAuth- és OIDC-funkciókat használnak, például Rich Authorization Requests. Azok az URL-címek, amelyek hosszú ideig okoznak problémákat számos böngészőben és hálózati infrastruktúrában.

A PAR használatát az OpenID Foundation FAPI munkacsoportja támogatja. Például a FAPI2.0 Biztonsági Profil a PAR használatát igényli. Ezt a biztonsági profilt számos olyan csoport használja, amelyek nyílt banki szolgáltatásokon dolgoznak (elsősorban Európában), az egészségügyben és más, magas biztonsági követelményekkel rendelkező iparágakban.

A PAR-t számos identitásszolgáltató támogatja, beleértve a

A .NET 9 esetében úgy döntöttünk, hogy alapértelmezés szerint engedélyezi a PAR-t, ha az identitásszolgáltató felderítési dokumentuma támogatja a PAR szolgáltatást, mivel fokozott biztonságot kell nyújtania az azt támogató szolgáltatók számára. Az identitásszolgáltató felderítési dokumentuma általában a következő helyen található: .well-known/openid-configuration. Ha ez problémákat okoz, a PAR letiltható az alábbiak szerint: OpenIdConnectOptions.PushedAuthorizationBehavior.

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect("oidc", oidcOptions =>
    {
        // Other provider-specific configuration goes here.

        // The default value is PushedAuthorizationBehavior.UseIfAvailable.

        // 'OpenIdConnectOptions' does not contain a definition for 'PushedAuthorizationBehavior'
        // and no accessible extension method 'PushedAuthorizationBehavior' accepting a first argument
        // of type 'OpenIdConnectOptions' could be found
        oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
    });

Annak érdekében, hogy a hitelesítés csak PAR használata esetén legyen sikeres, használja PushedAuthorizationBehavior.Require. Ez a módosítás egy új OnPushAuthorization eseményt is bevezet az OpenIdConnectEvents , amely a leküldéses engedélyezési kérelem testreszabására vagy manuális kezelésére használható. További részletekért tekintse meg a API-javaslat.

OIDC és OAuth paraméter testreszabása

Az OAuth- és OIDC-hitelesítési kezelők mostantól AdditionalAuthorizationParameters beállítással egyszerűbben testre szabhatják azokat az engedélyezési üzenetparamétereket, amelyek általában az átirányítási lekérdezési sztring részeként szerepelnek. A .NET 8-ban és a korábbi verziókban ehhez egyéni OnRedirectToIdentityProvider visszahívásra vagy felülrekedt BuildChallengeUrl metódusra van szükség egy egyéni kezelőben. Íme egy példa a .NET 8-kódra:

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

Az előző példa mostantól egyszerűsíthető a következő kódra:

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

Kiterjesztett hitelesítési jelzők konfigurálása HTTP.sys

Most már konfigurálhatja a HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING és HTTP_AUTH_EX_FLAG_CAPTURE_CREDENTIAL HTTP.sys jelzőket a HTTP.sys EnableKerberosCredentialCaching új CaptureCredentials és AuthenticationManager tulajdonságaival a Windows-hitelesítés kezelésének optimalizálása érdekében. Például:

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

Vegyes

A következő szakaszok a különböző új funkciókat ismertetik.

Új HybridCache könyvtár

Fontos

jelenleg még előzetes verzió, de után a .NET 9.0-s verzióban egy későbbi, kisebb .NET-bővítmény kiadásban teljesen ki lesz adva.

A HybridCache API áthidal néhány rést a meglévő IDistributedCache és IMemoryCache API-kban. Emellett új képességeket is kínál, például:

  • "Stampede" védelem, hogy megakadályozza ugyanannak a munkának a párhuzamos lekérését.
  • Konfigurálható szerializálás.

A HybridCache a meglévő IDistributedCache és IMemoryCache használat legördülő helyére lett tervezve, és egy egyszerű API-t biztosít az új gyorsítótárazási kód hozzáadásához. Egységes API-t biztosít a folyamatban lévő és a folyamaton kívüli gyorsítótárazáshoz is.

A HybridCache API leegyszerűsítéséhez hasonlítsa össze a IDistributedCachehasználó kóddal. Íme egy példa a IDistributedCache használatára:

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)
    { /* ... */ }
}

Ez sok munka minden alkalommal, beleértve a szerializálást is. A gyorsítótár-kihagyási forgatókönyvben több egyidejű szál is lehet, amelyek mindegyikük cache-hibát szenved el, mindegyikük beolvassa a háttéradatokat, szerializálják őket, majd mindegyikük elküldi az adatokat a gyorsítótárba.

A kód HybridCachehasználatával történő egyszerűsítése és fejlesztése érdekében először hozzá kell adnunk az új kódtárat Microsoft.Extensions.Caching.Hybrid:

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

Regisztrálja a HybridCache szolgáltatást, mintha egy IDistributedCache implementációt regisztrálna:

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

Most a legtöbb gyorsítótárazási problémát át lehet helyezni 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
        );
    }
}

A HybridCache absztrakt osztály konkrét implementációját függőséginjektálással biztosítjuk, de a fejlesztőknek egyéni implementációkat kell biztosítaniuk az API-hoz. A HybridCache implementáció a gyorsítótárazással kapcsolatos mindennel foglalkozik, beleértve az egyidejű műveletkezelést is. Az token itt az összes egyidejű hívó együttes lemondását jelenti – nem csak annak a hívónak a lemondását, akit látunk (azaz ).

A nagy átviteli sebességű forgatókönyvek tovább optimalizálhatók a TState mintával, így elkerülhető a rögzített változók és példányonkénti visszahívások terhelése:

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 a konfigurált IDistributedCache implementációt használja, ha van ilyen, a másodlagos folyamaton kívüli gyorsítótárazáshoz, például a Redis használatával. De még IDistributedCachenélkül is a HybridCache szolgáltatás továbbra is biztosítja a folyamat közbeni gyorsítótárazást és a "túlterhelési" védelmet.

Megjegyzés az objektumok újrafelhasználásával kapcsolatban

A IDistributedCachehasználó tipikus meglévő kódban egy objektum gyorsítótárból való minden lekérése deszerializálást eredményez. Ez a viselkedés azt jelenti, hogy minden egyidejű hívó külön példányt kap az objektumból, amely nem tud más példányokkal kommunikálni. Az eredmény a szálbiztonság, mivel nem áll fenn az ugyanazon objektumpéldány egyidejű módosításának kockázata.

Mivel sok HybridCache használat lesz adaptálva a meglévő IDistributedCache kódból, HybridCache alapértelmezés szerint megőrzi ezt a viselkedést az egyidejűségi hibák elkerülése érdekében. Azonban egy bizonyos használati eset eredendően szálbiztos.

  • Ha a gyorsítótárazott típusok nem módosíthatók.
  • Ha a kód nem módosítja őket.

Ilyen esetekben tájékoztassa HybridCache, hogy biztonságosan újra felhasználhatja a példányokat a következő módon:

  • A sealedtípus megjelölése. A C# sealed kulcsszó azt jelenti, hogy az osztály nem örökölhető.
  • A [ImmutableObject(true)] attribútum alkalmazása rá. A [ImmutableObject(true)] attribútum azt jelzi, hogy az objektum állapota nem módosítható a létrehozása után.

A példányok újrafelhasználásával HybridCache csökkentheti a hívásonkénti deszerializálással társított processzor- és objektumfoglalások többletterhelését. Ez teljesítménybeli javuláshoz vezethet olyan esetekben, amikor a gyorsítótárazott objektumok nagy méretűek vagy gyakran érhetők el.

Egyéb HybridCache funkciók

A IDistributedCache-hez hasonlóan a HybridCache is támogatja a kulcs szerinti eltávolítást egy RemoveKeyAsync metódussal.

HybridCache opcionális API-kat is biztosít IDistributedCache implementációkhoz a byte[] lefoglalások elkerülése érdekében. Ezt a funkciót a Microsoft.Extensions.Caching.StackExchangeRedis és Microsoft.Extensions.Caching.SqlServer csomagok előzetes verziói implementálják.

A szerializálás a szolgáltatás regisztrálásának részeként van konfigurálva, és támogatja a típusspecifikus és általános szerializálókat a WithSerializer és .WithSerializerFactory metódusok segítségével, a AddHybridCache hívástól láncolt módon. Alapértelmezés szerint a kódtár belsőleg kezeli string és byte[], és minden máshoz System.Text.Json használ, de használhat protobuf, xml vagy bármi mást.

HybridCache támogatja a régebbi .NET rendszereket, egészen a .NET Framework 4.7.2-ig és a .NET Standard 2.0-ig.

További információkért a HybridCache-ról tekintse meg a HybridCache-könyvtárat az ASP.NET Core-ben.

Fejlesztői kivételkezelő oldal fejlesztései

A ASP.NET Core fejlesztői kivétellap jelenik meg, amikor egy alkalmazás kezeletlen kivételt dob a fejlesztés során. A fejlesztői kivételoldal részletes információkat nyújt a kivételről és a kérésről.

A 3. előzetes verzió hozzáadta a végpont metaadatait a fejlesztői kivételoldalhoz. ASP.NET Core végponti metaadatokat használ a végpont viselkedésének szabályozásához, például útválasztás, válasz gyorsítótárazása, sebességkorlátozás, OpenAPI-generálás stb. Az alábbi képen a fejlesztői kivételoldal Routing szakaszában található új metaadat-információk láthatók:

A fejlesztői kivételoldal új metaadat-információi

A fejlesztői kivételoldal tesztelése során a rendszer kis életminőség-javulást észlelt. A 4. előzetes verzióban lettek szállítva:

  • Jobb szövegburkolás. A hosszú cookie-k, a lekérdezési sztringértékek és a metódusnevek többé nem adnak hozzá vízszintes böngésző görgetősávokat.
  • A modern dizájnokban található nagyobb szöveg.
  • Konzisztensebb táblázatméretek.

Az alábbi animált képen az új fejlesztői kivétellap látható:

Az új fejlesztői kivételoldal

A szótár hibakeresési fejlesztései

A szótárak és más kulcs-érték gyűjtemények hibakeresési megjelenítése továbbfejlesztett elrendezést biztosít. A kulcs a hibakereső kulcsoszlopában jelenik meg ahelyett, hogy összefűzne az értékkel. Az alábbi képeken egy szótár régi és új megjelenítése látható a hibakeresőben.

Előtt:

Az előző hibakeresői élmény

Után:

Az új hibakeresői élmény

ASP.NET Core számos kulcs-érték gyűjteményből áll. Ez a továbbfejlesztett hibakeresési felület a következőkre vonatkozik:

  • HTTP-fejlécek
  • Lekérdezési sztringek
  • Formák
  • Sütik
  • Adatok megtekintése
  • Útvonal adatok
  • Funkciók

A 503-as hibára vonatkozó javítás az IIS-ben történő alkalmazás újraindítása során

Alapértelmezés szerint 1 másodperces késés áll fenn, amikor az IIS értesítést kap az újrahasznosításról vagy a leállításról, és amikor az ANCM arra utasítja a felügyelt kiszolgálót, hogy kezdjen leállni. A késés a ANCM_shutdownDelay környezeti változóval vagy a shutdownDelay kezelőbeállításával konfigurálható. Mindkét érték ezredmásodpercben van. A késés elsősorban egy olyan verseny valószínűségének csökkentése, ahol:

  • Az IIS nem indította el a sorba állítási kérelmeket az új alkalmazásba való ugráshoz.
  • Az ANCM elkezdi elutasítani a régi alkalmazásba érkező új kéréseket.

Előfordulhat, hogy a lassabb gépek vagy a nagyobb processzorhasználattal rendelkező gépek ezt az értéket az 503-ra való valószínűség csökkentése érdekében módosítani szeretnék.

Példa a shutdownDelaybeállítására:

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

A javítás a globálisan telepített ANCM-modulban található, amely az üzemeltetési csomagból származik.

ASP0026: Az analizátor figyelmeztet, ha az [Authorize] felülbírálva van egy távolabbi [AllowAnonymous] által.

Magától értetődőnek tűnik, hogy egy [Authorize] attribútum, amely közelebb van egy MVC-művelethez, mint egy [AllowAnonymous] attribútum, felülírja a [AllowAnonymous] attribútumot és kényszeríti az engedélyezést. Ez azonban nem feltétlenül igaz. Az attribútumok relatív sorrendje számít.

Az alábbi kód olyan példákat mutat be, ahol egy közelebbi [Authorize] attribútumot felülír egy távolabbi [AllowAnonymous] attribútum.

[AllowAnonymous]
public class MyController
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on the class
    public IActionResult Private() => null;
}
[AllowAnonymous]
public class MyControllerAnon : ControllerBase
{
}

[Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
public class MyControllerInherited : MyControllerAnon
{
}

public class MyControllerInherited2 : MyControllerAnon
{
    [Authorize] // Overridden by the [AllowAnonymous] attribute on MyControllerAnon
    public IActionResult Private() => null;
}
[AllowAnonymous]
[Authorize] // Overridden by the preceding [AllowAnonymous]
public class MyControllerMultiple : ControllerBase
{
}

A .NET 9 6. előzetes verziójában bevezettünk egy elemzőt, amely az ilyen példányokat emeli ki, ahol egy közelebbi [Authorize] attribútum felülbírálásra kerül egy MVC-művelettől távolabb eső [AllowAnonymous] attribútummal. A figyelmeztetés a felülírt [Authorize] attribútumra mutat az alábbi üzenettel:

ASP0026 [Authorize] overridden by [AllowAnonymous] from farther away

Ha ezt a figyelmeztetést látja, a megfelelő művelet az attribútumok mögötti szándéktól függ. A távolabbi [AllowAnonymous] attribútumot el kell távolítani, ha véletlenül felfedi a végpontot névtelen felhasználóknak. Ha a [AllowAnonymous] attribútum egy közelebbi [Authorize] attribútum felülbírálásához készült, a szándék tisztázásához ismételje meg a [AllowAnonymous] attribútumot a [Authorize] attribútum után.

[AllowAnonymous]
public class MyController
{
    // This produces no warning because the second, "closer" [AllowAnonymous]
    // clarifies that [Authorize] is intentionally overridden.
    // Specifying AuthenticationSchemes can still be useful
    // for endpoints that allow but don't require authenticated users.
    [Authorize(AuthenticationSchemes = "Cookies")]
    [AllowAnonymous]
    public IActionResult Privacy() => null;
}

Továbbfejlesztett Kestrel kapcsolati metrikák

Jelentősen javítottuk Kestrelkapcsolati metrikáit azáltal, hogy metaadatokat is felveszünk arról, hogy miért hiúsult meg a kapcsolat. A kestrel.connection.duration metrika mostantól tartalmazza a kapcsolat szoros okát a error.type attribútumban.

Íme egy kis minta az error.type értékekből:

  • tls_handshake_failed – A kapcsolathoz TLS szükséges, és a TLS-kézfogás sikertelen volt.
  • connection_reset – Az ügyfél váratlanul bezárta a kapcsolatot, miközben a kérések folyamatban voltak.
  • request_headers_timeout – Kestrel bezárta a kapcsolatot, mert nem kapott időben kérésfejléceket.
  • max_request_body_size_exceeded – Kestrel lezárta a kapcsolatot, mert a feltöltött adatok mérete meghaladta a maximális méretet.

Korábban a Kestrel kapcsolati problémák diagnosztizálásához a kiszolgálónak részletes, alacsony szintű naplózást kellett rögzítenie. A naplók létrehozása és tárolása azonban költséges lehet, és nehéz lehet megtalálni a megfelelő információkat a zaj között.

A metrikák sokkal olcsóbb alternatívát jelentenek, amelyet minimális hatással lehet folyamatosan működtetni az éles környezetben. Az összegyűjtött metrikák meghajtó irányítópultokat és riasztásokat. Ha a metrikákkal kapcsolatos magas szintű probléma merül fel, a naplózással és más eszközökkel végzett további vizsgálat megkezdődhet.

A továbbfejlesztett kapcsolati metrikák számos esetben hasznosak lehetnek:

  • A rövid kapcsolati élettartamok által okozott teljesítményproblémák vizsgálata.
  • A teljesítményre és stabilitásra hatással lévő Kestrel elleni folyamatos külső támadások megfigyelése.
  • A felvétel olyan külső támadásokat kísérelt meg Kestrel, amelyek Kestrelbeépített biztonsági megkeményedése megakadályozva.

További információ: ASP.NET Alapvető metrikák.

Kestrel nevesített csővégpontok testreszabása

Kestrelnévvel ellátott cső támogatása továbbfejlesztésre került speciális testreszabási lehetőségekkel. A nevesített csőbeállítások új CreateNamedPipeServerStream metódusa lehetővé teszi a csövek végpontonkénti testreszabását.

Erre példa egy Kestrel alkalmazás, amely két különböző hozzáférési biztonságirendelkező csővégpontot igényel. A CreateNamedPipeServerStream beállítással a cső nevétől függően egyéni biztonsági beállításokkal rendelkező csövek hozhatók létre.

var builder = WebApplication.CreateBuilder();

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenNamedPipe("pipe1");
    options.ListenNamedPipe("pipe2");
});

builder.WebHost.UseNamedPipes(options =>
{
    options.CreateNamedPipeServerStream = (context) =>
    {
        var pipeSecurity = CreatePipeSecurity(context.NamedPipeEndpoint.PipeName);

        return NamedPipeServerStreamAcl.Create(context.NamedPipeEndPoint.PipeName, PipeDirection.InOut,
            NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte,
            context.PipeOptions, inBufferSize: 0, outBufferSize: 0, pipeSecurity);
    };
});

ExceptionHandlerMiddleware lehetőség az állapotkód kivételtípus alapján történő kiválasztására

A ExceptionHandlerMiddleware konfigurálásakor egy új lehetőség lehetővé teszi, hogy az alkalmazásfejlesztők kiválasztják, milyen állapotkódot adjanak vissza, amikor kivétel történik a kérések kezelése során. Az új beállítás módosítja a ProblemDetailsExceptionHandlerMiddlewareválaszában beállított állapotkódot.

app.UseExceptionHandler(new ExceptionHandlerOptions
{
    StatusCodeSelector = ex => ex is TimeoutException
        ? StatusCodes.Status503ServiceUnavailable
        : StatusCodes.Status500InternalServerError,
});

HTTP-metrikák letiltása bizonyos végpontokon és kéréseken

A .NET 9 lehetővé teszi a HTTP-metrikák letiltását adott végpontok és kérések esetében. A metrikák rögzítésének letiltása előnyös az automatizált rendszerek által gyakran hívott végpontok, például az állapot-ellenőrzések esetében. Ezeknek a kéréseknek a metrikáinak rögzítése általában szükségtelen.

A végpontra irányuló HTTP-kérések metaadatok hozzáadásával kizárhatók a metrikákból. Vagy:

  • Adja hozzá a [DisableHttpMetrics] attribútumot a webes API-vezérlőhöz, SignalR központhoz vagy gRPC szolgáltatáshoz.
  • Hívás DisableHttpMetrics az alkalmazás indításakor a végpontok leképezésekor:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHealthChecks();

var app = builder.Build();
app.MapHealthChecks("/healthz").DisableHttpMetrics();
app.Run();

A MetricsDisabled tulajdonság hozzá lett adva a következőhöz: IHttpMetricsTagsFeature.

  • Speciális forgatókönyvek, ahol a kérések nem vezetnek végponthoz.
  • A metrikák gyűjteményének dinamikus letiltása adott HTTP-kérésekhez.
// Middleware that conditionally opts-out HTTP requests.
app.Use(async (context, next) =>
{
    var metricsFeature = context.Features.Get<IHttpMetricsTagsFeature>();
    if (metricsFeature != null &&
        context.Request.Headers.ContainsKey("x-disable-metrics"))
    {
        metricsFeature.MetricsDisabled = true;
    }

    await next(context);
});

Adatvédelmi támogatás kulcsok törléséhez

A .NET 9-et megelőzően az adatvédelmi kulcsok nem törölhetők a terv szerint, hogy megelőzzék az adatvesztést. A kulcs törlése visszavonhatatlanná teszi a védett adatokat. Kis méretük miatt ezeknek a kulcsoknak a felhalmozódása általában minimális hatást gyakorolt. A rendkívül hosszú ideig futó szolgáltatások fogadására azonban bevezettük a kulcsok törlésének lehetőségét. Általában csak a régi kulcsokat kell törölni. Csak akkor törölje a kulcsokat, ha el tudja fogadni az adatvesztés kockázatát a tárolási megtakarításokért cserébe. Javasoljuk, hogy ne törölje az adatvédelmi kulcsokat.

using Microsoft.AspNetCore.DataProtection.KeyManagement;

var services = new ServiceCollection();
services.AddDataProtection();

var serviceProvider = services.BuildServiceProvider();

var keyManager = serviceProvider.GetService<IKeyManager>();

if (keyManager is IDeletableKeyManager deletableKeyManager)
{
    var utcNow = DateTimeOffset.UtcNow;
    var yearAgo = utcNow.AddYears(-1);

    if (!deletableKeyManager.DeleteKeys(key => key.ExpirationDate < yearAgo))
    {
        Console.WriteLine("Failed to delete keys.");
    }
    else
    {
        Console.WriteLine("Old keys deleted successfully.");
    }
}
else
{
    Console.WriteLine("Key manager does not support deletion.");
}

A köztes szoftver támogatja a keyed DI-t

A Middleware mostantól a konstruktorban és a Invoke/ metódusban is támogatja a InvokeAsync.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddKeyedSingleton<MySingletonClass>("test");
builder.Services.AddKeyedScoped<MyScopedClass>("test2");

var app = builder.Build();
app.UseMiddleware<MyMiddleware>();
app.Run();

internal class MyMiddleware
{
    private readonly RequestDelegate _next;

    public MyMiddleware(RequestDelegate next,
        [FromKeyedServices("test")] MySingletonClass service)
    {
        _next = next;
    }

    public Task Invoke(HttpContext context,
        [FromKeyedServices("test2")]
            MyScopedClass scopedService) => _next(context);
}

Bízzon az ASP.NET Core HTTPS fejlesztői tanúsítványban Linuxon

Az Ubuntu- és Fedora-alapú Linux-disztribúciókon dotnet dev-certs https --trust mostantól megbízható tanúsítványként konfigurálja ASP.NET Core HTTPS fejlesztési tanúsítványt a következőkhöz:

  • Chromium böngészők, például Google Chrome, Microsoft Edge és Chromium.
  • Mozilla Firefox és Mozilla származtatott böngészők.
  • .NET API-k, például HttpClient

Korábban --trust csak Windows és macOS rendszeren működött. A rendszer felhasználónként alkalmazza a tanúsítványmegbízhatóságot.

Az OpenSSL-ben való bizalom kialakításához az dev-certs eszköz:

A dotnetbe vetett bizalom létrehozásához az eszköz a tanúsítványt a My/Root tanúsítványtárolóba helyezi.

Az NSS-adatbázisokmegbízhatóságának kialakításához, ha van ilyen, az eszköz megkeresi a saját könyvtárban a Firefox-profilokat, ~/.pki/nssdbés ~/snap/chromium/current/.pki/nssdb. Az eszköz minden talált könyvtárhoz hozzáad egy bejegyzést a nssdb-ba.

A legújabb Bootstrap-, jQuery- és jQuery-érvényesítési verziókra frissített sablonok

A ASP.NET Core-projektsablonok és -kódtárak a Bootstrap, a jQuery és a jQuery Validation legújabb verzióinak használatára lettek frissítve, különösen a következőkkel:

  • Bootstrap 5.3.3
  • jQuery 3.7.1
  • jQuery validation 1.21.0