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
4 changes: 4 additions & 0 deletions .openpublishing.redirection.core.json
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,10 @@
"source_path_from_root": "/docs/core/porting/tools.md",
"redirect_url": "/dotnet/core/porting/#tools-to-assist-porting"
},
{
"source_path_from_root": "/docs/core/porting/unsupported-apis.md",
"redirect_url": "/dotnet/core/compatibility/unsupported-apis"
},
{
"source_path_from_root": "/docs/core/porting/upgrade-assistant-aspnetmvc.md",
"redirect_url": "/aspnet/core/migration/mvc"
Expand Down
208 changes: 104 additions & 104 deletions docs/azure/includes/dotnet-all.md

Large diffs are not rendered by default.

154 changes: 77 additions & 77 deletions docs/azure/includes/dotnet-new.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/core/compatibility/11.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ See [Breaking changes in EF Core 11](/ef/core/what-is-new/ef-core-11.0/breaking-

| Title | Type of change |
|-------|-------------------|
| [ChangeToken.OnChange async overloads rebind existing Task-returning callbacks](extensions/11/changetoken-onchange-async-overloads-rebind-callbacks.md) | Behavioral change |
| [IHost.RunAsync and IHost.StopAsync throw when a BackgroundService fails](extensions/11/ihost-runasync-stopasync-throw-backgroundservice-failure.md) | Behavioral change |
| [Some Microsoft.Extensions packages included in shared framework](extensions/11/extensions-in-shared-framework.md) | Behavioral change |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "Breaking change: ChangeToken.OnChange async overloads rebind existing Task-returning callbacks"
description: "Learn about the breaking change in .NET 11 where new ChangeToken.OnChange async overloads can change overload binding for existing async callbacks."
ms.date: 08/03/2026
ai-usage: ai-assisted
---

# ChangeToken.OnChange async overloads rebind existing Task-returning callbacks

Starting in .NET 11, <xref:Microsoft.Extensions.Primitives.ChangeToken.OnChange*> adds async callback overloads. After you recompile against .NET 11, existing calls that pass an `async` lambda or a `Task`-returning callback can silently bind to a different overload and behave differently at runtime.

## Version introduced

.NET 11 Preview 7

## Previous behavior

Previously, `ChangeToken.OnChange` only exposed synchronous callback overloads:

```csharp
public static IDisposable OnChange(Func<IChangeToken?> changeTokenProducer, Action changeTokenConsumer);
public static IDisposable OnChange<TState>(Func<IChangeToken?> changeTokenProducer, Action<TState> changeTokenConsumer, TState state);
```

If you passed an `async` lambda, the compiler bound the call to an `Action` overload and compiled the lambda as `async void`. The callback behaved as fire-and-forget. `ChangeToken.OnChange` re-registered for the next change as soon as the callback yielded at its first incomplete `await`, and exceptions thrown later surfaced on the synchronization context or thread pool.

```csharp
// Bound to OnChange(Func<IChangeToken?>, Action) and compiled as 'async void'.
ChangeToken.OnChange(config.GetReloadToken, async () =>
{
await Task.Delay(1000);
Console.WriteLine("Reloaded");
});
```

## New behavior

Starting in .NET 11, `ChangeToken.OnChange` includes two asynchronous callback overloads:

```csharp
public static IDisposable OnChange(Func<IChangeToken?> changeTokenProducer, Func<Task> changeTokenConsumer);
public static IDisposable OnChange<TState>(Func<IChangeToken?> changeTokenProducer, Func<TState, Task> changeTokenConsumer, TState state);
```

If you pass an `async` lambda or another `Task`-returning callback, the compiler now binds to `Func<Task>` or `Func<TState, Task>`. The callback compiles as `async Task` instead of `async void`, and `ChangeToken.OnChange` re-registers only after the returned task completes. If multiple changes occur while the callback task runs, `ChangeToken.OnChange` coalesces those changes into one later callback invocation.

```csharp
// Binds to OnChange(Func<IChangeToken?>, Func<Task>) and compiles as 'async Task'.
// The token re-registers after the returned task completes.
ChangeToken.OnChange(config.GetReloadToken, async () =>
{
await Task.Delay(1000);
Console.WriteLine("Reloaded");
});
```

This overload rebinding is silent. The same source code still compiles, and the compiler reports no ambiguity.

## Type of breaking change

This change is a [behavioral change](../../categories.md#behavioral-change).

## Reason for change

To support correct asynchronous workflows, `ChangeToken.OnChange` now provides callback overloads that return `Task`. Before .NET 11, asynchronous callback logic required `async void` or synchronous blocking, which made error handling and callback timing harder to control. For API approval details, see [dotnet/runtime#69099](https://github.com/dotnet/runtime/issues/69099).

## Recommended action

For most code, no action is required. The new binding usually improves behavior because asynchronous work now completes before `ChangeToken.OnChange` re-registers for the next notification.

If you need the previous fire-and-forget `async void` behavior, cast the callback to `Action` (or `Action<TState>`) so your call continues to bind to the synchronous overload:

```csharp
ChangeToken.OnChange(config.GetReloadToken, (Action)(async () =>
{
await Task.Delay(1000);
Console.WriteLine("Reloaded");
}));
```

You can't control this behavior with an AppContext switch or configuration setting. Overload selection happens at compile time.

## Affected APIs

- `OnChange(Func<IChangeToken?> changeTokenProducer, Func<Task> changeTokenConsumer)` <!-- <xref:Microsoft.Extensions.Primitives.ChangeToken.OnChange(System.Func{Microsoft.Extensions.Primitives.IChangeToken},System.Func{System.Threading.Tasks.Task})?displayProperty=fullName> -->
- `OnChange<TState>(Func<IChangeToken?> changeTokenProducer, Func<TState, Task> changeTokenConsumer, TState state)` <!-- <xref:Microsoft.Extensions.Primitives.ChangeToken.OnChange``1(System.Func{Microsoft.Extensions.Primitives.IChangeToken},System.Func{``0,System.Threading.Tasks.Task},``0)?displayProperty=fullName> -->
- <xref:Microsoft.Extensions.Primitives.ChangeToken.OnChange(System.Func{Microsoft.Extensions.Primitives.IChangeToken},System.Action)?displayProperty=fullName>
- <xref:Microsoft.Extensions.Primitives.ChangeToken.OnChange``1(System.Func{Microsoft.Extensions.Primitives.IChangeToken},System.Action{``0},``0)?displayProperty=fullName>
2 changes: 2 additions & 0 deletions docs/core/compatibility/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ items:
href: deployment/11/runtimeconfigdev-configproperties-precedence.md
- name: Extensions
items:
- name: ChangeToken.OnChange async overloads rebind existing Task-returning callbacks
href: extensions/11/changetoken-onchange-async-overloads-rebind-callbacks.md
- name: IHost.RunAsync and IHost.StopAsync throw when a BackgroundService fails
href: extensions/11/ihost-runasync-stopasync-throw-backgroundservice-failure.md
- name: Some Microsoft.Extensions packages included in shared framework
Expand Down
2 changes: 1 addition & 1 deletion docs/core/extensions/primitives.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ As an alternative to calling `RegisterChangeCallback`, you could use the <xref:M

:::code source="./snippets/primitives/change/Example.Static.cs" id="Static":::

Much like previous examples, you'll need an implementation of `IChangeToken` that is produced by the `changeTokenProducer`. The producer is defined as a `Func<IChangeToken>` and it's expected that this will return a new token every invocation. The `consumer` is either an `Action` when not using `state`, or an `Action<TState>` where the generic type `TState` flows through the change notification.
Much like previous examples, you'll need an implementation of `IChangeToken` that is produced by the `changeTokenProducer`. The producer is defined as a `Func<IChangeToken>` and it's expected that this will return a new token every invocation. The `consumer` is an `Action` or `Func<Task>` when not using `state`, or an `Action<TState>` or `Func<TState, Task>` where the generic type `TState` flows through the change notification.

## String tokenizers, segments, and values

Expand Down
2 changes: 2 additions & 0 deletions docs/core/install/includes/microsoft-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ While most users prefer to be kept up to date, it is possible to block .NET upda
| .NET version | Registry key | Name | Type | Value |
| -------------- | :--------- | :---------- | :---------- | :---------- |
| All | HKLM\SOFTWARE\Microsoft\\.NET | BlockMU | REG_DWORD | 0x00000001 |
| .NET 10 | HKLM\SOFTWARE\Microsoft\\.NET\10.0 | BlockMU | REG_DWORD | 0x00000001 |
| .NET 9 | HKLM\SOFTWARE\Microsoft\\.NET\9.0 | BlockMU | REG_DWORD | 0x00000001 |
| .NET 8 | HKLM\SOFTWARE\Microsoft\\.NET\8.0 | BlockMU | REG_DWORD | 0x00000001 |
| .NET 7 | HKLM\SOFTWARE\Microsoft\\.NET\7.0 | BlockMU | REG_DWORD | 0x00000001 |
Expand All @@ -33,6 +34,7 @@ Updates for server operating systems are supported by WSUS and Microsoft Update
| .NET version | Registry key | Name | Type | Value |
| -------------- | :--------- | :---------- | :---------- | :---------- |
| All | HKLM\SOFTWARE\Microsoft\\.NET | AllowAUOnServerOS | REG_DWORD | 0x00000001 |
| .NET 10 | HKLM\SOFTWARE\Microsoft\\.NET\10.0 | AllowAUOnServerOS | REG_DWORD | 0x00000001 |
| .NET 9 | HKLM\SOFTWARE\Microsoft\\.NET\9.0 | AllowAUOnServerOS | REG_DWORD | 0x00000001 |
| .NET 8 | HKLM\SOFTWARE\Microsoft\\.NET\8.0 | AllowAUOnServerOS | REG_DWORD | 0x00000001 |
| .NET 7 | HKLM\SOFTWARE\Microsoft\\.NET\7.0 | AllowAUOnServerOS | REG_DWORD | 0x00000001 |
Expand Down
22 changes: 0 additions & 22 deletions docs/core/porting/unsupported-apis.md

This file was deleted.

78 changes: 78 additions & 0 deletions docs/core/tools/dotnet-scaffold-telemetry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
title: dotnet-scaffold telemetry
description: Learn about the telemetry collected by the dotnet-scaffold CLI tool.
author: tdykstra
ms.author: tdykstra
ms.date: 08/03/2026
ai-usage: ai-assisted
---
# dotnet-scaffold telemetry

The `dotnet-scaffold` tool includes a telemetry feature that collects usage data. This feature helps the `dotnet-scaffold` team understand how the tool is used so they can improve it.

`dotnet-scaffold` is a .NET global tool that generates scaffolding code for common components, such as controllers, views, and pages, so you don't have to write that boilerplate by hand. It isn't included with the .NET SDK. To install it, run the following command:

```dotnetcli
dotnet tool install --global Microsoft.dotnet-scaffold
```

For more information about the tool, see the [dotnet/Scaffolding repository](https://github.com/dotnet/Scaffolding) and the [Getting Started guide](https://github.com/dotnet/Scaffolding/blob/main/docs/Getting-Started.md).

## How to opt out

The `dotnet-scaffold` telemetry feature is enabled by default. To opt out of the telemetry feature, set the `DOTNET_SCAFFOLD_TELEMETRY_OPTOUT` environment variable to `1` or `true`.

## Disclosure

When you run the `dotnet-scaffold` tool for the first time, it displays output similar to the following example. The text might vary slightly depending on the version of the tool you're running. This "first run" experience is how Microsoft notifies you about data collection.

```console
dotnet-scaffold collects usage data in order to help us improve your experience. The data is collected by Microsoft and shared with the community. You can opt-out of telemetry by setting the DOTNET_SCAFFOLD_TELEMETRY_OPTOUT environment variable to '1' or 'true' using your favorite shell.

Read more about dotnet-scaffold telemetry:
https://aka.ms/dotnet-scaffold/telemetry
Read more about .NET CLI Tools telemetry:
https://aka.ms/dotnet-cli-telemetry
```

To suppress the "first run" experience text, set the `DOTNET_SCAFFOLD_SKIP_FIRST_TIME_EXPERIENCE` environment variable to `1` or `true`.

## Data points

The telemetry feature collects the following data for .NET SDK version 8.0 and later:

* Timestamp of invocation.
* Three-octet IP address used to determine the geographical location.
* Operating system and version.
* Runtime ID (RID) the tool is running on.
* Whether the tool is running in a container.
* Hashed Media Access Control (MAC) address: a cryptographically (SHA256) hashed and unique ID for a machine.
* Kernel version.
* dotnet-scaffold version.
* Hashed tool information (tool name, tool version, tool package name, tool package version, chosen scaffolder category, related scaffolding categories).
* Tool level (global or local tool).
* Hashed command invoked (for example, `mvccontroller`) and whether it succeeded.
* dotnet-scaffold-aspnet scaffolder name, step names, and whether they succeeded.
* dotnet-scaffold-aspire scaffolder name and whether it succeeded.
* dotnet-scaffold-aspnet scaffolder validation method name and whether it succeeded.
* dotnet-scaffold-aspire scaffolder validation method name and whether it succeeded.

The telemetry feature **does not** collect:

* Personal data, such as usernames, email addresses, or URLs.
* Any project data.

The data is sent securely to Microsoft servers and held under restricted access.

Protecting your privacy is important to us. If you suspect the telemetry feature is collecting sensitive data or the data is being insecurely or inappropriately handled, take one of the following actions:

* File an issue in the [dotnet/scaffolding](https://github.com/dotnet/scaffolding/issues) repository.
* Send an email to [dotnet@microsoft.com](mailto:dotnet@microsoft.com) for investigation.

## Additional resources

* [.NET SDK telemetry](telemetry.md)
* [.NET CLI telemetry data](https://dotnet.microsoft.com/platform/telemetry)
* [dotnet/Scaffolding repository](https://github.com/dotnet/Scaffolding)
* [Get started with dotnet-scaffold](https://github.com/dotnet/Scaffolding/blob/main/docs/Getting-Started.md)
* [Microsoft.dotnet-scaffold NuGet package](https://www.nuget.org/packages/Microsoft.dotnet-scaffold/)
4 changes: 2 additions & 2 deletions docs/csharp/language-reference/builtin-types/struct.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Structure types"
description: Learn about the struct type in C#
title: Structure types
description: "Structure types (struct) give C# lightweight, data-centric value types. See how value semantics, copying, and boxing work, and when to choose a class instead."
ms.date: 01/14/2026
f1_keywords:
- "struct_CSharpKeyword"
Expand Down
2 changes: 1 addition & 1 deletion docs/csharp/whats-new/csharp-12.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: What's new in C# 12
description: Get an overview of the new features in C# 12.
description: "Discover what's new in C# 12, including collection expressions, inline arrays, default lambda parameters, and interceptors. Try examples in your code."
ms.date: 03/19/2024
ms.topic: whats-new
---
Expand Down
2 changes: 1 addition & 1 deletion docs/csharp/whats-new/csharp-13.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: What's new in C# 13
description: Get an overview of the new features in C# 13.
description: "Discover what's new in C# 13, including params collections, a new lock object, ref struct interfaces, partial properties, and more. Try examples in your code."
ms.date: 11/18/2025
ms.topic: whats-new
---
Expand Down
2 changes: 1 addition & 1 deletion docs/csharp/whats-new/csharp-15.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: What's new in C# 15
description: Get an overview of the new features in C# 15. C# 15 ships with .NET 11.
description: "Discover what's new in C# 15, including features such as union types, the closed modifier, extension indexers, and pointer relaxations. Try examples in your code."
ms.date: 07/08/2026
ms.topic: whats-new
ms.update-cycle: 365-days
Expand Down
2 changes: 1 addition & 1 deletion docs/framework/get-started/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Get started with .NET Framework
description: Get started with .NET Framework, which is a runtime execution environment that manages apps. It contains a common language runtime (CLR) and an extensive class library.
description: Get started with .NET Framework, which is a runtime environment that manages apps. It contains a common language runtime (CLR) and an extensive class library.
ms.date: 10/21/2020
helpviewer_keywords:
- ".NET Framework, getting started"
Expand Down
6 changes: 2 additions & 4 deletions docs/navigate/migration-guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,8 @@ items:
href: ../../core/porting/net-framework-tech-unavailable.md
- name: Unsupported APIs
items:
- name: Tools to find unsupported APIs
href: ../../core/porting/unsupported-apis.md
- name: Unsupported API list
href: ../../core/compatibility/unsupported-apis.md
- name: Unsupported API list
href: ../../core/compatibility/unsupported-apis.md
- name: Needed changes before porting code
href: ../../core/porting/premigration-needed-changes.md
- name: Upgrade
Expand Down
2 changes: 2 additions & 0 deletions docs/navigate/tools-diagnostics/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ items:
href: ../../core/tools/test-prerelease-sdk-locally.md
- name: Telemetry
href: ../../core/tools/telemetry.md
- name: dotnet-scaffold telemetry
href: ../../core/tools/dotnet-scaffold-telemetry.md
- name: Signed-package verification
href: ../../core/tools/nuget-signed-package-verification.md
- name: Artifacts output layout
Expand Down
Loading
Loading