Skip to content

Commit 33a8473

Browse files
authored
Merge pull request #35605 from dotnet/main
2 parents 6c4b421 + 1a951bc commit 33a8473

File tree

6 files changed

+215
-42
lines changed

6 files changed

+215
-42
lines changed

aspnetcore/blazor/call-web-api.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1289,8 +1289,6 @@ Calling <xref:System.Net.Http.HttpContent.ReadAsStreamAsync%2A?displayProperty=n
12891289
12901290
[!INCLUDE[](~/includes/aspnetcore-repo-ref-source-links.md)]
12911291
1292-
<!-- UPDATE 10.0 - Tracking on https://github.com/dotnet/runtime/issues/97449
1293-
12941292
To opt-out of response streaming globally, use either of the following approaches:
12951293
12961294
* Add the `<WasmEnableStreamingResponse>` property to the project file with a value of `false`:
@@ -1301,12 +1299,6 @@ To opt-out of response streaming globally, use either of the following approache
13011299
13021300
* Set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
13031301
1304-
............. AND REMOVE THE NEXT LINE .............
1305-
1306-
-->
1307-
1308-
To opt-out of response streaming globally, set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
1309-
13101302
To opt-out of response streaming for an individual request, set <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> to `false` on the <xref:System.Net.Http.HttpRequestMessage> (`request` in the following example):
13111303
13121304
```csharp

aspnetcore/blazor/fundamentals/routing.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -730,35 +730,33 @@ When a component is rendered statically (static SSR) and `NavigationManager.NotF
730730
}
731731
```
732732

733-
Two approaches for providing Not Found content for global interactive rendering:
733+
To provide Not Found content for global interactive rendering, use a Not Found page (Razor component).
734734

735-
* Use a Not Found page (Razor component).
736-
* Specify Not Found content in the [`Router` component's](xref:blazor/fundamentals/routing#route-templates) <xref:Microsoft.AspNetCore.Components.Routing.Router.NotFound%2A> property (`<NotFound>...</NotFound>` markup or by setting the `NotFound` parameter to a render fragment in C# code).
737-
738-
The following example uses a Not Found page (`NotFoundPage` component) to render Not Found content.
735+
> [!NOTE]
736+
> The Blazor project template includes a `NotFound.razor` page by default. This page automatically renders whenever `NavigationManager.NotFound` is called, making it easier to handle missing routes with a consistent user experience.
739737
740-
`NotFoundPage.razor`:
738+
`NotFound.razor`:
741739

742740
```razor
743741
<h1>Not Found</h1>
744742
745743
<p>Sorry! Nothing to show.</p>
746744
```
747745

748-
Specify the `NotFoundPage` component to the `Router` component in `Routes.razor`. You might need to specify the component's namespace with an [`@using`](xref:mvc/views/razor#using) directive either at the top of the `Routes.razor` file or in an [`_Imports.razor` file](xref:blazor/components/index#component-name-class-name-and-namespace).
746+
Assign the `NotFound` component to the router's `NotFoundPage` parameter. `NotFoundPage` supports routing that can be used across re-execution middleware, including non-Blazor middleware. If the `NotFound` render fragment is defined together with `NotFoundPage`, the page has higher priority.
747+
748+
In the following example, the preceding `NotFound` component is present in the app's `Pages` folder and passed to the `NotFoundPage` parameter:
749749

750750
```razor
751-
<Router ...>
752-
<Found ...>
753-
...
751+
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
752+
<Found Context="routeData">
753+
<RouteView RouteData="@routeData" />
754+
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
754755
</Found>
755-
<NotFound>
756-
<NotFoundPage />
757-
</NotFound>
758756
</Router>
759757
```
760758

761-
When a component is rendered with a global interactive render mode, calling `NotFound` signals the Blazor router to render Not Found content, which is the `NotFoundPage` component:
759+
When a component is rendered with a global interactive render mode, calling `NotFound` signals the Blazor router to render the `NotFound` component:
762760

763761
```razor
764762
@page "/render-not-found-interactive"

aspnetcore/blazor/performance/index.md

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
22
title: ASP.NET Core Blazor performance best practices
33
author: guardrex
4-
description: Tips for increasing the performance of ASP.NET Core Blazor apps and avoiding common performance problems.
4+
description: Guidance on ASP.NET Core Blazor metrics and tracing, improving app performance, and avoiding common performance problems.
55
monikerRange: '>= aspnetcore-3.1'
66
ms.author: wpickett
77
ms.custom: mvc
8-
ms.date: 04/16/2025
8+
ms.date: 06/08/2025
99
uid: blazor/performance/index
1010
---
1111
# ASP.NET Core Blazor performance best practices
@@ -24,3 +24,91 @@ Blazor is optimized for high performance in most realistic application UI scenar
2424
Ahead-of-time (AOT) compilation compiles a Blazor app's .NET code directly into native WebAssembly for direct execution by the browser. AOT-compiled apps result in larger apps that take longer to download, but AOT-compiled apps usually provide better runtime performance, especially for apps that execute CPU-intensive tasks. For more information, see <xref:blazor/tooling/webassembly#ahead-of-time-aot-compilation>.
2525

2626
:::moniker-end
27+
28+
:::moniker range=">= aspnetcore-10.0"
29+
30+
## Metrics and tracing
31+
32+
Metrics and tracing capabilities help you monitor and diagnose app performance, track user interactions, and understand component behavior in production environments.
33+
34+
### Configuration
35+
36+
To enable Blazor metrics and tracing in your app, configure [OpenTelemetry](https://github.com/open-telemetry/opentelemetry-dotnet) with the following meters and activity sources in the app's `Program` file where services are registered:
37+
38+
```csharp
39+
builder.Services.ConfigureOpenTelemetryMeterProvider(meterProvider =>
40+
{
41+
meterProvider.AddMeter("Microsoft.AspNetCore.Components");
42+
meterProvider.AddMeter("Microsoft.AspNetCore.Components.Lifecycle");
43+
meterProvider.AddMeter("Microsoft.AspNetCore.Components.Server.Circuits");
44+
});
45+
46+
builder.Services.ConfigureOpenTelemetryTracerProvider(tracerProvider =>
47+
{
48+
tracerProvider.AddSource("Microsoft.AspNetCore.Components");
49+
});
50+
```
51+
52+
### Performance meters
53+
54+
For more information on the following performance meters, see <xref:log-mon/metrics/built-in>.
55+
56+
`Microsoft.AspNetCore.Components` meter:
57+
58+
* `aspnetcore.components.navigation`: Tracks the total number of route changes in the app.
59+
* `aspnetcore.components.event_handler`: Measures the duration of processing browser events, including business logic.
60+
61+
`Microsoft.AspNetCore.Components.Lifecycle` meter:
62+
63+
* `aspnetcore.components.update_parameters`: Measures the duration of processing component parameters, including business logic.
64+
* `aspnetcore.components.render_diff`: Tracks the duration of rendering batches.
65+
66+
`Microsoft.AspNetCore.Components.Server.Circuits` meter:
67+
68+
In server-side Blazor apps, additional circuit-specific metrics include:
69+
70+
* `aspnetcore.components.circuit.active`: Shows the number of active circuits currently in memory.
71+
* `aspnetcore.components.circuit.connected`: Tracks the number of circuits connected to clients.
72+
* `aspnetcore.components.circuit.duration`: Measures circuit lifetime duration and provides total circuit count.
73+
74+
### Blazor tracing
75+
76+
For more information on the following tracing activities, see <xref:log-mon/metrics/built-in>.
77+
78+
The new activity tracing capabilities use the `Microsoft.AspNetCore.Components` activity source and provide three main types of tracing activities: circuit lifecycle, navigation, and event handling.
79+
80+
Circuit lifecycle tracing:
81+
82+
`Microsoft.AspNetCore.Components.CircuitStart`: Traces circuit initialization with the format `Circuit {circuitId}`.
83+
84+
* Tag: `aspnetcore.components.circuit.id`
85+
* Link: HTTP activity
86+
87+
Navigation tracing:
88+
89+
`Microsoft.AspNetCore.Components.RouteChange`: Tracks route changes with the format `Route {route} -> {componentType}`.
90+
91+
* Tags
92+
* `aspnetcore.components.circuit.id`
93+
* `aspnetcore.components.route`
94+
* `aspnetcore.components.type`
95+
* Links
96+
* HTTP trace
97+
* Circuit trace
98+
99+
Event handling tracing:
100+
101+
`Microsoft.AspNetCore.Components.HandleEvent`: Traces event handling with the format `Event {attributeName} -> {componentType}.{methodName}`.
102+
103+
* Tags
104+
* `aspnetcore.components.attribute.name`
105+
* `aspnetcore.components.circuit.id`
106+
* `aspnetcore.components.method`
107+
* `aspnetcore.components.type`
108+
* `error.type`
109+
* Links
110+
* HTTP trace
111+
* Circuit trace
112+
* Router trace
113+
114+
:::moniker-end

aspnetcore/log-mon/metrics/built-in/includes/built-in10.md

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,93 @@
33
This article describes the metrics built-in for ASP.NET Core produced using the
44
<xref:System.Diagnostics.Metrics?displayProperty=nameWithType> API. For a listing of metrics based on the older [EventCounters](/dotnet/core/diagnostics/event-counters) API, see [Available counters](/dotnet/core/diagnostics/available-counters).
55

6-
See [Using ASP.NET Core metrics](xref:log-mon/metrics/metrics) for information about how to collect, report, enrich, and test ASP.NET Core metrics
6+
For information about how to collect, report, enrich, and test ASP.NET Core metrics, see <xref:log-mon/metrics/metrics>.
7+
8+
## `Microsoft.AspNetCore.Components`
9+
10+
The `Microsoft.AspNetCore.Components` metrics report information on Razor component route changes and browser events:
11+
12+
* [`aspnetcore.components.navigation`](#metric-aspnetcorecomponentsnavigation)
13+
* [`aspnetcore.components.event_handler`](#metric-aspnetcorecomponentsevent_handler)
14+
15+
#### Metric: `aspnetcore.components.navigation`
16+
17+
Name | Instrument Type | Unit (UCUM) | Description
18+
--- | --- | --- | ---
19+
`aspnetcore.components.navigation`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentsnavigation)--> | Counter | `{route}` | Tracks the total number of route changes in the app.
20+
21+
Attribute | Type | Description | Examples | Presence
22+
--- | --- | --- | --- | ---
23+
`aspnetcore.components.type` | string | Component navigated to. | `TestComponent` | Always
24+
`aspnetcore.components.route` | string | The component's route. | `/test-route` | Always
25+
26+
#### Metric: `aspnetcore.components.event_handler`
27+
28+
Name | Instrument Type | Unit (UCUM) | Description
29+
--- | --- | --- | ---
30+
`aspnetcore.components.event_handler`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentsevent_handler)--> | Histogram | `s` | Measures the duration of processing browser events, including business logic.
31+
32+
Attribute | Type | Description | Examples | Presence
33+
--- | --- | --- | --- | ---
34+
`aspnetcore.components.type` | string | Component type handling the event. | `TestComponent` | Always
35+
`aspnetcore.components.method` | string | C# method handling the event. | `OnClick` | Always
36+
`aspnetcore.components.attribute.name` | string | Component attribute name handling the event. | `onclick` | Always
37+
`error.type` | string | The full name of exception type. | `System.InvalidOperationException`; `Contoso.MyException` | If an exception is thrown.
38+
39+
## `Microsoft.AspNetCore.Components.Lifecycle`
40+
41+
The `Microsoft.AspNetCore.Components.Lifecycle` metrics report information on Razor component lifecycle events:
42+
43+
* [`aspnetcore.components.update_parameters`](#metric-aspnetcorecomponentsupdate_parameters)
44+
* [`aspnetcore.components.render_diff`](#metric-aspnetcorecomponentsrender_diff)
45+
46+
#### Metric: `aspnetcore.components.update_parameters`
47+
48+
Name | Instrument Type | Unit (UCUM) | Description
49+
--- | --- | --- | ---
50+
`aspnetcore.components.update_parameters`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentsupdate_parameters)--> | Histogram | `s` | Measures the duration of processing component parameters, including business logic.
51+
52+
Attribute | Type | Description | Examples | Presence
53+
--- | --- | --- | --- | ---
54+
`aspnetcore.components.type` | string | Component type handling the event. | `TestComponent` | Always
55+
`error.type` | string | The full name of exception type. | `System.InvalidOperationException`; `Contoso.MyException` | If an exception is thrown.
56+
57+
#### Metric: `aspnetcore.components.render_diff`
58+
59+
Name | Instrument Type | Unit (UCUM) | Description
60+
--- | --- | --- | ---
61+
`aspnetcore.components.render_diff`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentsrender_diff)--> | Histogram | `s` | Tracks the duration of rendering batches.
62+
63+
Attribute | Type | Description | Examples | Presence
64+
--- | --- | --- | --- | ---
65+
`aspnetcore.components.diff.length` | int | The length of the render diff. | 50 | Always
66+
`error.type` | string | The full name of exception type. | `System.InvalidOperationException`; `Contoso.MyException` | If an exception is thrown.
67+
68+
## `Microsoft.AspNetCore.Components.Server.Circuits`
69+
70+
The `Microsoft.AspNetCore.Components.Server.Circuits` metrics report information on server-side Blazor circuits in Blazor Server and Blazor Web Apps:
71+
72+
* [`aspnetcore.components.circuit.active`](#metric-aspnetcorecomponentscircuitactive)
73+
* [`aspnetcore.components.circuit.connected`](#metric-aspnetcorecomponentscircuitconnected)
74+
* [`aspnetcore.components.circuit.duration`](#metric-aspnetcorecomponentscircuitduration)
75+
76+
#### Metric: `aspnetcore.components.circuit.active`
77+
78+
Name | Instrument Type | Unit (UCUM) | Description
79+
--- | --- | --- | ---
80+
`aspnetcore.components.circuit.active`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentscircuitactive)--> | UpDownCounter | `{circuit}` | Shows the number of active circuits currently in memory.
81+
82+
#### Metric: `aspnetcore.components.circuit.connected`
83+
84+
Name | Instrument Type | Unit (UCUM) | Description
85+
--- | --- | --- | ---
86+
`aspnetcore.components.circuit.connected`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentscircuitconnected)--> | UpDownCounter | `{circuit}` | Tracks the number of circuits connected to clients.
87+
88+
#### Metric: `aspnetcore.components.circuit.duration`
89+
90+
Name | Instrument Type | Unit (UCUM) | Description
91+
--- | --- | --- | ---
92+
`aspnetcore.components.circuit.duration`<!--](https://opentelemetry.io/docs/specs/semconv/dotnet/dotnet-http-metrics/#metric-aspnetcorecomponentscircuitduration)--> | Histogram | `s` | Measures circuit lifetime duration and provides total circuit count.
793

894
## `Microsoft.AspNetCore.Hosting`
995

aspnetcore/release-notes/aspnetcore-10.0.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ author: wadepickett
44
description: Learn about the new features in ASP.NET Core in .NET 10.
55
ms.author: wpickett
66
ms.custom: mvc
7-
ms.date: 06/10/2025
7+
ms.date: 6/9/2025
88
uid: aspnetcore-10
99
---
1010
# What's new in ASP.NET Core in .NET 10
@@ -13,7 +13,6 @@ This article highlights the most significant changes in ASP.NET Core in .NET 10
1313

1414
This article will be updated as new preview releases are made available. For breaking changes, see [Breaking changes in .NET](/dotnet/core/compatibility/breaking-changes).
1515

16-
1716
## Blazor
1817

1918
This section describes new features for Blazor.

aspnetcore/release-notes/aspnetcore-10/includes/blazor.md

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### New and updated Blazor Web App security samples
22

3-
We've added and updated Blazor Web App security samples cross-linked in the following articles:
3+
We've added and updated the Blazor Web App security samples linked in the following articles:
44

55
* <xref:blazor/security/blazor-web-app-oidc>
66
* <xref:blazor/security/blazor-web-app-entra>
@@ -110,10 +110,6 @@ In prior Blazor releases, response streaming for <xref:System.Net.Http.HttpClien
110110

111111
This is a breaking change because calling <xref:System.Net.Http.HttpContent.ReadAsStreamAsync%2A?displayProperty=nameWithType> for an <xref:System.Net.Http.HttpResponseMessage.Content%2A?displayProperty=nameWithType> (`response.Content.ReadAsStreamAsync()`) returns a `BrowserHttpReadStream` and no longer a <xref:System.IO.MemoryStream>. `BrowserHttpReadStream` doesn't support synchronous operations, such as `Stream.Read(Span<Byte>)`. If your code uses synchronous operations, you can opt-out of response streaming or copy the <xref:System.IO.Stream> into a <xref:System.IO.MemoryStream> yourself.
112112

113-
<!-- UNCOMMENT FOR PREVIEW 5 ...
114-
Waiting on https://github.com/dotnet/runtime/issues/97449
115-
... and update the Call web API article Line 983
116-
117113
To opt-out of response streaming globally, use either of the following approaches:
118114

119115
* Add the `<WasmEnableStreamingResponse>` property to the project file with a value of `false`:
@@ -124,12 +120,6 @@ To opt-out of response streaming globally, use either of the following approache
124120

125121
* Set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
126122

127-
............. AND REMOVE THE NEXT LINE .............
128-
129-
-->
130-
131-
To opt-out of response streaming globally, set the `DOTNET_WASM_ENABLE_STREAMING_RESPONSE` environment variable to `false` or `0`.
132-
133123
To opt-out of response streaming for an individual request, set <xref:Microsoft.AspNetCore.Components.WebAssembly.Http.WebAssemblyHttpRequestMessageExtensions.SetBrowserResponseStreamingEnabled%2A> to `false` on the <xref:System.Net.Http.HttpRequestMessage> (`requestMessage` in the following example):
134124

135125
```csharp
@@ -387,8 +377,6 @@ Calling <xref:Microsoft.AspNetCore.Components.NavigationManager.NavigateTo%2A?di
387377

388378
Code that relied on <xref:Microsoft.AspNetCore.Components.NavigationException> being thrown should be updated. For example, in the default Blazor Identity UI, the `IdentityRedirectManager` previously threw an <xref:System.InvalidOperationException> after calling `RedirectTo` to ensure it wasn't invoked during interactive rendering. This exception and the [`[DoesNotReturn]` attributes](xref:System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute) should now be removed.
389379

390-
<!-- HOLD FOR PREVIEW 5
391-
392380
To revert to the previous behavior of throwing a <xref:Microsoft.AspNetCore.Components.NavigationException>, set the following <xref:System.AppContext> switch:
393381

394382
```csharp
@@ -397,8 +385,6 @@ AppContext.SetSwitch(
397385
isEnabled: true);
398386
```
399387

400-
-->
401-
402388
### Not Found responses using `NavigationManager` for static SSR and global interactive rendering
403389

404390
The <xref:Microsoft.AspNetCore.Components.NavigationManager> now includes a `NotFound` method to handle scenarios where a requested resource isn't found during static server-side rendering (static SSR) or global interactive rendering:
@@ -412,3 +398,27 @@ Per-page/component rendering support is planned for Preview 5 in June, 2025.
412398
You can use the `NavigationManager.OnNotFound` event for notifications when `NotFound` is invoked.
413399

414400
For more information and examples, see <xref:blazor/fundamentals/routing?view=aspnetcore-10.0#not-found-responses>.
401+
402+
### Blazor router has a `NotFoundPage` parameter
403+
404+
Blazor now provides an improved way to display a "Not Found" page when navigating to a non-existent page. You can specify a page to render when `NavigationManager.NotFound` by passing a page type to the `Router` component using the `NotFoundPage` parameter. This approach is recommended over the previous `NotFound` fragment, as it supports routing, works across code re-execution middleware, and is compatible even with non-Blazor scenarios. If both a `NotFound` fragment and `NotFoundPage` are defined, the page specified by `NotFoundPage` takes priority.
405+
406+
```razor
407+
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
408+
<Found Context="routeData">
409+
<RouteView RouteData="@routeData" />
410+
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
411+
</Found>
412+
<NotFound>This content is ignored because NotFoundPage is defined.</NotFound>
413+
</Router>
414+
```
415+
416+
The Blazor project template now includes a `NotFound.razor` page by default. This page automatically renders whenever `NavigationManager.NotFound` is called in your app, making it easier to handle missing routes with a consistent user experience.
417+
418+
For more information, see <xref:blazor/fundamentals/routing#not-found-responses>.
419+
420+
### Metrics and tracing
421+
422+
This release introduces comprehensive metrics and tracing capabilities for Blazor apps, providing detailed observability of the component lifecycle, navigation, event handling, and circuit management.
423+
424+
For more information, see <xref:blazor/performance/index#metrics-and-tracing>.

0 commit comments

Comments
 (0)