Skip to content

.NET 10 - Preview 3 #9817

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

Merged
merged 35 commits into from
Apr 10, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f296f11
stage P3
jamesmontemagno Mar 20, 2025
7c31946
cleanup
jamesmontemagno Mar 20, 2025
6b24e9d
efcore doc updates for preview 3
maumar Mar 27, 2025
2cb43de
.NET MAUI in .NET 10 Preview 3 (#9826)
davidortinau Apr 7, 2025
91fd38a
.NET 10 P3 - SDK Notes (#9822)
jamesmontemagno Apr 7, 2025
1290dec
.NET 10 Preview 3 - Runtime (#9823)
jamesmontemagno Apr 7, 2025
463d692
Add ASP.NET Core release notes for .NET 10 Preview 3 (#9835)
danroth27 Apr 7, 2025
48000f4
Updates for P3 (#9831)
merriemcgaw Apr 7, 2025
86762d1
.NET 10 P3 - Libraries (#9824)
jamesmontemagno Apr 7, 2025
db9391c
Merge branch 'main' into dotnet10-p3
jamesmontemagno Apr 7, 2025
0ff0997
Merge branch 'dotnet10-p3' of https://github.com/dotnet/core into dot…
jamesmontemagno Apr 7, 2025
7c3842a
cleanup
jamesmontemagno Apr 7, 2025
740ec28
cleanup
jamesmontemagno Apr 7, 2025
a13b555
cleanup
jamesmontemagno Apr 7, 2025
8e7b8f3
cleanup
jamesmontemagno Apr 7, 2025
1b88e4e
Initial draft of P3 release notes (#9832)
KathleenDollard Apr 7, 2025
35b2b19
cleanup
jamesmontemagno Apr 7, 2025
5450a99
cleanup
jamesmontemagno Apr 7, 2025
3cd9536
Update release-notes/10.0/preview/preview3/csharp.md
jamesmontemagno Apr 8, 2025
665dcb4
Update release-notes/10.0/preview/preview3/aspnetcore.md
jamesmontemagno Apr 9, 2025
c858c8a
update code block
jamesmontemagno Apr 9, 2025
db6af0f
Add global.json local sdk support details
baronfel Apr 9, 2025
e43d2df
Added WPF notes (#9844)
adegeo Apr 9, 2025
275f9de
update readmes
jamesmontemagno Apr 10, 2025
e4f8366
fix readme
jamesmontemagno Apr 10, 2025
1162064
Updated 10.0.0-preview.3.md with content and Nuget list
victorisr Apr 10, 2025
71bce23
cleanup 1
jamesmontemagno Apr 10, 2025
97f61dc
Implement feature X to enhance user experience and optimize performance
jamesmontemagno Apr 10, 2025
c8fd385
Update release-notes/10.0/preview/preview3/10.0.0-preview.3.md
jamesmontemagno Apr 10, 2025
f58b4fb
Updated windowsdesktop Urls
victorisr Apr 10, 2025
7bafe69
cleanup
jamesmontemagno Apr 10, 2025
ce1bd3f
updat elinux
jamesmontemagno Apr 10, 2025
ff31d58
udpated
jamesmontemagno Apr 10, 2025
cc0ad06
Fix table
adegeo Apr 10, 2025
fcff52c
Merge branch 'main' into dotnet10-p3
jamesmontemagno Apr 10, 2025
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
6 changes: 6 additions & 0 deletions release-notes/10.0/preview/preview3/10.0.0-preview.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# .NET 10 Preview 3 Binaries

.NET 10 Preview 3 installers and binaries can be downloaded for the following product versions:

- `.NET 10.0.0 Preview 3`
- `.NET SDK 10.0.100-preview.3.xxxx.xx`
40 changes: 40 additions & 0 deletions release-notes/10.0/preview/preview3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# .NET 10 Preview 3 - Release Notes

.NET 10 Preview 3 released on April X, 2025. Find more information on new features released in .NET 10 Preview 3 by browsing through the release notes below:

- [Libraries](./libraries.md)
- [Runtime](./runtime.md)
- [SDK](./sdk.md)

## Languages

- [C#](./csharp.md)
- [F#](./fsharp.md)
- [Visual Basic](./visualbasic.md)

## Workloads, Libraries, & More

- [.NET MAUI](./dotnetmaui.md)
- [ASP.NET Core](./aspnetcore.md)
- [Container images](./containers.md)
- [EF Core & Data](./efcore.md)
- [Windows Forms](./winforms.md)
- [WPF](./wpf.md)

## Get Started

Instructions on getting started with .NET 10 can be found in the [getting started guide](../../get-started.md). Installers and binaries for .NET 10 Preview 3 can be found [here on GitHub](./10.0.0-preview.3.md).

## Stay up-to-date

You can find a detailed overview of all new features in .NET 10:

- [What's new in .NET 10](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-10/overview)
- [What's new in C# 14](https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-14)
- [What's new in .NET MAUI](https://learn.microsoft.com/dotnet/maui/whats-new/dotnet-10)
- [What's new in ASP.NET Core](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-10.0)
- [What's new in Entity Framework Core](https://learn.microsoft.com/ef/core/what-is-new/ef-core-10.0/whatsnew)
- [What's new in Windows Forms](https://learn.microsoft.com/dotnet/desktop/winforms/whats-new/net100)
- [What's new in WPF](https://learn.microsoft.com/dotnet/desktop/wpf/whats-new/net100)

The latest .NET 10 release is always available at [dotnet.microsoft.com](https://dotnet.microsoft.com/download/dotnet/10.0) and [.NET 10 Releases](../../README.md).
271 changes: 271 additions & 0 deletions release-notes/10.0/preview/preview3/aspnetcore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# ASP.NET Core in .NET 10 Preview 3 - Release Notes

Here's a summary of what's new in ASP.NET Core in this preview release:

- [Declarative model for persisting state from components and services](#declarative-model-for-persisting-state-from-components-and-services)
- [Reference fingerprinted static web assets in standalone Blazor WebAssembly apps](#reference-fingerprinted-static-web-assets-in-standalone-blazor-webassembly-apps)
- [`HttpClient` response streaming enabled by default on WebAssembly](#httpclient-response-streaming-enabled-by-default-on-webassembly)
- [`DisableMatchAllIgnoresLeftUriPart` app context switch renamed to `EnableMatchAllForQueryStringAndFragment`](#disablematchallignoreslefturipart-app-context-switch-renamed-to-enablematchallforquerystringandfragment)
- [Set the environment at build-time for standalone Blazor WebAssembly apps](#set-the-environment-at-build-time-for-standalone-blazor-webassembly-apps)
- [Validation support in minimal APIs](#validation-support-in-minimal-apis)
- [OpenAPI support enabled by default in the ASP.NET Core Web API (native AOT) template](#openapi-support-enabled-by-default-in-the-aspnet-core-web-api-native-aot-template)
- [Support for Server-Sent Events (SSE)](#support-for-server-sent-events-sse)

ASP.NET Core updates in .NET 10:

- [What's new in ASP.NET Core in .NET 10](https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-10.0) documentation.
- [Breaking changes](https://docs.microsoft.com/dotnet/core/compatibility/10.0#aspnet-core)
- [Roadmap](https://github.com/dotnet/aspnetcore/issues/59443)

## Declarative model for persisting state from components and services

You can now declaratively specify state to persist from components and services using the `SupplyParameterFromPersistentComponentState` attribute. Properties with this attribute will automatically be persisted using the `PersistentComponentState` service during prerendering and then loaded when the component renders interactively or the service is instantiated.

Previously, persisting state from a component during prerendering using the `PersistentComponentState` service involved a significant amount of code:

```razor
@page "/movies"
@inject IMovieService MovieService
@inject PersistentComponentState ApplicationState
@implements IDisposable

<PageTitle>Movies</PageTitle>

<h3>Movies</h3>

@if (MoviesList == null)
{
<p><em>Loading...</em></p>
}
else
{
<QuickGrid Items="MoviesList.AsQueryable()">
<PropertyColumn Property="@(m => m.Title)" Title="Title" Sortable="true" />
<PropertyColumn Property="@(m => m.ReleaseDate)" Title="Release Date" Sortable="true" />
<PropertyColumn Property="@(m => m.Genre)" Title="Genre" Sortable="true" />
<PropertyColumn Property="@(m => m.Price)" Title="Price" Sortable="true" />
</QuickGrid>
}

@code {
public List<Movie>? MoviesList { get; set; }
private PersistingComponentStateSubscription? persistingSubscription;

protected override async Task OnInitializedAsync()
{
if (!ApplicationState.TryTakeFromJson<List<Movie>>("movies", out var movies))
{
MoviesList = await MovieService.GetMoviesAsync();
}
else
{
MoviesList = movies;
}

persistingSubscription = ApplicationState.RegisterOnPersisting(() =>
{
ApplicationState.PersistAsJson("movies", MoviesList);
return Task.CompletedTask;
});
}

public void Dispose() => persistingSubscription?.Dispose();
}
```

This code can now be simplified using the new declarative model:

```razor
@page "/movies"
@inject IMovieService MovieService

<PageTitle>Movies</PageTitle>

<h3>Movies</h3>

@if (MoviesList == null)
{
<p><em>Loading...</em></p>
}
else
{
<QuickGrid Items="MoviesList.AsQueryable()">
<PropertyColumn Property="@(m => m.Title)" Title="Title" Sortable="true" />
<PropertyColumn Property="@(m => m.ReleaseDate)" Title="Release Date" Sortable="true" />
<PropertyColumn Property="@(m => m.Genre)" Title="Genre" Sortable="true" />
<PropertyColumn Property="@(m => m.Price)" Title="Price" Sortable="true" />
</QuickGrid>
}

@code {
[SupplyParameterFromPersistentComponentState]
public List<Movie>? MoviesList { get; set; }

protected override async Task OnInitializedAsync()
{
MoviesList ??= await MovieService.GetMoviesAsync();
}
}
```

## Reference fingerprinted static web assets in standalone Blazor WebAssembly apps

Standalone Blazor WebAssembly apps can now reference framework static web assets using either a generated import map or a fingerprinted URL. The import map and fingerprinted URLs are generated during the build process when the `<WriteImportMapToHtml>true</WriteImportMapToHtml>` property is specified in the project file.

blazorwasm.csproj:

```diff
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
+ <WriteImportMapToHtml>true</WriteImportMapToHtml>
</PropertyGroup>
</Project>
```

To specify where the import map should be generated, add an empty `<script type="importmap"></script>` element to your _index.html_ file. To generate fingerprinted URLs for referenced static web assets, use the `#[.{fingerprint}]` placeholder.

index.html:

```diff
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlazorWasmFingerprintingE2E</title>
<base href="/" />
....
+ <script type="importmap"></script>
</head>

<body>
<div id="app">
<svg class="loading-progress">
<circle r="40%" cx="50%" cy="50%" />
<circle r="40%" cx="50%" cy="50%" />
</svg>
<div class="loading-progress-text"></div>
</div>

<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
- <script src="_framework/blazor.webassembly.js"></script>
+ <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>

</html>
```

## `HttpClient` response streaming enabled by default on WebAssembly

Response streaming is now enabled by default for `HttpClient` in Blazor WebAssembly. This change improves performance and reduces memory usage when handling large responses. However, it also means the response stream no longer supports synchronous operations because it is no longer a `MemoryStream`. If your code requires using synchronous operations, you can opt-out of response streaming for an individual request using the `SetBrowserResponseStreamingEnabled` extension method on the response message:

```csharp
requestMessage.SetBrowserResponseStreamingEnabled(false);
```

## `DisableMatchAllIgnoresLeftUriPart` app context switch renamed to `EnableMatchAllForQueryStringAndFragment`

The `Microsoft.AspNetCore.Components.Routing.NavLink.DisableMatchAllIgnoresLeftUriPart` app context switch was renamed to `Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragment`.

## Set the environment at build-time for standalone Blazor WebAssembly apps

You can now specify the environment for a standalone Blazor WebAssembly app at build-time using the `<WasmApplicationEnvironmentName>` property in the client app's project file (`.csproj`). In .NET 10, the `Blazor-Environment` header is no longer generated or used for setting the client environment.

The following example sets the app's environment to `Staging`:

```xml
<WasmApplicationEnvironmentName>Staging</WasmApplicationEnvironmentName>
```

The default environments applied to the app are:

- `Development` for build.
- `Production` for publish.

## Validation support in minimal APIs

Support for validation in minimal APIs is now available. This feature allows you to request validation of data sent to your API endpoints. When validation is enabled, the ASP.NET Core runtime performs any validations defined on query, header, and route parameters, as well as on the request body. Validations can be defined using attributes in the `System.ComponentModel.DataAnnotations` namespace.

Developers can customize the behavior of the validation system by:

- creating custom [ValidationAttribute](https://learn.microsoft.com/dotnet/api/system.componentmodel.dataannotations.validationattribute) implementations
- implementing the [IValidatableObject](https://learn.microsoft.com/dotnet/api/system.componentmodel.dataannotations.ivalidatableobject) interface for complex validation logic

When validation fails, the runtime returns a 400 Bad Request response with details of the validation errors.

To enable built-in validation support for minimal APIs, call the `AddValidation` extension method to register the required services into the service container for your application.

```csharp
builder.Services.AddValidation();
```

The implementation automatically discovers types that are defined in minimal API handlers or as base types of types defined in minimal API handlers. Validation is performed on these types by an endpoint filter added to each endpoint.

Validation can be disabled for specific endpoints by using the `DisableValidation` extension method.

```csharp
app.MapPost("/products",
([EvenNumber(ErrorMessage = "Product ID must be even")] int productId, [Required] string name)
=> TypedResults.Ok(productId))
.DisableValidation();
```

## OpenAPI support enabled by default in the ASP.NET Core Web API (native AOT) template

The ASP.NET Core Web API (native AOT) project template now has OpenAPI document generation support enabled by default using the Microsoft.AspNetCore.OpenApi package. This support can be disabled if desired, using the `--no-openapi` flag when creating a new project from the command-line interface.

Thank you [@sander1095](https://github.com/sander1095) for this contribution!

## Support for Server-Sent Events (SSE)

ASP.NET Core now supports returning a `ServerSentEvents` result using the `TypedResults.ServerSentEvents` API. This feature is supported in both minimal APIs and controller-based apps.

Server-Sent Events (SSE) is a server push technology that allows a server to send a stream of event messages to a client over a single HTTP connection. In .NET the event messages are represented as [`SseItem<T>`](https://learn.microsoft.com/dotnet/api/system.net.serversentevents.sseitem-1) objects, which may contain an event type, an ID, and a data payload of type `T`.

The TypedResults class includes a new static `ServerSentEvents` method for returning a `ServerSentEvents` result. The first parameter to this method is an `IAsyncEnumerable<SseItem<T>>` that represents the stream of event messages to be sent to the client.

The following example illustrates how to use the `TypedResults.ServerSentEvents` API to return a stream of heart rate events as JSON objects to the client:

```csharp
app.MapGet("/json-item", (CancellationToken cancellationToken) =>
{
async IAsyncEnumerable<HeartRateEvent> GetHeartRate(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
var heartRate = Random.Shared.Next(60, 100);
yield return HeartRateEvent.Create(heartRate);
await Task.Delay(2000, cancellationToken);
}
}

return TypedResults.ServerSentEvents(GetHeartRate(cancellationToken), eventType: "heartRate");
});
```

## Community contributors

Thank you contributors! ❤️

- [@NSTom](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3ANSTom)
- [@Varorbc](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3AVarorbc)
- [@Youssef1313](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3AYoussef1313)
- [@alexbeeston](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Aalexbeeston)
- [@benhopkinstech](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Abenhopkinstech)
- [@jnjudge1](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Ajnjudge1)
- [@lextm](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Alextm)
- [@mapedersen](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Amapedersen)
- [@nidaca](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Anidaca)
- [@sander1095](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Asander1095)
- [@shethaadit](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Ashethaadit)
- [@smnsht](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Asmnsht)
- [@xt0rted](https://github.com/dotnet/aspnetcore/pulls?q=is%3Apr+is%3Amerged+milestone%3A10.0-preview3+author%3Axt0rted)
3 changes: 3 additions & 0 deletions release-notes/10.0/preview/preview3/containers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Container image updates in .NET 10 Preview 3 - Release Notes

This preview release does not contain new Container image features.
Loading