Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions aspnetcore/6.0/blazor/components/class-libraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,8 @@ An alternative to using the `Link` component is to link to the library's stylesh

`wwwroot/index.html` file (Blazor WebAssembly) or `Pages/_Layout.cshtml` file (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```diff
+ <link href="_content/ComponentLibrary/additionalStyles.css" rel="stylesheet" />
```
Expand Down
87 changes: 87 additions & 0 deletions aspnetcore/6.0/blazor/components/control-head-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Control &lt;head&gt; content in ASP.NET Core Blazor apps
author: guardrex
description: Learn how to control &lt;head&gt; content in Blazor apps, including how to set the page title from a component.
monikerRange: 'aspnetcore-6.0'
ms.author: riande
ms.custom: mvc
ms.date: 08/03/2021
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
uid: blazor/components/control-head-content
---
# Control `<head>` content in ASP.NET Core Blazor apps

*This feature applies to ASP.NET Core 6.0 Preview 7 or later. ASP.NET Core 6.0 Preview 7 is scheduled for release in August, 2021. ASP.NET Core 6.0 is scheduled for release later this year.*

Razor components can modify the HTML `<head>` element content of a page, including setting the page's title (`<title>` element) and modifying metadata (`<meta>` elements).

## Control `<head>` content in a Razor component

Specify the page's title with the `PageTitle` component. Specify `<head>` element content with the `HeadContent` component. The following example sets the page's title and description using Razor.

`Pages/ControlHeadContent.razor`:

```razor
@page "/control-head-content"

<h1>Control &lt;head&gt; content</h1>

<p>
Title: @title
</p>

<p>
Description: @description
</p>

<PageTitle>@title</PageTitle>

<HeadContent>
<meta name="description" content="@description">
</HeadContent>

@code {
private string description = "Description set by component";
private string title = "Title set by component";
}
```

## `HeadOutlet` component

The `HeadOutlet` component renders content provided by `HeadContent` components.

In an app created from the Blazor WebAssembly project template, the `HeadOutlet` component is added to the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder.RootComponents> collection of the <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.WebAssemblyHostBuilder> in `Program.Main`:

```csharp
builder.RootComponents.Add<HeadOutlet>("head::after");
```

When the [`::after` pseudo-selector](https://developer.mozilla.org/docs/Web/CSS/::after) is specified, the contents of the root component are appended to the existing head contents instead of replacing the content. This allows the app to retain static head content in `wwwroot/index.html` without having to repeat the content in the app's Razor components.

In Blazor Server apps created from the Blazor Server project template, a [Component Tag Helper](xref:mvc/views/tag-helpers/builtin-th/component-tag-helper) renders `<head>` content for the `HeadOutlet` component in `Pages/_Layout.cshtml`:

```cshtml
<head>
...
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
```

## Not found page title

In Blazor apps created from Blazor project templates, the `NotFound` component template in the `App` component (`App.razor`) sets the page title to `Not found`.

`App.razor`:

```razor
<PageTitle>Not found</PageTitle>
```

## Additional resources

Mozilla MDN Web Docs documentation:

* [What's in the head? Metadata in HTML](https://developer.mozilla.org/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML)
* [\<head>: The Document Metadata (Header) element](https://developer.mozilla.org/docs/Web/HTML/Element/head)
* [\<title>: The Document Title element](https://developer.mozilla.org/docs/Web/HTML/Element/title)
* [\<meta>: The metadata element](https://developer.mozilla.org/docs/Web/HTML/Element/meta)
4 changes: 4 additions & 0 deletions aspnetcore/6.0/blazor/components/css-isolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ h1 {

CSS isolation occurs at build time. Blazor rewrites CSS selectors to match markup rendered by the component. The rewritten CSS styles are bundled and produced as a static asset. The stylesheet is referenced inside the `<head>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server). The following `<link>` element is added by default to an app created from the Blazor project templates, where the placeholder `{ASSEMBLY NAME}` is the project's assembly name:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<link href="{ASSEMBLY NAME}.styles.css" rel="stylesheet">
```
Expand Down Expand Up @@ -210,6 +212,8 @@ In the following example:

`wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<link href="_content/ClassLib/ClassLib.bundle.scp.css" rel="stylesheet">
```
Expand Down
4 changes: 4 additions & 0 deletions aspnetcore/6.0/blazor/components/event-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ Custom events with custom event arguments are generally enabled with the followi

1. Register the custom event with the preceding handler in `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server) immediately after the Blazor `<script>`:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
Blazor.registerCustomEventType('customevent', {
Expand Down Expand Up @@ -169,6 +171,8 @@ public class CustomPasteEventArgs : EventArgs

Add JavaScript code to supply data for the <xref:System.EventArgs> subclass. In the `wwwroot/index.html` or `Pages/_Layout.cshtml` file, add the following `<script>` tag and content immediately after the Blazor script. The following example only handles pasting text, but you could use arbitrary JavaScript APIs to deal with users pasting other types of data, such as images.

[!INCLUDE[](../includes/layout-page-preview-7.md)]

`wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server) immediately after the Blazor script:

```html
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ To set up prerendering for a hosted Blazor WebAssembly app:

1. Add `_Host.cshtml` and `_Layout.cshtml` files to the **`Server`** project's `Pages` folder. You can obtain `_Host.cshtml` and `_Layout.cshtml` files from a project created from the Blazor Server template 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 **`Server`** project's `Pages` folder, make the following changes to the `_Layout.cshtml` file:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

* Provide an [`@using`](xref:mvc/views/razor#using) directive for the **`Client`** project (for example, `@using BlazorHosted.Client`).
* Update the stylesheet links to point to the WebAssembly project's stylesheets. In the following example, the client project's namespace is `BlazorHosted.Client`:

Expand All @@ -54,6 +56,8 @@ To set up prerendering for a hosted Blazor WebAssembly app:

* In the `_Layout.cshtml` file, update the Blazor script source to use the client-side Blazor WebAssembly script:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```diff
- <script src="_framework/blazor.server.js"></script>
+ <script src="_framework/blazor.webassembly.js"></script>
Expand Down Expand Up @@ -671,6 +675,8 @@ To solve these problems, Blazor supports persisting state in a prerendered page

::: zone pivot="server"

[!INCLUDE[](../includes/layout-page-preview-7.md)]

`Pages/_Layout.cshtml`:

```cshtml
Expand Down
2 changes: 2 additions & 0 deletions aspnetcore/6.0/blazor/fundamentals/handle-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ The UI for this error handling experience is part of the [Blazor project templat

In a Blazor Server app, customize the experience in the `Pages/_Layout.cshtml` file:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```cshtml
<div id="blazor-error-ui">
<environment include="Staging,Production">
Expand Down
4 changes: 4 additions & 0 deletions aspnetcore/6.0/blazor/fundamentals/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Components support multiple route templates using multiple [`@page` directives](
> [!IMPORTANT]
> For URLs to resolve correctly, the app must include a `<base>` tag in its `wwwroot/index.html` file (Blazor WebAssembly) or `Pages/_Layout.cshtml` file (Blazor Server) with the app base path specified in the `href` attribute. For more information, see <xref:blazor/host-and-deploy/index#app-base-path>.

[!INCLUDE[](../includes/layout-page-preview-7.md)]

The <xref:Microsoft.AspNetCore.Components.Routing.Router> doesn't interact with query string values. To work with query strings, see the [Query string and parse parameters](#query-string-and-parse-parameters) section.

## Focus an element on navigation
Expand Down Expand Up @@ -232,6 +234,8 @@ Use <xref:Microsoft.AspNetCore.Components.NavigationManager> to manage URIs and
| <xref:Microsoft.AspNetCore.Components.NavigationManager.ToAbsoluteUri%2A> | Converts a relative URI into an absolute URI. |
| <xref:Microsoft.AspNetCore.Components.NavigationManager.ToBaseRelativePath%2A> | Given a base URI (for example, a URI previously returned by <xref:Microsoft.AspNetCore.Components.NavigationManager.BaseUri>), converts an absolute URI into a URI relative to the base URI prefix. |

[!INCLUDE[](../includes/layout-page-preview-7.md)]

For the <xref:Microsoft.AspNetCore.Components.NavigationManager.LocationChanged> event, <xref:Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs> provides the following information about navigation events:

* <xref:Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs.Location>: The URL of the new location.
Expand Down
12 changes: 12 additions & 0 deletions aspnetcore/6.0/blazor/fundamentals/signalr.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ When the client detects that the connection has been lost, a default UI is displ

To customize the UI, define an element with an `id` of `components-reconnect-modal` in the `<body>` of the `_Layout.cshtml` Razor page.

[!INCLUDE[](../includes/layout-page-preview-7.md)]

`Pages/_Layout.cshtml`:

```cshtml
Expand Down Expand Up @@ -176,6 +178,8 @@ By default, Blazor Server apps prerender the UI on the server before the client

Configure the manual start of a Blazor Server app's [SignalR circuit](xref:blazor/hosting-models#circuits) in the `Pages/_Layout.cshtml` file:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

* Add an `autostart="false"` attribute to the `<script>` tag for the `blazor.server.js` script.
* Place a script that calls `Blazor.start` after the `blazor.server.js` script's `<script>` tag and inside the closing `</body>` tag.

Expand All @@ -189,6 +193,8 @@ On the client builder, pass in the `configureSignalR` configuration object that

`Pages/_Layout.cshtml`:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```cshtml
<body>
...
Expand Down Expand Up @@ -224,6 +230,8 @@ To modify the connection events, register callbacks for the following connection

`Pages/_Layout.cshtml`:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```cshtml
<body>
...
Expand All @@ -248,6 +256,8 @@ To adjust the reconnection retry count and interval, set the number of retries (

`Pages/_Layout.cshtml`:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```cshtml
<body>
...
Expand All @@ -272,6 +282,8 @@ To hide the reconnection display, set the reconnection handler's `_reconnectionD

`Pages/_Layout.cshtml`:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```cshtml
<body>
...
Expand Down
2 changes: 2 additions & 0 deletions aspnetcore/6.0/blazor/fundamentals/startup.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ uid: blazor/fundamentals/startup

Configure a manual start in the `wwwroot/index.html` file (Blazor WebAssembly) or `Pages/_Layout.cshtml` file (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

* Add an `autostart="false"` attribute and value to the `<script>` tag for the Blazor script.
* Place a script that calls `Blazor.start` after the Blazor `<script>` tag and inside the closing `</body>` tag.

Expand Down
6 changes: 6 additions & 0 deletions aspnetcore/6.0/blazor/globalization-localization.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,13 +441,17 @@ The following example shows how to set the current culture in a cookie that can

Add the following namespaces to the top of the `Pages/_Layout.cshtml` file:

[!INCLUDE[](includes/layout-page-preview-7.md)]

```csharp
@using System.Globalization
@using Microsoft.AspNetCore.Localization
```

Immediately after the opening `<body>` tag of `Pages/_Layout.cshtml`, add the following Razor expression:

[!INCLUDE[](includes/layout-page-preview-7.md)]

```cshtml
@{
this.HttpContext.Response.Cookies.Append(
Expand Down Expand Up @@ -646,6 +650,8 @@ For information on ordering the Localization Middleware in the middleware pipeli

If the app should localize resources based on storing a user's culture setting, use a localization culture cookie. Use of a cookie ensures that the WebSocket connection can correctly propagate the culture. If localization schemes are based on the URL path or query string, the scheme might not be able to work with [WebSockets](xref:fundamentals/websockets), thus fail to persist the culture. Therefore, the recommended approach is to use a localization culture cookie. See the [Dynamically set the culture by user preference](#dynamically-set-the-culture-by-user-preference) section of this article to see an example Razor expression for the `Pages/_Layout.cshtml` file that persists the user's culture selection.

[!INCLUDE[](includes/layout-page-preview-7.md)]

::: zone-end

The example of localized resources in this section works with the prior examples in this article where the app's supported cultures are English (`en`) as a default locale and Spanish (`es`) as a user-selectable or browser-specified alternate locale.
Expand Down
4 changes: 4 additions & 0 deletions aspnetcore/6.0/blazor/host-and-deploy/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ Blazor WebAssembly (`wwwroot/index.html`):

Blazor Server (`Pages/_Layout.cshtml`):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<base href="~/CoolApp/">
```
Expand All @@ -86,6 +88,8 @@ In many hosting scenarios, the relative URL path to the app is the root of the a

To set the app's base path, update the `<base>` tag within the `<head>` tag elements of the `Pages/_Layout.cshtml` file (Blazor Server) or `wwwroot/index.html` file (Blazor WebAssembly). Set the `href` attribute value to `/{RELATIVE URL PATH}/` (Blazor WebAssembly) or `~/{RELATIVE URL PATH}/` (Blazor Server). **The trailing slash is required.** The placeholder `{RELATIVE URL PATH}` is the app's full relative URL path.

[!INCLUDE[](../includes/layout-page-preview-7.md)]

For a Blazor WebAssembly app with a non-root relative URL path (for example, `<base href="/CoolApp/">`), the app fails to find its resources *when run locally*. To overcome this problem during local development and testing, you can supply a *path base* argument that matches the `href` value of the `<base>` tag at runtime. **Don't include a trailing slash.** To pass the path base argument when running the app locally, execute the `dotnet run` command from the app's directory with the `--pathbase` option:

```dotnetcli
Expand Down
5 changes: 5 additions & 0 deletions aspnetcore/6.0/blazor/includes/layout-page-preview-7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
no-loc: [Home, Privacy, Kestrel, appsettings.json, "ASP.NET Core Identity", cookie, Cookie, Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR]
---
> [!NOTE]
> In Blazor Server Preview 6 or earlier of ASP.NET Core 6.0, all root page HTML markup is found in `Pages/_Host.cshtml`. In Preview 7 or later, most root page markup is found in `Pages/_Layout.cshtml`. Preview 7 of ASP.NET Core 6.0 is scheduled for release in August, 2021. ASP.NET Core 6.0 is scheduled for release later this year.
4 changes: 4 additions & 0 deletions aspnetcore/6.0/blazor/includes/prerendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ While an app is prerendering, certain actions, such as calling into JavaScript,

For the following example, the `setElementText1` function is placed inside the `<head>` element of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server). The function is called with <xref:Microsoft.JSInterop.JSRuntimeExtensions.InvokeVoidAsync%2A?displayProperty=nameWithType> and doesn't return a value:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.setElementText1 = (element, text) => element.innerText = text;
Expand Down Expand Up @@ -35,6 +37,8 @@ The following component demonstrates how to use JavaScript interop as part of a

For the following example, the `setElementText2` function is placed inside the `<head>` element of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server). The function is called with<xref:Microsoft.JSInterop.IJSRuntime.InvokeAsync%2A?displayProperty=nameWithType> and returns a value:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.setElementText2 = (element, text) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ The following `returnArrayAsync` JS function, calls the `ReturnArrayAsync` .NET

Inside the closing `</body>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.returnArrayAsync = () => {
Expand Down Expand Up @@ -119,6 +121,8 @@ The following `sayHello1` JS function receives a <xref:Microsoft.JSInterop.DotNe

Inside the closing `</body>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.sayHello1 = (dotNetHelper) => {
Expand Down Expand Up @@ -168,6 +172,8 @@ The following `sayHello1` JS function:

Inside the closing `</body>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.sayHello1 = (dotNetHelper) => {
Expand Down Expand Up @@ -247,6 +253,8 @@ The following `updateMessageCaller` JS function invokes the `UpdateMessageCaller

Inside the closing `</body>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server):

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.updateMessageCaller = (dotnetHelper) => {
Expand Down Expand Up @@ -306,6 +314,8 @@ Blazor supports optimized byte array JS interop that avoids encoding/decoding by

Inside the closing `</body>` tag of `wwwroot/index.html` (Blazor WebAssembly) or `Pages/_Layout.cshtml` (Blazor Server), provide a `sendByteArray` JS function. The function is called by a button in the component and doesn't return a value:

[!INCLUDE[](../includes/layout-page-preview-7.md)]

```html
<script>
window.sendByteArray = () => {
Expand Down
Loading