diff --git a/aspnetcore/blazor/call-web-api.md b/aspnetcore/blazor/call-web-api.md index 3ecb098a60ca..c3f308b3025b 100644 --- a/aspnetcore/blazor/call-web-api.md +++ b/aspnetcore/blazor/call-web-api.md @@ -57,7 +57,7 @@ Example: In the app's `Program` file, call: - + * : Enables token acquisition to call web APIs. * `AddDownstreamApi`: Microsoft Identity Web packages provide API to create a named downstream web service for making web API calls. is injected into a server-side class, which is used to call to obtain weather data from an external web API (`MinimalApiJwt` project). diff --git a/aspnetcore/blazor/forms/validation.md b/aspnetcore/blazor/forms/validation.md index 8e7a41cc6725..ef4990fc372a 100644 --- a/aspnetcore/blazor/forms/validation.md +++ b/aspnetcore/blazor/forms/validation.md @@ -1582,9 +1582,6 @@ For model validation defined in a different assembly, such as a library or the ` The preceding approach results in validation of the types from both assemblies. - - In the following example, the `AddValidationForTypesInClient` method is created for the `.Client` project of a Blazor Web App for validation using types defined in the `.Client` project. `ServiceCollectionExtensions.cs` (in the `.Client` project): diff --git a/aspnetcore/blazor/fundamentals/environments.md b/aspnetcore/blazor/fundamentals/environments.md index fc4ca2790dd0..2b7d3da2993d 100644 --- a/aspnetcore/blazor/fundamentals/environments.md +++ b/aspnetcore/blazor/fundamentals/environments.md @@ -219,10 +219,6 @@ For more information, see the following resources: ### Set the environment for Azure App Service - - For a standalone Blazor WebAssembly app, you can set the environment manually via [start configuration](#set-the-client-side-environment-via-blazor-startup-configuration) or the [`Blazor-Environment` header](#set-the-client-side-environment-via-header). For a server-side app, set the environment via an `ASPNETCORE_ENVIRONMENT` app setting in Azure: diff --git a/aspnetcore/blazor/fundamentals/static-files.md b/aspnetcore/blazor/fundamentals/static-files.md index e048c6a31ffa..b9522fc99d36 100644 --- a/aspnetcore/blazor/fundamentals/static-files.md +++ b/aspnetcore/blazor/fundamentals/static-files.md @@ -78,8 +78,6 @@ For more information, see . *This section applies to server-side Blazor apps.* - - Assets are delivered via the property, which resolves the fingerprinted URL for a given asset. In the following example, Bootstrap, the Blazor project template app stylesheet (`app.css`), and the [CSS isolation stylesheet](xref:blazor/components/css-isolation) (based on an app's namespace of `BlazorSample`) are linked in a root component, typically the `App` component (`Components/App.razor`): ```razor diff --git a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md index e45c59ea8d53..addb70fd1bb6 100644 --- a/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md +++ b/aspnetcore/blazor/hybrid/tutorials/maui-blazor-web-app.md @@ -76,7 +76,7 @@ Add new project to the solution with the **Blazor Web App** project template. Se * **Interactivity location**: **Global** * **Sample pages**: Unselected (disabled) - + The **Interactivity location** setting to **Global** is important because MAUI apps always run interactively and throw errors on Razor component pages that explicitly specify a render mode. If you don't use a global render mode, you must implement the approach described in the [Use Blazor render modes](#use-blazor-render-modes) section after following the guidance in this section. For more information, see [BlazorWebView needs a way to enable overriding ResolveComponentForRenderMode (`dotnet/aspnetcore` #51235)](https://github.com/dotnet/aspnetcore/issues/51235). diff --git a/aspnetcore/blazor/includes/prerendering.md b/aspnetcore/blazor/includes/prerendering.md index c158a07f5ccb..e4b35558b8f8 100644 --- a/aspnetcore/blazor/includes/prerendering.md +++ b/aspnetcore/blazor/includes/prerendering.md @@ -1,13 +1,12 @@ -:::moniker range=">= aspnetcore-8.0" +:::moniker range=">= aspnetcore-10.0" *This section applies to server-side apps that prerender Razor components. Prerendering is covered in .* - +:::moniker-end + +:::moniker range=">= aspnetcore-8.0 < aspnetcore-10.0" + +*This section applies to server-side apps that prerender Razor components. Prerendering is covered in .* > [!NOTE] > Internal navigation for [interactive routing](xref:blazor/fundamentals/routing#static-versus-interactive-routing) in Blazor Web Apps doesn't involve requesting new page content from the server. Therefore, prerendering doesn't occur for internal page requests. If the app adopts interactive routing, perform a full page reload for component examples that demonstrate prerendering behavior. For more information, see . diff --git a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md index 8fe37c5fdd9f..c4db66c6f5c2 100644 --- a/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md +++ b/aspnetcore/blazor/javascript-interoperability/call-javascript-from-dotnet.md @@ -461,14 +461,12 @@ IJSRuntime JS { get; set; } :::moniker range=">= aspnetcore-10.0" - - ## Create an instance of a JS object using a constructor function Create an instance of a JS object using a constructor function and get the / .NET handle for referencing the instance with the following API: * (asynchronous) -* `InvokeConstructor` (synchronous) +* (synchronous) Examples in this section demonstrate the API calls with the following `TestClass` with a constructor function (`constructor(text)`): @@ -498,7 +496,7 @@ An overload is available that takes a ### Synchronous `InvokeConstructor` -Use `InvokeConstructor` on and to invoke the specified JS constructor function synchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an : +Use on and to invoke the specified JS constructor function synchronously. The function is invoked with the `new` operator. In the following example, `TestClass` contains a constructor function, and `classRef` is an : ```csharp var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); @@ -629,13 +627,12 @@ In server-side scenarios, JS interop calls can't be issued after Blazor's Signal :::moniker range=">= aspnetcore-10.0" - - * JS interop method calls * * * * + * * * * /`DisposeAsync` calls on any . diff --git a/aspnetcore/blazor/javascript-interoperability/index.md b/aspnetcore/blazor/javascript-interoperability/index.md index a4a0e7785b9b..acdda1c58132 100644 --- a/aspnetcore/blazor/javascript-interoperability/index.md +++ b/aspnetcore/blazor/javascript-interoperability/index.md @@ -331,13 +331,12 @@ JavaScript (JS) interop calls can't be issued after Blazor's SignalR circuit is :::moniker range=">= aspnetcore-10.0" - - * JS interop method calls * * * * + * * * * `Dispose`/`DisposeAsync` calls on any . diff --git a/aspnetcore/blazor/security/blazor-web-app-with-entra.md b/aspnetcore/blazor/security/blazor-web-app-with-entra.md index 92353eed044e..7b512b64a3f6 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-entra.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-entra.md @@ -52,7 +52,7 @@ We recommend using separate registrations for apps and web APIs, even when the a Register the web API (`MinimalApiJwt`) first so that you can then grant access to the web API when registering the app. The web API's tenant ID and client ID are used to configure the web API in its `Program` file. After registering the web API, expose the web API in **App registrations** > **Expose an API** with a scope name of `Weather.Get`. Record the App ID URI for use in the app's configuration. -Next, register the app (`BlazorWebAppEntra`) with a **Web** platform configuration and a **Redirect URI** of `https://localhost/signin-oidc` (a port isn't required). The app's tenant ID, tenant domain, and client ID, along with the web API's base address, App ID URI, and weather scope name, are used to configure the app in its `appsettings.json` file. Grant API permission to access the web API in **App registrations** > **API permissions**. If the app's security specification calls for it, you can grant admin consent for the organization to access the web API. Authorized users and groups are assigned to the app's registration in **App registrations** > **Enterprise applications**. +Next, register the app (`BlazorWebAppEntra`) with a **Web** platform configuration with two entries under **Redirect URI**: `https://localhost/signin-oidc` and `https://localhost/signout-callback-oidc` (ports aren't required on these URIs). Set the **Front-channel logout URL** to `https://localhost/signout-callback-oidc` (a port isn't required). The app's tenant ID, tenant domain, and client ID, along with the web API's base address, App ID URI, and weather scope name, are used to configure the app in its `appsettings.json` file. Grant API permission to access the web API in **App registrations** > **API permissions**. If the app's security specification calls for it, you can grant admin consent for the organization to access the web API. Authorized users and groups are assigned to the app's registration in **App registrations** > **Enterprise applications**. In the Entra or Azure portal's **Implicit grant and hybrid flows** app registration configuration, don't select either checkbox for the authorization endpoint to return **Access tokens** or **ID tokens**. The OpenID Connect handler automatically requests the appropriate tokens using the code returned from the authorization endpoint. @@ -205,6 +205,12 @@ builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddDistributedTokenCaches(); ``` +The callback path (`CallbackPath`) must match the redirect URI (login callback path) configured when registering the application in the Entra or Azure portal. Paths are configured in the **Authentication** blade of the app's registration. The default value of `CallbackPath` is `/signin-oidc` for a registered redirect URI of `https://localhost/signin-oidc` (a port isn't required). + +The is the request path within the app's base path intercepted by the OpenID Connect handler where the user agent is first returned after signing out from Entra. The sample app doesn't set a value for the path because the default value of "`/signout-callback-oidc`" is used. After intercepting the request, the OpenID Connect handler redirects to the or , if specified. + +[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] + :::zone-end :::zone pivot="bff-pattern" @@ -252,7 +258,7 @@ We recommend using separate registrations for apps and web APIs, even when the a Register the web API (`MinimalApiJwt`) first so that you can then grant access to the web API when registering the app. The web API's tenant ID and client ID are used to configure the web API in its `Program` file. After registering the web API, expose the web API in **App registrations** > **Expose an API** with a scope name of `Weather.Get`. Record the App ID URI for use in the app's configuration. -Next, register the app (`BlazorWebAppEntra`) with a **Web** platform configuration and a **Redirect URI** of `https://localhost/signin-oidc` (a port isn't required). The app's tenant ID, tenant domain, and client ID, along with the web API's base address, App ID URI, and weather scope name, are used to configure the app in its `appsettings.json` file. Grant API permission to access the web API in **App registrations** > **API permissions**. If the app's security specification calls for it, you can grant admin consent for the organization to access the web API. Authorized users and groups are assigned to the app's registration in **App registrations** > **Enterprise applications**. +Next, register the app (`BlazorWebAppEntra`) with a **Web** platform configuration with two entries under **Redirect URI**: `https://localhost/signin-oidc` and `https://localhost/signout-callback-oidc` (ports aren't required on these URIs). The app's tenant ID, tenant domain, and client ID, along with the web API's base address, App ID URI, and weather scope name, are used to configure the app in its `appsettings.json` file. Grant API permission to access the web API in **App registrations** > **API permissions**. If the app's security specification calls for it, you can grant admin consent for the organization to access the web API. Authorized users and groups are assigned to the app's registration in **App registrations** > **Enterprise applications**. In the Entra or Azure portal's **Implicit grant and hybrid flows** app registration configuration, don't select either checkbox for the authorization endpoint to return **Access tokens** or **ID tokens**. The OpenID Connect handler automatically requests the appropriate tokens using the code returned from the authorization endpoint. @@ -435,22 +441,6 @@ The callback path (`CallbackPath`) must match the redirect URI (login callback p The is the request path within the app's base path intercepted by the OpenID Connect handler where the user agent is first returned after signing out from Entra. The sample app doesn't set a value for the path because the default value of "`/signout-callback-oidc`" is used. After intercepting the request, the OpenID Connect handler redirects to the or , if specified. -Configure the signed-out callback path in the app's Entra registration. In the Entra or Azure portal, set the path in the **Web** platform configuration's **Redirect URI** entries: - -> :::no-loc text="https://localhost/signout-callback-oidc"::: - -> [!NOTE] -> A port isn't required for `localhost` addresses when using Entra. - -If you don't add the signed-out callback path URI to the app's registration in Entra, Entra refuses to redirect the user back to the app and merely asks them to close their browser window. - - - -> [!NOTE] -> Entra doesn't redirect a primary admin user (root account) or external user back to the Blazor application. Instead, Entra logs the user out of the app and recommends that they close all of their browser windows. For more information, see [postLogoutRedirectUri not working when authority url contains a tenant ID (`AzureAD/microsoft-authentication-library-for-js` #5783)](https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/5783#issuecomment-1465217522). - [!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)] ### Establish the client secret diff --git a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md index 880281e59a81..a1a2485fbe3d 100644 --- a/aspnetcore/blazor/security/blazor-web-app-with-oidc.md +++ b/aspnetcore/blazor/security/blazor-web-app-with-oidc.md @@ -1283,9 +1283,6 @@ Alternatively, use the following `LogInOrOut` component, which doesn't supply a ## Token refresh - - The custom cookie refresher (`CookieOidcRefresher.cs`) implementation updates the user's claims automatically when they expire. The current implementation expects to receive an ID token from the token endpoint in exchange for the refresh token. The claims in this ID token are then used to overwrite the user's claims. The sample implementation doesn't include code for requesting claims from the [UserInfo endpoint](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) on token refresh. For more information, see [`BlazorWebAppOidc AddOpenIdConnect with GetClaimsFromUserInfoEndpoint = true doesn't propogate [sic] role claims to client` (`dotnet/aspnetcore` #58826)](https://github.com/dotnet/aspnetcore/issues/58826#issuecomment-2492738142). diff --git a/aspnetcore/blazor/state-management/prerendered-state-persistence.md b/aspnetcore/blazor/state-management/prerendered-state-persistence.md index ce770852cfc1..37bf9d3f13ce 100644 --- a/aspnetcore/blazor/state-management/prerendered-state-persistence.md +++ b/aspnetcore/blazor/state-management/prerendered-state-persistence.md @@ -324,14 +324,12 @@ When the component executes, `currentCount` is only set once during prerendering ## Serialization extensibility for persistent component state - - -Implement a custom serializer with the `IPersistentComponentStateSerializer` interface. Without a registered custom serializer, serialization falls back to the existing JSON serialization. +Implement a custom serializer with . Without a registered custom serializer, serialization falls back to the existing JSON serialization. -The custom serializer is registered in the app's `Program` file. In the following example, the `CustomUserSerializer` is registered for the `User` type: +The custom serializer is registered in the app's `Program` file. In the following example, the `CustomUserSerializer` is registered for the `TUser` type: ```csharp -builder.Services.AddSingleton, +builder.Services.AddSingleton, CustomUserSerializer>(); ``` @@ -360,8 +358,6 @@ For components embedded into a page or view of a Razor Pages or MVC app, you mus ## Interactive routing and prerendering - - When the `Routes` component doesn't define a render mode, the app is using per-page/component interactivity and navigation. Using per-page/component navigation, internal navigation is handled by [enhanced routing](xref:blazor/fundamentals/routing#enhanced-navigation-and-form-handling) after the app becomes interactive. "Internal navigation" in this context means that the URL destination of the navigation event is a Blazor endpoint inside the app. :::moniker range=">= aspnetcore-10.0" @@ -396,6 +392,8 @@ To skip restoring state during reconnection, set `RestoreBehavior` to `SkipLastS public int CounterNotRestoredOnReconnect { get; set; } ``` + + Call `PersistentComponentState.RegisterOnRestoring` to register a callback for imperatively controlling how state is restored, similar to how provides full control of how state is persisted. :::moniker-end diff --git a/aspnetcore/fundamentals/app-state.md b/aspnetcore/fundamentals/app-state.md index cf4fd4a5978b..68e5d0dfaaf4 100644 --- a/aspnetcore/fundamentals/app-state.md +++ b/aspnetcore/fundamentals/app-state.md @@ -35,16 +35,6 @@ State can be stored using several approaches. Each approach is described later i [SignalR](xref:signalr/introduction) apps shouldn't use session state and other state management approaches that rely upon a stable HTTP context to store information. SignalR apps can store per-connection state in [`Context.Items` in the hub](xref:signalr/hubs). For more information and alternative state management approaches for Blazor Server apps, see and . - - ## Cookies Cookies store data across requests. Because cookies are sent with every request, their size should be kept to a minimum. Ideally, only an identifier should be stored in a cookie with the data stored by the app. Most browsers restrict cookie size to 4096 bytes. Only a limited number of cookies are available for each domain. @@ -325,14 +315,6 @@ State can be stored using several approaches. Each approach is described later i [SignalR](xref:signalr/introduction) apps shouldn't use session state and other state management approaches that rely upon a stable HTTP context to store information. SignalR apps can store per-connection state in [`Context.Items` in the hub](xref:signalr/hubs). For more information and alternative state management approaches for Blazor Server apps, see and . - - ## Cookies Cookies store data across requests. Because cookies are sent with every request, their size should be kept to a minimum. Ideally, only an identifier should be stored in a cookie with the data stored by the app. Most browsers restrict cookie size to 4096 bytes. Only a limited number of cookies are available for each domain. diff --git a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md index 22e170d397e6..649280c8c0ef 100644 --- a/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md +++ b/aspnetcore/release-notes/aspnetcore-10/includes/blazor.md @@ -692,12 +692,12 @@ We recommend using the option set to `none` in all PWAs, including those that ta ### Serialization extensibility for persistent component state -Implement a custom serializer with the `IPersistentComponentStateSerializer` interface. Without a registered custom serializer, serialization falls back to the existing JSON serialization. +Implement a custom serializer with . Without a registered custom serializer, serialization falls back to the existing JSON serialization. -The custom serializer is registered in the app's `Program` file. In the following example, the `CustomUserSerializer` is registered for the `User` type: +The custom serializer is registered in the app's `Program` file. In the following example, the `CustomUserSerializer` is registered for the `TUser` type: ```csharp -builder.Services.AddSingleton, +builder.Services.AddSingleton, CustomUserSerializer>(); ``` diff --git a/aspnetcore/release-notes/aspnetcore-8.0.md b/aspnetcore/release-notes/aspnetcore-8.0.md index 4422d4599cb2..2adb8d3766bb 100644 --- a/aspnetcore/release-notes/aspnetcore-8.0.md +++ b/aspnetcore/release-notes/aspnetcore-8.0.md @@ -327,9 +327,9 @@ For more information, see + -Support for multiple Blazor Web Apps per server project will be considered for a future .NET release. +Support for multiple Blazor Web Apps per server project is under consideration for a future .NET release. For more information, see [Support for multiple Blazor Web apps per server project (`dotnet/aspnetcore` #52216)](https://github.com/dotnet/aspnetcore/issues/52216).