1
0
mirror of synced 2025-12-19 18:06:02 -05:00
Files
core/release-notes/10.0/preview/preview4/aspnetcore.md
James Montemagno 780b48a043 .NET 10 Preview 4 (#9828)
* Add .NET 10 Preview 4

* adding release notes for ef core

* updated cosmos section of ef docs and added missing small improvements

* fixed headings

* fix linter error in ef docs

* Update 10.0 Preview 4 Release notes (#9867)

* Update winforms.md

First draft with copilit

* Review feedback

latest updates

* Update winforms.md

* Update release-notes/10.0/preview/preview4/winforms.md

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

* Update release-notes/10.0/preview/preview4/winforms.md

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

* Update release-notes/10.0/preview/preview4/winforms.md

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

* Update release-notes/10.0/preview/preview4/winforms.md

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

* Update release-notes/10.0/preview/preview4/winforms.md

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

---------

Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>

* cleanup

* update C# 14

* .NET 10 Preview 4 - Containers (#9879)

* add here

* udpate

* update links

* Updated [dotnet-sdk-win-x86.zip] link 10.0.0-preview.4.md

* .NET 10 Preview 4 - Libraries (#9875)

* update here

* Add Out-of-Proc Trace Support for Activity Events and Links

* Rate Limiting Trace Sampling Support

* Clean-ip

* minor touch

* zip async

* gzip perf improvement

* Update release-notes/10.0/preview/preview4/libraries.md

Co-authored-by: Martin Costello <martin@martincostello.com>

* Update release-notes/10.0/preview/preview4/libraries.md

Co-authored-by: Rich Lander <rlander@microsoft.com>

* updates

---------

Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com>
Co-authored-by: Rich Lander <rlander@microsoft.com>
Co-authored-by: Martin Costello <martin@martincostello.com>

* .NET 10 Preview 4 - WPF (#9877)

* Add here

* Add WPF notes

* Add blurb about breaking changes

* cleanup messagebox stuff

* Update release-notes/10.0/preview/preview4/wpf.md

Co-authored-by: Harshit <62823486+harshit7962@users.noreply.github.com>

---------

Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com>
Co-authored-by: Harshit <62823486+harshit7962@users.noreply.github.com>

* .NET 10 Preview 4 - SDK (#9876)

* add here

* update

* .NET 10 Preview 4 - Runtime (#9874)

* Update runtime.md

* Add JIT notes

* Update inlining notes

Co-authored-by: Andy Ayers <andya@microsoft.com>

* Remove whitespace

* Brevity

Co-authored-by: Rich Lander <rlander@microsoft.com>

* cleanup top links

---------

Co-authored-by: Aman Khalid (from Dev Box) <amankhalid@microsoft.com>
Co-authored-by: Andy Ayers <andya@microsoft.com>
Co-authored-by: Rich Lander <rlander@microsoft.com>

* Add ASP.NET Core release notes for .NET 10 Preview 4 (#9881)

* Add ASP.NET Core release notes for .NET 10 Preview 4

* Add IJSObjectReference to JS function

* Update release-notes/10.0/preview/preview4/aspnetcore.md

Co-authored-by: Martin Costello <martin@martincostello.com>

* Fix OpenAPI.NET version

* Add todo for remaining features

* Add WebApplicationFactory with Kestrel

* Update todos

* Update todos

* Add NavigationManager.NotFound

* Add Blazor WebAssembly runtime diagnostics

* Edits

* Edits

* Edits

---------

Co-authored-by: Martin Costello <martin@martincostello.com>

* cleanup

* linter

* Address default Blazor UI template update.

* Add hyphen to dotnet-gcdump

* some updates

* updates

* .NET MAUI in .NET 10 Preview 4 (#9873)

* .NET MAUI in .NET 10 Preview 4

* added new MAUI features

* updates for known issues

* updates

---------

Co-authored-by: James Montemagno <james.montemagno@gmail.com>

* fix up md

* Update install-linux.md

* Update install-macos.md

* Update install-windows.md

* Update releases.json

* Updated release date in README.md

* Updated line16 with preview4 in releases.json

---------

Co-authored-by: maumar <maumar@microsoft.com>
Co-authored-by: Merrie McGaw <mmcgaw@microsoft.com>
Co-authored-by: Tanya Solyanik <tanyaso@microsoft.com>
Co-authored-by: victorisr <victorisr@microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com>
Co-authored-by: Rich Lander <rlander@microsoft.com>
Co-authored-by: Martin Costello <martin@martincostello.com>
Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com>
Co-authored-by: Harshit <62823486+harshit7962@users.noreply.github.com>
Co-authored-by: Aman Khalid (from Dev Box) <amankhalid@microsoft.com>
Co-authored-by: Andy Ayers <andya@microsoft.com>
Co-authored-by: Daniel Roth <daroth@microsoft.com>
Co-authored-by: David Ortinau <david.ortinau@microsoft.com>
Co-authored-by: padmasrid <38444564+padmasrid@users.noreply.github.com>
2025-05-13 10:32:54 -07:00

21 KiB

ASP.NET Core in .NET 10 Preview 4 - Release Notes

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

ASP.NET Core updates in .NET 10:

JSON Patch with System.Text.Json

JSON Patch is a standard format for describing changes to apply to a JSON document, defined in RFC 6902. It represents a sequence of operations (e.g., add, remove, replace, move, copy, test) that can be applied to modify a JSON document. In web applications, JSON Patch is commonly used in a PATCH operation to perform partial updates of a resource. Instead of sending the entire resource for an update, clients can send a JSON Patch document containing only the changes. This reduces payload size and improves efficiency.

This release introduces a new implementation of JSON Patch (RFC 6902) for ASP.NET Core based on System.Text.Json. This new implementation provides improved performance and reduced memory usage compared to the existing Newtonsoft.Json based implementation.

To enable JSON Patch support with System.Text.Json, use the Microsoft.AspNetCore.JsonPatch.SystemTextJson NuGet package. This package provides a JsonPatchDocument<T> class to represent a JSON Patch document for objects of type T and custom logic for serializing and deserializing JSON Patch documents using System.Text.Json. The key method of the JsonPatchDocument<T> class is ApplyTo, which applies the patch operations to a target object of type T.

Note that the new System.Text.Json implementation of JSON Patch isn't a complete drop-in replacement for the existing Newtonsoft.Json based implementation. In particular, the new implementation doesn't support dynamic types (like ExpandoObject).

The following examples demonstrate how to use the ApplyTo method to apply a JSON Patch document to an object.

The example demonstrates:

  1. The "add", "replace", and "remove" operations.
  2. Operations on nested properties.
  3. Adding a new item to an array.
  4. Using a JSON String Enum Converter in a JSON patch document.
// Original object
var person = new Person
{
    FirstName = "John",
    LastName = "Doe",
    Email = "johndoe@gmail.com",
    PhoneNumbers = [new() { Number = "123-456-7890", Type = PhoneNumberType.Mobile }],
    Address = new Address
    {
        Street = "123 Main St",
        City = "Anytown",
        State = "TX"
    }
};

// Raw JSON patch document
string jsonPatch = """
[
    { "op": "replace", "path": "/FirstName", "value": "Jane" },
    { "op": "remove", "path": "/Email"},
    { "op": "add", "path": "/Address/ZipCode", "value": "90210" },
    { "op": "add", "path": "/PhoneNumbers/-", "value": { "Number": "987-654-3210", "Type": "Work" } }
]
""";

// Deserialize the JSON patch document
var patchDoc = JsonSerializer.Deserialize<JsonPatchDocument<Person>>(jsonPatch);

// Apply the JSON patch document
patchDoc!.ApplyTo(person);

// Output updated object
Console.WriteLine(JsonSerializer.Serialize(person, serializerOptions));

// Output:
// {
//   "firstName": "Jane",
//   "lastName": "Doe",
//   "address": {
//     "street": "123 Main St",
//     "city": "Anytown",
//     "state": "TX",
//     "zipCode": "90210"
//   },
//   "phoneNumbers": [
//     {
//       "number": "123-456-7890",
//       "type": "Mobile"
//     },
//     {
//       "number": "987-654-3210",
//       "type": "Work"
//     }
//   ]
// }

Minimal API validation for record types

Minimal APIs now automatically validate record type parameters, similar to class types.

Generate OpenAPI schemas in transformers

Developers can now generate a schema for a C# type, using the same logic as ASP.NET Core OpenAPI document generation, and add it to the OpenAPI document. The schema can then be referenced from elsewhere in the OpenAPI document.

The context passed to document, operation, and schema transformers now has a GetOrCreateSchemaAsync method that can be used to generate a schema for a type. This method also has an optional ApiParameterDescription parameter to specify additional metadata for the generated schema.

To support adding the schema to the OpenAPI document, a Document property has been added to the Operation and Schema transformer contexts. This allows any transformer to add a schema to the OpenAPI document using the document's AddComponent method.

To use this feature in a document, operation, or schema transformer, create the schema using the GetOrCreateSchemaAsync method provided in the context and add it to the OpenAPI document using the document's AddComponent method.

builder.Services.AddOpenApi(options =>
{
    options.AddOperationTransformer(async (operation, context, cancellationToken) =>
    {
        // Generate schema for error responses
        var errorSchema = await context.GetOrCreateSchemaAsync(typeof(ProblemDetails), null, cancellationToken);
        context.Document?.AddComponent("Error", errorSchema);

        operation.Responses ??= new OpenApiResponses();
        // Add a "4XX" response to the operation with the newly created schema
        operation.Responses["4XX"] = new OpenApiResponse
        {
            Description = "Bad Request",
            Content = new Dictionary<string, OpenApiMediaType>
            {
                ["application/problem+json"] = new OpenApiMediaType
                {
                    Schema = new OpenApiSchemaReference("Error", context.Document)
                }
            }
        };
    });
});

Improved OpenAPI XML documentation support

ASP.NET Core now provides enhanced support for OpenAPI XML documentation comments, particularly for complex types. The updated generator also skips processing problematic complex types, preventing build errors and ensuring smoother builds. Note that this may result in missing metadata in some cases.

You can also now configure XML documentation processing to include comments from other assemblies. This is helpful for documenting types defined outside the current assembly, like ProblemDetails from the ASP.NET Core shared framework.

The following example demonstrates how to include XML comments for types in the Microsoft.AspNetCore.Http assembly:

<Target Name="AddOpenApiDependencies" AfterTargets="ResolveReferences">
    <ItemGroup>
        <!-- Include XML documentation for ProblemDetails -->
        <AdditionalFiles
                Include="@(ReferencePath->'%(RootDir)%(Directory)%(Filename).xml')"
                Condition="'%(ReferencePath.Filename)' == 'Microsoft.AspNetCore.Http.Abstractions'"
                KeepMetadata="Identity;HintPath" />
    </ItemGroup>
</Target>

In future previews we expect to include XML comments from key assemblies in the shared framework, reducing the need for manual configuration.

Access the OpenAPI document with IOpenApiDocumentProvider

ASP.NET Core now supports injecting IOpenApiDocumentProvider via dependency injection. This enables accessing the OpenAPI document in scenarios like background services or custom middleware, beyond the context of an HTTP request.

public class MyService(IOpenAPiDocumentProvider openApiDocumentProvider)
{
    public async Task DoSomething()
    {
        OpenApiDocument document = await openApiDocumentProvider.GetOpenApiDocumentAsync();
    }
}

OpenAPI.NET updated to Preview.17

The OpenAPI.NET library used in ASP.NET Core OpenAPI document generation has been upgraded to v2.0.0-preview.17. This version includes a number of bug fixes and improvements and also introduces some breaking changes. The breaking changes should only impact users that use document, operation, or schema transformers. Breaking changes in this iteration that may impact developers include the following:

JavaScript interop for constructors and properties

Use the new InvokeNewAsync and GetValueAsync/SetValueAsync methods to call JavaScript constructors and properties from .NET. The new methods are available on IJSRuntime and IJSObjectReference for asynchronous calls. Synchronous versions available on IJSInProcessRuntime and IJSInProcessObjectReference.

The following example shows creating an instance of a JavaScript class and calling its properties and methods:

window.TestClass = class {
  constructor(text) {
    this.text = text;
  }

  getTextLength() {
    return this.text.length;
  }
}
var jsObj = await JSRuntime.InvokeNewAsync("jsInterop.TestClass", "Blazor!");
var text = await jsObj.GetValueAsync<string>("text");
var textLength = await jsObj.InvokeAsync<int>("getTextLength");

Reference a JavaScript function with IJSObjectReference

You can now use JavaScript interop to retrieve an IJSObjectReference pointing to a JavaScript function, for example via GetValueAsync<IJSObjectReference> or InvokeAsync<IJObjectReference>. You can then use this reference to set a JavaScript handler.

Blazor WebAssembly runtime diagnostics

You can now collect runtime diagnostic information from Blazor WebAssembly apps, including performance profiles, memory dumps, and runtime metrics.

To collect runtime diagnostic information from a Blazor WebAssembly app, first ensure you have the .NET WebAssembly build tools installed:

dotnet workload install wasm-tools

The following MSBuild properties together enable support in the runtime for collecting diagnostics:

Property Default Set value to… Description
<WasmPerfTracing> false true Enables support for WebAssembly performance tracing.
<WasmPerfInstrumentation> none all Enables instrumentation necessary for the sampling profiler.
<EventSourceSupport> false true Enables EventPipe support.
<MetricsSupport> false true Enables System.Diagnostics.Metrics support.

Note that enabling runtime diagnostics may negatively impact app size and performance. Publishing an app to production with profilers enabled is not recommended.

You can then use the following JavaScript APIs to collect runtime diagnostics, which will be downloaded in a .nettrace file:

// Collect a performance profile using CPU sampling for a specified duration.
globalThis.getDotnetRuntime(0).collectCpuSamples({durationSeconds: 60});

// Collect metrics for a specified duration.
globalThis.getDotnetRuntime(0).collectPerfCounters({durationSeconds: 5});

// Collect a memory dump.
globalThis.getDotnetRuntime(0).collectGcDump();

Note that to enable loading the collected memory dump in Visual Studio, you can convert the downloaded .nettrace file to a .gcdump file using the dotnet-gcdump convert command.

You can also use the browser performance profiler to collect and view performance traces. To enable the browser performance profiler, add the following to your project file:

Property Default Set value to… Description
<WasmProfilers> No value browser Specifies the profilers to use. The browser profiler enables integration with the browser's developer tools profiler.
<WasmNativeStrip> true false Disables stripping the native executable.
<WasmNativeDebugSymbols> true true Enables building with native debug symbols.

Once the Blazor WebAssebly app has loaded, use the Performance tab in the browser developer tools to record runtime performance while interacting with the app. Analyze the recorded performance data for .NET using the Timings section:

Blazor WebAssembly browser performance profiler

Signal Not Found responses using NavigationManager

The NavigationManager class now includes a NotFound method to handle scenarios where a requested resource is not found:

  • Static server-side rendering: Calling NotFound sets the HTTP status code to 404.
  • Streaming rendering: Throws an exception if the response has already started.
  • Interactive rendering: Signals the Router to render a Not Found page.

You can use the OnNotFound event on NavigationManager to be notified when NotFound is invoked.

NavigationManager.NavigateTo no longer throws a NavigationException

Previously, calling NavigationManager.NavigateTo during static server-side rendering (SSR) would throw a NavigationException, interrupting execution before being converted to a redirection response. This caused confusion during debugging and was inconsistent with interactive rendering, where code after NavigateTo continues to execute normally.

Calling NavigationManager.NavigateTo during static SSR no longer throws a NavigationException. Instead, it behaves consistently with interactive rendering by performing the navigation without throwing an exception.

Code that previously relied on NavigationException being thrown should be updated. For example, in the default Blazor Identity UI, the IdentityRedirectManager throws an InvalidOperationException after calling RedirectTo to ensure it wasn't invoked during interactive rendering. This exception and the [DoesNotReturn] attributes should now be removed. For now, this manual update is required when using the Blazor Web App template with Individual Accounts authentication. A future template update will address this change.

To revert to the previous behavior of throwing a NavigationException, set the following AppContext switch:

AppContext.SetSwitch("Microsoft.AspNetCore.Components.Endpoints.NavigationManager.EnableThrowNavigationException", isEnabled: true);

QuickGrid method CloseColumnOptionsAsync renamed to HideColumnOptionsAsync

The CloseColumnOptionsAsync method on the QuickGrid component has been renamed to HideColumnOptionsAsync.

WriteImportMapToHtml renamed to OverrideHtmlAssetPlaceholders

The WriteImportMapToHtml MSBuild property has been renamed to OverrideHtmlAssetPlaceholders.

The OverrideHtmlAssetPlaceholders property enables the following build-time replacements in the root index.html file:

  • Replacing the importmap placeholder in the HTML file with a generated import map.
  • Replacing the <link rel="preload" id="webassembly" /> tag with link tags for preloading static framework assets.
  • Replacing the #[.{fingerprint}] placeholder with the appropriate fingerprint for the static web asset.

Preload Blazor framework static assets

In Blazor Web Apps, framework static assets are now automatically preloaded using Link headers, which allows the browser to preload resources before the initial page is fetched and rendered.

In standalone Blazor WebAssembly apps, framework assets can be preloaded using link tags generated from a <link rel="preload" id="webassembly" /> placeholder using the OverrideHtmlAssetPlaceholders MSBuild property setting.

Blazor WebAssembly Standalone App template updates

The Blazor WebAssembly Standalone app template has been updated to enable preloading of state framework assets, include a generated JavaScript import map, and fingerprinting for blazor.webassembly.js using the OverrideHtmlAssetPlaceholders setting.

index.html:

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

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>BlazorApp1</title>
    <base href="/" />
    <link rel="preload" id="webassembly" />
    <link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="css/app.css" />
    <link rel="icon" type="image/png" href="favicon.png" />
    <link href="BlazorApp1.styles.css" rel="stylesheet" />
    <script type="importmap"></script>
</head>

<body>
    <div id="app">...</div>
    <div id="blazor-error-ui">...</div>
    <script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
</body>

</html>

BlazorApp1.csproj:

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
  </PropertyGroup>

  <ItemGroup>...</ItemGroup>

</Project>

Blazor boot manifest merged into dotnet.js

The Blazor boot manifest (blazor.boot.json) is now integrated into the dotnet.js framework file. This reduces HTTP requests and improves Blazor WebAssembly runtime performance. Remove any dependencies on blazor.boot.json in existing apps.

Use WebApplicationFactory with Kestrel for integration testing

You can now use WebApplicationFactory with Kestrel for integration testing instead of the in-memory TestServer. This allows you to run integration tests against a real Kestrel server, including automated browser testing.

To use Kestrel with WebApplicationFactory, first call UseKestrel and then StartServer() to start the server. Use overloads of UseKestrel to optionally configure the port or other Kestrel options.

The following example shows testing an web app using WebApplicationFactory, Kestrel, xUnit.net, and Playwright:

public class BlazorWebAppFactory : WebApplicationFactory<Program>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(svc =>
        {
            svc.AddTransient<IWeatherService, TestWeatherService>();
        });
    }
}

public class WeatherPageTests : PageTest
{
    [Fact]
    public async Task Page_LoadsSuccessfully()
    {
        using var waf = new BlazorWebAppFactory();

        waf.UseKestrel();
        waf.StartServer();

        await Task.Delay(30000);
        var privacyPagePath = waf.ClientOptions.BaseAddress.ToString() + "weather";
        var response = await Page.GotoAsync(privacyPagePath);
        var content = await response!.TextAsync();

        await Expect(Page).ToHaveTitleAsync("Weather");
        Assert.Contains(TestWeatherService.TestWeatherSummary, content);
    }
}

Contributors

Thank you contributors! ❤️