From 9dd1393e02a039b3c1331cb99662515769b8ba30 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Thu, 30 Apr 2026 13:07:55 -0700 Subject: [PATCH 01/10] Updates for jsonpatch.md Fixes #36419 - Replace references to T with TModel - Replace "Action method code" section with Minimal APIs PATCH endpoint - Replace "Action method code" section with Minimal APIs PATCH endpoint - Update the "Get the code" section -Update "Additional resources" source code link --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index d9644898c533..91a6e7af729a 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -57,7 +57,7 @@ To enable JSON Patch support with , install the [`Microso dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson ``` -This package provides a class to represent a JSON Patch document for objects of type `T` and custom logic for serializing and deserializing JSON Patch documents using . The key method of the class is , which applies the patch operations to a target object of type `T`. +This package provides a class to represent a JSON Patch document for objects of type `TModel` and custom logic for serializing and deserializing JSON Patch documents using . The key method of the class is , which applies the patch operations to a target object of type `TModel`. ## Action method code applying JSON Patch From ed04bb42cb80af4f1dac1825f11106925d3c8c39 Mon Sep 17 00:00:00 2001 From: Wade Pickett Date: Thu, 30 Apr 2026 13:26:35 -0700 Subject: [PATCH 02/10] Apply suggestion from @wadepickett --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index 91a6e7af729a..ace93b33e81c 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -5,7 +5,7 @@ description: Learn how to handle JSON Patch requests in an ASP.NET Core web API. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: mvc -ms.date: 06/03/2025 +ms.date: 04/30/2026 uid: web-api/jsonpatch --- # JSON Patch support in ASP.NET Core web API From 48163e4ac5eed0343c1cc8b96cf6370c8a212835 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Thu, 30 Apr 2026 13:56:45 -0700 Subject: [PATCH 03/10] Added new Min API section draft --- aspnetcore/web-api/jsonpatch.md | 47 +++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index ace93b33e81c..b6ade1945dd3 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -1,9 +1,10 @@ --- title: JsonPatch in ASP.NET Core web API author: wadepickett -description: Learn how to handle JSON Patch requests in an ASP.NET Core web API. +description: "JSON Patch in ASP.NET Core web API: Learn how to handle JSON Patch requests, apply partial updates, and improve API efficiency with System.Text.Json." monikerRange: '>= aspnetcore-3.1' ms.author: wpickett +ms.reviewer: wpickett ms.custom: mvc ms.date: 04/30/2026 uid: web-api/jsonpatch @@ -67,9 +68,17 @@ In an API controller, an action method for JSON Patch: * Accepts a , typically with [](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute). * Calls on the patch document to apply the changes. -### Example Controller Action method: +## Minimal API PATCH endpoint applying JSON Patch -:::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/Controllers/CustomerController.cs" id="snippet_PatchAction" highlight="1,2,14-19"::: +In a Minimal API, a PATCH endpoint for JSON Patch: + +* Uses `MapPatch` to define the route. +* Accepts a parameter. +* Calls on the patch document to apply the changes. + +### Example Minimal API PATCH endpoint: + +:::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs"::: This code from the sample app works with the following `Customer` and `Order` models: @@ -77,29 +86,33 @@ This code from the sample app works with the following `Customer` and `Order` mo :::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/Models/Order.cs"::: -The sample action method's key steps: +The sample PATCH endpoint's key steps: * **Retrieve the Customer**: - * The method retrieves a `Customer` object from the database `AppDb` using the provided id. - * If no `Customer` object is found, it returns a `404 Not Found` response. + * The endpoint retrieves a `Customer` object from the database `AppDb` using the provided `id`. + * If no `Customer` object is found, it returns a `404 Not Found` response via `TypedResults.NotFound()`. * **Apply JSON Patch**: - * The method applies the JSON Patch operations from the patchDoc to the retrieved `Customer` object. - * If errors occur during the patch application, such as invalid operations or conflicts, they are captured by an error handling delegate. This delegate adds error messages to the `ModelState` using the type name of the affected object and the error message. -* **Validate ModelState**: - * After applying the patch, the method checks the `ModelState` for errors. - * If the `ModelState` is invalid, such as due to patch errors, it returns a `400 Bad Request` response with the validation errors. -* **Return the Updated Customer**: - * If the patch is successfully applied and the `ModelState` is valid, the method returns the updated `Customer` object in the response. + * The method applies the JSON Patch operations from the `patchDoc` to the retrieved `Customer` object. + * If errors occur during the patch application, such as invalid operations or conflicts, they are captured by an error handling delegate. This delegate collects error messages into a dictionary keyed by the type name of the affected object. +* **Return validation errors**: + * If any errors were captured during the patch application, the endpoint returns a `ValidationProblem` response containing the error details via `TypedResults.ValidationProblem(errors)`. +* **Save and return the Updated Customer**: + * If the patch is successfully applied with no errors, the changes are saved to the database and the endpoint returns the updated `Customer` object via `TypedResults.Ok(customer)`. ### Example error response: -The following example shows the body of a `400 Bad Request` response for a JSON Patch operation when the specified path is invalid: +The following example shows the body of a validation problem response for a JSON Patch operation when the specified path is invalid: ```json { - "Customer": [ - "The target location specified by path segment 'foobar' was not found." - ] + "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", + "title": "One or more validation errors occurred.", + "status": 400, + "errors": { + "Customer": [ + "The target location specified by path segment 'foobar' was not found." + ] + } } ``` From c7a56c3ea7d4dca8379733a5dd63ba57d4ca7cd2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 22:40:55 +0000 Subject: [PATCH 04/10] Update ms.date to 05/05/2026 Agent-Logs-Url: https://github.com/dotnet/AspNetCore.Docs/sessions/aeafec8f-2c79-4276-8119-8c94e8313584 Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com> --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index b6ade1945dd3..bdf69cd76a4a 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -6,7 +6,7 @@ monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.reviewer: wpickett ms.custom: mvc -ms.date: 04/30/2026 +ms.date: 05/05/2026 uid: web-api/jsonpatch --- # JSON Patch support in ASP.NET Core web API From ae5748911eea78644ed44bce3e9c34ddcb999c02 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 13:56:02 -0700 Subject: [PATCH 05/10] Replaced action code --- aspnetcore/web-api/jsonpatch.md | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index b6ade1945dd3..8a5afdc47a2b 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -6,7 +6,7 @@ monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.reviewer: wpickett ms.custom: mvc -ms.date: 04/30/2026 +ms.date: 05/05/2026 uid: web-api/jsonpatch --- # JSON Patch support in ASP.NET Core web API @@ -60,14 +60,6 @@ dotnet add package Microsoft.AspNetCore.JsonPatch.SystemTextJson This package provides a class to represent a JSON Patch document for objects of type `TModel` and custom logic for serializing and deserializing JSON Patch documents using . The key method of the class is , which applies the patch operations to a target object of type `TModel`. -## Action method code applying JSON Patch - -In an API controller, an action method for JSON Patch: - -* Is annotated with the attribute. -* Accepts a , typically with [](xref:Microsoft.AspNetCore.Mvc.FromBodyAttribute). -* Calls on the patch document to apply the changes. - ## Minimal API PATCH endpoint applying JSON Patch In a Minimal API, a PATCH endpoint for JSON Patch: @@ -322,14 +314,9 @@ public void Validate(JsonPatchDocument patch) ## Get the code -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/jsonpatch/samples). ([How to download](xref:fundamentals/index#how-to-download-a-sample)). - -To test the sample, run the app and send HTTP requests with the following settings: +[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample). ([How to download](xref:fundamentals/index#how-to-download-a-sample)). -* URL: `http://localhost:{port}/jsonpatch/jsonpatchwithmodelstate` -* HTTP method: `PATCH` -* Header: `Content-Type: application/json-patch+json` -* Body: Copy and paste one of the JSON patch document samples from the *JSON* project folder. +To test the sample, run the app and send HTTP requests using the included `.http` file. ## Additional resources From d0c4200ef0ef40243d5ba932c5c4a81f6a600eec Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 14:58:19 -0700 Subject: [PATCH 06/10] Update sample to mikekistler aspnet-json-patch latest --- .../Controllers/CustomerController.cs | 43 +++++++++++++++---- .../10.x/JsonPatchSample/CustomerApi.cs | 37 +++++++++++++--- .../10.x/JsonPatchSample/JsonPatchSample.http | 20 +++++---- .../10.x/JsonPatchSample/Models/Customer.cs | 3 +- .../samples/10.x/JsonPatchSample/Program.cs | 4 +- .../appsettings.Development.json | 3 +- 6 files changed, 85 insertions(+), 25 deletions(-) diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Controllers/CustomerController.cs b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Controllers/CustomerController.cs index f1b1255f9182..14b6900285d4 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Controllers/CustomerController.cs +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Controllers/CustomerController.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.JsonPatch.SystemTextJson; +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using App.Data; using App.Models; @@ -11,27 +13,48 @@ namespace App.Controllers; public class CustomerController : ControllerBase { [HttpGet("{id}", Name = "GetCustomer")] - public Customer Get(AppDb db, string id) + public async Task Get(AppDb db, string id) { // Retrieve the customer by ID - var customer = db.Customers.FirstOrDefault(c => c.Id == id); + var customer = await db.Customers.FirstOrDefaultAsync(c => c.Id == id); // Return 404 Not Found if customer doesn't exist if (customer == null) { - Response.StatusCode = 404; - return null; + return NotFound(); + } + + return Ok(customer); + } + + [HttpPut("{id}", Name = "PutCustomer")] + public async Task Put(AppDb db, string id, [FromBody] Customer body) + { + var customer = await db.Customers.Include(c => c.Orders).FirstOrDefaultAsync(c => c.Id == id); + if (customer is null) + { + body.Id = id; + db.Customers.Add(body); + await db.SaveChangesAsync(); + return CreatedAtRoute("GetCustomer", new { id }, body); } - return customer; + customer.Name = body.Name; + customer.Email = body.Email; + customer.PhoneNumber = body.PhoneNumber; + customer.Address = body.Address; + + await db.SaveChangesAsync(); + + return Ok(customer); } // [HttpPatch("{id}", Name = "UpdateCustomer")] - public IActionResult Update(AppDb db, string id, [FromBody] JsonPatchDocument patchDoc) + public async Task Update(AppDb db, string id, [FromBody] JsonPatchDocument patchDoc) { // Retrieve the customer by ID - var customer = db.Customers.FirstOrDefault(c => c.Id == id); + var customer = await db.Customers.FirstOrDefaultAsync(c => c.Id == id); // Return 404 Not Found if customer doesn't exist if (customer == null) @@ -48,9 +71,13 @@ public IActionResult Update(AppDb db, string id, [FromBody] JsonPatchDocument diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs index 693d29955f9c..2aff6c951db7 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs @@ -1,7 +1,8 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.JsonPatch.SystemTextJson; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; - +using System.ComponentModel.DataAnnotations; using App.Data; using App.Models; @@ -10,20 +11,42 @@ public static void MapCustomerApi(this IEndpointRouteBuilder routes) { var group = routes.MapGroup("/customers").WithTags("Customers"); - group.MapGet("/{id}", async Task, NotFound>> (AppDb db, string id) => + group.MapGet("/{id}", async Task, NotFound>> (AppDb db, string id) => { return await db.Customers.Include(c => c.Orders).FirstOrDefaultAsync(c => c.Id == id) is Customer customer ? TypedResults.Ok(customer) - : TypedResults.NotFound(); + : TypedResults.NotFound(new ()); }); - group.MapPatch("/{id}", async Task,NotFound,BadRequest, ValidationProblem>> (AppDb db, string id, + group.MapPut("/{id}", async Task,Created,ValidationProblem>> (AppDb db, string id, Customer body) => + { + var customer = await db.Customers.Include(c => c.Orders).FirstOrDefaultAsync(c => c.Id == id); + if (customer is null) + { + body.Id = id; + db.Customers.Add(body); + await db.SaveChangesAsync(); + return TypedResults.Created($"/customers/{id}", body); + } + + customer.Name = body.Name; + customer.Email = body.Email; + customer.PhoneNumber = body.PhoneNumber; + customer.Address = body.Address; + + await db.SaveChangesAsync(); + + return TypedResults.Ok(customer); + }); + + // + group.MapPatch("/{id}", async Task,ValidationProblem,NotFound>> (AppDb db, string id, JsonPatchDocument patchDoc) => { var customer = await db.Customers.Include(c => c.Orders).FirstOrDefaultAsync(c => c.Id == id); if (customer is null) { - return TypedResults.NotFound(); + return TypedResults.NotFound(new ()); } if (patchDoc != null) { @@ -38,15 +61,19 @@ public static void MapCustomerApi(this IEndpointRouteBuilder routes) } errors[key] = errors[key].Append(jsonPatchError.ErrorMessage).ToArray(); }); + if (errors != null) { return TypedResults.ValidationProblem(errors); } + + // Only save if there are no errors await db.SaveChangesAsync(); } return TypedResults.Ok(customer); }) .Accepts>("application/json-patch+json"); + // } } \ No newline at end of file diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/JsonPatchSample.http b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/JsonPatchSample.http index eb981fd996be..3daf5ab5c4e6 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/JsonPatchSample.http +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/JsonPatchSample.http @@ -3,14 +3,16 @@ GET {{HostAddress}}/openapi/v1.json Accept: application/json +### +### Minimal API requests ### -GET {{HostAddress}}/api/customers/1 +GET {{HostAddress}}/customers/1 Accept: application/json ### -PATCH {{HostAddress}}/api/customers/1 +PATCH {{HostAddress}}/customers/1 Content-Type: application/json-patch+json Accept: application/json @@ -18,7 +20,7 @@ Accept: application/json { "op": "replace", "path": "/email", - "value": "foo@bar.baz" + "value": "jdoe456@outlook.com" } ] @@ -26,7 +28,7 @@ Accept: application/json # Error response -PATCH {{HostAddress}}/api/customers/1 +PATCH {{HostAddress}}/customers/1 Content-Type: application/json-patch+json Accept: application/json @@ -39,15 +41,15 @@ Accept: application/json ] ### -### Minimal API requests +### Controllers requests ### -GET {{HostAddress}}/customers/1 +GET {{HostAddress}}/api/customers/1 Accept: application/json ### -PATCH {{HostAddress}}/customers/1 +PATCH {{HostAddress}}/api/customers/1 Content-Type: application/json-patch+json Accept: application/json @@ -55,7 +57,7 @@ Accept: application/json { "op": "replace", "path": "/email", - "value": "foo@bar.baz" + "value": "baz@foo.qux" } ] @@ -63,7 +65,7 @@ Accept: application/json # Error response -PATCH {{HostAddress}}/customers/1 +PATCH {{HostAddress}}/api/customers/1 Content-Type: application/json-patch+json Accept: application/json diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Models/Customer.cs b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Models/Customer.cs index 1af9e4fda0d3..67e8eaecc793 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Models/Customer.cs +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Models/Customer.cs @@ -1,3 +1,5 @@ +using System.ComponentModel.DataAnnotations; + namespace App.Models; public class Customer @@ -8,7 +10,6 @@ public class Customer public string? PhoneNumber { get; set; } public string? Address { get; set; } public List? Orders { get; set; } - public Customer() { Id = Guid.NewGuid().ToString(); diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Program.cs b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Program.cs index 1abd02b425a7..ffca5c69b3ae 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Program.cs +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/Program.cs @@ -12,6 +12,8 @@ builder.Services.AddDbContext(options => options.UseSqlite(builder.Configuration.GetConnectionString("AppDb"))); +builder.Services.AddProblemDetails(); + builder.Services.AddOpenApi(); var app = builder.Build(); @@ -26,7 +28,7 @@ app.UseHttpsRedirection(); -app.UseAuthorization(); +app.UseStatusCodePages(); app.MapControllers(); diff --git a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/appsettings.Development.json b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/appsettings.Development.json index 0c208ae9181e..d7b2fc5dca0f 100644 --- a/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/appsettings.Development.json +++ b/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample/appsettings.Development.json @@ -2,7 +2,8 @@ "Logging": { "LogLevel": { "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Microsoft.AspNetCore": "Warning", + "Microsoft.EntityFrameworkCore": "Warning" } } } From 0e984b0cd79fc66588745fcfb425aededd1816c4 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 15:28:00 -0700 Subject: [PATCH 07/10] link fix --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index 8a5afdc47a2b..c299cca2264a 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -323,7 +323,7 @@ To test the sample, run the app and send HTTP requests using the included `.http * [IETF RFC 5789 PATCH method specification](https://tools.ietf.org/html/rfc5789) * [IETF RFC 6902 JSON Patch specification](https://tools.ietf.org/html/rfc6902) * [IETF RFC 6901 JSON Pointer](https://tools.ietf.org/html/rfc6901) -* [ASP.NET Core JSON Patch source code](https://github.com/dotnet/AspNetCore/tree/main/src/Features/JsonPatch/src) +* [ASP.NET Core JSON Patch source code](https://github.com/dotnet/aspnetcore/tree/main/src/Features/JsonPatch.SystemTextJson/src) :::moniker-end From f2fe5a6af51cf85ca777064bd265cd837f0bf0ea Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 15:40:15 -0700 Subject: [PATCH 08/10] Additional edit sweep --- aspnetcore/web-api/jsonpatch.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index c299cca2264a..4fa7324bb869 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -6,7 +6,7 @@ monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.reviewer: wpickett ms.custom: mvc -ms.date: 05/05/2026 +ms.date: 05/27/2026 uid: web-api/jsonpatch --- # JSON Patch support in ASP.NET Core web API @@ -38,14 +38,14 @@ For an overview of the JSON Patch standard, see [jsonpatch.com](https://jsonpatc ## JSON Patch support in ASP.NET Core web API -JSON Patch support in ASP.NET Core web API is based on serialization, starting with .NET 10, implementing based on serialization. This feature: +JSON Patch support in ASP.NET Core web API is based on serialization, starting with .NET 10. It implements based on serialization. This feature: * Requires the [`Microsoft.AspNetCore.JsonPatch.SystemTextJson`](https://www.nuget.org/packages/Microsoft.AspNetCore.JsonPatch.SystemTextJson) NuGet package. * Aligns with modern .NET practices by leveraging the library, which is optimized for .NET. * Provides improved performance and reduced memory usage compared to the legacy `Newtonsoft.Json`-based implementation. For more information on the legacy `Newtonsoft.Json`-based implementation, see the [.NET 9 version of this article](?view=aspnetcore-9.0&preserve-view=true). > [!NOTE] -> The implementation of based on serialization isn't a drop-in replacement for the legacy `Newtonsoft.Json`-based implementation. It doesn't support dynamic types, for example . +> The implementation of based on serialization isn't a drop-in replacement for the legacy `Newtonsoft.Json`-based implementation. It doesn't support dynamic types, such as . > [!IMPORTANT] > The JSON Patch standard has ***inherent security risks***. Since these risks are inherent to the JSON Patch standard, the ASP.NET Core implementation ***doesn't attempt to mitigate inherent security risks***. It's the responsibility of the developer to ensure that the JSON Patch document is safe to apply to the target object. For more information, see the [Mitigating Security Risks](#mitigating-security-risks) section. @@ -85,13 +85,13 @@ The sample PATCH endpoint's key steps: * If no `Customer` object is found, it returns a `404 Not Found` response via `TypedResults.NotFound()`. * **Apply JSON Patch**: * The method applies the JSON Patch operations from the `patchDoc` to the retrieved `Customer` object. - * If errors occur during the patch application, such as invalid operations or conflicts, they are captured by an error handling delegate. This delegate collects error messages into a dictionary keyed by the type name of the affected object. + * If errors occur during the patch application, such as invalid operations or conflicts, an error handling delegate captures them. This delegate collects error messages into a dictionary keyed by the type name of the affected object. * **Return validation errors**: - * If any errors were captured during the patch application, the endpoint returns a `ValidationProblem` response containing the error details via `TypedResults.ValidationProblem(errors)`. + * If the error handling delegate captures any errors during the patch application, the endpoint returns a `ValidationProblem` response containing the error details via `TypedResults.ValidationProblem(errors)`. * **Save and return the Updated Customer**: * If the patch is successfully applied with no errors, the changes are saved to the database and the endpoint returns the updated `Customer` object via `TypedResults.Ok(customer)`. -### Example error response: +### Example error response The following example shows the body of a validation problem response for a JSON Patch operation when the specified path is invalid: @@ -194,7 +194,7 @@ Key differences between and the new patch) } ``` -### Business Logic Subversion +### Business logic subversion * **Scenario**: Patch operations can manipulate fields with implicit invariants (for example, internal flags, IDs, or computed fields), violating business constraints. * **Impact**: Data integrity issues and unintended app behavior. @@ -309,14 +309,14 @@ public void Validate(JsonPatchDocument patch) * **Scenario**: Unauthenticated or unauthorized clients send malicious JSON Patch requests. * **Impact**: Unauthorized access to modify sensitive data or disrupt app behavior. * **Mitigation**: - * Protect endpoints accepting JSON Patch requests with proper authentication and authorization mechanisms. + * Protect endpoints that accept JSON Patch requests by using proper authentication and authorization mechanisms. * Restrict access to trusted clients or users with appropriate permissions. ## Get the code [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/jsonpatch/samples/10.x/JsonPatchSample). ([How to download](xref:fundamentals/index#how-to-download-a-sample)). -To test the sample, run the app and send HTTP requests using the included `.http` file. +To test the sample, run the app and send HTTP requests by using the included `.http` file. ## Additional resources From 65dd22b5e8e4ce2af638117d112566be47c6b139 Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 15:55:33 -0700 Subject: [PATCH 09/10] Added snippet section --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index 4fa7324bb869..fd5109239b2f 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -70,7 +70,7 @@ In a Minimal API, a PATCH endpoint for JSON Patch: ### Example Minimal API PATCH endpoint: -:::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs"::: +:::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs" id="snippet_PatchMethod"::: This code from the sample app works with the following `Customer` and `Order` models: From 9ab0505a57fa7587eaa0c383ba2248b4c33a9ebc Mon Sep 17 00:00:00 2001 From: wadepickett Date: Wed, 27 May 2026 16:36:15 -0700 Subject: [PATCH 10/10] Small edit --- aspnetcore/web-api/jsonpatch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/web-api/jsonpatch.md b/aspnetcore/web-api/jsonpatch.md index fd5109239b2f..34698dc7c0da 100644 --- a/aspnetcore/web-api/jsonpatch.md +++ b/aspnetcore/web-api/jsonpatch.md @@ -68,7 +68,7 @@ In a Minimal API, a PATCH endpoint for JSON Patch: * Accepts a parameter. * Calls on the patch document to apply the changes. -### Example Minimal API PATCH endpoint: +### Example Minimal API PATCH endpoint :::code language="csharp" source="~/web-api/jsonpatch/samples/10.x/JsonPatchSample/CustomerApi.cs" id="snippet_PatchMethod":::