Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel worden de belangrijkste wijzigingen in ASP.NET Core in .NET 10 gemarkeerd met koppelingen naar relevante documentatie.
Raadpleeg de Breaking changes in .NET voor ingrijpende wijzigingen.
Blazor
In deze sectie worden nieuwe functies voor Blazorbeschreven.
Nieuwe en bijgewerkte Blazor Web App beveiligingsvoorbeelden
De beveiligingsvoorbeelden die zijn gekoppeld aan de volgende artikelen, zijn toegevoegd en bijgewerkt Blazor Web App :
- Een ASP.NET Core Blazor Web App beveiligen met OpenID Connect (OIDC)
- Een ASP.NET Core Blazor Web App beveiligen met Microsoft Entra-id
- Een ASP.NET Core Blazor Web App beveiligen met Windows-verificatie
Al onze OIDC- en Entra-voorbeeldoplossingen bevatten nu een afzonderlijk web-API-project (MinimalApiJwt) om te laten zien hoe u een externe web-API veilig configureert en aanroept. Het oproepen van web-API's wordt gedemonstreerd met een tokenhandler en een benoemde HTTP-client voor een OIDC-identiteitsprovider of Microsoft Identity Webpakketten/API voor Microsoft Entra ID.
De voorbeeldoplossingen worden geconfigureerd in C#-code in hun Program bestanden. Zie de sectie appsettings.jsonConfiguratie leveren met de JSON-configuratieprovider (app-instellingen) in de OIDC- of Entra-artikelen om de oplossingen te configureren vanuit app-instellingenbestanden (bijvoorbeeld ).
Ons Entra-artikel en voorbeeld-apps bevatten ook nieuwe richtlijnen voor de volgende benaderingen:
- Een versleutelde gedistribueerde tokencache gebruiken voor hostingscenario's in webfarms.
- Azure Key Vault gebruiken met Azure Managed Identities voor gegevensbeveiliging.
parameter QuickGridRowClass
Pas een opmaakmodelklasse toe op een rij van de grid op basis van het item van de rij met behulp van de nieuwe parameter RowClass. In het volgende voorbeeld wordt de methode GetRowCssClass aangeroepen op elke rij om voorwaardelijk een stijlklasse toe te passen op basis van het item in de rij.
<QuickGrid ... RowClass="GetRowCssClass">
...
</QuickGrid>
@code {
private string GetRowCssClass(MyGridItem item) =>
item.IsArchived ? "row-archived" : null;
}
Zie ASP.NET Core BlazorQuickGridcomponentvoor meer informatie.
Blazor script als statisch webbestand
In eerdere versies van .NET wordt het Blazor-script geleverd vanuit een ingesloten resource in het gedeelde ASP.NET Core-framework. In .NET 10 of hoger wordt het Blazor-script geleverd als een statische webasset met automatische compressie en vingerafdruk.
Het Blazor script (blazor.web.js of blazor.server.js) wordt opgenomen in het framework als het project ten minste één Razor onderdeelbestand (.razor) bevat. Als uw app het Blazor script vereist, maar niet ten minste één onderdeel bevat, voegt u de volgende MSBuild-eigenschap toe aan het projectbestand van de app om onvoorwaardelijke scriptopname af te dwingen:
<RequiresAspNetWebAssets>true</RequiresAspNetWebAssets>
Zie de volgende bronnen voor meer informatie:
Hoogtepunten van routesjabloon
Het kenmerk [Route] ondersteunt nu markering van routesyntaxis om de structuur van de routesjabloon te visualiseren:
NavigateTo scrollt niet meer naar boven bij navigaties op dezelfde pagina
Eerder scrolde NavigationManager.NavigateTo naar boven op de pagina voor navigaties op dezelfde pagina. Dit gedrag is gewijzigd in .NET 10, zodat de browser niet meer naar de bovenkant van de pagina schuift wanneer u naar dezelfde pagina navigeert. Dit betekent dat de viewport niet meer opnieuw wordt ingesteld bij het bijwerken van het adres voor de huidige pagina, zoals het wijzigen van de querytekenreeks of het fragment.
Reconnection-UI-component toegevoegd aan het Blazor Web App-project-sjabloon
De Blazor Web App projectsjabloon bevat nu een ReconnectModal-onderdeel, waaronder collocated stylesheet- en JavaScript-bestanden, voor verbeterde controle van ontwikkelaars over de gebruikersinterface voor opnieuw verbinden wanneer de client de WebSocket-verbinding met de server verliest. Het onderdeel voegt geen stijlen programmatisch in en zorgt ervoor dat de naleving van strengere CSP-instellingen (Content Security Policy) voor het style-src-beleid wordt nageleefd. In eerdere versies is de standaardinterface voor opnieuw verbinden gemaakt door het framework op een manier die CSP-schendingen kan veroorzaken. Houd er rekening mee dat de standaardgebruikersinterface voor opnieuw verbinden nog steeds wordt gebruikt als terugval wanneer de app de gebruikersinterface voor opnieuw verbinden niet definieert, zoals met behulp van het ReconnectModal-onderdeel van de projectsjabloon of een vergelijkbaar aangepast onderdeel.
Nieuwe ui-functies voor opnieuw verbinden:
- Afgezien van het aangeven van de herverbindingsstatus door een specifieke CSS-klasse in te stellen op het element van de gebruikersinterface voor opnieuw verbinden, wordt de nieuwe
components-reconnect-state-changedgebeurtenis verzonden voor herverbindingsstatuswijzigingen. - Code kan beter onderscheid maken tussen de fasen van het proces voor opnieuw verbinden met de nieuwe herverbindingsstatus "
retrying", aangegeven door zowel de CSS-klasse als de nieuwe gebeurtenis.
Zie ASP.NET Core BlazorSignalR guidancevoor meer informatie.
Negeer de queryreeks en het fragment bij het gebruik van NavLinkMatch.All.
Het NavLink-onderdeel negeert nu de querytekenreeks en het fragment bij het gebruik van de NavLinkMatch.All-waarde voor de parameter Match. Dit betekent dat de koppeling de active-klasse behoudt als het URL-pad overeenkomt, maar de querystring of het fragment verandert. Voor het herstellen van het oorspronkelijke gedrag, gebruik de Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext schakelaar ingesteld op true.
U kunt ook de methode ShouldMatch op NavLink overschrijven om het overeenkomende gedrag aan te passen:
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
Zie ASP.NET Core-navigatie Blazorvoor meer informatie.
Opties voor QuickGrid kolom sluiten
U kunt nu de gebruikersinterface voor QuickGrid kolomopties sluiten met behulp van de nieuwe methode HideColumnOptionsAsync.
In het volgende voorbeeld wordt de methode HideColumnOptionsAsync gebruikt om de gebruikersinterface met kolomopties te sluiten zodra het titelfilter is toegepast:
<QuickGrid @ref="movieGrid" Items="movies">
<PropertyColumn Property="@(m => m.Title)" Title="Title">
<ColumnOptions>
<input type="search" @bind="titleFilter" placeholder="Filter by title"
@bind:after="@(() => movieGrid.HideColumnOptionsAsync())" />
</ColumnOptions>
</PropertyColumn>
<PropertyColumn Property="@(m => m.Genre)" Title="Genre" />
<PropertyColumn Property="@(m => m.ReleaseYear)" Title="Release Year" />
</QuickGrid>
@code {
private QuickGrid<Movie>? movieGrid;
private string titleFilter = string.Empty;
private IQueryable<Movie> movies = new List<Movie> { ... }.AsQueryable();
private IQueryable<Movie> filteredMovies =>
movies.Where(m => m.Title!.Contains(titleFilter));
}
HttpClient-antwoordstreaming standaard ingeschakeld
In eerdere Blazor releases was het streamen van antwoorden voor HttpClient verzoeken opt-in. Nu is respons-streaming standaard ingeschakeld.
Dit is een fundamentele wijziging, omdat bij het aanroepen van HttpContent.ReadAsStreamAsync voor een HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) nu een BrowserHttpReadStream wordt geretourneerd en niet langer een MemoryStream.
BrowserHttpReadStream biedt geen ondersteuning voor synchrone bewerkingen, zoals Stream.Read(Span<Byte>). Als uw code synchrone bewerkingen gebruikt, kunt u streaming van reacties vermijden of de Stream zelf in een MemoryStream kopiëren.
Als u zich wereldwijd wilt afmelden voor het streamen van antwoorden, gebruikt u een van de volgende methoden:
Voeg de
<WasmEnableStreamingResponse>eigenschap toe aan het projectbestand met de waarde :false<WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>Stel de
DOTNET_WASM_ENABLE_STREAMING_RESPONSEomgevingsvariabele in opfalseof0.
Om het streamen van antwoorden voor een afzonderlijk verzoek uit te schakelen, stelt u SetBrowserResponseStreamingEnabled in op false op HttpRequestMessage (requestMessage in het volgende voorbeeld):
requestMessage.SetBrowserResponseStreamingEnabled(false);
Voor meer informatie, zie HttpClient en HttpRequestMessage met Fetch API-aanroepopties (Call web API artikel).
Vingerafdrukken aan de klantzijde
In de release van .NET 9 zijn server-side fingerprinting van statische assets in Blazor Web Apps geïntroduceerd met de introductie van conventies voor routeringseindpunten van statische assets (MapStaticAssets), de ImportMap component en de ComponentBase.Assets eigenschap (@Assets["..."]) om gefingerprinte JavaScript (JS) modules op te lossen. Voor .NET 10 kunt u client-side fingerprinting van de JS modules inschakelen voor zelfstandige Blazor WebAssembly apps.
In zelfstandige Blazor WebAssembly apps overschrijft het framework tijdens build en publicatie placeholder-tekens in index.html met waarden die tijdens de build zijn berekend om statische assets te voorzien van vingerafdrukken. Er wordt een vingerafdruk geplaatst in de blazor.webassembly.js scriptbestandsnaam.
De volgende markeringen moeten aanwezig zijn in het wwwroot/index.html bestand om de vingerafdrukfunctie te kunnen gebruiken:
<head>
...
+ <script type="importmap"></script>
</head>
<body>
...
- <script src="_framework/blazor.webassembly.js"></script>
+ <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>
</html>
In het projectbestand (.csproj), voeg de <OverrideHtmlAssetPlaceholders>-eigenschap toe die is ingesteld op true:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
+ <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
</PropertyGroup>
</Project>
In het volgende voorbeeld zijn alle door ontwikkelaars geleverde JS bestanden modules met een .js bestandsextensie.
Een module met de naam scripts.js in de map wwwroot/js van de app wordt gefingerprint door #[.{fingerprint}] toe te voegen vóór de bestandsextensie (.js).
<script type="module" src="js/scripts#[.{fingerprint}].js"></script>
Geef de vingerafdrukexpressie op met de <StaticWebAssetFingerprintPattern> eigenschap in het projectbestand van de app (.csproj):
<ItemGroup>
<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.js"
Expression="#[.{fingerprint}]!" />
</ItemGroup>
Elk JS bestand (*.js) index.html met de vingerafdrukmarkering wordt door het framework voorzien van een vingerafdruk, ook wanneer de app wordt gepubliceerd.
Als u de .mjs bestandsextensie voor JS modules gebruikt, stelt u de bestandsextensie in met de Pattern parameter:
<ItemGroup>
<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs"
Expression="#[.{fingerprint}]!" />
</ItemGroup>
Bestanden worden in het importschema geplaatst.
- Automatisch voor Blazor Web App rendering aan clientzijde (CSR).
- Wanneer u ervoor kiest om module-fingerprinting in standalone Blazor WebAssembly apps te implementeren volgens de eerdere instructies.
Bij het oplossen van de import voor JavaScript-interoperabiliteit, wordt de importmap door de browser gebruikt om bestanden met vingerafdrukken op te lossen.
Vooraf geladen statische framework-assets
In Blazor Web Apps worden de statische assets van het framework automatisch vooraf geladen met behulp van Link headers, waardoor de browser bronnen kan preloaden voordat de eerste pagina wordt opgehaald en weergegeven.
In zelfstandige Blazor WebAssembly apps worden frameworkassets gepland voor het downloaden en het cachen met hoge prioriteit vroeg in de browserpagina-verwerking index.html wanneer:
De
OverrideHtmlAssetPlaceholderseigenschap MSBuild in het projectbestand van de app (.csproj) is ingesteld optrue:<PropertyGroup> <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders> </PropertyGroup>Het volgende
<link>element datrel="preload"bevat is aanwezig in de<head>inhoud vanwwwroot/index.html:<link rel="preload" id="webassembly" />
Stel de omgeving in voor zelfstandige Blazor WebAssembly apps
Het Properties/launchSettings.json-bestand wordt niet langer gebruikt om de omgeving te beheren in standalone Blazor WebAssembly-apps.
Beginnend in .NET 10, stel de omgeving in met de <WasmApplicationEnvironmentName> eigenschap in het projectbestand van de app (.csproj).
Het volgende voorbeeld stelt de omgeving van de app in op Staging:
<WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName>
De standaardomgevingen zijn:
-
Developmentvoor constructie. -
Productionom te publiceren.
Zie ASP.NET Core-omgevingen Blazorvoor meer informatie.
Opstartconfiguratiebestand ingesloten
BlazorDe opstartconfiguratie, die vóór de release van .NET 10 bestond in een bestand met de naam blazor.boot.json, is inline opgenomen in het dotnet.js script. Dit is alleen van invloed op ontwikkelaars die rechtstreeks met het blazor.boot.json bestand werken, zoals wanneer ontwikkelaars:
- Controleer de bestandsintegriteit voor gepubliceerde assets met het PowerShell-script voor het controleren van integriteit volgens de richtlijnen in ASP.NET Core caching Blazor WebAssembly en controleer fouten bij de integriteitscontrole.
- De bestandsnaamextensie van DLL-bestanden wijzigen wanneer het standaard Webcil-bestandsformaat niet wordt gebruikt volgens de richtlijnen in ASP.NET Core hosten en implementerenBlazor WebAssembly.
Er is momenteel geen gedocumenteerde vervangingsstrategie voor de voorgaande benaderingen. Als u een van de voorgaande strategieën nodig hebt, opent u een nieuw documentatieprobleem met een beschrijving van uw scenario met behulp van de koppeling Een documentatieprobleem openen onderaan een van beide artikelen.
Declaratief model voor het bewaren van de status vanuit componenten en services
U kunt nu declaratief de status specificeren die moet worden behouden voor componenten en diensten met behulp van het [PersistentState]-attribuut. Eigenschappen met dit kenmerk worden tijdens het prerenderen automatisch opgeslagen met behulp van de PersistentComponentState service. De status wordt opgehaald wanneer het onderdeel interactief wordt weergegeven of wanneer de service wordt geïnstantieerd.
In eerdere Blazor releases vereiste het behouden van de componentstatus tijdens prerendering met behulp van de PersistentComponentState service een aanzienlijke hoeveelheid code, zoals het volgende voorbeeld aantoont:
@page "/movies"
@implements IDisposable
@inject IMovieService MovieService
@inject PersistentComponentState ApplicationState
@if (MoviesList == null)
{
<p><em>Loading...</em></p>
}
else
{
<QuickGrid Items="MoviesList.AsQueryable()">
...
</QuickGrid>
}
@code {
public List<Movie>? MoviesList { get; set; }
private PersistingComponentStateSubscription? persistingSubscription;
protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<List<Movie>>(nameof(MoviesList),
out var movies))
{
MoviesList = await MovieService.GetMoviesAsync();
}
else
{
MoviesList = movies;
}
persistingSubscription = ApplicationState.RegisterOnPersisting(() =>
{
ApplicationState.PersistAsJson(nameof(MoviesList), MoviesList);
return Task.CompletedTask;
});
}
public void Dispose() => persistingSubscription?.Dispose();
}
Deze code kan nu worden vereenvoudigd met behulp van het nieuwe declaratieve model.
@page "/movies"
@inject IMovieService MovieService
@if (MoviesList == null)
{
<p><em>Loading...</em></p>
}
else
{
<QuickGrid Items="MoviesList.AsQueryable()">
...
</QuickGrid>
}
@code {
[PersistentState]
public List<Movie>? MoviesList { get; set; }
protected override async Task OnInitializedAsync()
{
MoviesList ??= await MovieService.GetMoviesAsync();
}
}
Toestand kan worden geserialiseerd voor meerdere componenten van hetzelfde type, en u kunt declaratieve toestand in een service instellen voor gebruik binnen de app door RegisterPersistentService aan te roepen op de Razor componentenbouwer (AddRazorComponents) met een aangepast servicetype en render-modus. Zie ASP.NET Vooraf samengestelde statuspersistentie van Core Blazorvoor meer informatie.
Nieuwe JavaScript-interoperabiliteitsfuncties
Blazor voegt ondersteuning toe voor de volgende JS interoperabiliteitsfuncties:
- Maak een exemplaar van een JS object met behulp van een constructorfunctie en haal de IJSObjectReference/IJSInProcessObjectReference .NET-ingang op om te verwijzen naar het exemplaar.
- Lees of wijzig de waarde van een JS objecteigenschap, zowel gegevens- als accessoreigenschappen.
De volgende asynchrone methoden zijn beschikbaar op IJSRuntime en IJSObjectReference met hetzelfde bereikgedrag als de bestaande IJSRuntime.InvokeAsync methode:
InvokeConstructorAsync(string identifier, object?[]? args): roept de opgegeven JS constructorfunctie asynchroon aan. De functie wordt aangeroepen met denewoperator. In het volgende voorbeeldjsInterop.TestClassis een klasse met een constructorfunctie enclassRefis dit een IJSObjectReference:var classRef = await JSRuntime.InvokeConstructorAsync("jsInterop.TestClass", "Blazor!"); var text = await classRef.GetValueAsync<string>("text"); var textLength = await classRef.InvokeAsync<int>("getTextLength");GetValueAsync<TValue>(string identifier): leest de waarde van de opgegeven JS eigenschap asynchroon. De eigenschap kan geenset-only eigenschap zijn. Er wordt een JSException geworpen als de eigenschap niet bestaat. In het volgende voorbeeld wordt een waarde van een gegevenseigenschap geretourneerd:var valueFromDataPropertyAsync = await JSRuntime.GetValueAsync<int>( "jsInterop.testObject.num");SetValueAsync<TValue>(string identifier, TValue value): Hiermee wordt de waarde van de opgegeven JS eigenschap asynchroon bijgewerkt. De eigenschap kan geenget-only eigenschap zijn. Als de eigenschap niet is gedefinieerd voor het doelobject, wordt de eigenschap gemaakt. Er wordt een JSException gegenereerd als de eigenschap bestaat, maar niet beschrijfbaar is of wanneer een nieuwe eigenschap niet kan worden toegevoegd aan het object. In het volgende voorbeeld wordtnumoptestObjectgemaakt met een waarde van 30, als het niet bestaat.await JSRuntime.SetValueAsync("jsInterop.testObject.num", 30);
Overbelastingen zijn beschikbaar voor elk van de voorgaande methoden die een CancellationToken argument of TimeSpan time-outargument gebruiken.
De volgende synchrone methoden zijn beschikbaar op IJSInProcessRuntime en IJSInProcessObjectReference met hetzelfde bereikgedrag als de bestaande IJSInProcessObjectReference.Invoke methode:
InvokeConstructor(string identifier, object?[]? args): roept de opgegeven JS constructorfunctie synchroon aan. De functie wordt aangeroepen met denewoperator. In het volgende voorbeeldjsInterop.TestClassis een klasse met een constructorfunctie enclassRefis dit een IJSInProcessObjectReference:var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); var classRef = inProcRuntime.InvokeConstructor("jsInterop.TestClass", "Blazor!"); var text = classRef.GetValue<string>("text"); var textLength = classRef.Invoke<int>("getTextLength");GetValue<TValue>(string identifier): leest de waarde van de opgegeven JS eigenschap synchroon. De eigenschap kan geenset-only eigenschap zijn. Er wordt een JSException geworpen als de eigenschap niet bestaat. In het volgende voorbeeld wordt een waarde van een gegevenseigenschap geretourneerd:var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); var valueFromDataProperty = inProcRuntime.GetValue<int>( "jsInterop.testObject.num");SetValue<TValue>(string identifier, TValue value): Werkt de waarde van de opgegeven JS eigenschap synchroon bij. De eigenschap kan geenget-only eigenschap zijn. Als de eigenschap niet is gedefinieerd voor het doelobject, wordt de eigenschap gemaakt. Er wordt een JSException gegenereerd als de eigenschap bestaat, maar niet beschrijfbaar is of wanneer een nieuwe eigenschap niet kan worden toegevoegd aan het object. In het volgende voorbeeld wordtnumoptestObjectaangemaakt met een waarde van 20, als het niet bestaat.var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); inProcRuntime.SetValue("jsInterop.testObject.num", 20);
Zie de volgende secties van de JavaScript-functies aanroepen vanuit het artikel over .NET-methoden voor meer informatie:
- Een exemplaar van een JS object maken met behulp van een constructorfunctie
- De waarde van een JS objecteigenschap lezen of wijzigen
Blazor WebAssembly prestatieprofielanalyse en diagnostische tellers
Er zijn nieuwe prestatieprofilering en diagnostische meteritems beschikbaar voor Blazor WebAssembly apps. Zie de volgende artikelen voor meer informatie:
- Diagnostische hulpmiddelen voor ASP.NET Core-browserontwikkelaars Blazor WebAssembly
- diagnostische gegevens van ASP.NET Core Blazor WebAssembly Event Pipe
Vooraf geladen statische framework-assets
In Blazor Web Apps worden de statische assets van het framework automatisch vooraf geladen met behulp van Link headers, waardoor de browser bronnen kan preloaden voordat de eerste pagina wordt opgehaald en weergegeven. In zelfstandige Blazor WebAssembly apps worden frameworkassets met hoge prioriteit gepland voor het downloaden en opslaan in de cache vroeg in de verwerking van de browserpagina index.html.
Zie ASP.NET Core Blazor statische bestandenvoor meer informatie.
Aanmelden om te voorkomen dat een NavigationException statische serverzijde wordt weergegeven met NavigationManager.NavigateTo
Tijdens het aanroepen NavigationManager.NavigateTo van statische serverzijde (statische SSR) wordt een NavigationException, onderbrekende uitvoering gegenereerd voordat deze wordt geconverteerd naar een omleidingsreactie. Dit kan leiden tot verwarring tijdens foutopsporing en is inconsistent met interactief renderinggedrag, waarbij code na NavigateTo normaal blijft worden uitgevoerd.
In .NET 10 kunt u de <BlazorDisableThrowNavigationException> eigenschap true MSBuild instellen op in het projectbestand van de app om te voorkomen dat de uitzondering tijdens statische SSR wordt gegenereerd:
<PropertyGroup>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
</PropertyGroup>
Met de MSBuild-eigenschap ingesteld, het aanroepen NavigationManager.NavigateTo tijdens statische SSR genereert geen NavigationException. In plaats daarvan gedraagt het zich consistent met interactieve rendering door de navigatie uit te voeren zonder een uitzondering te genereren. Code na NavigationManager.NavigateTo uitvoering voordat de omleiding plaatsvindt.
De .NET 10-projectsjabloon Blazor Web App stelt de MSBuild-eigenschap true standaard in. Het is raadzaam dat apps die worden bijgewerkt naar .NET 10, gebruikmaken van de nieuwe MSBuild-eigenschap en het eerdere gedrag voorkomen.
Als de MSBuild-eigenschap wordt gebruikt, moet code die wordt NavigationException gegenereerd, worden bijgewerkt. In de standaardgebruikersinterface BlazorIdentity van de Blazor Web App projectsjabloon vóór de release van .NET 10 wordt er IdentityRedirectManager een InvalidOperationException gegenereerd na het aanroepen RedirectTo om ervoor te zorgen dat de methode niet is aangeroepen tijdens interactieve rendering. Deze uitzondering en de [DoesNotReturn] kenmerken moeten nu worden verwijderd wanneer de EIGENSCHAP MSBuild wordt gebruikt. Zie Migreren van ASP.NET Core in .NET 9 naar ASP.NET Core in .NET 10 voor meer informatie.
Blazor Router heeft een NotFoundPage parameter
Blazor biedt nu een verbeterde manier om een pagina Niet gevonden weer te geven wanneer u naar een niet-bestaande pagina navigeert. U kunt een pagina opgeven die moet worden weergegeven wanneer NavigationManager.NotFound (beschreven in de volgende sectie) wordt aangeroepen door een paginatype door te geven aan het Router onderdeel met behulp van de NotFoundPage parameter. De functie biedt ondersteuning voor routering, werkt met het heruitvoeren van statuscodepagina's in middleware en is ook compatibel met andere scenario's dan niet-Blazor scenario's.
Het NotFound renderfragment (<NotFound>...</NotFound>) wordt niet ondersteund in .NET 10 of hoger.
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>This content is ignored because NotFoundPage is defined.</NotFound>
</Router>
De Blazor projectsjabloon bevat nu standaard een NotFound.razor pagina. Deze pagina wordt automatisch weergegeven wanneer NotFound wordt aangeroepen in uw app, waardoor ontbrekende routes eenvoudiger kunnen worden afgehandeld met een consistente gebruikerservaring.
Zie ASP.NET Core-navigatie Blazorvoor meer informatie.
Antwoorden niet gevonden voor het gebruik van NavigationManager bij statische SSR en globale interactieve rendering
Deze NavigationManager bevat nu een NotFound methode voor het afhandelen van scenario's waarbij een aangevraagde resource niet wordt gevonden tijdens statische server-side rendering (statische SSR) of globale interactieve rendering:
Statische server-side rendering (statische SSR): aanroepen NotFound stelt de HTTP-statuscode in op 404.
Interactieve rendering: Signaleert de Blazor router (
Routercomponent) om 'Niet Gevonden'-inhoud weer te geven.Streamingrendering: als verbeterde navigatie actief is, maakt streamingrendering het mogelijk om niet gevonden content weer te geven zonder de pagina opnieuw te laden. Wanneer verbeterde navigatie wordt geblokkeerd, wordt het framework omgeleid naar niet-gevonden inhoud met een paginavernieuwing.
Streaming rendering kan alleen componenten weergeven die een route hebben, zoals een NotFoundPage toewijzing (NotFoundPage="...") of een Status Code Pages Re-execution Middleware paginatoewijzing (UseStatusCodePagesWithReExecute).
DefaultNotFound 404-inhoud (Not found'' tekst zonder opmaak) heeft geen route, dus deze kan niet worden gebruikt tijdens streamingrendering.
NotFound inhoudsweergave maakt gebruik van het volgende, ongeacht of het antwoord al dan niet is gestart (in volgorde):
- Als NotFoundEventArgs.Path dit is ingesteld, geeft u de inhoud van de toegewezen pagina weer.
- Als
Router.NotFoundPagedit is ingesteld, geeft u de toegewezen pagina weer. - Een middlewarepagina voor het opnieuw uitvoeren van statuscodepagina's, indien geconfigureerd.
- Geen actie als geen van de voorgaande benaderingen wordt aangenomen.
Statuscode pages Re-execution Middleware with UseStatusCodePagesWithReExecute heeft voorrang op browsergebaseerde adresrouteringsproblemen, zoals een onjuiste URL die is getypt in de adresbalk van de browser of het selecteren van een koppeling die geen eindpunt in de app heeft.
U kunt de NavigationManager.OnNotFound gebeurtenis gebruiken voor meldingen wanneer NotFound aangeroepen wordt.
Zie ASP.NET Core-navigatie Blazorvoor meer informatie en voorbeelden.
Ondersteuning voor niet-gevonden antwoorden in apps zonder Blazorrouter
Apps die een aangepaste router implementeren, kunnen gebruiken NotFound. Er zijn twee manieren om de renderer te informeren welke pagina moet worden weergegeven wanneer NotFound deze wordt aangeroepen.
De aanbevolen aanpak die werkt, ongeacht de antwoordstatus, is door aan te roepen UseStatusCodePagesWithReExecute. Wanneer NotFound wordt aangeroepen, geeft de middleware het pad weer dat wordt doorgegeven aan de methode:
app.UseStatusCodePagesWithReExecute(
"/not-found", createScopeForStatusCodePages: true);
Als u UseStatusCodePagesWithReExecute niet wilt gebruiken, kan de app nog steeds NotFound ondersteunen voor antwoorden die al zijn gestart. Abonneer u op OnNotFoundEvent in de router en wijs het pad naar de 404-pagina toe aan NotFoundEventArgs.Path om de renderer te informeren over welke inhoud moet worden weergegeven wanneer NotFound wordt aangeroepen.
CustomRouter.razor:
@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Http
@implements IDisposable
@inject NavigationManager NavigationManager
@code {
protected override void OnInitialized() =>
NavigationManager.OnNotFound += OnNotFoundEvent;
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
private void OnNotFoundEvent(object sender, NotFoundEventArgs e)
{
// Only execute the logic if HTTP response has started
// because setting NotFoundEventArgs.Path blocks re-execution
if (HttpContext?.Response.HasStarted == false)
{
return;
}
e.Path = GetNotFoundRoutePath();
}
// Return the path of the Not Found page that you want to display
private string GetNotFoundRoutePath()
{
...
}
public void Dispose() => NavigationManager.OnNotFound -= OnNotFoundEvent;
}
Als u beide benaderingen in uw app gebruikt, heeft het Niet Gevonden-pad dat is opgegeven in de OnNotFoundEvent handler voorrang op het pad dat is geconfigureerd in de heruitvoeringsmiddleware.
Metrische gegevens en tracering
Deze release introduceert uitgebreide metrische gegevens en traceringsmogelijkheden voor Blazor apps, die gedetailleerde waarneembaarheid bieden van de levenscyclus van onderdelen, navigatie, gebeurtenisafhandeling en circuitbeheer.
Voor meer informatie, zie ASP.NET Core-prestaties beste praktijkenBlazor.
Ondersteuning voor JavaScript-bundelaar
BlazorDe build-uitvoer is niet compatibel met JavaScript-bundelaars, zoals Gulp, Webpack en Rollup.
Blazor kan nu bundelvriendelijke uitvoer produceren tijdens het publiceren door de WasmBundlerFriendlyBootConfig eigenschap MSBuild in te stellen op true.
Zie Host en implementeer ASP.NET Core Blazorvoor meer informatie.
Blazor WebAssembly het vooraf laden van statische assets in Blazor Web Apps
We hebben <link> headers vervangen door een ResourcePreloader component (<ResourcePreloader />) voor het vooraf laden van WebAssembly-assets in Blazor Web Apps. Hierdoor kan de configuratie van het basispad van de app (<base href="..." />) correct de root van de app identificeren.
Als u het onderdeel verwijdert, wordt de functie uitgeschakeld als de app een loadBootResource callback gebruikt om URL's te wijzigen.
De Blazor Web App sjabloon gebruikt de functie standaard in .NET 10 en apps die upgraden naar .NET 10, kunnen de functie implementeren door het ResourcePreloader onderdeel na de basis-URL-tag (<base>) te plaatsen in de hoofdinhoud van het App onderdeel (App.razor):
<head>
...
<base href="/" />
+ <ResourcePreloader />
...
</head>
Voor meer informatie, zie Host en implementeer ASP.NET Core-Blazor-apps.
Verbeterde formuliervalidatie
Blazor heeft nu verbeterde mogelijkheden voor formuliervalidatie, waaronder ondersteuning voor het valideren van eigenschappen van geneste objecten en elementen van verzamelingen.
Als u een gevalideerd formulier wilt maken, gebruikt u een DataAnnotationsValidator onderdeel in een EditForm onderdeel, net als voorheen.
Als u zich wilt aanmelden voor de nieuwe validatiefunctie:
- Roep de
AddValidationextensiemethode aan in hetProgrambestand waarin services zijn geregistreerd. - Declareer de formuliermodeltypen in een C#-klassebestand, niet in een Razor onderdeel (
.razor). - Annoteer het root form modeltype met behulp van het
[ValidatableType]-attribuut.
Zonder de voorgaande stappen te volgen, blijft het validatiegedrag hetzelfde als in eerdere .NET-releases.
In het volgende voorbeeld ziet u klantorders met de verbeterde formuliervalidatie (details weggelaten voor beknoptheid):
In Program.cs roep AddValidation aan in de service verzameling om het nieuwe validatiegedrag in te schakelen.
builder.Services.AddValidation();
In de volgende Order klasse is het [ValidatableType] kenmerk vereist voor het modeltype op het hoogste niveau. De andere typen worden automatisch gedetecteerd.
OrderItem en ShippingAddress worden niet weergegeven voor beknoptheid, maar geneste validatie en verzamelingsvalidatie werken op dezelfde manier als ze wel getoond zouden worden.
Order.cs:
[ValidatableType]
public class Order
{
public Customer Customer { get; set; } = new();
public List<OrderItem> OrderItems { get; set; } = [];
}
public class Customer
{
[Required(ErrorMessage = "Name is required.")]
public string? FullName { get; set; }
[Required(ErrorMessage = "Email is required.")]
public string? Email { get; set; }
public ShippingAddress ShippingAddress { get; set; } = new();
}
In het volgende OrderPage onderdeel is het DataAnnotationsValidator onderdeel aanwezig in het EditForm onderdeel.
OrderPage.razor:
<EditForm Model="Model">
<DataAnnotationsValidator />
<h3>Customer Details</h3>
<div class="mb-3">
<label>
Full Name
<InputText @bind-Value="Model!.Customer.FullName" />
</label>
<ValidationMessage For="@(() => Model!.Customer.FullName)" />
</div>
@* ... form continues ... *@
</EditForm>
@code {
public Order? Model { get; set; }
protected override void OnInitialized() => Model ??= new();
// ... code continues ...
}
De vereiste om de modeltypen buiten Razor onderdelen (.razor bestanden) te declareren, is te wijten aan het feit dat zowel de nieuwe validatiefunctie als de Razor compiler zelf een brongenerator gebruiken. Momenteel kan uitvoer van één brongenerator niet worden gebruikt als invoer voor een andere brongenerator.
Validatieondersteuning omvat nu:
- Validatie van geneste complexe objecten en verzamelingen wordt nu ondersteund.
- Dit omvat validatieregels die zijn gedefinieerd door eigenschapskenmerken, klassekenmerken en de IValidatableObject implementatie.
- Het
[SkipValidation]kenmerk kan eigenschappen of typen uitsluiten van validatie.
- Validatie maakt nu gebruik van een op brongenerator gebaseerde implementatie in plaats van implementatie op basis van reflectie voor verbeterde prestaties en compatibiliteit met AOT-compilatie (Vooruit-of-tijd).
Het DataAnnotationsValidator onderdeel heeft nu dezelfde validatievolgorde en kortsluitingsgedrag als System.ComponentModel.DataAnnotations.Validator. De volgende regels worden toegepast bij het valideren van een exemplaar van het type T:
- Lideigenschappen
Tworden gevalideerd, inclusief recursief valideren van geneste objecten. - Kenmerken
Top typeniveau worden gevalideerd. - De IValidatableObject.Validate methode wordt uitgevoerd als
Tdeze wordt geïmplementeerd.
Als een van de voorgaande stappen een validatiefout produceert, worden de resterende stappen overgeslagen.
Validatiemodellen uit een andere assembly gebruiken
U kunt formulieren valideren met modellen die zijn gedefinieerd in een andere assembly, zoals een bibliotheek of het .Client-project van een Blazor Web App, door een methode te maken in de bibliotheek of het .Client-project dat een IServiceCollection-exemplaar als argument ontvangt en roept AddValidation aan.
- Roep in de app zowel de methode als
AddValidationaan.
Zie ASP.NET Kernformuliervalidatie Blazorvoor meer informatie en een voorbeeld.
Aangepaste Blazor cache en BlazorCacheBootResources MSBuild-eigenschap verwijderd
Nu alle Blazor bestanden aan de clientzijde zijn vingerafdruk en in de cache opgeslagen door de browser, Blazorzijn het aangepaste cachemechanisme en de BlazorCacheBootResources MSBuild-eigenschap verwijderd uit het framework. Als het projectbestand aan de clientzijde de eigenschap MSBuild bevat, verwijdert u de eigenschap, omdat deze geen effect meer heeft:
- <BlazorCacheBootResources>...</BlazorCacheBootResources>
Zie voor meer informatie ASP.NET Core-cache Blazor WebAssembly - en integriteitscontrolefouten.
Ondersteuning voor webverificatie-API (wachtwoordsleutel) voor ASP.NET Core Identity
Webverificatie -API-ondersteuning (WebAuthn), ook wel bekend als wachtwoordsleutels, is een moderne, phishingbestendige verificatiemethode die de beveiliging en gebruikerservaring verbetert door gebruik te maken van cryptografie op basis van openbare sleutels en verificatie op basis van apparaten. ASP.NET Core Identity ondersteunt nu wachtwoordverificatie op basis van WebAuthn- en FIDO2-standaarden. Met deze functie kunnen gebruikers zich aanmelden zonder wachtwoorden, met behulp van veilige verificatiemethoden op basis van apparaten, zoals biometrische gegevens of beveiligingssleutels.
De Blazor Web App projectsjabloon biedt out-of-the-box wachtwoordsleutelbeheer en aanmeldingsfunctionaliteit.
Zie de volgende artikelen voor meer informatie:
- Wachtwoordsleutels voor webverificatie-API (WebAuthn) inschakelen
- Wachtwoordsleutels implementeren in ASP.NET Core Blazor Web Apps
Persistentie van circuitstatus
Tijdens het server-side renderen kunnen Blazor Web Apps nu de circuitstatus van een gebruiker behouden wanneer de verbinding met de server gedurende een langere periode is verbroken of proactief onderbroken, zolang er geen volledige paginavernieuwing wordt geactiveerd. Hierdoor kunnen gebruikers hun sessie hervatten zonder niet-opgeslagen werk kwijt te raken in de volgende scenario's:
- Regulering van browsertabbladen
- Gebruikers van mobiel apparaat wisselen van apps
- Netwerkonderbrekingen
- Proactief resourcebeheer (onderbreken van inactieve circuits)
- Verbeterde navigatie
Zie ASP.NET Core-statusbeheer Blazor aan de serverzijde voor meer informatie.
Hot Reload voor Blazor WebAssembly en .NET op WebAssembly
De SDK is gemigreerd naar een Hot Reload voor WebAssembly-scenario's voor algemeen gebruik. Er is een nieuwe MSBuild-eigenschap WasmEnableHotReload die standaard is true ingesteld voor de Debug configuratie (Configuration == "Debug") die Hot Reload inschakelt.
Voor andere configuraties met aangepaste configuratienamen stelt u de waarde true in op in het projectbestand van de app om Hot Reload in te schakelen:
<PropertyGroup>
<WasmEnableHotReload>true</WasmEnableHotReload>
</PropertyGroup>
Als u Hot Reload voor de Debug configuratie wilt uitschakelen, stelt u de waarde falsein op:
<PropertyGroup>
<WasmEnableHotReload>false</WasmEnableHotReload>
</PropertyGroup>
Registratie van PWA-servicemedewerkers bijgewerkt om cachingproblemen te voorkomen
De registratie van servicemedewerkers in de Blazor PWA-projectsjabloon (Progressive Web Application) bevat nu de updateViaCache: 'none' optie, waardoor cachingproblemen tijdens het bijwerken van servicemedewerkers worden voorkomen.
- navigator.serviceWorker.register('service-worker.js');
+ navigator.serviceWorker.register('service-worker.js', { updateViaCache: 'none' });
De optie zorgt ervoor dat:
- De browser gebruikt geen versies in de cache van het service worker-script.
- Service worker-updates worden betrouwbaar toegepast zonder te worden geblokkeerd door HTTP-caching.
- PWA-toepassingen kunnen hun servicemedewerkers voorspelbaarder bijwerken.
Hiermee worden cacheproblemen opgelost die kunnen voorkomen dat updates van servicemedewerkers correct worden toegepast, wat met name belangrijk is voor PWA's die afhankelijk zijn van servicemedewerkers voor offlinefunctionaliteit.
We raden aan de optie ingesteld op none te gebruiken in alle PWA's, inclusief die gericht zijn op .NET 9 of eerder.
Serialisatie-uitbreidbaarheid voor permanente onderdeelstatus
Implementeer een aangepaste serializer met PersistentComponentStateSerializer<T>. Zonder een geregistreerde aangepaste serialisatie valt serialisatie terug op de bestaande JSON-serialisatie.
De aangepaste serializer is geregistreerd in het bestand van Program de app. In het volgende voorbeeld is het CustomUserSerializer geregistreerd voor het TUser type:
builder.Services.AddSingleton<PersistentComponentStateSerializer<TUser>,
CustomUserSerializer>();
Het type wordt automatisch behouden en hersteld met de aangepaste serializer:
[PersistentState]
public User? CurrentUser { get; set; } = new();
OwningComponentBase implementeert nu IAsyncDisposable
OwningComponentBase bevat nu ondersteuning voor asynchrone verwijdering, waardoor resourcebeheer wordt verbeterd. Er zijn nieuwe DisposeAsync methoden en DisposeAsyncCore methoden met een bijgewerkte Dispose methode voor het verwerken van zowel synchrone als asynchrone verwijdering van het servicebereik.
Nieuw InputHidden onderdeel voor het afhandelen van verborgen invoervelden in formulieren
Het nieuwe InputHidden onderdeel biedt een verborgen invoerveld voor het opslaan van tekenreekswaarden.
In het volgende voorbeeld wordt een verborgen invoerveld gemaakt voor de eigenschap van Parameter het formulier. Wanneer het formulier wordt verzonden, wordt de waarde van het verborgen veld weergegeven:
<EditForm Model="Parameter" OnValidSubmit="Submit" FormName="InputHidden Example">
<InputHidden id="hidden" @bind-Value="Parameter" />
<button type="submit">Submit</button>
</EditForm>
@if (submitted)
{
<p>Hello @Parameter!</p>
}
@code {
private bool submitted;
[SupplyParameterFromForm]
public string Parameter { get; set; } = "stranger";
private void Submit() => submitted = true;
}
Statusondersteuning voor permanente onderdelen voor verbeterde navigatie
Blazor biedt nu ondersteuning voor het verwerken van de status van permanente onderdelen tijdens verbeterde navigatie. Status behouden tijdens verbeterde navigatie kan worden gelezen door interactieve onderdelen op de pagina.
De status van permanente onderdelen wordt standaard alleen geladen door interactieve onderdelen wanneer deze in eerste instantie op de pagina worden geladen. Dit voorkomt dat belangrijke status, zoals gegevens in een bewerkt webformulier, wordt overschreven als er extra uitgebreide navigatiegebeurtenissen naar dezelfde pagina plaatsvinden nadat het onderdeel is geladen.
Als de gegevens alleen-lezen zijn en niet regelmatig worden gewijzigd, meldt u zich aan om updates toe te staan tijdens verbeterde navigatie door het AllowUpdates = true in te stellen[PersistentState]. Dit is handig voor scenario's zoals het weergeven van gegevens in de cache die duur zijn om op te halen, maar die niet vaak veranderen. In het volgende voorbeeld ziet u het gebruik van AllowUpdates weersvoorspellingsgegevens:
[PersistentState(AllowUpdates = true)]
public WeatherForecast[]? Forecasts { get; set; }
protected override async Task OnInitializedAsync()
{
Forecasts ??= await ForecastService.GetForecastAsync();
}
Als u de herstelstatus tijdens het voorbereiden wilt overslaan, stelt u het volgende in RestoreBehaviorSkipInitialValue:
[PersistentState(RestoreBehavior = RestoreBehavior.SkipInitialValue)]
public string NoPrerenderedData { get; set; }
Als u de herstelstatus tijdens het opnieuw verbinden wilt overslaan, stelt u deze in RestoreBehavior op SkipLastSnapshot. Dit kan handig zijn om ervoor te zorgen dat nieuwe gegevens na opnieuw verbinding worden gemaakt:
[PersistentState(RestoreBehavior = RestoreBehavior.SkipLastSnapshot)]
public int CounterNotRestoredOnReconnect { get; set; }
Aanroep PersistentComponentState.RegisterOnRestoring om een callback te registreren voor imperatief bepalen hoe de status wordt hersteld, vergelijkbaar met hoe PersistentComponentState.RegisterOnPersisting de status volledig wordt gecontroleerd.
Blazor WebAssembly respecteert de huidige cultuurinstelling voor de gebruikersinterface
In .NET 9 of eerder laden onafhankelijke Blazor WebAssembly-apps UI-globalisatiebronnen op basis van CultureInfo.DefaultThreadCurrentCulture. Als u aanvullende globalisatiegegevens wilt laden voor uw lokalisatiecultuur die is gedefinieerd door CultureInfo.DefaultThreadCurrentUICulture, voert u een upgrade uit van de app naar .NET 10 of hoger.
Blazor Hybrid
In deze sectie worden nieuwe functies voor Blazor Hybridbeschreven.
Nieuwe .NET MAUIBlazor Hybrid met een Blazor Web App- en ASP.NET Core Identity-artikel en voorbeeld
Er is een nieuw artikel en voorbeeld-app toegevoegd voor .NET MAUIBlazor Hybrid en web-app met behulp van ASP.NET Core Identity.
Zie de volgende bronnen voor meer informatie:
- .NET MAUI Blazor Hybrid en web-app met ASP.NET Core-Identity
-
MauiBlazorWebIdentityvoorbeeld-app (dotnet/blazor-samplesGitHub-opslagplaats)
SignalR
In deze sectie worden nieuwe functies voor SignalRbeschreven.
Minimale APIs
In deze sectie worden nieuwe functies voor minimale API's beschreven.
Lege tekenreeks in formulierinvoer behandelen als null voor nulbare typen.
Wanneer u het [FromForm] kenmerk gebruikt met een complex object in minimale API's, worden lege tekenreekswaarden in een formulierbericht nu geconverteerd naar null in plaats van een parseringsfout te veroorzaken. Dit gedrag komt overeen met de verwerkingslogica voor formulierposts die niet zijn gekoppeld aan complexe objecten in minimale API's.
using Microsoft.AspNetCore.Http;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/todo", ([FromForm] Todo todo) => TypedResults.Ok(todo));
app.Run();
public class Todo
{
public int Id { get; set; }
public DateOnly? DueDate { get; set; } // Empty strings map to `null`
public string Title { get; set; }
public bool IsCompleted { get; set; }
}
Dankzij @nvmkpk voor deze wijziging!
Ondersteuning voor validatie in minimale API's
Ondersteuning voor validatie in Minimal APIs is nu beschikbaar. Deze functie stelt u in staat om validatie van gegevens die naar uw API-eindpunten zijn verzonden aan te vragen. Het inschakelen van validatie stelt de ASP.NET Core-runtime in staat om alle gedefinieerde validaties uit te voeren op de:
- Query
- Header
- Inhoud van het verzoek
Validaties worden gedefinieerd met behulp van attributen in de DataAnnotations namespace. Ontwikkelaars passen het gedrag van het validatiesysteem aan door:
- Aangepaste
[Validation]attribuutimplementaties maken. - Het implementeren van de
IValidatableObjectinterface voor complexe validatielogica.
Als verificatie mislukt, retourneert de runtime een 400 Onjuiste Verzoek-reactie met details van de verificatiefouten.
Ingebouwde validatieondersteuning inschakelen voor minimale API's
Schakel de ingebouwde validatieondersteuning voor minimale API's in door de AddValidation extensiemethode aan te roepen om de vereiste services te registreren in de servicecontainer voor uw toepassing:
builder.Services.AddValidation();
De implementatie detecteert automatisch typen die zijn gedefinieerd in minimale API-handlers of als basistypen die zijn gedefinieerd in minimale API-handlers. Een eindpuntfilter voert validatie uit op deze types en wordt toegevoegd voor elk eindpunt.
Validatie kan voor specifieke eindpunten worden uitgeschakeld met behulp van de DisableValidation extensiemethode, zoals in het volgende voorbeeld:
app.MapPost("/products",
([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();
Note
Er zijn verschillende kleine verbeteringen en oplossingen aangebracht in de minimale API-validatiegenerator die is geïntroduceerd in ASP.NET Core voor .NET 10. Ter ondersteuning van toekomstige verbeteringen worden de onderliggende api's voor validatie-resolver nu gemarkeerd als experimenteel. De API's op het hoogste niveau AddValidation en het ingebouwde validatiefilter blijven stabiel en niet experimenteel.
Validatie met recordtypen
Minimale API's ondersteunen ook validatie met C#-recordtypen. Recordtypen kunnen worden gevalideerd met behulp van kenmerken uit de System.ComponentModel.DataAnnotations naamruimte, vergelijkbaar met klassen. Voorbeeld:
public record Product(
[Required] string Name,
[Range(1, 1000)] int Quantity);
Wanneer u recordtypen gebruikt als parameters in minimale API-eindpunten, worden validatiekenmerken automatisch op dezelfde manier toegepast als klassetypen:
app.MapPost("/products", (Product product) =>
{
// Endpoint logic here
return TypedResults.Ok(product);
});
Minimale INTEGRATIE van API-validatie met IProblemDetailsService
Foutreacties van de validatielogica voor minimale API's kunnen nu worden aangepast door een IProblemDetailsService implementatie die wordt geleverd in de verzameling application services (container voor afhankelijkheidsinjectie). Dit maakt consistentere en gebruikersspecifieke foutreacties mogelijk.
Support voor Server-Sent Events (SSE)
ASP.NET Core ondersteunt nu het retourneren van een ServerSentEvents-resultaat met behulp van de TypedResults.ServerSentEvents API. Deze functie wordt ondersteund in zowel Minimal APIs als controller-gebaseerde apps.
Server-Sent Events is een technologie voor server-push die het mogelijk maakt voor een server om een stroom van evenementberichten naar een client te sturen via een enkele HTTP-verbinding. In .NET worden de gebeurtenisberichten weergegeven als SseItem<T>-objecten, die een gebeurtenistype, een ID en een gegevenslading van het type T kunnen bevatten.
De klasse TypedResults heeft een nieuwe statische methode genaamd ServerSentEvents die kan worden gebruikt om een ServerSentEvents resultaat te retourneren. De eerste parameter van deze methode is een IAsyncEnumerable<SseItem<T>> die de stroom van gebeurtenisberichten vertegenwoordigt die naar de client moeten worden verzonden.
Het volgende voorbeeld illustreert hoe u de TypedResults.ServerSentEvents API kunt gebruiken om een stroom van hartslagevenementen als JSON-objecten naar de client te retourneren.
app.MapGet("/json-item", (CancellationToken cancellationToken) =>
{
async IAsyncEnumerable<HeartRateRecord> GetHeartRate(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var heartRate = Random.Shared.Next(60, 100);
yield return HeartRateRecord.Create(heartRate);
await Task.Delay(2000, cancellationToken);
}
}
return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken),
eventType: "heartRate");
});
Voor meer informatie, zie:
- Server-Sent Events op MDN.
-
Minimal API-voorbeeldtoepassing met behulp van de
TypedResults.ServerSentEventsAPI om een stroom van hartslaggebeurtenissen als string,ServerSentEvents, en JSON-objecten naar de client te retourneren. -
Controller API voorbeeldapp gebruikmakend van de
TypedResults.ServerSentEventsAPI om een stroom van hartslaggebeurtenissen als string,ServerSentEvents, en JSON-objecten naar de cliënt terug te geven.
Validatie-API's zijn verplaatst naar Microsoft.Extensions.Validation
De validatie-API's zijn verplaatst naar de naamruimte en het Microsoft.Extensions.Validation NuGet-pakket. Deze wijziging maakt de API's bruikbaar buiten ASP.NET Core HTTP-scenario's. De openbare API's en het gedrag blijven ongewijzigd. Alleen het pakket en de naamruimte zijn anders. Voor bestaande projecten zijn geen codewijzigingen vereist, omdat oude verwijzingen worden omgeleid naar de nieuwe implementatie.
Verbeterde validatie voor klassen en records
Validatiekenmerken kunnen nu worden toegepast op zowel klassen als records met consistent gedrag voor het genereren van code en validatie. Deze verbetering verbetert de flexibiliteit bij het ontwerpen van modellen met behulp van records in ASP.NET Core-apps.
Bijdrage van de gemeenschap: Dankzij @marcominerva!
OpenAPI
In deze sectie worden nieuwe functies voor OpenAPI beschreven.
Ondersteuning voor OpenAPI 3.1
ASP.NET Core heeft ondersteuning toegevoegd voor het genereren van OpenAPI versie 3.1 documenten in .NET 10. Ondanks de kleine versie-increment is OpenAPI 3.1 een belangrijke update van de OpenAPI-specificatie, met name met volledige ondersteuning voor JSON Schema draft 2020-12.
Enkele van de wijzigingen die u in het gegenereerde OpenAPI-document ziet, zijn:
- Nullable typen hebben niet meer de
nullable: trueeigenschap in het schema. - In plaats van een
nullable: trueeigenschap hebben ze eentypetrefwoord waarvan de waarde een matrix is dienullbevat als een van de typen. - Eigenschappen of parameters die zijn gedefinieerd als een C#
intoflongworden nu weergegeven in het gegenereerde OpenAPI-document zonder hettype: integerveld en hebben eenpatternveld dat de waarde beperkt tot cijfers. Dit gebeurt wanneer de NumberHandling eigenschap in de JsonSerializerOptions eigenschap is ingesteld opAllowReadingFromString, de standaardinstelling voor ASP.NET Core-web-apps. Als u C#intwilt inschakelen enlongin het OpenAPI-document wilt weergeven alstype: integer, stelt u de NumberHandling eigenschap in opStrict.
Met deze functie wordt de standaardVersie van OpenAPI voor gegenereerde documenten3.1. De versie kan worden gewijzigd door expliciet de eigenschap OpenApiVersion van de OpenApiOptions in te stellen in de configureOptions gedelegeerde parameter van AddOpenApi:
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_1;
});
Wanneer u het OpenAPI-document tijdens de build genereert, kan de OpenAPI-versie worden geselecteerd door het --openapi-version in te stellen in het OpenApiGenerateDocumentsOptions MSBuild-item:
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
<!-- Configure build-time OpenAPI generation to produce an OpenAPI 3.1 document. -->
<OpenApiGenerateDocumentsOptions>--openapi-version OpenApi3_1</OpenApiGenerateDocumentsOptions>
</PropertyGroup>
OpenAPI 3.1-ondersteuning is voornamelijk toegevoegd in de volgende PR-.
Breekende wijzigingen in OpenAPI 3.1
Ondersteuning voor OpenAPI 3.1 vereist een update naar de onderliggende OpenAPI.NET-bibliotheek naar een nieuwe primaire versie, 2.0. Deze nieuwe versie heeft enkele belangrijke wijzigingen ten opzichte van de vorige versie. De ingrijpende wijzigingen kunnen van invloed zijn op apps als deze document-, bewerking- of schematransformaties hebben. Belangrijke wijzigingen in deze iteratie zijn onder andere:
- Entiteiten in het OpenAPI-document, zoals bewerkingen en parameters, worden getypt als interfaces. Er bestaan concrete implementaties voor de ingebedde en verwijzingsvarianten van een entiteit. Een
IOpenApiSchemakan bijvoorbeeld een inlineOpenApiSchemazijn of eenOpenApiSchemaReferencedie verwijst naar een schema dat ergens anders in het document is gedefinieerd. - De eigenschap
Nullableis verwijderd uit hetOpenApiSchematype. Om te bepalen of een type nullable is, controleer of de eigenschapOpenApiSchema.TypeJsonSchemaType.Nullinstelt.
Een van de belangrijkste wijzigingen is dat de OpenApiAny klasse is verwijderd ten gunste van het rechtstreeks gebruiken van JsonNode. Transformatoren die gebruikmaken van OpenApiAny moeten worden bijgewerkt om JsonNodete kunnen gebruiken. In de volgende diff ziet u de wijzigingen in de schematransformator van .NET 9 naar .NET 10:
options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
if (context.JsonTypeInfo.Type == typeof(WeatherForecast))
{
- schema.Example = new OpenApiObject
+ schema.Example = new JsonObject
{
- ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")),
+ ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"),
- ["temperatureC"] = new OpenApiInteger(0),
+ ["temperatureC"] = 0,
- ["temperatureF"] = new OpenApiInteger(32),
+ ["temperatureF"] = 32,
- ["summary"] = new OpenApiString("Bracing"),
+ ["summary"] = "Bracing",
};
}
return Task.CompletedTask;
});
Houd er rekening mee dat deze wijzigingen nodig zijn, zelfs wanneer u de OpenAPI-versie alleen configureert op 3.0.
OpenAPI in YAML
ASP.NET biedt nu ondersteuning voor het leveren van het gegenereerde OpenAPI-document in YAML-indeling. YAML kan beknopter zijn dan JSON, waarbij accolades en aanhalingstekens worden geëlimineerd wanneer deze kunnen worden afgeleid. YAML ondersteunt ook tekenreeksen met meerdere regels, wat handig kan zijn voor lange beschrijvingen.
Als u een app wilt configureren voor het gegenereerde OpenAPI-document in YAML-indeling, geeft u het eindpunt op in de MapOpenApi-aanroep met het achtervoegsel '.yaml' of '.yml', zoals wordt weergegeven in het volgende voorbeeld:
if (app.Environment.IsDevelopment())
{
app.MapOpenApi("/openapi/{documentName}.yaml");
}
Ondersteuning voor:
- YAML is momenteel alleen beschikbaar voor de OpenAPI die wordt geleverd vanuit het OpenAPI-eindpunt.
- Het genereren van OpenAPI-documenten in YAML-indeling tijdens de build wordt toegevoegd in een toekomstige preview.
Zie deze PR die ondersteuning heeft toegevoegd voor het uitserveren van het gegenereerde OpenAPI-document in YAML-formaat.
Beschrijving van antwoord voor ProducesResponseType API-controllers
De ProducesAttribute, ProducesResponseTypeAttributeen ProducesDefaultResponseTypeAttribute nu accepteren een optionele tekenreeksparameter, Descriptionwaarmee de beschrijving van het antwoord wordt ingesteld:
[HttpGet(Name = "GetWeatherForecast")]
[ProducesResponseType<IEnumerable<WeatherForecast>>(StatusCodes.Status200OK,
Description = "The weather forecast for the next 5 days.")]
public IEnumerable<WeatherForecast> Get()
{
Gegenereerde OpenAPI-gegevens:
"responses": {
"200": {
"description": "The weather forecast for the next 5 days.",
"content": {
Deze functionaliteit wordt ondersteund in api-controllers en minimale API's. Voor minimale API's is de Description eigenschap correct ingesteld, zelfs wanneer het type van het kenmerk en het uitgestelde retourtype geen exacte overeenkomst zijn.
Bijdrage van de gemeenschap (dotnet/aspnetcore #58193) door Sander ten Brinke.
Xml-documentopmerkingen invullen in OpenAPI-document
ASP.NET Core OpenAPI-documentgeneratie bevat nu metagegevens uit XML-documentenopmerkingen over methode-, klasse- en liddefinities in het OpenAPI-document. U moet xml-documentopmerkingen inschakelen in uw projectbestand om deze functie te kunnen gebruiken. U kunt dit doen door de volgende eigenschap toe te voegen aan uw projectbestand:
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Tijdens de build maakt het OpenAPI-pakket gebruik van een brongenerator om XML-opmerkingen in de huidige toepassingsassembly en projectverwijzingen te detecteren en broncode te verzenden om deze in het document in te voegen via een OpenAPI-documenttransformatie.
Houd er rekening mee dat tijdens het C#-buildproces geen XML-documentopmerkingen worden vastgelegd die in lambda expresions worden geplaatst. Als u dus xml-documentopmerkingen wilt gebruiken om metagegevens toe te voegen aan een minimal API-eindpunt, moet u de eindpunthandler definiëren als een methode, de OPMERKINGEN van het XML-document op de methode plaatsen en vervolgens naar die methode verwijzen vanuit de MapXXX methode. Als u bijvoorbeeld xml-documentopmerkingen wilt gebruiken om metagegevens toe te voegen aan een minimaal API-eindpunt dat oorspronkelijk is gedefinieerd als een lambda-expressie:
app.MapGet("/hello", (string name) =>$"Hello, {name}!");
Wijzig de MapGet-aanroep om te verwijzen naar een methode:
app.MapGet("/hello", Hello);
Definieer de methode Hello met xml-documentenopmerkingen:
static partial class Program
{
/// <summary>
/// Sends a greeting.
/// </summary>
/// <remarks>
/// Greeting a person by their name.
/// </remarks>
/// <param name="name">The name of the person to greet.</param>
/// <returns>A greeting.</returns>
public static string Hello(string name)
{
return $"Hello, {name}!";
}
}
In het vorige voorbeeld wordt de methode Hello toegevoegd aan de Program-klasse, maar u kunt deze toevoegen aan elke klasse in uw project.
In het vorige voorbeeld ziet u de <summary>, <remarks>en <param> XML-documentopmerkingen.
Zie de C#-documentatievoor meer informatie over xml-documentopmerkingen, inclusief alle ondersteunde tags.
Omdat de kernfunctionaliteit wordt geboden via een brongenerator, kan deze worden uitgeschakeld door de volgende MSBuild toe te voegen aan uw projectbestand.
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.2.*" GeneratePathProperty="true" />
</ItemGroup>
<Target Name="DisableCompileTimeOpenApiXmlGenerator" BeforeTargets="CoreCompile">
<ItemGroup>
<Analyzer Remove="$(PkgMicrosoft_AspNetCore_OpenApi)/analyzers/dotnet/cs/Microsoft.AspNetCore.OpenApi.SourceGenerators.dll" />
</ItemGroup>
</Target>
De brongenerator verwerkt XML-bestanden die zijn opgenomen in de eigenschap AdditionalFiles. Als u de eigenschap wilt toevoegen (of verwijderen), wijzigt u de eigenschap als volgt:
<Target Name="AddXmlSources" BeforeTargets="CoreCompile">
<ItemGroup>
<AdditionalFiles Include="$(PkgSome_Package)/lib/net10.0/Some.Package.xml" />
</ItemGroup>
</Target>
Microsoft.AspNetCore.OpenApi toegevoegd aan de ASP.NET Core web-API (Native AOT) template
De projectsjabloon ASP.NET Core Web API (Native AOT) (korte naam webapiaot) bevat nu standaard ondersteuning voor het genereren van OpenAPI-documenten met behulp van het Microsoft.AspNetCore.OpenApi pakket . Deze ondersteuning wordt uitgeschakeld door de --no-openapi vlag te gebruiken bij het aanmaken van een nieuw project.
Bijdrage van de gemeenschap (dotnet/aspnetcore #60337) door Sander ten Brinke.
Ondersteuning voor IOpenApiDocumentProvider in de DI-container.
ASP.NET Core in .NET 10 ondersteunt IOpenApiDocumentProvider in de container voor afhankelijkheidsinjectie (DI). Ontwikkelaars kunnen in hun apps injecteren IOpenApiDocumentProvider en gebruiken om toegang te krijgen tot het OpenAPI-document. Deze methode is handig voor het openen van OpenAPI-documenten buiten de context van HTTP-aanvragen, zoals in achtergrondservices of aangepaste middleware.
Voorheen kon het uitvoeren van opstartlogica voor toepassingen zonder een HTTP-server te starten worden uitgevoerd met behulp van HostFactoryResolver een no-op-implementatie IServer . De nieuwe functie vereenvoudigt dit proces door een gestroomlijnde API te bieden die geïnspireerd is op Aspire's IDistributedApplicationPublisher, dat deel uitmaakt van het framework voor het hosten en publiceren van Aspiregedistribueerde toepassingen.
Zie dotnet/aspnetcore #61463 voor meer informatie.
Verbeteringen in de XML-opmerkingengenerator
Het genereren van XML-opmerkingen verwerkt complexe typen in .NET 10 beter dan eerdere versies van .NET.
- Het produceert nauwkeurige en volledige XML-opmerkingen voor een breder scala aan typen.
- Het verwerkt complexere scenario's.
- Het slaat de verwerking probleemloos over voor complexe typen die buildfouten in eerdere versies veroorzaken.
Deze verbeteringen wijzigen de foutmodus voor bepaalde scenario's van buildfouten in ontbrekende metagegevens.
Daarnaast kan de verwerking van xml-documentenopmerkingen nu worden geconfigureerd voor toegang tot XML-opmerkingen in andere assembly's. Dit is handig voor het genereren van documentatie voor typen die buiten de huidige assembly zijn gedefinieerd, zoals het ProblemDetails type in de Microsoft.AspNetCore.Http naamruimte.
Deze configuratie wordt uitgevoerd met instructies in het projectbuildbestand. In het volgende voorbeeld ziet u hoe u de GENERATOR voor XML-opmerkingen configureert voor toegang tot XML-opmerkingen voor typen in de Microsoft.AspNetCore.Http assembly, waaronder de ProblemDetails klasse.
<Target Name="AddOpenApiDependencies" AfterTargets="ResolveReferences">
<ItemGroup>
<!-- Include XML documentation from Microsoft.AspNetCore.Http.Abstractions
to get metadata for ProblemDetails -->
<AdditionalFiles
Include="@(ReferencePath->'
%(RootDir)%(Directory)%(Filename).xml')"
Condition="'%(ReferencePath.Filename)' ==
'Microsoft.AspNetCore.Http.Abstractions'"
KeepMetadata="Identity;HintPath" />
</ItemGroup>
</Target>
In toekomstige previews verwachten we XML-opmerkingen van een geselecteerde set assembly's in het gedeelde framework op te nemen om te voorkomen dat deze configuratie in de meeste gevallen nodig is.
Geïntegreerde verwerking van documentatie-id's in openAPI XML-opmerkingengenerator
XML-documentatieopmerkingen van assembly's waarnaar wordt verwezen, worden correct samengevoegd, zelfs wanneer de bijbehorende documentatie-id's retourtypeachtervoegsels bevatten. Als gevolg hiervan worden alle geldige XML-opmerkingen betrouwbaar opgenomen in gegenereerde OpenAPI-documentatie, waardoor de nauwkeurigheid en volledigheid van documentatie voor API's worden verbeterd met behulp van assembly's waarnaar wordt verwezen.
Formuliergegevens enumparameters maken gebruik van het werkelijke enumtype in OpenAPI
Formuliergegevensparameters in MVC-controlleracties genereren nu OpenAPI-metagegevens met behulp van het werkelijke enumtype in plaats van standaardtekenreeksen.
Bijdrage van de Gemeenschap: Dankzij @ascott18!
Ondersteuning voor het genereren van OpenApiSchema's in transformatoren
Ontwikkelaars kunnen nu een schema genereren voor een C#-type met dezelfde logica als ASP.NET Core OpenAPI-documentgeneratie en dit toevoegen aan het OpenAPI-document. Er kan vervolgens naar het schema worden verwezen vanuit een andere locatie in het OpenAPI-document.
De context die wordt doorgegeven aan document-, bewerkings- en schematransformatoren bevat een nieuwe GetOrCreateSchemaAsync methode die kan worden gebruikt om een schema voor een type te genereren.
Deze methode heeft ook een optionele ApiParameterDescription parameter voor het opgeven van aanvullende metagegevens voor het gegenereerde schema.
Ter ondersteuning van het toevoegen van het schema aan het OpenAPI-document is een Document eigenschap toegevoegd aan de contexten van de bewerkings- en schematransformatie. Hierdoor kan elke transformator een schema toevoegen aan het OpenAPI-document met behulp van de methode van AddComponent het document.
Example
Als u deze functie wilt gebruiken in een document, bewerking of schematransformatie, maakt u het schema met behulp van de GetOrCreateSchemaAsync methode in de context en voegt u het toe aan het OpenAPI-document met behulp van de methode van AddComponent het document.
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer(async (operation, context, cancellationToken) =>
{
// Generate schema for error responses
var errorSchema = await context.GetOrCreateSchemaAsync(typeof(ProblemDetails), null, cancellationToken);
context.Document?.AddComponent("Error", errorSchema);
operation.Responses ??= new OpenApiResponses();
// Add a "4XX" response to the operation with the newly created schema
operation.Responses["4XX"] = new OpenApiResponse
{
Description = "Bad Request",
Content = new Dictionary<string, OpenApiMediaType>
{
["application/problem+json"] = new OpenApiMediaType
{
Schema = new OpenApiSchemaReference("Error", context.Document)
}
}
};
});
});
Eindpuntspecifieke OpenAPI-bewerkingstransformatoren
Met eindpuntspecifieke bewerkingstransformatoren kunt u nauwkeurig aangepaste openAPI-documentatie aanpassen voor afzonderlijke route-eindpunten. Met deze functie kunnen ontwikkelaars Swagger-/OpenAPI-metagegevens en -beschrijvingen aanpassen per actie of per route, waardoor uitbreidingsmogelijkheden voor geavanceerde API-scenario's worden verbeterd.
Zie OpenAPI-documenten aanpassen voor implementatiedetails en codevoorbeelden.
Microsoft.OpenApi upgraden naar 2.0.0
De Microsoft.OpenApi bibliotheek die wordt gebruikt voor het genereren van OpenAPI-documenten in ASP.NET Core is bijgewerkt naar versie 2.0.0 (GA).
Belangrijke wijzigingen in 2.0.0
De volgende belangrijke wijzigingen zijn geïntroduceerd in de preview-versies en blijven in de GA-versie. Deze zijn voornamelijk van invloed op gebruikers die document-, bewerkings- of schematransformaties implementeren:
- Tijdelijke objecteigenschappen bevinden zich nu in metagegevens
- HTTP-methodeobject gebruiken in plaats van Enum
Met de update van de GA-versie worden er geen verdere belangrijke wijzigingen verwacht in het genereren van OpenAPI-documenten.
Verbeteringen voor het genereren van OpenAPI-schema's
Nullable typen modelleren met oneOf in het OpenAPI-schema
Het genereren van openAPI-schema's voor null-typen is verbeterd met behulp van het oneOf patroon in plaats van de eigenschap null voor complexe typen en verzamelingen. De implementatie:
- Gebruikt
oneOfmetnullen het daadwerkelijke typeschema voor nulwaarde complexe typen in aanvraag- en antwoordschema's. - Detecteert null-waarde voor parameters, eigenschappen en retourtypen met weerspiegeling en
NullabilityInfoContext. - Verwijdert null-typen uit gecomponentiseerde schema's om duplicatie te voorkomen.
Herstelacties en verbeteringen voor schema-referentieoplossing
Deze release verbetert de verwerking van JSON-schema's voor het genereren van OpenAPI-documenten door relatieve JSON-schemaverwijzingen ($ref) in het hoofdschemadocument correct op te lossen.
Eigenschapsbeschrijvingen opnemen als elementen van $ref in OpenAPI-schema's
Voorafgaand aan .NET 10, verwijderde ASP.NET Core beschrijvingen van eigenschappen die met $ref zijn gedefinieerd in het gegenereerde OpenAPI-document, omdat OpenAPI v3.0 in schemadefinities geen eigenschappen als broeders naast $ref toestaat. Met OpenAPI 3.1 kunt u nu beschrijvingen opnemen naast $ref. RC1 voegt ondersteuning toe voor het opnemen van eigenschapsbeschrijvingen als naastgelegen elementen van $ref in het gegenereerde OpenAPI-schema.
Dit was een bijdrage van de gemeenschap. Bedankt @desjoerd!
Metagegevens van XML-opmerkingen toevoegen aan [AsParameters]-typen in het OpenAPI-schema
Het genereren van openAPI-schema's verwerkt nu XML-opmerkingen over eigenschappen van [AsParameters] parameterklassen om metagegevens voor documentatie te extraheren.
Onbekende HTTP-methoden uitsluiten van OpenAPI
Het genereren van een OpenAPI-schema sluit nu onbekende HTTP-methoden uit van het gegenereerde OpenAPI-document. Querymethoden, die standaard HTTP-methoden zijn, maar niet worden herkend door OpenAPI, worden nu probleemloos uitgesloten van het gegenereerde OpenAPI-document.
Dit was een bijdrage van de gemeenschap. Bedankt @martincostello!
De beschrijving van JSON Patch-aanvraagteksten verbeteren
De openAPI-schemageneratie voor JSON Patch-bewerkingen past nu het application/json-patch+json mediatype correct toe op aanvraagteksten die gebruikmaken van JSON Patch. Dit zorgt ervoor dat het gegenereerde OpenAPI-document het verwachte mediatype voor JSON Patch-bewerkingen nauwkeurig weergeeft. Daarnaast heeft de aanvraagbody van de JSON Patch een gedetailleerd schema dat de structuur van het JSON Patch-document beschrijft, inclusief de bewerkingen die kunnen worden uitgevoerd.
Dit was een bijdrage van de gemeenschap. Bedankt @martincostello!
Invariante cultuur gebruiken voor het genereren van OpenAPI-documenten
Het genereren van OpenAPI-documenten maakt nu gebruik van invariante cultuur voor het opmaken van getallen en datums in het gegenereerde OpenAPI-document. Dit zorgt ervoor dat het gegenereerde document consistent is en niet varieert op basis van de cultuurinstellingen van de server.
Dit was een bijdrage van de gemeenschap. Bedankt @martincostello!
Verificatie en autorisatie
Metrische gegevens over verificatie en autorisatie
Er zijn metrische gegevens toegevoegd voor bepaalde verificatie- en autorisatiegebeurtenissen in ASP.NET Core. Met deze wijziging kunt u nu metrische gegevens verkrijgen voor de volgende gebeurtenissen:
- Authentication:
- Geverifieerde aanvraagduur
- Aantal uitdagingen
- Het tellen verbieden
- Aantal aanmeldingen
- Aantal afmelden
- Authorization:
- Aantal aanvragen waarvoor autorisatie is vereist
In de volgende afbeelding ziet u een voorbeeld van de metrische gegevens voor de geverifieerde aanvraagduur in het Aspire dashboard:
Voor meer informatie, zie ASP.NET Core ingebouwde statistieken.
Identity metrische kerngegevens ASP.NET
ASP.NET Core Identity waarneembaarheid is verbeterd in .NET 10 met metrische gegevens. Metrische gegevens zijn tellers, histogrammen en meters die tijdreeksmetingen bieden van systeem- of toepassingsgedrag.
Gebruik bijvoorbeeld de nieuwe metrische gegevens van ASP.NET Core Identity om het volgende te bekijken:
- Gebruikersbeheer: Nieuwe gebruikerscreaties, wachtwoordwijzigingen en roltoewijzingen.
- Aanmeldings-/sessieafhandeling: aanmeldingspogingen, aanmeldingen, afmeldingen en gebruikers met tweeledige verificatie.
De nieuwe metrische gegevens bevinden zich in de Microsoft.AspNetCore.Identity meter:
aspnetcore.identity.user.create.durationaspnetcore.identity.user.update.durationaspnetcore.identity.user.delete.durationaspnetcore.identity.user.check_password_attemptsaspnetcore.identity.user.generated_tokensaspnetcore.identity.user.verify_token_attemptsaspnetcore.identity.sign_in.authenticate.durationaspnetcore.identity.sign_in.check_password_attemptsaspnetcore.identity.sign_in.sign_insaspnetcore.identity.sign_in.sign_outsaspnetcore.identity.sign_in.two_factor_clients_rememberedaspnetcore.identity.sign_in.two_factor_clients_forgotten
Zie ASP.NET Core-metrische gegevens voor meer informatie over het gebruik van metrische gegevens in ASP.NET Core.
Aanmeldingsomleidingen voorkomen cookie voor bekende API-eindpunten
Standaard leiden niet-geverifieerde en niet-geautoriseerde aanvragen die zijn gedaan naar bekende API-eindpunten die worden beveiligd door cookie verificatie, nu tot 401- en 403-antwoorden in plaats van om te leiden naar een aanmeldings- of toegang geweigerde URI.
Deze wijziging is zeer aangevraagd, omdat het omleiden van niet-geverifieerde aanvragen naar een aanmeldingspagina meestal niet zinvol is voor API-eindpunten die doorgaans afhankelijk zijn van 401- en 403-statuscodes in plaats van HTML-omleidingen om verificatiefouten te communiceren.
Bekende API-eindpunten worden geïdentificeerd met behulp van de nieuwe IApiEndpointMetadata interface en metagegevens die de nieuwe interface implementeren, worden automatisch toegevoegd aan het volgende:
-
[ApiController]Eindpunten - Minimale API-eindpunten die JSON-aanvraagteksten lezen of JSON-antwoorden schrijven
- Eindpunten met retourtypen
TypedResults - SignalR Eindpunten
Wanneer IApiEndpointMetadata deze aanwezig is, retourneert de cookie verificatiehandler nu de juiste HTTP-statuscodes (401 voor niet-geverifieerde aanvragen, 403 voor verboden aanvragen) in plaats van omleiden.
Als u dit nieuwe gedrag wilt voorkomen en altijd wilt omleiden naar de aanmeldings- en toegang geweigerde URI's voor niet-geverifieerde of niet-geautoriseerde aanvragen, ongeacht het doeleindpunt, kunt u de RedirectToLogin en RedirectToAccessDenied gebeurtenissen als volgt overschrijven:
builder.Services.AddAuthentication()
.AddCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
Zie ASP.NET Aankondiging van belangrijke wijzigingen voor belangrijke wijzigingen voor meer informatie over deze belangrijke wijziging.
Miscellaneous
In deze sectie worden diverse nieuwe functies in .NET 10 beschreven.
Diagnostische gegevens van uitzonderingshandlers onderdrukken
Er is een nieuwe configuratieoptie toegevoegd aan de middleware van de ASP.NET Core-uitzonderingshandler om diagnostische uitvoer te beheren: ExceptionHandlerOptions.SuppressDiagnosticsCallback. Deze callback wordt doorgegeven in de context van de aanvraag en uitzondering, zodat u logica kunt toevoegen die bepaalt of de middleware uitzonderingslogboeken en andere telemetriegegevens moet schrijven.
Deze instelling is handig wanneer u weet dat een uitzondering tijdelijk is of is verwerkt door de middleware van de uitzonderingshandler en u geen foutenlogboeken wilt schrijven naar uw waarneembaarheidsplatform.
Het standaardgedrag van de middleware is ook gewijzigd: er wordt geen uitzonderingsdiagnose meer geschreven voor uitzonderingen die worden verwerkt door IExceptionHandler. Op basis van feedback van gebruikers was logboekregistratie afgehandelde uitzonderingen op foutniveau vaak ongewenst bij IExceptionHandler.TryHandleAsync het retourneren true.
U kunt terugkeren naar het vorige gedrag door het volgende te SuppressDiagnosticsCallbackconfigureren:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
SuppressDiagnosticsCallback = context => false;
});
Zie voor meer informatie over deze wijziging die fouten veroorzaken https://github.com/aspnet/Announcements/issues/524.
Ondersteuning voor het domein .localhost Top-Level
Het .localhost domein op het hoogste niveau (TLD) wordt gedefinieerd in RFC2606 en RFC6761 als gereserveerd voor testdoeleinden en beschikbaar voor gebruikers om lokaal te gebruiken, net als elke andere domeinnaam. Dit betekent dat het gebruik van een naam zoals myapp.localhost lokaal die wordt omgezet in het IP-loopback-adres is toegestaan en verwacht volgens deze RFC's. Bovendien worden in moderne groenblijvende browsers al automatisch elke *.localhost naam omgezet in het IP-loopback-adres (127.0.0.1/::1), waardoor ze effectief een alias worden voor elke service die al wordt gehost op localhost de lokale computer, dat wil gezegd, elke service waarop wordt gereageerd ook reageert http://localhost:6789http://anything-here.localhost:6789, ervan uitgaande dat er geen verdere specifieke hostnaamverificatie of afdwinging wordt uitgevoerd door de service.
ASP.NET Core is bijgewerkt in .NET 10 Preview 7 om de .localhost TLD beter te ondersteunen, zodat deze nu eenvoudig kan worden gebruikt bij het maken en uitvoeren van ASP.NET Core-toepassingen in uw lokale ontwikkelomgeving. Als verschillende apps lokaal worden uitgevoerd, kunnen deze worden omgezet via verschillende namen, waardoor sommige aan een domeinnaam gekoppelde websiteassets beter kunnen worden gescheiden, bijvoorbeeld cookies, en kunt u gemakkelijker identificeren welke app u bladert via de naam die wordt weergegeven in de adresbalk van de browser.
ASP.NET Ingebouwde HTTP-server van Core worden Kestrelnu alle *.localhost namen die zijn ingesteld via ondersteunde eindpuntconfiguratiemechanismen correct behandeld als het lokale loopback-adres en binden deze dus in plaats van alle externe adressen (dus binden aan127.0.0.1)./::10.0.0.0/:: Dit omvat de "applicationUrl" eigenschap in startprofielen die zijn geconfigureerd in een launchSettings.json-bestand en de ASPNETCORE_URLS omgevingsvariabele. Wanneer deze is geconfigureerd om op een .localhost adres te luisteren, Kestrel wordt er een informatiebericht voor .localhost de localhost adressen vastgelegd om duidelijk te maken dat beide namen kunnen worden gebruikt.
Hoewel webbrowsers namen automatisch omzetten *.localhost in het lokale loopback-adres, kunnen andere apps namen behandelen *.localhost als gewone domeinnamen en proberen ze op te lossen via hun bijbehorende DNS-stack. Als uw DNS-configuratie geen namen naar een adres oplost *.localhost , kunnen ze geen verbinding maken. U kunt de normale localhost naam blijven gebruiken om uw apps te adresseren wanneer u zich niet in een webbrowser aanmeldt.
Het ASP.NET Core HTTPS-ontwikkelingscertificaat (inclusief de dotnet dev-certs https opdracht) is bijgewerkt om ervoor te zorgen dat het certificaat geldig is voor gebruik met de *.dev.localhost domeinnaam. Nadat u .NET 10 SDK Preview 7 hebt geïnstalleerd, vertrouwt u het nieuwe ontwikkelaarscertificaat door op de opdrachtregel uit te voeren dotnet dev-certs https --trust om ervoor te zorgen dat uw systeem is geconfigureerd om het nieuwe certificaat te vertrouwen.
Het certificaat vermeldt de *.dev.localhost naam als een alternatieve naam voor onderwerp (SAN) in plaats *.localhost van omdat het gebruik van een jokertekencertificaat voor een domeinnaam op het hoogste niveau ongeldig is.
De projectsjablonen voor ASP.NET Core Empty (web) en Blazor Web App (blazor) zijn bijgewerkt met een nieuwe optie die, wanneer opgegeven het gemaakte project configureert voor gebruik van het achtervoegsel van de .dev.localhost domeinnaam, waarbij deze wordt gecombineerd met de projectnaam, zodat de app naar een adres kan worden gekeken, zoals https://myapp.dev.localhost:5036:
$ dotnet new web -n MyApp --localhost-tld
The template "ASP.NET Core Empty" was created successfully.
Processing post-creation actions...
Restoring D:\src\MyApp\MyApp.csproj:
Restore succeeded.
$ cd .\MyApp\
$ dotnet run --launch-profile https
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://myapp.dev.localhost:7099
info: Microsoft.Hosting.Lifetime[14]
Now listening on: https://localhost:7099/
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://myapp.dev.localhost:5036
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5036/
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: D:\src\local\10.0.1xx\MyApp
Ondersteuning voor Json+PipeReader-deserialisatie in MVC en minimale API's
PR: https://github.com/dotnet/aspnetcore/pull/62895
MVC, Minimale API's en de HttpRequestJsonExtensions.ReadFromJsonAsync methoden zijn allemaal bijgewerkt om de nieuwe ondersteuning voor Json+PipeReader te gebruiken zonder dat er codewijzigingen van toepassingen nodig zijn.
Voor de meeste toepassingen heeft de toevoeging van deze ondersteuning geen effect op hun gedrag. Als de toepassing echter een aangepaste JsonConvertertoepassing gebruikt, is er een kans dat het conversieprogramma niet correct wordt verwerkt Utf8JsonReader.HasValueSequence . Dit kan leiden tot ontbrekende gegevens en fouten, zoals ArgumentOutOfRangeException, bij het deserialiseren.
De snelle tijdelijke oplossing (vooral als u niet de eigenaar bent van de gebruikte aangepaste JsonConverter versie) is het instellen van de "Microsoft.AspNetCore.UseStreamBasedJsonParsing"AppContext schakeloptie op "true". Dit moet een tijdelijke tijdelijke oplossing zijn en de JsonConverter oplossing moet worden bijgewerkt ter ondersteuning HasValueSequence.
JsonConverter Er is een snelle oplossing die een matrix van de ReadOnlySequence implementaties toewijst en eruitziet als in het volgende voorbeeld:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
// previous code
}
Er is ook een complexere (maar performante) oplossing, waarbij een afzonderlijk codepad voor de ReadOnlySequence verwerking nodig is:
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.HasValueSequence)
{
reader.ValueSequence;
// ReadOnlySequence optimized path
}
else
{
reader.ValueSpan;
// ReadOnlySpan optimized path
}
}
Automatische verwijdering uit geheugengroep
De geheugenpools, die worden gebruikt door Kestrel, IIS en HTTP.sys, maken nu automatisch geheugenblokken vrij wanneer de toepassing niet actief is of minder belast. De functie wordt automatisch uitgevoerd en hoeft niet handmatig te worden ingeschakeld of geconfigureerd.
Waarom geheugenverwijdering belangrijk is
Voorheen zou geheugen dat door de pool is toegewezen, gereserveerd blijven, zelfs wanneer deze niet in gebruik is. Met deze functie wordt geheugen terug naar het systeem vrijgegeven wanneer de app gedurende een bepaalde periode niet actief is. Deze verwijdering vermindert het totale geheugengebruik en helpt toepassingen responsief te blijven onder verschillende werkbelastingen.
Metrische gegevens over het verwijderen van geheugen gebruiken
Er zijn metrische gegevens toegevoegd aan de standaardgeheugengroep die wordt gebruikt door onze server-implementaties. De nieuwe metrische gegevens staan onder de naam "Microsoft.AspNetCore.MemoryPool".
Zie ASP.NET Kerngegevens voor informatie over metrische gegevens en hoe u deze kunt gebruiken.
Geheugengroepen beheren
Naast het efficiënter gebruiken van geheugengroepen door overbodige geheugenblokken te verwijderen, verbetert .NET 10 de ervaring van het maken van geheugengroepen. Dit doet het door een ingebouwde IMemoryPoolFactory en een MemoryPoolFactory implementatie te bieden. Hiermee wordt de implementatie beschikbaar voor uw toepassing via afhankelijkheidsinjectie.
In het volgende codevoorbeeld ziet u een eenvoudige achtergrondservice die gebruikmaakt van de implementatie van de ingebouwde geheugenpoolfactory om geheugengroepen te maken. Deze pools profiteren van de functie voor automatische verwijdering:
public class MyBackgroundService : BackgroundService
{
private readonly MemoryPool<byte> _memoryPool;
public MyBackgroundService(IMemoryPoolFactory<byte> factory)
{
_memoryPool = factory.Create();
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
await Task.Delay(20, stoppingToken);
// do work that needs memory
var rented = _memoryPool.Rent(100);
rented.Dispose();
}
catch (OperationCanceledException)
{
return;
}
}
}
}
Als u uw eigen geheugenpoolfabriek wilt gebruiken, maakt u een klasse die IMemoryPoolFactory implementeert en deze registreert bij afhankelijkheidsinjectie, zoals in het volgende voorbeeld. Geheugengroepen die op deze manier zijn gemaakt, profiteren ook van de functie voor automatische verwijdering:
services.AddSingleton<IMemoryPoolFactory<byte>,
CustomMemoryPoolFactory>();
public class CustomMemoryPoolFactory : IMemoryPoolFactory<byte>
{
public MemoryPool<byte> Create()
{
// Return a custom MemoryPool implementation
// or the default, as is shown here.
return MemoryPool<byte>.Shared;
}
}
Aanpasbare beveiligingsdescriptors voor HTTP.sys
U kunt nu een aangepaste beveiligingsdescriptor opgeven voor HTTP.sys aanvraagwachtrijen. De nieuwe eigenschap RequestQueueSecurityDescriptor op HttpSysOptions maakt gedetailleerdere controle mogelijk over toegangsrechten voor de aanvraagwachtrij. Met deze gedetailleerde controle kunt u de beveiliging aanpassen aan de behoeften van uw toepassing.
Wat u kunt doen met de nieuwe eigenschap
Een aanvraagwachtrij in HTTP.sys is een structuur op kernelniveau waarin binnenkomende HTTP-aanvragen tijdelijk worden opgeslagen totdat uw toepassing klaar is om ze te verwerken. Door de beveiligingsdescriptor aan te passen, kunt u specifieke gebruikers of groepen toegang tot de aanvraagwachtrij toestaan of weigeren. Dit is handig in scenario's waarin u HTTP.sys aanvraagafhandeling op besturingssysteemniveau wilt beperken of delegeren.
Hoe de nieuwe eigenschap te gebruiken
De RequestQueueSecurityDescriptor eigenschap is alleen van toepassing wanneer u een nieuwe aanvraagwachtrij maakt. De eigenschap heeft geen invloed op bestaande verzoekwachtrijen. Als u deze eigenschap wilt gebruiken, stelt u deze in op een GenericSecurityDescriptor exemplaar bij het configureren van uw HTTP.sys-server.
De volgende code staat bijvoorbeeld alle geverifieerde gebruikers toe, maar weigert gasten:
using System.Security.AccessControl;
using System.Security.Principal;
using Microsoft.AspNetCore.Server.HttpSys;
// Create a new security descriptor
var securityDescriptor = new CommonSecurityDescriptor(isContainer: false, isDS: false, sddlForm: string.Empty);
// Create a discretionary access control list (DACL)
var dacl = new DiscretionaryAcl(isContainer: false, isDS: false, capacity: 2);
dacl.AddAccess(
AccessControlType.Allow,
new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null),
-1,
InheritanceFlags.None,
PropagationFlags.None
);
dacl.AddAccess(
AccessControlType.Deny,
new SecurityIdentifier(WellKnownSidType.BuiltinGuestsSid, null),
-1,
InheritanceFlags.None,
PropagationFlags.None
);
// Assign the DACL to the security descriptor
securityDescriptor.DiscretionaryAcl = dacl;
// Configure HTTP.sys options
var builder = WebApplication.CreateBuilder();
builder.WebHost.UseHttpSys(options =>
{
options.RequestQueueSecurityDescriptor = securityDescriptor;
});
Zie HTTP.sys webserver-implementatie in ASP.NET Corevoor meer informatie.
Betere ondersteuning voor het testen van apps met instructies op het hoogste niveau
.NET 10 biedt nu betere ondersteuning voor het testen van apps die gebruikmaken van top-level instructies. Voorheen moesten ontwikkelaars handmatig public partial class Program toevoegen aan het Program.cs-bestand, zodat het testproject naar de Program classkon verwijzen.
public partial class Program was nodig omdat de top-level statement functie in C# 9 een Program class heeft gegenereerd die is gedeclareerd als interne.
In .NET 10 wordt een brongenerator gebruikt om de declaratie public partial class Program te genereren als de programmeur deze niet expliciet heeft gededeclaratie. Daarnaast is er een analyse toegevoegd om te detecteren wanneer public partial class Program expliciet wordt gedeclareerd en adviseert de ontwikkelaar om deze te verwijderen.
De volgende pull-aanvragen hebben aan deze functionaliteit bijgedragen:
Nieuwe JSON Patch-implementatie met System.Text.Json
- Is een standaardindeling voor het beschrijven van wijzigingen die moeten worden toegepast op een JSON-document.
- Wordt gedefinieerd in RFC 6902 en wordt veel gebruikt in RESTful-API's om gedeeltelijke updates uit te voeren voor JSON-resources.
- Vertegenwoordigt een reeks bewerkingen (bijvoorbeeld Toevoegen, Verwijderen, Vervangen, Verplaatsen, Kopiëren, Testen) die kunnen worden toegepast om een JSON-document te wijzigen.
In web-apps wordt JSON Patch vaak gebruikt in een PATCH-bewerking om gedeeltelijke updates van een resource uit te voeren. In plaats van de hele resource voor een update te verzenden, kunnen clients een JSON Patch-document met alleen de wijzigingen verzenden. Patching vermindert de payload en verbetert de efficiëntie.
In deze release wordt een nieuwe implementatie van Microsoft.AspNetCore.JsonPatch geïntroduceerd op basis van System.Text.Json serialisatie. Deze functie:
- Komt overeen met moderne .NET-procedures door gebruik te maken van de
System.Text.Jsonbibliotheek, die is geoptimaliseerd voor .NET. - Biedt verbeterde prestaties en minder geheugengebruik in vergelijking met de verouderde implementatie op basis van een oudere
Newtonsoft.Jsonversie.
De volgende benchmarks vergelijken de prestaties van de nieuwe System.Text.Json implementatie met de verouderde Newtonsoft.Json implementatie.
| Scenario | Implementation | Mean | Toegewezen geheugen |
|---|---|---|---|
| Benchmarks voor toepassingen | Newtonsoft.JsonPatch | 271.924 μs | 25 KB |
| System.Text.JsonPatch | 1,584 μs | 3 KB | |
| Deserialisatiebenchmarks | Newtonsoft.JsonPatch | 19,261 μs | 43 KB |
| System.Text.JsonPatch | 7,917 μs | 7 KB |
Deze benchmarks markeren aanzienlijke prestatieverbeteringen en een verminderd geheugengebruik met de nieuwe implementatie.
Notes:
- De nieuwe implementatie is geen vervanging voor de verouderde implementatie. In het bijzonder biedt de nieuwe implementatie geen ondersteuning voor dynamische typen, ExpandoObjectbijvoorbeeld.
- De JSON Patch-standaard heeft inherente beveiligingsrisico's. Omdat deze risico's inherent zijn aan de JSON Patch-standaard, probeert de nieuwe implementatie geen inherente beveiligingsrisico's te beperken. Het is de verantwoordelijkheid van de ontwikkelaar om ervoor te zorgen dat het JSON Patch-document veilig kan worden toegepast op het doelobject. Zie de sectie Beveiligingsrisico's beperken voor meer informatie.
Usage
Als u ondersteuning voor JSON Patch wilt inschakelen, System.Text.Jsoninstalleert u het Microsoft.AspNetCore.JsonPatch.SystemTextJson NuGet-pakket.
dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson --prerelease
Dit pakket biedt een JsonPatchDocument<T> klasse die een JSON Patch-document vertegenwoordigt voor objecten van het type T en aangepaste logica voor het serialiseren en deserialiseren van JSON Patch-documenten met behulp van System.Text.Json. De belangrijkste methode van de JsonPatchDocument<T> klasse is ApplyTo, waarmee de patchbewerkingen worden toegepast op een doelobject van het type T.
In de volgende voorbeelden ziet u hoe u de ApplyTo methode gebruikt om een JSON Patch-document toe te passen op een object.
Voorbeeld: Het toepassen van JsonPatchDocument
In het volgende voorbeeld ziet u:
- De
add,replaceenremovebewerkingen. - Bewerkingen op geneste eigenschappen.
- Een nieuw item toevoegen aan een matrix.
- Een JSON String Enum Converter gebruiken in een JSON Patch-document.
// Original object
var person = new Person {
FirstName = "John",
LastName = "Doe",
Email = "johndoe@gmail.com",
PhoneNumbers = [new() {Number = "123-456-7890", Type = PhoneNumberType.Mobile}],
Address = new Address
{
Street = "123 Main St",
City = "Anytown",
State = "TX"
}
};
// Raw JSON Patch document
var jsonPatch = """
[
{ "op": "replace", "path": "/FirstName", "value": "Jane" },
{ "op": "remove", "path": "/Email"},
{ "op": "add", "path": "/Address/ZipCode", "value": "90210" },
{
"op": "add",
"path": "/PhoneNumbers/-",
"value": { "Number": "987-654-3210", "Type": "Work" }
}
]
""";
// Deserialize the JSON Patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);
// Apply the JSON Patch document
patchDoc!.ApplyTo(person);
// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));
// Output:
// {
// "firstName": "Jane",
// "lastName": "Doe",
// "address": {
// "street": "123 Main St",
// "city": "Anytown",
// "state": "TX",
// "zipCode": "90210"
// },
// "phoneNumbers": [
// {
// "number": "123-456-7890",
// "type": "Mobile"
// },
// {
// "number": "987-654-3210",
// "type": "Work"
// }
// ]
// }
De ApplyTo methode volgt over het algemeen de conventies en opties voor het verwerken van System.Text.Json de JsonPatchDocument, inclusief het gedrag dat wordt beheerd door de volgende opties:
-
NumberHandling: Of numerieke eigenschappen worden gelezen uit tekenreeksen. -
PropertyNameCaseInsensitive: Of eigenschapsnamen al dan niet hoofdlettergevoelig zijn.
Belangrijke verschillen tussen System.Text.Json en de nieuwe JsonPatchDocument<T> implementatie:
- Het looptijdtype van het doelobject, niet het gedeclareerde type, bepaalt welke eigenschappen door
ApplyToworden aangepast. -
System.Text.Jsondeserialisatie is afhankelijk van het gedeclareerde type om in aanmerking komende eigenschappen te identificeren.
Voorbeeld: Toepassen van een JsonPatchDocument met foutafhandeling
Er zijn verschillende fouten die kunnen optreden bij het toepassen van een JSON Patch-document. Het doelobject heeft bijvoorbeeld mogelijk niet de opgegeven eigenschap of de opgegeven waarde is mogelijk niet compatibel met het eigenschapstype.
JSON Patch ondersteunt ook de test bewerking. De test bewerking controleert of een opgegeven waarde gelijk is aan de doeleigenschap en als dat niet het probleem is, wordt een fout geretourneerd.
In het volgende voorbeeld ziet u hoe u deze fouten probleemloos kunt afhandelen.
Important
Het object dat aan de ApplyTo methode wordt doorgegeven, wordt ter plaatse gewijzigd. Het is de verantwoordelijkheid van de beller om deze wijzigingen te negeren als een bewerking mislukt.
// Original object
var person = new Person {
FirstName = "John",
LastName = "Doe",
Email = "johndoe@gmail.com"
};
// Raw JSON Patch document
var jsonPatch = """
[
{ "op": "replace", "path": "/Email", "value": "janedoe@gmail.com"},
{ "op": "test", "path": "/FirstName", "value": "Jane" },
{ "op": "replace", "path": "/LastName", "value": "Smith" }
]
""";
// Deserialize the JSON Patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);
// Apply the JSON Patch document, catching any errors
Dictionary<string, string[]>? errors = null;
patchDoc!.ApplyTo(person, jsonPatchError =>
{
errors ??= new ();
var key = jsonPatchError.AffectedObject.GetType().Name;
if (!errors.ContainsKey(key))
{
errors.Add(key, new string[] { });
}
errors[key] = errors[key].Append(jsonPatchError.ErrorMessage).ToArray();
});
if (errors != null)
{
// Print the errors
foreach (var error in errors)
{
Console.WriteLine($"Error in {error.Key}: {string.Join(", ", error.Value)}");
}
}
// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));
// Output:
// Error in Person: The current value 'John' at path 'FirstName' is not equal
// to the test value 'Jane'.
// {
// "firstName": "John",
// "lastName": "Smith", <<< Modified!
// "email": "janedoe@gmail.com", <<< Modified!
// "phoneNumbers": []
// }
Beveiligingsrisico's beperken
Wanneer u het Microsoft.AspNetCore.JsonPatch.SystemTextJson pakket gebruikt, is het essentieel om mogelijke beveiligingsrisico's te begrijpen en te beperken. In de volgende secties worden de geïdentificeerde beveiligingsrisico's beschreven die zijn gekoppeld aan JSON Patch en worden aanbevolen oplossingen geboden om veilig gebruik van het pakket te garanderen.
Important
Dit is geen volledige lijst met bedreigingen. App-ontwikkelaars moeten hun eigen beoordelingen voor bedreigingsmodellen uitvoeren om een app-specifieke uitgebreide lijst te bepalen en zo nodig passende oplossingen te bedenken. Apps die verzamelingen beschikbaar maken voor patchbewerkingen, moeten bijvoorbeeld rekening houden met het potentieel voor algoritmen complexe aanvallen als deze bewerkingen elementen invoegen of verwijderen aan het begin van de verzameling.
Door uitgebreide bedreigingsmodellen voor hun eigen apps uit te voeren en geïdentificeerde bedreigingen aan te pakken terwijl ze de aanbevolen oplossingen hieronder volgen, kunnen consumenten van deze pakketten JSON Patch-functionaliteit integreren in hun apps en tegelijkertijd beveiligingsrisico's minimaliseren.
Consumenten van deze pakketten kunnen JSON Patch-functionaliteit integreren in hun apps en tegelijkertijd beveiligingsrisico's minimaliseren, waaronder:
- Voer uitgebreide bedreigingsmodellen uit voor hun eigen apps.
- Identificeer geïdentificeerde bedreigingen.
- Volg de aanbevolen maatregelen in de volgende gedeelten.
Denial of Service (DoS) via geheugenversterking
-
Scenario: Een kwaadwillende client verzendt een
copybewerking waarmee grote objectgrafieken meerdere keren worden gedupliceerd, wat leidt tot overmatig geheugenverbruik. - Impact: Potentiële out-Of-Memory (OOM)-omstandigheden, waardoor serviceonderbrekingen ontstaan.
-
Mitigation:
- Valideer binnenkomende JSON Patch-documenten voor grootte en structuur voordat u aanroept
ApplyTo. - De validatie moet specifiek zijn voor de app, maar een voorbeeldvalidatie kan er ongeveer als volgt uitzien:
- Valideer binnenkomende JSON Patch-documenten voor grootte en structuur voordat u aanroept
public void Validate(JsonPatchDocument<T> patch)
{
// This is just an example. It's up to the developer to make sure that
// this case is handled properly, based on the app's requirements.
if (patch.Operations.Where(op=>op.OperationType == OperationType.Copy).Count()
> MaxCopyOperationsCount)
{
throw new InvalidOperationException();
}
}
Subversie van bedrijfslogica
- Scenario: Patchbewerkingen kunnen velden bewerken met impliciete invarianten (bijvoorbeeld interne vlaggen, id's of berekende velden), die zakelijke beperkingen schenden.
- Impact: Problemen met gegevensintegriteit en onbedoeld app-gedrag.
-
Mitigation:
- Gebruik POCO-objecten met expliciet gedefinieerde eigenschappen die veilig kunnen worden gewijzigd.
- Vermijd het blootstellen van gevoelige of beveiligingskritieke eigenschappen in het doelobject.
- Als er geen POCO-object wordt gebruikt, valideert u het gepatchte object na het toepassen van bewerkingen om ervoor te zorgen dat bedrijfsregels en invarianten niet worden geschonden.
Verificatie en autorisatie
- Scenario: Niet-geverifieerde of niet-geautoriseerde clients verzenden schadelijke JSON Patch-aanvragen.
- Impact: onbevoegde toegang om gevoelige gegevens te wijzigen of het gedrag van apps te verstoren.
-
Mitigation:
- Beveilig eindpunten die JSON Patch-aanvragen accepteren met de juiste verificatie- en autorisatiemechanismen.
- Beperk de toegang tot vertrouwde clients of gebruikers met de juiste machtigingen.
Detecteren of een URL lokaal is met RedirectHttpResult.IsLocalUrl
Gebruik de nieuwe RedirectHttpResult.IsLocalUrl(url) helpermethode om te detecteren of een URL lokaal is. Een URL wordt beschouwd als lokaal als het volgende waar is:
- Het bevat geen host- of authoriteitgedeelte.
- Het heeft een absoluut pad.
URL's die gebruikmaken van virtuele paden"~/" zijn ook lokaal.
IsLocalUrl is handig voor het valideren van URL's voordat u ze omleidt om open omleidingsaanvallente voorkomen.
if (RedirectHttpResult.IsLocalUrl(url))
{
return Results.LocalRedirect(url);
}
Bedankt @martincostello voor deze bijdrage!
Brekende wijzigingen
Gebruik de artikelen in Belangrijke wijzigingen in .NET om belangrijke wijzigingen te vinden die van toepassing kunnen zijn bij het upgraden van een app naar een nieuwere versie van .NET.