From 8c78c41d163d4d7a8b17227961d0d3cf1fb264aa Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:23:28 -0500 Subject: [PATCH] Client services during prerendering (#31382) --- aspnetcore/blazor/call-web-api.md | 26 +++++++++++++++++++ aspnetcore/blazor/components/render-modes.md | 6 +++-- .../fundamentals/dependency-injection.md | 19 ++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/aspnetcore/blazor/call-web-api.md b/aspnetcore/blazor/call-web-api.md index 453ee0bc0a..3445c78583 100644 --- a/aspnetcore/blazor/call-web-api.md +++ b/aspnetcore/blazor/call-web-api.md @@ -93,6 +93,32 @@ builder.Services.AddScoped(sp => }); ``` +:::moniker range=">= aspnetcore-8.0" + +## Client-side services for `HttpClient` fail during prerendering + +*This section only applies to WebAssembly components in Blazor Web Apps.* + +Blazor Web Apps normally prerender client-side WebAssembly components. services aren't registered by default in a Blazor Web App's main project. If the app is run with only the services registered in the `.Client` project, as described in the [Add the `HttpClient` service](#add-the-httpclient-service) section, executing the app results in a runtime error: + +> :::no-loc text="InvalidOperationException: Cannot provide a value for property 'Http' on type '{ASSEMBLY}.Client.Pages.{COMPONENT}'. There is no registered service of type 'System.Net.Http.HttpClient'."::: + +Use ***either*** of the following approaches to resolve this problem: + +* Add the services to the main project to make them available during component prerendering. Use the following service registration in the main project's `Program` file: + + ```csharp + builder.Services.AddHttpClient(); + ``` + + No explicit package reference is required for the main project because services are provided by the shared framework. + +* If prerendering isn't required for the component, disable prerendering by following the guidance in . If you adopt this approach, you don't need to add services to the main project of the Blazor Web App. + +For more information, see [Client-side services fail to resolve during prerendering](xref:blazor/components/render-modes#client-side-services-fail-to-resolve-during-prerendering). + +:::moniker-end + ## `HttpClient` and JSON helpers is available as a preconfigured service for making requests back to the origin server. diff --git a/aspnetcore/blazor/components/render-modes.md b/aspnetcore/blazor/components/render-modes.md index f9442615a1..9696574805 100644 --- a/aspnetcore/blazor/components/render-modes.md +++ b/aspnetcore/blazor/components/render-modes.md @@ -341,7 +341,7 @@ For example, consider the following `Home` component in the `.Client` project in No compile time error occurs, but a runtime error occurs during prerendering: -> :::no-loc text="Cannot provide a value for property 'Environment' on type 'BlazorWebAppSample.Client.Pages.Home'. There is no registered service of type 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment'."::: +> :::no-loc text="Cannot provide a value for property 'Environment' on type 'BlazorSample.Client.Pages.Home'. There is no registered service of type 'Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment'."::: This error occurs because the component must compile and execute on the server during prerendering, but isn't a registered service on the server. @@ -379,7 +379,9 @@ You can also avoid the problem if you [disable prerendering](#prerendering) for There are a three approaches that you can take to address this scenario. The following are listed from most recommended to least recommended: -* *Recommended*: Create a custom service implementation for the service on the server. Use the service normally in interactive components of the `.Client` project. For a demonstration of this approach, see . +* *Recommended* for shared framework services: For shared framework services that merely aren't registered server-side in the main project, register the services in the main project, which makes them available during prerendering. For an example of this scenario, see the guidance for services in . + +* *Recommended* for services outside of the shared framework: Create a custom service implementation for the service on the server. Use the service normally in interactive components of the `.Client` project. For a demonstration of this approach, see . * Create a service abstraction and create implementations for the service in the `.Client` and server projects. Register the services in each project. Inject the custom service in the component. diff --git a/aspnetcore/blazor/fundamentals/dependency-injection.md b/aspnetcore/blazor/fundamentals/dependency-injection.md index 0f183d9b52..073a21380f 100644 --- a/aspnetcore/blazor/fundamentals/dependency-injection.md +++ b/aspnetcore/blazor/fundamentals/dependency-injection.md @@ -180,6 +180,25 @@ Client.Program.ConfigureCommonServices(builder.Services); For an example of this approach, see . +:::moniker range=">= aspnetcore-8.0" + +## Client-side services that fail during prerendering + +*This section only applies to WebAssembly components in Blazor Web Apps.* + +Blazor Web Apps normally prerender client-side WebAssembly components. If an app is run with a required service only registered in the `.Client` project, executing the app results in a runtime error similar to the following when a component attempts to use the required service during prerendering: + +> :::no-loc text="InvalidOperationException: Cannot provide a value for {PROPERTY} on type '{ASSEMBLY}}.Client.Pages.{COMPONENT NAME}'. There is no registered service of type '{SERVICE}'."::: + +Use ***either*** of the following approaches to resolve this problem: + +* Register the service in the main project to make it available during component prerendering. +* If prerendering isn't required for the component, disable prerendering by following the guidance in . If you adopt this approach, you don't need to register the service in the main project. + +For more information, see [Client-side services fail to resolve during prerendering](xref:blazor/components/render-modes#client-side-services-fail-to-resolve-during-prerendering). + +:::moniker-end + ## Service lifetime Services can be configured with the lifetimes shown in the following table.