.NET 10.0 Preview 4 focuses on web development
The fourth preview version of .NET 10.0 mainly delivers improvements for web APIs based on ASP.NET Core and the web front-end framework Blazor.
(Image: Pincasso/Shutterstock.com)
- Dr. Holger Schwichtenberg
NET 10.0 Preview 4 has been available for download on the .NET download page since yesterday. The new features relate in particular to web development with new web APIs based on ASP.NET Core and improvements to the Blazor framework.
At the same time, Visual Studio 2022 version 17.14 has been released in a stable version. Unlike before, there is no new preview version 17.5 for Visual Studio, but a version 17.14 Preview 7. As Microsoft's Build 2025 conference will take place next week from May 19 to 22 in Seattle and online, Microsoft could present the preview of a new major version there. The last major release before Visual Studio 2022 was Visual Studio 2019.
Videos by heise
(Image:Â Screenshot (Holger Schwichtenberg))
JSON patch for System.Text.Json and ASP.NET Core-based web APIs
ASP.NET Core 10.0 now also supports the JSON patch standard according to RFC 6902 in conjunction with Microsoft's JSON serializer System.Text.Json using the add-on package Microsoft.AspNetCore.JsonPatch.SystemTextJson
Previously, JSON Patch was only possible in conjunction with the older library Newtonsoft.Json. In comparison, Microsoft promises in the release notes improved performance and less memory usage in conjunction with a similar design to Newtonsoft.Json, including the updating of embedded objects and arrays. Not yet available is JSON patch for dynamic objects, because Newtonsoft.Json uses Reflection for this, but System.Text.Json should also work with the NativeAOT compiler.
In the NuGet package Microsoft.AspNetCore.JsonPatch.SystemTextJson there is a class JsonPatchDocument<T> with a method ApplyTo(obj) that applies a JSON patch operation to the passed object, as in the following code from the release notes:
// 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));
The code produces the following result:
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"
}
]
}
Rounding for previous updates
Since ASP.NET Core 10.0 Preview 3, parameter validation is also available in Minimal Web APIs. In Preview 4, this also works if the parameters are a record type.
The previously introduced consideration of XML documentation for OpenAPI documents can now be extended to XML comments from other assemblies. In the release notes, Microsoft shows a code example that integrates the XML comments from the SDK assembly Microsoft.AspNetCore.Http:
<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>
Diagnostic data for Blazor WebAssembly
The WebAssembly-based version of Blazor, which runs as a single-page app in the web browser, has a major new function: Developers can collect diagnostic data on performance, memory content and various metrics there at runtime. To do this, they must install the latest version of the .NET WebAssembly Build Tools (dotnet workload install wasm-tools) and the entries in the following table from the release notes in the project file:
| 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. |
You can then access the diagnostic data via JavaScript APIs:
// 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();
The result is a .nettrace file that can be viewed in Visual Studio. Alternatively, you can also use the performance tools of the web browser.
(Image:Â Microsoft)
Interoperability between C# and JavaScript
In Blazor, Microsoft is adding new members to the interfaces for interoperability between C# and JavaScript (IJSRuntime, IJSObjectReference, IJSInProcessRuntime and IJSInProcessObjectReference). [InvokeNew()[/code] and InvokeNewAsync() create an instance of a JavaScript object. There are also methods for reading object properties (GetValue() and GetValueAsync()) and setting them (SetValue() and SetValueAsync()).
Previously, it was only possible to call functions in JavaScript from C# with Invoke(), InvokeVoid(), InvokeAsync() and InvokeVoidAsync(). In some cases, the new interopability methods avoid having to write a JavaScript function. Instead, you can now create objects directly and read and write values. For the JavaScript class
window.TestClass = class {
constructor(text) {
this.text = text;
}
getTextLength() {
return this.text.length;
}
}
a code example in the release notes shows the use of the new methods:
var jsObj = await JSRuntime.InvokeNewAsync("jsInterop.TestClass", "Blazor!");
var text = await jsObj.GetValueAsync<string>("text");
var textLength = await jsObj.InvokeAsync<int>("getTextLength");