diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index fe2520579040..faaf355d258b 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -1117,7 +1117,7 @@ }, { "source_path": "aspnetcore/blazor/integrate-components.md", - "redirect_url": "/aspnet/core/blazor/components/prerendering-and-integration", + "redirect_url": "/aspnet/core/blazor/components/integration", "redirect_document_id": false }, { @@ -1157,7 +1157,7 @@ }, { "source_path": "aspnetcore/blazor/components/integrate-components-into-razor-pages-and-mvc-apps.md", - "redirect_url": "/aspnet/core/blazor/components/prerendering-and-integration", + "redirect_url": "/aspnet/core/blazor/components/integration", "redirect_document_id": false }, { @@ -1317,6 +1317,11 @@ "source_path": "aspnetcore/blazor/images.md", "redirect_url": "/aspnet/core/blazor/images-and-documents", "redirect_document_id": false + }, + { + "source_path": "aspnetcore/blazor/components/prerendering-and-integration.md", + "redirect_url": "/aspnet/core/blazor/components/integration", + "redirect_document_id": false } ] } diff --git a/aspnetcore/blazor/components/index.md b/aspnetcore/blazor/components/index.md index 941c744b040f..79ffc9fc7466 100644 --- a/aspnetcore/blazor/components/index.md +++ b/aspnetcore/blazor/components/index.md @@ -1843,8 +1843,6 @@ In the preceding code, the CSS selector, `#app`, indicates that the `App` compon MVC and Razor Pages apps can also use the [Component Tag Helper](xref:Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper) to register statically-rendered Blazor WebAssembly root components: -:::moniker range=">= aspnetcore-6.0" - ```cshtml ``` @@ -1853,22 +1851,9 @@ Statically-rendered components can only be added to the app. They can't be remov For more information, see the following resources: -:::moniker-end - -:::moniker range=">= aspnetcore-8.0" - * * -:::moniker-end - -:::moniker range=">= aspnetcore-6.0 < aspnetcore-8.0" - -* -* - -:::moniker-end - [1]: [2]: diff --git a/aspnetcore/blazor/components/integration.md b/aspnetcore/blazor/components/integration.md index be74fa2b5a29..824313ef36de 100644 --- a/aspnetcore/blazor/components/integration.md +++ b/aspnetcore/blazor/components/integration.md @@ -1,607 +1,754 @@ --- -title: Integrate ASP.NET Core Razor components into ASP.NET Core apps +title: Integrate ASP.NET Core Razor components author: guardrex -description: Learn about Razor component integration scenarios ASP.NET Core apps, Razor Pages and MVC. -monikerRange: '>= aspnetcore-8.0' +description: Learn about Razor component integration scenarios for Blazor apps, including prerendering of Razor components on the server. +monikerRange: '>= aspnetcore-3.1' ms.author: riande ms.custom: mvc ms.date: 02/09/2024 uid: blazor/components/integration +zone_pivot_groups: blazor-hosting-models --- -# Integrate ASP.NET Core Razor components into ASP.NET Core apps +# Prerender and integrate ASP.NET Core Razor components -[!INCLUDE[](~/includes/not-latest-version-without-not-supported-content.md)] +[!INCLUDE[](~/includes/not-latest-version.md)] -This article explains Razor component integration scenarios for ASP.NET Core apps. +This article explains Razor component integration scenarios for Blazor apps, including prerendering of Razor components on the server. -## Razor component integration +> [!IMPORTANT] +> Framework changes across ASP.NET Core releases led to different sets of instructions in this article. Before using this article's guidance, confirm that the document version selector at the top of this article matches the version of ASP.NET Core that you intend to use for your app. -Razor components can be integrated into Razor Pages, MVC, and other types of ASP.NET Core apps. Razor components can also be integrated into any web app, including apps not based on ASP.NET Core, as [custom HTML elements](xref:blazor/components/js-spa-frameworks#blazor-custom-elements). +:::moniker range=">= aspnetcore-7.0" -Use the guidance in the following sections depending on the app's requirements: +:::zone pivot="webassembly" -* To integrate components that aren't directly routable from user requests, follow the guidance in the [Use non-routable components in pages or views](#use-non-routable-components-in-pages-or-views) section. Follow this guidance when the app should only embed components into existing pages and views with the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper). -* To integrate components with full Blazor support, follow the guidance in the [Add Blazor support to an ASP.NET Core app](#add-blazor-support-to-an-aspnet-core-app) section. +Razor components can be integrated into Razor Pages and MVC apps in a hosted Blazor WebAssembly [solution](xref:blazor/tooling#visual-studio-solution-file-sln). When the page or view is rendered, components can be prerendered at the same time. -## Use non-routable components in pages or views +Prerendering can improve [Search Engine Optimization (SEO)](https://developer.mozilla.org/docs/Glossary/SEO) by rendering content for the initial HTTP response that search engines can use to calculate page rank. -Use the following guidance to integrate Razor components into pages or views of an existing Razor Pages or MVC app with the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper). +## Solution configuration -> [!NOTE] -> If your app requires directly-routable components (not embedded into pages or views), skip this section and use the guidance in the [Add Blazor support to an ASP.NET Core app](#add-blazor-support-to-an-aspnet-core-app) section. +### Prerendering configuration -When server prerendering is used and the page or view renders: +To set up prerendering for a hosted Blazor WebAssembly app: -* The component is prerendered with the page or view. -* The initial component state used for prerendering is lost. -* New component state is created when the SignalR connection is established. +1. Host the Blazor WebAssembly app in an ASP.NET Core app. A standalone Blazor WebAssembly app can be added to an ASP.NET Core solution, or you can use a hosted Blazor WebAssembly app created from the [Blazor WebAssembly project template](xref:blazor/tooling) with the hosted option: -For more information on rendering modes, including non-interactive static component rendering, see . To save the state of prerendered Razor components, see . + * Visual Studio: In the **Additional information** dialog, select the **ASP.NET Core Hosted** checkbox when creating the Blazor WebAssembly app. In this article's examples, the solution is named `BlazorHosted`. + * Visual Studio Code/.NET CLI command shell: `dotnet new blazorwasm -ho` (use the `-ho|--hosted` option). Use the `-o|--output {LOCATION}` option to create a folder for the solution and set the solution's project namespaces. In this article's examples, the solution is named `BlazorHosted` (`dotnet new blazorwasm -ho -o BlazorHosted`). -Add a `Components` folder to the root folder of the project. + For the examples in this article, the hosted solution's name (assembly name) is `BlazorHosted`. The client project's namespace is `BlazorHosted.Client`, and the server project's namespace is `BlazorHosted.Server`. -Add an imports file to the `Components` folder with the following content. Change the `{APP NAMESPACE}` placeholder to the namespace of the project. +1. **Delete** the `wwwroot/index.html` file from the Blazor WebAssembly **:::no-loc text="Client":::** project. -`Components/_Imports.razor`: +1. In the **:::no-loc text="Client":::** project, **delete** the following lines in `Program.cs`: -```razor -@using System.Net.Http -@using System.Net.Http.Json -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.AspNetCore.Components.Routing -@using Microsoft.AspNetCore.Components.Web -@using static Microsoft.AspNetCore.Components.Web.RenderMode -@using Microsoft.AspNetCore.Components.Web.Virtualization -@using Microsoft.JSInterop -@using {APP NAMESPACE} -@using {APP NAMESPACE}.Components -``` + ```diff + - builder.RootComponents.Add("#app"); + - builder.RootComponents.Add("head::after"); + ``` -In the project's layout file (`Pages/Shared/_Layout.cshtml` in Razor Pages apps or `Views/Shared/_Layout.cshtml` in MVC apps): +1. Add `_Host.cshtml` file to the **:::no-loc text="Server":::** project's `Pages` folder. You can obtain the files from a project created from the Blazor Server template using Visual Studio or using the .NET CLI with the `dotnet new blazorserver -o BlazorServer` command in a command shell (the `-o BlazorServer` option creates a folder for the project). After placing the files into the **:::no-loc text="Server":::** project's `Pages` folder, make the following changes to the files. -* Add the following `` tag and [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper) for a component to the `` markup: + Make the following changes to the `_Host.cshtml` file: - ```cshtml - - - ``` + * Update the `Pages` namespace at the top of the file to match the namespace of the **:::no-loc text="Server":::** app's pages. The `{APP NAMESPACE}` placeholder in the following example represents the namespace of the donor app's pages that provided the `_Host.cshtml` file: - The `href` value (the *app base path*) in the preceding example assumes that the app resides at the root URL path (`/`). If the app is a sub-application, follow the guidance in the *App base path* section of the article. + Delete: - The component is used to render head (``) content for page titles ( component) and other head elements ( component) set by Razor components. For more information, see . + ```diff + - @namespace {APP NAMESPACE}.Pages + ``` -* Add a ` - ``` + ```razor + @namespace BlazorHosted.Server.Pages + ``` - The Blazor framework automatically adds the `blazor.web.js` script to the app. + * Add an [`@using`](xref:mvc/views/razor#using) directive for the **:::no-loc text="Client":::** project at the top of the file: -> [!NOTE] -> Typically, the layout loads via a `_ViewStart.cshtml` file. + ```razor + @using BlazorHosted.Client + ``` -Add an non-operational (no-op) `App` component to the project. + * Update the stylesheet links to point to the WebAssembly project's stylesheets. In the following example, the client project's namespace is `BlazorHosted.Client`. The `{APP NAMESPACE}` placeholder represents the namespace of the donor app that provided the `_Host.cshtml` file. Update the Component Tag Helper (`` tag) for the `HeadOutlet` component to prerender the component. -`Components/App.razor`: + Delete: -```razor -@* No-op App component *@ -``` + ```diff + - + - + - + ``` -Where services are registered, add services for Razor components and services to support rendering Interactive Server components. + Add: -At the top of the `Program` file, add a `using` statement to the top of the file for the project's components: + ```cshtml + + + + ``` -```csharp -using {APP NAMESPACE}.Components; + > [!NOTE] + > Leave the `` element that requests the Bootstrap stylesheet (`css/bootstrap/bootstrap.min.css`) in place. + + * Update the Blazor script source to use the client-side Blazor WebAssembly script: + + Delete: + + ```diff + - + ``` + + Add: + + ```html + + ``` + + * Update the `render-mode` of the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper) to prerender the root `App` component with : + + Delete: + + ```diff + - + ``` + + Add: + + ```cshtml + + ``` + + > [!IMPORTANT] + > Prerendering isn't supported for authentication endpoints (`/authentication/` path segment). For more information, see . + +1. In the `Program.cs` file of the **:::no-loc text="Server":::** project, change the fallback endpoint from the `index.html` file to the `_Host.cshtml` page: + + Delete: + + ```diff + - app.MapFallbackToFile("index.html"); + ``` + + Add: + + ```csharp + app.MapFallbackToPage("/_Host"); + ``` + +1. If the **:::no-loc text="Client":::** and **:::no-loc text="Server":::** projects use one or more common services during prerendering, factor the service registrations into a method that can be called from both projects. For more information, see . + +1. Run the **:::no-loc text="Server":::** project. The hosted Blazor WebAssembly app is prerendered by the **:::no-loc text="Server":::** project for clients. + +### Configuration for embedding Razor components into pages and views + +The following sections and examples for embedding Razor components from the **:::no-loc text="Client":::** Blazor WebAssembly app into pages and views of the server app require additional configuration. + +The **:::no-loc text="Server":::** project must have the following files and folders. + +Razor Pages: + +* `Pages/Shared/_Layout.cshtml` +* `Pages/Shared/_Layout.cshtml.css` +* `Pages/_ViewImports.cshtml` +* `Pages/_ViewStart.cshtml` + +MVC: + +* `Views/Shared/_Layout.cshtml` +* `Views/Shared/_Layout.cshtml.css` +* `Views/_ViewImports.cshtml` +* `Views/_ViewStart.cshtml` + +The preceding files can be obtained by generating an app from the ASP.NET Core project templates using: + +* Visual Studio's new project creation tools. +* Opening a command shell and executing `dotnet new webapp -o {PROJECT NAME}` (Razor Pages) or `dotnet new mvc -o {PROJECT NAME}` (MVC). The option `-o|--output` with a value for the `{PROJECT NAME}` placeholder provides a name for the app and creates a folder for the app. + +Update the namespaces in the imported `_ViewImports.cshtml` file to match those in use by the **:::no-loc text="Server":::** project receiving the files. + +`Pages/_ViewImports.cshtml` (Razor Pages): + +```razor +@using BlazorHosted.Server +@namespace BlazorHosted.Server.Pages +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers ``` -In the preceding line, change the `{APP NAMESPACE}` placeholder to the app's namespace. For example: +`Views/_ViewImports.cshtml` (MVC): -```csharp -using BlazorSample.Components; +```razor +@using BlazorHosted.Server +@using BlazorHosted.Server.Models +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers ``` -In the `Program` file before the line that builds the app (`builder.Build()`): +Update the imported layout file, which is `Pages/Shared/_Layout.cshtml` for Razor Pages or `Views/Shared/_Layout.cshtml` for MVC. -```csharp -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents(); +First, delete the title and the stylesheet from the donor project, which is `RPDonor.styles.css` in the following example. The `{PROJECT NAME}` placeholder represents the donor project's app name. + +```diff +- @ViewData["Title"] - {PROJECT NAME} +- ``` -For more information on adding support for Interactive Server and WebAssembly components, see . +Include the **:::no-loc text="Client":::** project's styles in the layout file. In the following example, the **:::no-loc text="Client":::** project's namespace is `BlazorHosted.Client`. The `` element can be updated at the same time. -In the `Program` file immediately after the call to map Razor Pages (<xref:Microsoft.AspNetCore.Builder.RazorPagesEndpointRouteBuilderExtensions.MapRazorPages%2A>) in a Razor Pages app or to map the default controller route (<xref:Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions.MapControllerRoute%2A>) in an MVC app, call <xref:Microsoft.AspNetCore.Builder.RazorComponentsEndpointRouteBuilderExtensions.MapRazorComponents%2A> to discover available components and specify the app's root component (the first component loaded). By default, the app's root component is the `App` component (`App.razor`). Chain a call to <xref:Microsoft.AspNetCore.Builder.ServerRazorComponentsEndpointConventionBuilderExtensions.AddInteractiveServerRenderMode%2A> to configure interactive server-side rendering (interactive SSR) for the app: +Place the following lines in the `<head>` content of the layout file: -```csharp -app.MapRazorComponents<App>() - .AddInteractiveServerRenderMode(); +```cshtml +<title>@ViewData["Title"] - BlazorHosted + + + ``` -> [!NOTE] -> If the app hasn't already been updated to include Antiforgery Middleware, add the following line after is called: -> -> ```csharp -> app.UseAntiforgery(); -> ``` +The imported layout contains two `Home` (`Index` page) and `Privacy` navigation links. To make the `Home` links point to the hosted Blazor WebAssembly app, change the hyperlinks: -Integrate components into any page or view. For example, add an `EmbeddedCounter` component to the project's `Components` folder. +```diff +- {PROJECT NAME} ++ BlazorHosted +``` -`Components/EmbeddedCounter.razor`: +```diff +- Home ++ Home +``` -```razor -

Embedded Counter

+In an MVC layout file: -

Current count: @currentCount

+```diff +- {PROJECT NAME} ++ BlazorHosted +``` - +```diff +- Home ++ Home +``` -@code { - private int currentCount = 0; +Update the `