Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor migration guidance 8.0 #30671

Merged
merged 20 commits into from
Oct 20, 2023
199 changes: 198 additions & 1 deletion aspnetcore/blazor/components/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,210 @@ uid: blazor/components/integration

This article explains Razor component integration scenarios for ASP.NET Core apps, including prerendering of Razor components on the server.
guardrex marked this conversation as resolved.
Show resolved Hide resolved

Razor components can be integrated into Razor Pages and MVC apps. When the page or view is rendered, components can be prerendered at the same time. 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.
Razor components can be integrated into Razor Pages, MVC, and other types of ASP.NET Core apps with prerendering. 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.
guardrex marked this conversation as resolved.
Show resolved Hide resolved

Use the guidance in the following sections depending on the project's requirements:

* Blazor support can be [added to an ASP.NET Core app](#add-blazor-support-to-an-aspnet-core-app).
* For interactive components that aren't directly routable from user requests, see the [Use non-routable components in pages or views](#use-non-routable-components-in-pages-or-views) section. Follow this guidance when the app embeds components into existing pages and views with the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper).
* For interactive components that are directly routable from user requests, see the [Use routable components](#use-routable-components) section. Follow this guidance when visitors should be able to make an HTTP request in their browser for a component with an [`@page`](xref:mvc/views/razor#page) directive.

## Add Blazor support to an ASP.NET Core app
guardrex marked this conversation as resolved.
Show resolved Hide resolved

This section covers adding Blazor support to an ASP.NET Core app.

> [!NOTE]
> For the examples in this section, the example app's name and namespace is `AspNetCoreApp`.

1. Add a package reference for the [`Microsoft.AspNetCore.Components.WebAssembly.Server`](https://www.nuget.org/packages/Microsoft.AspNetCore.Components.WebAssembly.Server) NuGet package to the app.

[!INCLUDE[](~/includes/package-reference.md)]

<!-- UPDATE 8.0 'Interactivity type' will change to 'Interactive render mode' at RTM -->

1. Create a donor Blazor Web App, which will provide assets to the app. Follow the guidance in the <xref:blazor/tooling> article, selecting support for the following template features when generating the Blazor Web App.

> [!IMPORTANT]
> For the app's name, use the same name as the ASP.NET Core app, which results in matching app name markup in components and matching namespaces in code. Using the same name/namespace isn't strictly required, as namespaces can be adjusted after assets are moved from the donor app to the ASP.NET Core app. However, time is saved by matching the namespaces at the outset, so that assets can be moved from the donor app to the ASP.NET Core app and used without spending time making manual namespace adjustments.

* For **Interactivity type**, select **Auto (Server and WebAssembly)** for Visual Studio or use the `-int Auto` option if using the .NET CLI.
* Set the **Interactivity location** to **Per page/component** for Visual Studio or ***avoid*** using the `-ai|--all-interactive` option when using the .NET CLI.

1. From the donor Blazor Web App, copy Bootstrap and Blazor styles into the ASP.NET Core project's `wwwroot` folder:

* `wwwroot/bootstrap` folder
* `app.css`

1. From the donor Blazor Web App, copy the entire `.Client` project into the solution folder of the ASP.NET Core app.

> [!IMPORTANT]
> **Don't copy the `.Client` folder into the ASP.NET Core project's folder.** The best approach for organizing .NET solutions is to place each project of the solution into its own folder inside of a top-level solution folder. If a solution folder above the ASP.NET Core project's folder doesn't exist, create one. Next, copy the `.Client` project's folder from the donor Blazor Web App into the solution folder. The final project folder structure should have the following layout:
>
> * `AspNetCoreAppSolution` (top-level solution folder)
> * `AspNetCoreApp` (original ASP.NET Core project)
> * `AspNetCoreApp.Client` (`.Client` project folder from the donor Blazor Web App)
>
> For the ASP.NET Core solution file, you can leave it in the ASP.NET Core project's folder. Alternatively, you can move the solution file or create a new one in the top-level solution folder as long as the project references correctly point to the project files (`.csproj`) of the two projects in the solution folder.

1. From the donor Blazor Web App, copy the entire `Components` folder into the ASP.NET Core project folder.

1. In the ASP.NET Core project's `Components` folder, delete the following components from the `Components/Pages` folder:

* `Home` component (`Home.razor`)
* `Weather` component (`Weather.razor`)

1. If you named the donor Blazor Web App when you created the donor project the same as the ASP.NET Core app, the namespaces used by the donated assets match those in the ASP.NET Core app. You shouldn't need to take further steps to match namespaces. If you used a different namespace when creating the donor Blazor Web App project, you must adjust the namespaces across the donated assets to match if you intend to use the rest of this guidance exactly as presented. If the namespaces don't match, ***either*** adjust the namespaces before proceeding ***or*** adjust the namespaces as you following the remaining guidance in this section.

1. Delete the donor Blazor Web App, as it has no further use in this process.

1. Add the `.Client` project to the solution:

In Visual Studio, right-click the solution in **Solution Explorer** and select **Add** > **Existing Project**. Navigate to the `.Client` folder and select the project file (`.csproj`).

If using the .NET CLI, use the [`dotnet sln add` command](/dotnet/core/tools/dotnet-sln#add) to add the `.Client` project to the solution.

1. Add a project reference to the ASP.NET Core project for the client project:

In Visual Studio, right-click the ASP.NET Core project and select **Add** > **Project Reference**. Select the `.Client` project and select **OK**.

If using the .NET CLI, from the ASP.NET Core project's folder, use the following command:

```dotnetcli
dotnet add reference ../AspNetCoreApp.Client/AspNetCoreApp.Client.csproj
```

> [!NOTE]
> The preceding command assumes the following:
>
> * The project file name is `AspNetCoreApp.Client.csproj`.
> * The `.Client` project is in a `AspNetCoreApp.Client` folder inside the solution folder. The `.Client` folder is side-by-side with the ASP.NET Core project's folder.
>
> For more information on the `dotnet add reference` command, see [`dotnet add reference` (.NET documentation)](/dotnet/core/tools/dotnet-add-reference).

1. In the ASP.NET Core project's `Program` file, add a `using` statement to the top of the file for the project's components:

```csharp
using AspNetCoreApp.Components;
```

Add the interactive component services (`AddInteractiveServerComponents` and `AddInteractiveWebAssemblyComponents`) with Razor component services (`AddRazorComponents`) before the app is built (the line that calls `builder.Build()`):

```csharp
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
```

Add [Antiforgery Middleware](xref:blazor/security/index#antiforgery-support) to the request processing pipeline after the call to `app.UseRouting`. If there are calls to `app.UseRouting` and `app.UseEndpoints`, the call to `app.UseAntiforgery` must go between them. A call to `app.UseAntiforgery` must be placed after calls to `app.UseAuthentication` and `app.UseAuthorization`.

```csharp
app.UseAntiforgery();
```

Add the interactive render modes (`AddInteractiveServerRenderMode` and `AddInteractiveWebAssemblyRenderMode`) and additional assemblies for the `.Client` project with `MapRazorComponents` before the app is run (the line that calls `app.Run`):

```csharp
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(AspNetCoreApp.Client._Imports).Assembly);
```

1. As you add Razor components to the solution, either in the ASP.NET Core project or the `.Client` project, configure the render mode of each component.

The donor Blazor Web App supplies a `Counter` component to the solution (`Pages/Counter.razor` in the `AspNetCoreApp.Client` project), which can be used for development testing.

Notice that the `Counter` component in the `.Client` project adopts the Auto render mode either using the `@attribute` ***or*** `@rendermode` directive:

```razor
@attribute [RenderModeInteractiveAuto]
```

```razor
@rendermode InteractiveAuto
```

For any of your ASP.NET Core app components that should also adopt the Auto render mode, place them in the `.Client` project's `Pages` folder (or `Shared` folder for non-routable, shared components) and provide the routable components in the `Pages` folder with ***either*** of the preceding directives, noting that a shared component typically inherits its render mode and doesn't require a directive.

Such components render on the server first, then render on the client after the Blazor bundle has been downloaded and the Blazor runtime activates. Keep in mind that component code is ***not*** private using the Auto render mode.

To further test in development with an interactive server `Counter` component, make a copy of the `Client` project's `Counter` component and change its file name to `Counter2.razor`. Place the file in the ASP.NET Core app (`Pages/Counter2.razor` in the `AspNetCoreApp` project).

Open the `Counter2.razor` file and change the route to avoid a conflict with the existing `Counter` component:

```diff
- @page "/counter"
+ @page "/counter-2"
```

Change the interactive render mode using ***either*** of the following lines:

```razor
@attribute [RenderModeInteractiveServer]
```

```razor
@rendermode InteractiveServer
```

Change the page title and heading markup to reflect that this is the 2nd counter component in the app:

```razor
<PageTitle>Counter 2</PageTitle>

<h1>Counter 2</h1>
```

Add the `Counter2` component to the `NavMenu` component (`Pages/Layout/NavMenu.razor`):

```razor
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter-2">
<span class="bi bi-plus-square-fill" aria-hidden="true"></span> Counter 2
</NavLink>
</div>
```

Remove the `Weather` component navigation menu entry from the `NavMenu` component:

```diff
- <div class="nav-item px-3">
- <NavLink class="nav-link" href="weather">
- <span class="bi bi-list-nested" aria-hidden="true"></span> Weather
- </NavLink>
- </div>
```

For components that should also strictly adopt the interactive server render mode, add ***either*** of the preceding directives to them and leave them in the ASP.NET Core project's `Pages`/`Shared` folders. Such components only ever render on the server. Component code is kept private on the server using the interactive server render mode.

When the app is run in the next step, navigate to each of the counter components (`/counter` and `/counter-2`) to inspect how they render.

If any of your server-side components should also disable prerendering, see <xref:blazor/components/render-modes#prerendering>.

For any components that should strictly adopt the interactive WebAssembly render mode in the `.Client` project (`Pages` folder of the `AspNetCoreApp.Client` project), explicitly configure the render mode:

```razor
@attribute [RenderModeInteractiveWebAssembly]
```

```razor
@rendermode InteractiveWebAssembly
```

Such components only render on the client after the Blazor bundle has been downloaded and the Blazor runtime activates. Keep in mind that component code is ***not*** private using the interactive WebAssembly render mode.

For additional information on applying render modes to components, see <xref:blazor/components/render-modes>.

1. Run the solution from the ***ASP.NET Core app*** project:

For Visual Studio, confirm that the ASP.NET Core project is selected in **Solution Explorer** when running the app.

If using the .NET CLI, run the project from the ASP.NET Core project's folder.

For the `Counter` component of the `.Client` project, navigate to `/counter`.

If you added the `Counter2` component, which is strictly configured for interactive server rendering, navigate to `/counter-2`.

## Use non-routable components in pages or views

Use the following guidance to integrate Razor components into pages and views of an existing Razor Pages or MVC app with the [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper).
Expand Down
Loading