From 92212788f44c26c6f83aa55dd6fe14047a46eee2 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 13:52:52 -0500 Subject: [PATCH 01/12] Public access modifier for [PersistentState] prop --- .../state-management/prerendered-state-persistence.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/aspnetcore/blazor/state-management/prerendered-state-persistence.md b/aspnetcore/blazor/state-management/prerendered-state-persistence.md index 35c197c05c9f..0e91749eb184 100644 --- a/aspnetcore/blazor/state-management/prerendered-state-persistence.md +++ b/aspnetcore/blazor/state-management/prerendered-state-persistence.md @@ -38,13 +38,15 @@ The persisted prerendered state is transferred to the client, where it's used to :::moniker range=">= aspnetcore-10.0" -To preserve prerendered state, use the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to persist state in properties. Properties with this attribute are automatically persisted using the service during prerendering. The state is retrieved when the component renders interactively or the service is instantiated. +To preserve prerendered state, use the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to persist state in public properties. Properties with this attribute are automatically persisted using the service during prerendering. The state is retrieved when the component renders interactively or the service is instantiated. + +Use *public* properties because reflection is used by the framework for tasks such as [trimming unused code](xref:blazor/performance/app-download-size#intermediate-language-il-trimming) and [source generation](/dotnet/csharp/roslyn-sdk/source-generators-overview). By default, properties are serialized using the serializer with default settings and persisted in the prerendered HTML. Serialization isn't trimmer safe and requires preservation of the types used. For more information, see . The following counter component persists counter state during prerendering and retrieves the state to initialize the component: -* The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) is applied to the nullable `int` type (`CurrentCount`). +* The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) is applied to the public, nullable `int` type (`CurrentCount`). * The counter's state is assigned when `null` in `OnInitialized` and restored automatically when the component renders interactively. `PrerenderedCounter2.razor`: @@ -94,7 +96,7 @@ When the component executes, `CurrentCount` is only set once during prerendering In the following example that serializes state for multiple components of the same type: -* Properties annotated with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) are serialized during prerendering. +* Public properties annotated with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) are serialized during prerendering. * The [`@key` directive attribute](xref:blazor/components/key#use-of-the-key-directive-attribute) is used to ensure that the state is correctly associated with the component instance. * The `Element` property is initialized in the [`OnInitialized` lifecycle method](xref:blazor/components/lifecycle#component-initialization-oninitializedasync) to avoid null reference exceptions, similarly to how null references are avoided for query parameters and form data. @@ -159,7 +161,7 @@ Serialized properties are identified from the actual service instance: * Supports shared code in different assemblies. * Results in each instance exposing the same properties. -The following counter service, `CounterTracker`, marks its current count property, `CurrentCount` with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute). The property is serialized during prerendering and deserialized when the app becomes interactive wherever the service is injected. +The following counter service, `CounterTracker`, marks its current count property, `CurrentCount` with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute). The public property is serialized during prerendering and deserialized when the app becomes interactive wherever the service is injected. `CounterTracker.cs`: From 48f84c158dae7ea7fb7ac4051e2e6268b7d2d8d9 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:00:16 -0500 Subject: [PATCH 02/12] Clarify property visibility for PersistentState attribute --- aspnetcore/blazor/components/integration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/components/integration.md b/aspnetcore/blazor/components/integration.md index 2dad9cc2c506..39604951f6fa 100644 --- a/aspnetcore/blazor/components/integration.md +++ b/aspnetcore/blazor/components/integration.md @@ -418,7 +418,7 @@ In `Pages/_Host.cshtml` of Blazor apps that are `ServerPrerendered` in a Blazor :::moniker range=">= aspnetcore-10.0" -Decide what state to persist using the service. The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) applied to a property registers a callback to persist the state during prerendering and loads it when the component renders interactively or the service is instantiated. +Decide what state to persist using the service. The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) applied to a public property registers a callback to persist the state during prerendering and loads it when the component renders interactively or the service is instantiated. In the following example, the `{TYPE}` placeholder represents the type of data to persist (for example, `WeatherForecast[]`). From 0c44a12c7f90d1fc9bbdcb234303b314ac7a5408 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:01:45 -0500 Subject: [PATCH 03/12] Update note on [PersistentState] attribute usage Clarify that the [PersistentState] attribute should be applied to public properties of components. --- aspnetcore/blazor/state-management/server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index 00a211032340..7e8388c74bc4 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -100,7 +100,7 @@ Persisting component state across circuits is built on top of the existing [NOTE] > Persisting component state for prerendering works for any interactive render mode, but circuit state persistence only works for the **Interactive Server** render mode. -Annotate component properties with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to enable circuit state persistence. The following example also keys the items with the [`@key` directive attribute](xref:blazor/components/key) to provide a unique identifier for each component instance: +Annotate component public properties with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to enable circuit state persistence. The following example also keys the items with the [`@key` directive attribute](xref:blazor/components/key) to provide a unique identifier for each component instance: ```razor @foreach (var item in Items) From b0c4d749fb3edac83eb004cdec11e41f31b53a06 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:02:59 -0500 Subject: [PATCH 04/12] Update documentation for persisting state in services Clarified the wording for persisting state in scoped services. --- aspnetcore/blazor/state-management/server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index 7e8388c74bc4..18e80f4db92a 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -119,7 +119,7 @@ Annotate component public properties with the [`[PersistentState]` attribute](xr } ``` -To persist state for scoped services, annotate service properties with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute), add the service to the service collection, and call the extension method with the service: +To persist state for a scoped service, annotate the public service property with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute), add the service to the service collection, and call the extension method with the service: ```csharp public class CustomUserService From de7246fb44fa0bffaa1fbe830bc6e165a1ed1959 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:07:08 -0500 Subject: [PATCH 05/12] Specify public properties for [PersistentState] attribute --- aspnetcore/release-notes/aspnetcore-10/includes/blazor.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md index 511f6c7c24e5..b30dedc22497 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md @@ -261,7 +261,7 @@ Currently, there's no documented replacement strategy for the preceding approach ### Declarative model for persisting state from components and services -You can now declaratively specify state to persist from components and services using the `[PersistentState]` attribute. Properties with this attribute are automatically persisted using the service during prerendering. The state is retrieved when the component renders interactively or the service is instantiated. +You can now declaratively specify state to persist from components and services using the `[PersistentState]` attribute. Public properties with this attribute are automatically persisted using the service during prerendering. The state is retrieved when the component renders interactively or the service is instantiated. In previous Blazor releases, persisting component state during prerendering using the service involved a significant amount of code, as the following example demonstrates: @@ -337,6 +337,8 @@ else } ``` +Use *public* properties because reflection is used by the framework for tasks such as [trimming unused code](xref:blazor/performance/app-download-size#intermediate-language-il-trimming) and [source generation](/dotnet/csharp/roslyn-sdk/source-generators-overview). + State can be serialized for multiple components of the same type, and you can establish declarative state in a service for use around the app by calling `RegisterPersistentService` on the Razor components builder () with a custom service type and render mode. For more information, see . ### New JavaScript interop features From d11e6c9603d37f0c8e40f0e23054deec0e622888 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:12:56 -0500 Subject: [PATCH 06/12] Update server.md --- aspnetcore/blazor/state-management/server.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index 18e80f4db92a..6235b4ea014d 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -119,7 +119,11 @@ Annotate component public properties with the [`[PersistentState]` attribute](xr } ``` -To persist state for a scoped service, annotate the public service property with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute), add the service to the service collection, and call the extension method with the service: +To persist state for a scoped service: + +* Annotate the public service property with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute). +* Add the service to the service collection. +* Call the extension method with the service: ```csharp public class CustomUserService From 4b05aa11dcca5f7761b28a20c8ebac5af7bd7132 Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:13:25 -0500 Subject: [PATCH 07/12] Change release date to April 15, 2026 Update the release date for ASP.NET Core 10.0. --- aspnetcore/release-notes/aspnetcore-10.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/release-notes/aspnetcore-10.0.md b/aspnetcore/release-notes/aspnetcore-10.0.md index 3224c2578a3a..9b9fe7dd2f70 100644 --- a/aspnetcore/release-notes/aspnetcore-10.0.md +++ b/aspnetcore/release-notes/aspnetcore-10.0.md @@ -5,7 +5,7 @@ author: wadepickett description: Learn about the new features in ASP.NET Core in .NET 10. ms.author: wpickett ms.custom: mvc -ms.date: 01/29/2026 +ms.date: 04/15/2026 uid: aspnetcore-10 --- # What's new in ASP.NET Core in .NET 10 From a8a60d3c6554a9b327189654a319183f4520d32f Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:14:47 -0500 Subject: [PATCH 08/12] Fix formatting of persistent state service instructions --- aspnetcore/blazor/state-management/server.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index 6235b4ea014d..e0f3e9d9d91e 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -123,7 +123,7 @@ To persist state for a scoped service: * Annotate the public service property with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute). * Add the service to the service collection. -* Call the extension method with the service: +* Call the extension method with the service. ```csharp public class CustomUserService From 3df971bbe7be95cb8f7e97f00b7e8076f156848b Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:35:17 -0500 Subject: [PATCH 09/12] Updates --- aspnetcore/blazor/components/integration.md | 2 +- aspnetcore/blazor/forms/index.md | 4 +-- .../prerendered-state-persistence.md | 2 +- aspnetcore/blazor/state-management/server.md | 2 +- .../tutorials/movie-database-app/part-5.md | 2 +- .../diagnostics/rdg006.md | 2 +- aspnetcore/fundamentals/http-requests.md | 6 ++-- .../fundamentals/openapi/include-metadata.md | 2 +- .../openapi/includes/include-metadata10.md | 2 +- .../openapi/includes/include-metadata9.md | 2 +- aspnetcore/mvc/models/model-binding.md | 10 +++---- .../model-binding/includes/model-binding7.md | 30 +++++++++---------- .../aspnetcore-10/includes/blazor.md | 4 +-- 13 files changed, 35 insertions(+), 35 deletions(-) diff --git a/aspnetcore/blazor/components/integration.md b/aspnetcore/blazor/components/integration.md index 39604951f6fa..c609b6e73d84 100644 --- a/aspnetcore/blazor/components/integration.md +++ b/aspnetcore/blazor/components/integration.md @@ -418,7 +418,7 @@ In `Pages/_Host.cshtml` of Blazor apps that are `ServerPrerendered` in a Blazor :::moniker range=">= aspnetcore-10.0" -Decide what state to persist using the service. The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) applied to a public property registers a callback to persist the state during prerendering and loads it when the component renders interactively or the service is instantiated. +Decide what state to persist using the service. The [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) applied to a `public` property registers a callback to persist the state during prerendering and loads it when the component renders interactively or the service is instantiated. In the following example, the `{TYPE}` placeholder represents the type of data to persist (for example, `WeatherForecast[]`). diff --git a/aspnetcore/blazor/forms/index.md b/aspnetcore/blazor/forms/index.md index 53d15574cd18..32f45fe7b295 100644 --- a/aspnetcore/blazor/forms/index.md +++ b/aspnetcore/blazor/forms/index.md @@ -69,7 +69,7 @@ Standard HTML forms are supported. Create a form using the normal HTML `
` In the preceding `StarshipPlainForm` component: * The form is rendered where the `` element appears. The form is named with the [`@formname`](xref:mvc/views/razor#formname) directive attribute, which uniquely identifies the form to the Blazor framework. -* The model is created in the component's `@code` block and held in a public property (`Model`). The `[SupplyParameterFromForm]` attribute indicates that the value of the associated property should be supplied from the form data. Data in the request that matches the property's name is bound to the property. +* The model is created in the component's `@code` block and held in a `public` property (`Model`). The `[SupplyParameterFromForm]` attribute indicates that the value of the associated property should be supplied from the form data. Data in the request that matches the property's name is bound to the property. * The component is an input component for editing string values. The `@bind-Value` directive attribute binds the `Model.Id` model property to the component's property. * The `Submit` method is registered as a handler for the `@onsubmit` callback. The handler is called when the form is submitted by the user. @@ -117,7 +117,7 @@ A form is defined using the Blazor framework's component is rendered where the `` element appears. The form is named with the property, which uniquely identifies the form to the Blazor framework. -* The model is created in the component's `@code` block and held in a public property (`Model`). The property is assigned to the parameter. The `[SupplyParameterFromForm]` attribute indicates that the value of the associated property should be supplied from the form data. Data in the request that matches the property's name is bound to the property. +* The model is created in the component's `@code` block and held in a `public` property (`Model`). The property is assigned to the parameter. The `[SupplyParameterFromForm]` attribute indicates that the value of the associated property should be supplied from the form data. Data in the request that matches the property's name is bound to the property. * The component is an [input component](xref:blazor/forms/input-components) for editing string values. The `@bind-Value` directive attribute binds the `Model.Id` model property to the component's property. * The `Submit` method is registered as a handler for the callback. The handler is called when the form is submitted by the user. diff --git a/aspnetcore/blazor/state-management/prerendered-state-persistence.md b/aspnetcore/blazor/state-management/prerendered-state-persistence.md index 0e91749eb184..2104c9095309 100644 --- a/aspnetcore/blazor/state-management/prerendered-state-persistence.md +++ b/aspnetcore/blazor/state-management/prerendered-state-persistence.md @@ -40,7 +40,7 @@ The persisted prerendered state is transferred to the client, where it's used to To preserve prerendered state, use the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to persist state in public properties. Properties with this attribute are automatically persisted using the service during prerendering. The state is retrieved when the component renders interactively or the service is instantiated. -Use *public* properties because reflection is used by the framework for tasks such as [trimming unused code](xref:blazor/performance/app-download-size#intermediate-language-il-trimming) and [source generation](/dotnet/csharp/roslyn-sdk/source-generators-overview). +Use `public` properties because reflection is used by the framework for tasks such as [trimming unused code](xref:blazor/performance/app-download-size#intermediate-language-il-trimming) and [source generation](/dotnet/csharp/roslyn-sdk/source-generators-overview). By default, properties are serialized using the serializer with default settings and persisted in the prerendered HTML. Serialization isn't trimmer safe and requires preservation of the types used. For more information, see . diff --git a/aspnetcore/blazor/state-management/server.md b/aspnetcore/blazor/state-management/server.md index e0f3e9d9d91e..a2069c5f3ee8 100644 --- a/aspnetcore/blazor/state-management/server.md +++ b/aspnetcore/blazor/state-management/server.md @@ -100,7 +100,7 @@ Persisting component state across circuits is built on top of the existing [NOTE] > Persisting component state for prerendering works for any interactive render mode, but circuit state persistence only works for the **Interactive Server** render mode. -Annotate component public properties with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to enable circuit state persistence. The following example also keys the items with the [`@key` directive attribute](xref:blazor/components/key) to provide a unique identifier for each component instance: +Annotate component `public` properties with the [`[PersistentState]` attribute](xref:Microsoft.AspNetCore.Components.PersistentStateAttribute) to enable circuit state persistence. The following example also keys the items with the [`@key` directive attribute](xref:blazor/components/key) to provide a unique identifier for each component instance: ```razor @foreach (var item in Items) diff --git a/aspnetcore/blazor/tutorials/movie-database-app/part-5.md b/aspnetcore/blazor/tutorials/movie-database-app/part-5.md index c2d7545c7c94..d291943464c6 100644 --- a/aspnetcore/blazor/tutorials/movie-database-app/part-5.md +++ b/aspnetcore/blazor/tutorials/movie-database-app/part-5.md @@ -19,7 +19,7 @@ This part of the tutorial series explains how metadata of the `Movie` model is u ## Validation using data annotations -Validation rules are specified on a model class using *data annotations*. The following list shows some of the attributes for user input validation of public properties in a form's model: +Validation rules are specified on a model class using *data annotations*. The following list shows some of the attributes for user input validation of `public` properties in a form's model: * [`[Required]`](xref:System.ComponentModel.DataAnnotations.RequiredAttribute): Require that the user provide a value. * [`[StringLength]`](xref:System.ComponentModel.DataAnnotations.StringLengthAttribute): Specifies the minimum and maximum length of characters. Note that a `MinimumLength` passed to the attribute doesn't make the string required (apply the [`[Required]` attribute](xref:System.ComponentModel.DataAnnotations.RequiredAttribute)). diff --git a/aspnetcore/fundamentals/aot/request-delegate-generator/diagnostics/rdg006.md b/aspnetcore/fundamentals/aot/request-delegate-generator/diagnostics/rdg006.md index b0af52de95fc..91f84b959d55 100644 --- a/aspnetcore/fundamentals/aot/request-delegate-generator/diagnostics/rdg006.md +++ b/aspnetcore/fundamentals/aot/request-delegate-generator/diagnostics/rdg006.md @@ -26,7 +26,7 @@ This diagnostic is emitted by the [Request Delegate Generator](/aspnet/core/fund ### Rule description -Types that are used for surrogate binding via the [`[AsParameters]`](xref:Microsoft.AspNetCore.Http.AsParametersAttribute) attribute must contain a public parameterized constructor where all parameters to the constructor match the public properties declared on the type. The `TodoRequest` type produces this diagnostic because there is no matching constructor parameter for the `Todo` property. +Types that are used for surrogate binding via the [`[AsParameters]`](xref:Microsoft.AspNetCore.Http.AsParametersAttribute) attribute must contain a `public` parameterized constructor where all parameters to the constructor match the `public` properties declared on the type. The `TodoRequest` type produces this diagnostic because there is no matching constructor parameter for the `Todo` property. :::code language="csharp" source="~/../AspNetCore.Docs.Samples/fundamentals/aot/diagnostics/Rdg6/Program.cs" id="snippet_1" highlight="14,18-22"::: diff --git a/aspnetcore/fundamentals/http-requests.md b/aspnetcore/fundamentals/http-requests.md index c5d44e61fecb..985d8fc1b2a9 100644 --- a/aspnetcore/fundamentals/http-requests.md +++ b/aspnetcore/fundamentals/http-requests.md @@ -469,7 +469,7 @@ A typed client accepts an `HttpClient` parameter in its constructor: In the preceding code: * The configuration is moved into the typed client. -* The `HttpClient` object is exposed as a public property. +* The `HttpClient` object is exposed as a `public` property.