Skip to content

Commit d6dfe84

Browse files
authored
Merge pull request #36104 from dotnet/main
2 parents 5ff86b9 + 94a6e13 commit d6dfe84

File tree

403 files changed

+1246
-383910
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

403 files changed

+1246
-383910
lines changed

.openpublishing.redirection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,11 @@
16471647
{
16481648
"source_path": "aspnetcore/fundamentals/handle-errors.md",
16491649
"redirect_url": "/aspnet/core/fundamentals/error-handling-api",
1650+
"redirect_document_id": false
1651+
},
1652+
{
1653+
"source_path": "aspnetcore/fundamentals/map-static-files.md",
1654+
"redirect_url": "/aspnet/core/fundamentals/static-files",
16501655
"redirect_document_id": false
16511656
}
16521657
]

aspnetcore/blazor/components/prerender.md

Lines changed: 65 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ This article explains Razor component prerendering scenarios for server-rendered
2525

2626
Prerendering is enabled by default for interactive components.
2727

28-
Internal navigation for interactive routing doesn't involve requesting new page content from the server. Therefore, prerendering doesn't occur for internal page requests, including for [enhanced navigation](xref:blazor/fundamentals/routing#enhanced-navigation-and-form-handling). For more information, see [Static versus interactive routing](xref:blazor/fundamentals/routing#static-versus-interactive-routing), [Interactive routing and prerendering](xref:blazor/state-management/prerendered-state-persistence#interactive-routing-and-prerendering), and [Enhanced navigation and form handling](xref:blazor/fundamentals/routing#enhanced-navigation-and-form-handling).
28+
Internal navigation with interactive routing doesn't use prerendering because the page is already interactive. For more information, see [Static versus interactive routing](xref:blazor/fundamentals/routing#static-versus-interactive-routing) and [Interactive routing and prerendering](xref:blazor/state-management/prerendered-state-persistence#interactive-routing-and-prerendering).
2929

3030
[`OnAfterRender{Async}` component lifecycle events](xref:blazor/components/lifecycle#after-component-render-onafterrenderasync) aren't called when prerendering, only after the component renders interactively.
3131

@@ -103,7 +103,53 @@ No compile time error occurs, but a runtime error occurs during prerendering:
103103
104104
This error occurs because the component must compile and execute on the server during prerendering, but <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment> isn't a registered service on the server.
105105

106-
If the app doesn't require the value during prerendering, this problem can be solved by injecting <xref:System.IServiceProvider> to obtain the service instead of the service type itself:
106+
Consider any of the following approaches to address this scenario:
107+
108+
* [Register the service on the server in addition to the client](#register-the-service-on-the-server-in-addition-to-the-client)
109+
* [Inject a service that the app can use during prerendering](#inject-a-service-that-the-app-can-use-during-prerendering)
110+
* [Make the service optional](#make-the-service-optional)
111+
* [Create a service abstraction](#create-a-service-abstraction)
112+
* [Disable prerendering for the component](#disable-prerendering-for-the-component)
113+
114+
### Register the service on the server in addition to the client
115+
116+
If the service supports server execution, register the service on the server in addition to the client so that it's available during prerendering. For an example of this scenario, see the guidance for <xref:System.Net.Http.HttpClient> services in the [Blazor Web App external web APIs](xref:blazor/call-web-api#blazor-web-app-external-web-apis) section of the *Call web API* article.
117+
118+
### Inject a service that the app can use during prerendering
119+
120+
In some cases, the app can use a service on the server during prerendering and a different service on the client.
121+
122+
For example, the following code obtains the app's environment whether the code is running on the server or on the client by injecting <xref:Microsoft.Extensions.Hosting.IHostEnvironment> from the [`Microsoft.Extensions.Hosting.Abstractions` NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Hosting.Abstractions):
123+
124+
```csharp
125+
private string? environmentName;
126+
127+
public Home(IHostEnvironment? serverEnvironment = null,
128+
IWebAssemblyHostEnvironment? wasmEnvironment = null)
129+
{
130+
environmentName = serverEnvironment?.EnvironmentName;
131+
environmentName ??= wasmEnvironment?.Environment;
132+
}
133+
```
134+
135+
However, this approach adds an additional dependency to the client project that isn't needed.
136+
137+
### Make the service optional
138+
139+
Make the service optional if it isn't required during prerendering using either of the following approaches.
140+
141+
The following example uses constructor injection of <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment>:
142+
143+
```csharp
144+
private string? environmentName;
145+
146+
public Home(IWebAssemblyHostEnvironment? env = null)
147+
{
148+
environmentName = env?.Environment;
149+
}
150+
```
151+
152+
Alternatively, inject <xref:System.IServiceProvider> to optionally obtain the service if it's available:
107153

108154
```razor
109155
@page "/"
@@ -131,95 +177,36 @@ If the app doesn't require the value during prerendering, this problem can be so
131177
}
132178
```
133179

134-
If you merely want to make the service injection optional, you can use constructor injection:
180+
### Create a service abstraction
135181

136-
```csharp
137-
private string? environmentName;
182+
If a different service implementation is needed on the server, create a service abstraction and create implementations for the service in the server and client projects. Register the services in each project. Inject the custom service abstraction into components where needed. The component then depends solely on the custom service abstraction.
138183

139-
public Home(IWebAssemblyHostEnvironment? env = null)
140-
{
141-
environmentName = env?.Environment;
142-
}
143-
```
184+
In the case of <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment>, we can reuse the existing interface instead of creating a new one:
144185

145-
Another option for obtaining the environment whether the code is running on the server or on the client is to inject <xref:Microsoft.Extensions.Hosting.IHostEnvironment> from the [`Microsoft.Extensions.Hosting.Abstractions` NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Hosting.Abstractions). Add a package reference to the app and use the following approach:
186+
`ServerHostEnvironment.cs`:
146187

147188
```csharp
148-
private string? environmentName;
189+
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
190+
using Microsoft.AspNetCore.Components;
149191

150-
public Home(IHostEnvironment? serverEnvironment = null,
151-
IWebAssemblyHostEnvironment? wasmEnvironment = null)
192+
public class ServerHostEnvironment(IWebHostEnvironment env, NavigationManager nav) :
193+
IWebAssemblyHostEnvironment
152194
{
153-
environmentName = serverEnvironment?.EnvironmentName;
154-
environmentName ??= wasmEnvironment?.Environment;
195+
public string Environment => env.EnvironmentName;
196+
public string BaseAddress => nav.BaseUri;
155197
}
156198
```
157199

158-
You can also avoid the problem if you [disable prerendering](#disable-prerendering) for the component, but that's an extreme measure to take in many cases that may not meet your component's specifications.
159-
160-
There are a four approaches that you can take to address this scenario for prerendering. The following are listed from most recommended to least recommended:
200+
In the server project's `Program` file, register the service:
161201

162-
* 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 <xref:System.Net.Http.HttpClient> services in the [Blazor Web App external web APIs](xref:blazor/call-web-api#blazor-web-app-external-web-apis) section of the *Call web API* article.
202+
```csharp
203+
builder.Services.TryAddScoped<IWebAssemblyHostEnvironment, ServerHostEnvironment>();
204+
```
163205

164-
* Make the service optional if it isn't always needed. See the first two examples in this section.
206+
At this point, the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment> service can be [injected into an interactive WebAssembly or Auto component that is also prerendered from the server](xref:blazor/fundamentals/environments#read-the-environment-in-a-blazor-webassembly-app).
165207

166-
* 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 abstraction in the component.
208+
### Disable prerendering for the component
167209

168-
* 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 <xref:blazor/fundamentals/environments#read-the-environment-client-side-in-a-blazor-web-app>.
210+
Disable prerendering for the component or for the entire app. For more information, see the [Disable prerendering](#disable-prerendering) section.
169211

170212
:::moniker-end
171-
172-
## Prerendering guidance
173-
174-
Prerendering guidance is organized in the Blazor documentation by subject matter. The following links cover all of the prerendering guidance throughout the documentation set by subject:
175-
176-
* Fundamentals
177-
* [Overview: Client and server rendering concepts](xref:blazor/fundamentals/index#client-and-server-rendering-concepts)
178-
* Routing
179-
* [Static versus interactive routing](xref:blazor/fundamentals/routing#static-versus-interactive-routing)
180-
* [Route to components from multiple assemblies: Interactive routing](xref:blazor/fundamentals/routing#interactive-routing)
181-
* <xref:Microsoft.AspNetCore.Components.Routing.Router.OnNavigateAsync> is executed *twice* when prerendering: [Handle asynchronous navigation events with `OnNavigateAsync`](xref:blazor/fundamentals/routing#handle-asynchronous-navigation-events-with-onnavigateasync)
182-
* Startup
183-
* [Control headers in C# code](xref:blazor/fundamentals/startup#control-headers-in-c-code)
184-
* [Client-side loading indicators](xref:blazor/fundamentals/startup#client-side-loading-indicators)
185-
* [Environments: Read the environment client-side in a Blazor Web App](xref:blazor/fundamentals/environments#read-the-environment-client-side-in-a-blazor-web-app)
186-
* [Handle Errors: Prerendering](xref:blazor/fundamentals/handle-errors#prerendering)
187-
* SignalR
188-
* [Client-side rendering](xref:blazor/fundamentals/signalr#client-side-rendering)
189-
* [Prerendered state size and SignalR message size limit](xref:blazor/fundamentals/signalr#prerendered-state-size-and-signalr-message-size-limit)
190-
191-
* Components
192-
* [Control `<head>` content during prerendering](xref:blazor/components/control-head-content#control-head-content-during-prerendering)
193-
* Render modes
194-
* [Detect rendering location, interactivity, and assigned render mode at runtime](xref:blazor/components/render-modes#detect-rendering-location-interactivity-and-assigned-render-mode-at-runtime)
195-
* [Custom shorthand render modes](xref:blazor/components/render-modes#custom-shorthand-render-modes)
196-
* Razor component lifecycle subjects that pertain to prerendering
197-
* [Component initialization (`OnInitialized{Async}`)](xref:blazor/components/lifecycle#component-initialization-oninitializedasync)
198-
* [After component render (`OnAfterRender{Async}`)](xref:blazor/components/lifecycle#after-component-render-onafterrenderasync)
199-
* [Stateful reconnection after prerendering](xref:blazor/components/lifecycle#stateful-reconnection-after-prerendering)
200-
* [Prerendering with JavaScript interop](xref:blazor/components/lifecycle#prerendering-with-javascript-interop): This section also appears in the two JS interop articles on calling JavaScript from .NET and calling .NET from JavaScript.
201-
* [Handle incomplete asynchronous actions at render](xref:blazor/components/lifecycle#handle-incomplete-asynchronous-actions-at-render): Guidance for delayed rendering due to long-running lifecycle tasks during prerendering on the server.
202-
* [`QuickGrid` component sample app](xref:blazor/components/quickgrid#sample-app): The [**QuickGrid for Blazor** sample app](https://aspnet.github.io/quickgridsamples/) is hosted on GitHub Pages. The site loads fast thanks to static prerendering using the community-maintained [`BlazorWasmPrerendering.Build` GitHub project](https://github.com/jsakamoto/BlazorWasmPreRendering.Build).
203-
* [Prerendering when integrating components into Razor Pages and MVC apps](xref:blazor/components/integration)
204-
205-
* [Call a web API: Prerendered data](xref:blazor/call-web-api#prerendered-data)
206-
207-
* [File uploads: Upload files to a server with client-side rendering (CSR)](xref:blazor/file-uploads#upload-files-to-a-server-with-client-side-rendering-csr)
208-
209-
* [Globalization and localization: Location override using "Sensors" pane in developer tools](xref:blazor/globalization-localization#location-override-using-sensors-pane-in-developer-tools)
210-
211-
* Authentication and authorization
212-
* [Server-side threat mitigation: Cross-site scripting (XSS)](xref:blazor/security/interactive-server-side-rendering#cross-site-scripting-xss)
213-
* Blazor server-side security overview
214-
* [Manage authentication state in Blazor Web Apps](xref:blazor/security/index#manage-authentication-state-in-blazor-web-apps)
215-
* [Unauthorized content display while prerendering with a custom `AuthenticationStateProvider`](xref:blazor/security/index#unauthorized-content-display-while-prerendering-with-a-custom-authenticationstateprovider)
216-
* [Blazor server-side additional scenarios: Reading tokens from `HttpContext`](xref:blazor/security/additional-scenarios#reading-tokens-from-httpcontext)
217-
* [Blazor WebAssembly overview: Prerendering support](xref:blazor/security/webassembly/index#prerendering-support)
218-
* Blazor WebAssembly additional scenarios
219-
* [Rendered component authentication with prerendering](xref:blazor/security/webassembly/additional-scenarios#prerendering-with-authentication)
220-
* [Secure a SignalR hub](xref:blazor/security/webassembly/additional-scenarios#secure-a-signalr-hub)
221-
* [Interactive server-side rendering: Cross-site scripting (XSS)](xref:blazor/security/interactive-server-side-rendering#cross-site-scripting-xss)
222-
223-
* [State management: Protected browser storage: Handle prerendering](xref:blazor/state-management/protected-browser-storage#handle-prerendering): Besides the *Handle prerendering* section, several article sections in the [State management node](xref:blazor/state-management/index) include remarks on prerendering.
224-
225-
For .NET 7 or earlier, see [Blazor WebAssembly security additional scenarios: Prerendering with authentication](xref:blazor/security/webassembly/additional-scenarios?view=aspnetcore-7.0&preserve-view=true#prerendering-with-authentication). After viewing the content in this section, reset the documentation article version selector dropdown to the latest .NET release version to ensure that documentation pages load for the latest release on subsequent visits.

0 commit comments

Comments
 (0)