From d06563262b8bafcb96e53129bb538815c13ff992 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Fri, 12 Sep 2025 15:49:47 -0700 Subject: [PATCH 1/3] draft --- aspnetcore/fundamentals/minimal-apis.md | 6 ++- .../includes/parameter-binding10.md | 4 ++ aspnetcore/includes/net10pipereader.md | 54 +++++++++++++++++++ aspnetcore/mvc/models/model-binding.md | 11 +++- 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 aspnetcore/includes/net10pipereader.md diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index 9c2a86ff3291..abe37b5073e6 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -68,7 +68,11 @@ The arguments passed to these methods are called "route h ## Parameter binding -[!INCLUDE [](~/fundamentals/minimal-apis/includes/parameter-binding10.md)] +[!INCLUDE [](~/includes/parameter-binding10.md)] + +## Json+PipeReader deserialization in minimal APIs + +[!INCLUDE [](~/includes/net10pipereader.md)] ## Validation support in Minimal APIs diff --git a/aspnetcore/fundamentals/minimal-apis/includes/parameter-binding10.md b/aspnetcore/fundamentals/minimal-apis/includes/parameter-binding10.md index 57e0fd53a662..7d67816d037a 100644 --- a/aspnetcore/fundamentals/minimal-apis/includes/parameter-binding10.md +++ b/aspnetcore/fundamentals/minimal-apis/includes/parameter-binding10.md @@ -427,4 +427,8 @@ The preceding code: * Accesses the request body using . * Copies the request body to a local file. +## JsonPipeReader deserialization in minimal APIs + +[!INCLUDE [](~/includes/net10pipereader.md)] + :::moniker-end diff --git a/aspnetcore/includes/net10pipereader.md b/aspnetcore/includes/net10pipereader.md new file mode 100644 index 000000000000..1c0121478a42 --- /dev/null +++ b/aspnetcore/includes/net10pipereader.md @@ -0,0 +1,54 @@ + + +Srtarting in .NET 10, the following functional areas of ASP.NET Core use overloads of `JsnSerializer.DeserializeAsync` based on PipeReader instead of Stream: + +* Minimal APIs (parameter binding, read request body) +* MVC (input formatters, model ) +* The methods + +For most applications, a transition from Stream to PipeReader provides better performance without requiring changes in application code. But if your application has a custom converter, the converter might not handle correctly. If it doesn't, the result could be errors such as with no warning, or missing data when deserializing. You have the following options for getting your converter to work without PipeReader-related errors + +## Option 1: Temporary workaround + +The quick workaround is to go back to using Stream without PipeReader support. To implement this option, set the "Microsoft.AspNetCore.UseStreamBasedJsonParsing" AppContext switch to "true". We recommend that you do this only as a temporary workaround, and update your converter to support`HasValueSequence` as soon as possible. The switch might be removed in .NET 11. Its purpose was to give developers time to get their converters updated. + +## Option 2: A quick fix for `JsonConverter` implementations + +For this fix, you allocate an array from the `ReadOnlySequence`. This example is what the code would look like:: + +```csharp +public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +{ + var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; + // previous code +} +``` + +## Option 3: ## Option 3: A more complicated but better performing fix + +This fix involves setting up a separate code path for the `ReadOnlySequence` handling: + +```csharp +public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +{ + if (reader.HasValueSequence) + { + reader.ValueSequence; + // ReadOnlySequence optimized path + } + else + { + reader.ValueSpan; + // ReadOnlySpan optimized path + } +} +``` + +For more information, see +* +* [github.com/dotnet/aspnetcore/pull/6289](https://github.com/dotnet/aspnetcore/pull/62895) \ No newline at end of file diff --git a/aspnetcore/mvc/models/model-binding.md b/aspnetcore/mvc/models/model-binding.md index 004f1268ba48..61241dd11f0b 100644 --- a/aspnetcore/mvc/models/model-binding.md +++ b/aspnetcore/mvc/models/model-binding.md @@ -8,7 +8,7 @@ ms.date: 07/19/2025 ai-usage: ai-assisted uid: mvc/models/model-binding --- - + # Model Binding in ASP.NET Core [!INCLUDE[](~/includes/not-latest-version.md)] @@ -723,6 +723,14 @@ If an instance of the type isn't registered in the dependency injection containe For nullable parameters, ensure that the parameter isn't `null` before accessing it. ## Additional resources +:::moniker-end +:::moniker range=">= aspnetcore-10.0" + +## Json+PipeReader deserialization in MVC + +[!INCLUDE [](~/includes/net10pipereader.md)] + +:::moniker range=">= aspnetcore-8.0" * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/model-binding/samples) ([how to download](xref:fundamentals/index#how-to-download-a-sample)) * @@ -731,4 +739,3 @@ For nullable parameters, ensure that the parameter isn't `null` before accessing :::moniker-end [!INCLUDE[](~/mvc/models/model-binding/includes/model-binding7.md)] - From 95c38127715a7bb2f1ddf6cf1012637d305b5a53 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Fri, 12 Sep 2025 19:54:10 -0700 Subject: [PATCH 2/3] fix moniker tags --- aspnetcore/fundamentals/minimal-apis.md | 2 +- aspnetcore/mvc/models/model-binding.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index abe37b5073e6..fc1d5682b8b0 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -68,7 +68,7 @@ The arguments passed to these methods are called "route h ## Parameter binding -[!INCLUDE [](~/includes/parameter-binding10.md)] +[!INCLUDE [](~/funddamentals/minimal-apis/includes/parameter-binding10.md)] ## Json+PipeReader deserialization in minimal APIs diff --git a/aspnetcore/mvc/models/model-binding.md b/aspnetcore/mvc/models/model-binding.md index 61241dd11f0b..a6cb05d1b67b 100644 --- a/aspnetcore/mvc/models/model-binding.md +++ b/aspnetcore/mvc/models/model-binding.md @@ -730,6 +730,7 @@ For nullable parameters, ensure that the parameter isn't `null` before accessing [!INCLUDE [](~/includes/net10pipereader.md)] +:::moniker-end :::moniker range=">= aspnetcore-8.0" * [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/model-binding/samples) ([how to download](xref:fundamentals/index#how-to-download-a-sample)) From 2733a8701d4ff436762f54bc62fec4f875506028 Mon Sep 17 00:00:00 2001 From: Tom Dykstra Date: Fri, 12 Sep 2025 20:13:57 -0700 Subject: [PATCH 3/3] fix includes --- aspnetcore/fundamentals/minimal-apis.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/fundamentals/minimal-apis.md b/aspnetcore/fundamentals/minimal-apis.md index fc1d5682b8b0..d2266a591c6e 100644 --- a/aspnetcore/fundamentals/minimal-apis.md +++ b/aspnetcore/fundamentals/minimal-apis.md @@ -68,7 +68,7 @@ The arguments passed to these methods are called "route h ## Parameter binding -[!INCLUDE [](~/funddamentals/minimal-apis/includes/parameter-binding10.md)] +[!INCLUDE [](~/fundamentals/minimal-apis/includes/parameter-binding10.md)] ## Json+PipeReader deserialization in minimal APIs