Skip to content
Merged
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
244 changes: 210 additions & 34 deletions aspnetcore/blazor/components/integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ This section covers adding Blazor support to an ASP.NET Core app:

* [Add static server Razor component rendering](#add-static-server-razor-component-rendering)
* [Enable interactive server rendering](#enable-interactive-server-rendering)
<!-- * [Enable interactive Auto or WebAssembly rendering](#enable-interactive-auto-or-webassembly-rendering) -->
* [Enable interactive Auto or WebAssembly rendering](#enable-interactive-auto-and-webassembly-rendering)

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

### Add static server Razor component rendering

Add the following assets to the app, updating the `{APP NAMESPACE}` to the app's namespace as each file is added.
Add a `Components` folder to the app.

Add the following `_Imports` file for namespaces used by Razor components.

`Components/_Imports.razor`:

Expand All @@ -52,10 +54,14 @@ Add the following assets to the app, updating the `{APP NAMESPACE}` to the app's
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using {APP NAMESPACE}
@using {APP NAMESPACE}.Components
@using AspNetCoreApp
@using AspNetCoreApp.Components
```

Change the namespace `AspNetCoreApp` in the preceding example to match the app.

Add the Blazor router (`<Router>`) to the app in a `Routes` component, which is placed in the app's `Components` folder.

`Components/Routes.razor`:

```razor
Expand All @@ -75,6 +81,8 @@ You can supply a default layout with the <xref:Microsoft.AspNetCore.Components.R

For more information, see <xref:blazor/components/layouts#apply-a-default-layout-to-an-app>.

Add an `App` component to the app, which serves as the root component for other components.

`Components/App.razor`:

```razor
Expand All @@ -85,7 +93,7 @@ For more information, see <xref:blazor/components/layouts#apply-a-default-layout
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="{APP NAMESPACE}.styles.css" />
<link rel="stylesheet" href="AspNetCoreApp.styles.css" />
<HeadOutlet />
</head>

Expand All @@ -97,6 +105,16 @@ For more information, see <xref:blazor/components/layouts#apply-a-default-layout
</html>
```

For the `<link>` element in the preceding example, change `AspNetCoreApp` in the stylesheet's file name to match the app's project name. For example, a project named `ContosoApp` uses the `ContosoApp.styles.css` stylesheet file name:

```html
<link rel="stylesheet" href="ContosoApp.styles.css" />
```

Add a `Pages` folder to the `Components` folder to hold routable Razor components.

Add the following `Welcome` component to demonstrate static server rendering.

`Components/Pages/Welcome.razor`:

```razor
Expand All @@ -114,53 +132,57 @@ For more information, see <xref:blazor/components/layouts#apply-a-default-layout
}
```

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

```csharp
using {APP NAMESPACE}.Components;
```
* Add a `using` statement to the top of the file for the project's components:

Add Razor component services (`AddRazorComponents`) before the app is built (the line that calls `builder.Build()`):
```csharp
using AspNetCoreApp.Components;
```

```csharp
builder.Services.AddRazorComponents();
```
In the preceding example, change `AspNetCoreApp` in the namespace to match the app.

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`.
* Add Razor component services (`AddRazorComponents`). Add the following line before the line that calls `builder.Build()`):

```csharp
app.UseAntiforgery();
```
```csharp
builder.Services.AddRazorComponents();
```

Add `MapRazorComponents` to the app's request processing pipeline with the `App` component (`App.razor`) specified as the default root component. Place the following code before the app is run (the line that calls `app.Run`):
* Add [Antiforgery Middleware](xref:blazor/security/index#antiforgery-support) to the request processing pipeline after the call to `UseRouting`. If there are calls to `UseRouting` and `UseEndpoints`, the call to `UseAntiforgery` must go between them. A call to `UseAntiforgery` must be placed after calls to `UseAuthentication` and `UseAuthorization`.

```csharp
app.MapRazorComponents<App>();
```
```csharp
app.UseAntiforgery();
```

* Add `MapRazorComponents` to the app's request processing pipeline with the `App` component (`App.razor`) specified as the default root component. Place the following code before the the line that calls `app.Run`:

```csharp
app.MapRazorComponents<App>();
```

When the app is run, the `Welcome` component is accessed at the `/welcome` endpoint.

### Enable interactive server rendering

Follow the guidance in the [Add static server Razor component rendering](#add-static-server-razor-component-rendering) section.

Make the following changes in the app's `Program` file.
Make the following changes in the app's `Program` file:

Add a call to `AddInteractiveServerComponents` where Razor component services are added with `AddRazorComponents`:
* Add a call to `AddInteractiveServerComponents` where Razor component services are added with `AddRazorComponents`:

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

Add a call to `AddInteractiveServerRenderMode` where Razor components are mapped with `MapRazorComponents`:
* Add a call to `AddInteractiveServerRenderMode` where Razor components are mapped with `MapRazorComponents`:

```csharp
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
```
```csharp
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
```

Add a `Counter` component to the app with the interactive server render mode.
Add the following `Counter` component to the app that adopts the interactive server render mode.

`Components/Pages/Counter.razor`:

Expand All @@ -186,9 +208,163 @@ Add a `Counter` component to the app with the interactive server render mode.
}
```

When the app is run, the `Counter` component is accessed at the `/counter` endpoint.
When the app is run, the `Counter` component is accessed at `/counter`.

### Enable interactive Auto and WebAssembly rendering

Follow the guidance in the [Add static server Razor component rendering](#add-static-server-razor-component-rendering) section.

Components using the Auto render mode initially use interactive server rendering, but then switch to render on the client after the Blazor bundle has been downloaded and the Blazor runtime activates. Components using the WebAssembly render mode only render interactively on the client after the Blazor bundle is downloaded and the Blazor runtime activates. Keep in mind that when using the Auto or WebAssembly render modes, component code downloaded to the client is ***not*** private. For more information, see <xref:blazor/components/render-modes>.

After deciding which render mode to adopt:

* If you plan to adopt the Auto render mode, follow the guidance in the [Enable interactive server rendering](#enable-interactive-server-rendering) section.
* If you plan to only adopt interactive WebAssembly rendering, continue without adding interactive server rendering.

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

Create a donor Blazor Web App to 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.

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.

Visual Studio:

* For **Interactivity type**, select **Auto (Server and WebAssembly)**.
* Set the **Interactivity location** to **Per page/component**.
* Deselect the checkbox for **Include sample pages**.

.NET CLI:

* Use the `-int Auto` option.
* Do ***not*** use the `-ai|--all-interactive` option.
* Pass the `-e|--empty` option.

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.

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 follow the remaining guidance in this section.

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

Add the `.Client` project to the solution:

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

* .NET CLI: Use the [`dotnet sln add` command](/dotnet/core/tools/dotnet-sln#add) to add the `.Client` project to the solution.

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

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

* .NET CLI: From the ASP.NET Core project's folder, use the following command:

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

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

Make the following changes to the ASP.NET Core app's `Program` file:

* Add interactive WebAssembly component services with `AddInteractiveWebAssemblyComponents` where Razor component services are added with `AddRazorComponents`.

For interactive Auto rendering:

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

For only interactive WebAssembly rendering:

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

* Add the interactive WebAssembly render mode (`AddInteractiveWebAssemblyRenderMode`) and additional assemblies for the `.Client` project where Razor components are mapped with `MapRazorComponents`.

For interactive Auto rendering:

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

For only interactive WebAssembly rendering:

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

In the preceding examples, change `AspNetCoreApp.Client` to match the `.Client` project's namespace.

Add a `Pages` folder to the `.Client` project.

If the ASP.NET Core project has an existing `Counter` component:

* Move the component to the `Pages` folder of the `.Client` project.
* Remove the `@rendermode` directive at the top of the component file.

If the ASP.NET Core app doesn't have a `Counter` component, add the following `Counter` component (`Pages/Counter.razor`) to the `.Client` project:

```razor
@page "/counter"
@rendermode InteractiveAuto

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
private int currentCount = 0;

private void IncrementCount()
{
currentCount++;
}
}
```

If the app is only adopting interactive WebAssembly rendering, remove the `@rendermode` directive and value:

```diff
- @rendermode InteractiveAuto
```

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

* Visual Studio: Confirm that the ASP.NET Core project is selected in **Solution Explorer** when running the app.

* .NET CLI: Run the project from the ASP.NET Core project's folder.

To load the `Counter` component, navigate to `/counter`.

## Use non-routable components in pages or views

Expand Down