Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aspnetcore/blazor/call-web-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Example:

In the app's `Program` file, call:

<!-- UPDATE 10.0 - Missing API doc for 'AddDownstreamApi' -->
<!-- UPDATE 10.0 - Missing API doc for 'Microsoft.Identity.Web.DownstreamApiExtensions.AddDownstreamApi' -->

* <xref:Microsoft.Identity.Web.MicrosoftIdentityWebApiAuthenticationBuilder.EnableTokenAcquisitionToCallDownstreamApi%2A>: 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. <xref:Microsoft.Identity.Abstractions.IDownstreamApi> is injected into a server-side class, which is used to call <xref:Microsoft.Identity.Abstractions.IDownstreamApi.CallApiForUserAsync%2A> to obtain weather data from an external web API (`MinimalApiJwt` project).
Expand Down
3 changes: 0 additions & 3 deletions aspnetcore/blazor/forms/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<!-- UPDATE 10.0 - MIA API
`AddValidationForTypesInClient` -->

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):
Expand Down
4 changes: 0 additions & 4 deletions aspnetcore/blazor/fundamentals/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,6 @@ For more information, see the following resources:

### Set the environment for Azure App Service

<!-- UPDATE 10.0 The underlying problem with app settings filename
case sensitivity is tracked for 10.0 by ...
https://github.com/dotnet/aspnetcore/issues/25152 -->

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:
Expand Down
2 changes: 0 additions & 2 deletions aspnetcore/blazor/fundamentals/static-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ For more information, see <xref:fundamentals/static-files>.

*This section applies to server-side Blazor apps.*

<!-- UPDATE 10.0 Compiler implementation for tilde/slash-based HREFs. -->

Assets are delivered via the <xref:Microsoft.AspNetCore.Components.ComponentBase.Assets?displayProperty=nameWithType> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)

<!-- UPDATE 10.0 Check on PU issue mentioned below and revise accordingly. -->
<!-- UPDATE 11.0 Check on PU issue mentioned below and revise accordingly. -->

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

Expand Down
13 changes: 6 additions & 7 deletions aspnetcore/blazor/includes/prerendering.md
Original file line number Diff line number Diff line change
@@ -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 <xref:blazor/components/prerender>.*

<!-- UPDATE 10.0 - Persistent component state across enhanced nav
is arriving for RC1.

The following remarks will be updated/versioned
on the upcoming docs RC1 PR.
-->
:::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 <xref:blazor/components/prerender>.*

> [!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 <xref:blazor/state-management/prerendered-state-persistence#interactive-routing-and-prerendering>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,12 @@ IJSRuntime JS { get; set; }

:::moniker range=">= aspnetcore-10.0"

<!-- UPDATE 10.0 - MIA API -->

## 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 <xref:Microsoft.JSInterop.IJSObjectReference>/<xref:Microsoft.JSInterop.IJSInProcessObjectReference> .NET handle for referencing the instance with the following API:

* <xref:Microsoft.JSInterop.JSRuntime.InvokeConstructorAsync%2A> (asynchronous)
* `InvokeConstructor` (synchronous)
* <xref:Microsoft.JSInterop.IJSInProcessObjectReference.InvokeConstructor%2A> (synchronous)

Examples in this section demonstrate the API calls with the following `TestClass` with a constructor function (`constructor(text)`):

Expand Down Expand Up @@ -498,7 +496,7 @@ An overload is available that takes a <xref:System.Threading.CancellationToken>

### Synchronous `InvokeConstructor`

Use `InvokeConstructor` on <xref:Microsoft.JSInterop.IJSInProcessRuntime> and <xref:Microsoft.JSInterop.IJSInProcessObjectReference> 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 <xref:Microsoft.JSInterop.IJSInProcessObjectReference>:
Use <xref:Microsoft.JSInterop.IJSInProcessObjectReference.InvokeConstructor%2A> on <xref:Microsoft.JSInterop.IJSInProcessRuntime> and <xref:Microsoft.JSInterop.IJSInProcessObjectReference> 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 <xref:Microsoft.JSInterop.IJSInProcessObjectReference>:

```csharp
var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
Expand Down Expand Up @@ -629,13 +627,12 @@ In server-side scenarios, JS interop calls can't be issued after Blazor's Signal

:::moniker range=">= aspnetcore-10.0"

<!-- UPDATE 10.0 - MIA API -->

* JS interop method calls
* <xref:Microsoft.JSInterop.IJSRuntime.InvokeAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.JSRuntimeExtensions.InvokeAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.JSRuntime.InvokeConstructorAsync%2A>
* <xref:Microsoft.JSInterop.IJSInProcessObjectReference.InvokeConstructor%2A>
* <xref:Microsoft.JSInterop.JSRuntime.GetValueAsync%2A>
* <xref:Microsoft.JSInterop.JSRuntime.SetValueAsync%2A>
* <xref:Microsoft.JSInterop.JSRuntime.Dispose%2A>/`DisposeAsync` calls on any <xref:Microsoft.JSInterop.IJSObjectReference>.
Expand Down
3 changes: 1 addition & 2 deletions aspnetcore/blazor/javascript-interoperability/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,12 @@ JavaScript (JS) interop calls can't be issued after Blazor's SignalR circuit is

:::moniker range=">= aspnetcore-10.0"

<!-- UPDATE 10.0 - MIA API -->

* JS interop method calls
* <xref:Microsoft.JSInterop.IJSRuntime.InvokeAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.JSRuntimeExtensions.InvokeAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync%2A?displayProperty=nameWithType>
* <xref:Microsoft.JSInterop.IJSObjectReference.InvokeConstructorAsync%2A>
* <xref:Microsoft.JSInterop.IJSInProcessObjectReference.InvokeConstructor%2A>
* <xref:Microsoft.JSInterop.IJSObjectReference.GetValueAsync%2A>
* <xref:Microsoft.JSInterop.IJSObjectReference.SetValueAsync%2A>
* `Dispose`/`DisposeAsync` calls on any <xref:Microsoft.JSInterop.IJSObjectReference>.
Expand Down
26 changes: 8 additions & 18 deletions aspnetcore/blazor/security/blazor-web-app-with-entra.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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 <xref:Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.SignedOutCallbackPath%2A> 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 <xref:Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.SignedOutRedirectUri%2A> or <xref:Microsoft.AspNetCore.Authentication.AuthenticationProperties.RedirectUri%2A>, if specified.

[!INCLUDE[](~/blazor/security/includes/secure-authentication-flows.md)]

:::zone-end

:::zone pivot="bff-pattern"
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -435,22 +441,6 @@ The callback path (`CallbackPath`) must match the redirect URI (login callback p

The <xref:Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.SignedOutCallbackPath%2A> 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 <xref:Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectOptions.SignedOutRedirectUri%2A> or <xref:Microsoft.AspNetCore.Authentication.AuthenticationProperties.RedirectUri%2A>, 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.

<!-- UPDATE 10.0 Keep an eye on this NOTE for removal or updates.
The remark on this subject is in the Program file of the
Entra sample app (Blazor samples repo). -->

> [!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
Expand Down
3 changes: 0 additions & 3 deletions aspnetcore/blazor/security/blazor-web-app-with-oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -1283,9 +1283,6 @@ Alternatively, use the following `LogInOrOut` component, which doesn't supply a

## Token refresh

<!-- UPDATE 10.0 - Check the PU issue for 10.0 work to resolve both issues.
The docs issue is https://github.com/dotnet/AspNetCore.Docs/issues/34235. -->

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).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,12 @@ When the component executes, `currentCount` is only set once during prerendering

## Serialization extensibility for persistent component state

<!-- UPDATE 10.0 - MIA API -->

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 <xref:Microsoft.AspNetCore.Components.PersistentComponentStateSerializer%601>. 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<IPersistentComponentStateSerializer<User>,
builder.Services.AddSingleton<PersistentComponentStateSerializer<TUser>,
CustomUserSerializer>();
```

Expand Down Expand Up @@ -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

<!-- UPDATE 10.0 - MIA API -->

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"
Expand Down Expand Up @@ -396,6 +392,8 @@ To skip restoring state during reconnection, set `RestoreBehavior` to `SkipLastS
public int CounterNotRestoredOnReconnect { get; set; }
```

<!-- UPDATE 10.0 - MIA API -->

Call `PersistentComponentState.RegisterOnRestoring` to register a callback for imperatively controlling how state is restored, similar to how <xref:Microsoft.AspNetCore.Components.PersistentComponentState.RegisterOnPersisting%2A?displayProperty=nameWithType> provides full control of how state is persisted.

:::moniker-end
Expand Down
Loading