@@ -10,7 +10,7 @@ uid: web-api/jsonpatch
1010---
1111# JsonPatch in ASP.NET Core web API
1212
13- :::moniker range=">= aspnetcore-6 .0"
13+ :::moniker range=">= aspnetcore-10 .0"
1414
1515This article explains how to handle JSON Patch requests in an ASP.NET Core web API.
1616
@@ -21,7 +21,7 @@ JSON Patch support in ASP.NET Core web API is based on `Newtonsoft.Json` and req
2121* Install the [ ` Microsoft.AspNetCore.Mvc.NewtonsoftJson ` ] ( https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.NewtonsoftJson/ ) NuGet package.
2222* Call < xref:Microsoft.Extensions.DependencyInjection.NewtonsoftJsonMvcBuilderExtensions.AddNewtonsoftJson%2A > . For example:
2323
24- :::code language="csharp" source="jsonpatch/samples/6.x/api/Program.cs" id="snippet1" highlight="4":::
24+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/Program.cs" id="snippet1" highlight="4":::
2525
2626` AddNewtonsoftJson ` replaces the default ` System.Text.Json ` -based input and output formatters used for formatting *** all*** JSON content. This extension method is compatible with the following MVC service registration methods:
2727
@@ -38,8 +38,8 @@ The `System.Text.Json`-based input formatter doesn't support JSON Patch. To add
3838* Install the [ ` Microsoft.AspNetCore.Mvc.NewtonsoftJson ` ] ( https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.NewtonsoftJson/ ) NuGet package.
3939* Update ` Program.cs ` :
4040
41- :::code language="csharp" source="jsonpatch/samples/6.x/api/Program.cs" id="snippet_both" highlight="6-9":::
42- :::code language="csharp" source="jsonpatch/samples/6.x/api/MyJPIF.cs":::
41+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/Program.cs" id="snippet_both" highlight="6-9":::
42+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/MyJPIF.cs":::
4343
4444The preceding code creates an instance of < xref:Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonPatchInputFormatter > and inserts it as the first entry in the < xref:Microsoft.AspNetCore.Mvc.MvcOptions.InputFormatters%2A?displayProperty=nameWithType > collection. This order of registration ensures that:
4545
@@ -60,11 +60,11 @@ For example, the following JSON documents represent a resource, a JSON Patch doc
6060
6161### Resource example
6262
63- :::code language="json" source="jsonpatch/snippets/customer.json":::
63+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/customer.json":::
6464
6565### JSON patch example
6666
67- :::code language="json" source="jsonpatch/snippets/add.json":::
67+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/add.json":::
6868
6969In the preceding JSON:
7070
@@ -131,13 +131,13 @@ In an API controller, an action method for JSON Patch:
131131
132132Here's an example:
133133
134- :::code language="csharp" source="jsonpatch/samples/3.x/api/Controllers/HomeController.cs" id="snippet_PatchAction" highlight="1,3,9":::
134+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/3.x/api/Controllers/HomeController.cs" id="snippet_PatchAction" highlight="1,3,9":::
135135
136136This code from the sample app works with the following ` Customer ` model:
137137
138- :::code language="csharp" source="jsonpatch/samples/6.x/api/Models/Customer.cs":::
138+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/Models/Customer.cs":::
139139
140- :::code language="csharp" source="jsonpatch/samples/6.x/api/Models/Order.cs":::
140+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/Models/Order.cs":::
141141
142142The sample action method:
143143
@@ -163,7 +163,7 @@ The preceding action method example calls an overload of `ApplyTo` that takes mo
163163
164164The following action method example shows how to apply a patch to a dynamic object:
165165
166- :::code language="csharp" source="jsonpatch/samples/6.x/api/Controllers/HomeController.cs" id="snippet_Dynamic":::
166+ :::code language="csharp" source="~ /web-api/ jsonpatch/samples/6.x/api/Controllers/HomeController.cs" id="snippet_Dynamic":::
167167
168168## The add operation
169169
@@ -175,7 +175,7 @@ The following action method example shows how to apply a patch to a dynamic obje
175175
176176The following sample patch document sets the value of ` CustomerName ` and adds an ` Order ` object to the end of the ` Orders ` array.
177177
178- :::code language="json" source="jsonpatch/snippets/add.json":::
178+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/add.json":::
179179
180180## The remove operation
181181
@@ -188,15 +188,15 @@ The following sample patch document sets the value of `CustomerName` and adds an
188188
189189The following sample patch document sets ` CustomerName ` to null and deletes ` Orders[0] ` :
190190
191- :::code language="json" source="jsonpatch/snippets/remove.json":::
191+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/remove.json":::
192192
193193## The replace operation
194194
195195This operation is functionally the same as a ` remove ` followed by an ` add ` .
196196
197197The following sample patch document sets the value of ` CustomerName ` and replaces ` Orders[0] ` with a new ` Order ` object:
198198
199- :::code language="json" source="jsonpatch/snippets/replace.json":::
199+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/replace.json":::
200200
201201## The move operation
202202
@@ -212,7 +212,7 @@ The following sample patch document:
212212* Sets ` Orders[0].OrderName ` to null.
213213* Moves ` Orders[1] ` to before ` Orders[0] ` .
214214
215- :::code language="json" source="jsonpatch/snippets/move.json":::
215+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/move.json":::
216216
217217## The copy operation
218218
@@ -223,7 +223,7 @@ The following sample patch document:
223223* Copies the value of ` Orders[0].OrderName ` to ` CustomerName ` .
224224* Inserts a copy of ` Orders[1] ` before ` Orders[0] ` .
225225
226- :::code language="json" source="jsonpatch/snippets/copy.json":::
226+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/copy.json":::
227227
228228## The test operation
229229
@@ -233,7 +233,7 @@ The `test` operation is commonly used to prevent an update when there's a concur
233233
234234The following sample patch document has no effect if the initial value of ` CustomerName ` is "John", because the test fails:
235235
236- :::code language="json" source="jsonpatch/snippets/test-fail.json":::
236+ :::code language="json" source="~ /web-api/ jsonpatch/snippets/test-fail.json":::
237237
238238## Get the code
239239
@@ -255,244 +255,4 @@ To test the sample, run the app and send HTTP requests with the following settin
255255
256256::: moniker-end
257257
258- :::moniker range="< aspnetcore-6.0"
259-
260- This article explains how to handle JSON Patch requests in an ASP.NET Core web API.
261-
262- ## Package installation
263-
264- To enable JSON Patch support in your app, complete the following steps:
265-
266- 1 . Install the [ ` Microsoft.AspNetCore.Mvc.NewtonsoftJson ` ] ( https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.NewtonsoftJson/ ) NuGet package.
267- 1 . Update the project's ` Startup.ConfigureServices ` method to call < xref:Microsoft.Extensions.DependencyInjection.NewtonsoftJsonMvcBuilderExtensions.AddNewtonsoftJson%2A > . For example:
268-
269- ``` csharp
270- services
271- .AddControllersWithViews ()
272- .AddNewtonsoftJson ();
273- ```
274-
275- `AddNewtonsoftJson ` is compatible with the MVC service registration methods :
276-
277- * < xref : Microsoft .Extensions .DependencyInjection .MvcServiceCollectionExtensions .AddRazorPages % 2A >
278- * < xref : Microsoft .Extensions .DependencyInjection .MvcServiceCollectionExtensions .AddControllersWithViews % 2A >
279- * < xref : Microsoft .Extensions .DependencyInjection .MvcServiceCollectionExtensions .AddControllers % 2A >
280-
281- ## JSON Patch, AddNewtonsoftJson, and System.Text.Json
282-
283- `AddNewtonsoftJson ` replaces the `System .Text .Json `- based input and output formatters used for formatting **all** JSON content. To add support for JSON Patch using `Newtonsoft.Json`, while leaving the other formatters unchanged, update the project's `Startup.ConfigureServices` method as follows:
284-
285- :::code language="csharp" source="jsonpatch/samples/3.x/WebApp1/Startup.cs" id="snippet":::
286-
287- The preceding code requires the `Microsoft.AspNetCore.Mvc.NewtonsoftJson` package and the following `using` statements:
288-
289- :::code language="csharp" source="jsonpatch/samples/3.x/WebApp1/Startup.cs" id="snippet1":::
290-
291- Use the `Newtonsoft.Json.JsonConvert.SerializeObject` method to serialize a JsonPatchDocument.
292-
293- ## PATCH HTTP request method
294-
295- The PUT and [PATCH](https:// tools.ietf.org/html/rfc5789) methods are used to update an existing resource. The difference between them is that PUT replaces the entire resource, while PATCH specifies only the changes.
296-
297- ## JSON Patch
298-
299- [JSON Patch](https:// tools.ietf.org/html/rfc6902) is a format for specifying updates to be applied to a resource. A JSON Patch document has an array of *operations*. Each operation identifies a particular type of change. Examples of such changes include adding an array element or replacing a property value.
300-
301- For example , the following JSON documents represent a resource , a JSON Patch document for the resource , and the result of applying the Patch operations .
302-
303- ### Resource example
304-
305- :::code language = " json" source = " jsonpatch/snippets/customer.json" :::
306-
307- ### JSON patch example
308-
309- ::: code language = " json" source = " jsonpatch/snippets/add.json" :::
310-
311- In the preceding JSON :
312-
313- * The `op ` property indicates the type of operation .
314- * The `path ` property indicates the element to update .
315- * The `value ` property provides the new value .
316-
317- ### Resource after patch
318-
319- Here 's the resource after applying the preceding JSON Patch document:
320-
321- ```json
322- {
323- " customerName" : " Barry" ,
324- " orders" : [
325- {
326- " orderName" : " Order0" ,
327- " orderType" : null
328- },
329- {
330- " orderName" : " Order1" ,
331- " orderType" : null
332- },
333- {
334- " orderName" : " Order2" ,
335- " orderType" : null
336- }
337- ]
338- }
339- ```
340-
341- The changes made by applying a JSON Patch document to a resource are atomic . If any operation in the list fails , no operation in the list is applied .
342-
343- ## Path syntax
344-
345- The [path ](https :// tools.ietf.org/html/rfc6901) property of an operation object has slashes between levels. For example, `"/address/zipCode"`.
346-
347- Zero -based indexes are used to specify array elements . The first element of the `addresses ` array would be at `/addresses /0`. To `add ` to the end of an array , use a hyphen (`-`) rather than an index number : `/ addresses /- `.
348-
349- ### Operations
350-
351- The following table shows supported operations as defined in the [JSON Patch specification ](https :// tools.ietf.org/html/rfc6902):
352-
353- | Operation | Notes |
354- | ---------- - | -------------------------------- |
355- | `add ` | Add a property or array element . For existing property : set value .|
356- | `remove ` | Remove a property or array element . |
357- | `replace ` | Same as `remove ` followed by `add ` at same location . |
358- | `move ` | Same as `remove ` from source followed by `add ` to destination using value from source . |
359- | `copy ` | Same as `add ` to destination using value from source . |
360- | `test ` | Return success status code if value at `path ` = provided `value `.|
361-
362- ## JSON Patch in ASP.NET Core
363-
364- The ASP .NET Core implementation of JSON Patch is provided in the [Microsoft .AspNetCore .JsonPatch ](https :// www.nuget.org/packages/microsoft.aspnetcore.jsonpatch/) NuGet package.
365-
366- ## Action method code
367-
368- In an API controller , an action method for JSON Patch :
369-
370- * Is annotated with the `HttpPatch ` attribute .
371- * Accepts a `JsonPatchDocument < T > `, typically with `[FromBody ]`.
372- * Calls `ApplyTo ` on the patch document to apply the changes .
373-
374- Here 's an example:
375-
376- ::: code language = " csharp" source = " jsonpatch/samples/3.x/api/Controllers/HomeController.cs" id = " snippet_PatchAction" highlight = " 1,3,9" :::
377-
378- This code from the sample app works with the following `Customer ` model :
379-
380- ::: code language = " csharp" source = " jsonpatch/samples/3.x/api/Models/Customer.cs" :::
381-
382- ::: code language = " csharp" source = " jsonpatch/samples/3.x/api/Models/Order.cs" :::
383-
384- The sample action method :
385-
386- * Constructs a `Customer `.
387- * Applies the patch .
388- * Returns the result in the body of the response .
389-
390- In a real app , the code would retrieve the data from a store such as a database and update the database after applying the patch .
391-
392- ### Model state
393-
394- The preceding action method example calls an overload of `ApplyTo ` that takes model state as one of its parameters . With this option , you can get error messages in responses . The following example shows the body of a 400 Bad Request response for a `test ` operation :
395-
396- ```json
397- {
398- " Customer" : [
399- " The current value 'John' at path 'customerName' is not equal to the test value 'Nancy'."
400- ]
401- }
402- ```
403-
404- ### Dynamic objects
405-
406- The following action method example shows how to apply a patch to a dynamic object :
407-
408- ::: code language = " csharp" source = " jsonpatch/samples/3.x/api/Controllers/HomeController.cs" id = " snippet_Dynamic" :::
409-
410- ## The add operation
411-
412- * If `path ` points to an array element : inserts new element before the one specified by `path `.
413- * If `path ` points to a property : sets the property value .
414- * If `path ` points to a nonexistent location :
415- * If the resource to patch is a dynamic object : adds a property .
416- * If the resource to patch is a static object : the request fails .
417-
418- The following sample patch document sets the value of `CustomerName ` and adds an `Order ` object to the end of the `Orders ` array .
419-
420- ::: code language = " json" source = " jsonpatch/snippets/add.json" :::
421-
422- ## The remove operation
423-
424- * If `path ` points to an array element : removes the element .
425- * If `path ` points to a property :
426- * If resource to patch is a dynamic object : removes the property .
427- * If resource to patch is a static object :
428- * If the property is nullable : sets it to null .
429- * If the property is non -nullable , sets it to `default < T > `.
430-
431- The following sample patch document sets `CustomerName ` to null and deletes `Orders [0 ]`:
432-
433- ::: code language = " json" source = " jsonpatch/snippets/remove.json" :::
434-
435- ## The replace operation
436-
437- This operation is functionally the same as a `remove ` followed by an `add `.
438-
439- The following sample patch document sets the value of `CustomerName ` and replaces `Orders [0]`with a new `Order ` object :
440-
441- ::: code language = " json" source = " jsonpatch/snippets/replace.json" :::
442-
443- ## The move operation
444-
445- * If `path ` points to an array element : copies `from ` element to location of `path ` element , then runs a `remove ` operation on the `from ` element .
446- * If `path ` points to a property : copies value of `from ` property to `path ` property , then runs a `remove ` operation on the `from ` property .
447- * If `path ` points to a nonexistent property :
448- * If the resource to patch is a static object : the request fails .
449- * If the resource to patch is a dynamic object : copies `from ` property to location indicated by `path `, then runs a `remove ` operation on the `from ` property .
450-
451- The following sample patch document :
452-
453- * Copies the value of `Orders [0 ].OrderName ` to `CustomerName `.
454- * Sets `Orders [0 ].OrderName ` to null .
455- * Moves `Orders [1 ]` to before `Orders [0 ]`.
456-
457- ::: code language = " json" source = " jsonpatch/snippets/move.json" :::
458-
459- ## The copy operation
460-
461- This operation is functionally the same as a `move ` operation without the final `remove ` step .
462-
463- The following sample patch document :
464-
465- * Copies the value of `Orders [0 ].OrderName ` to `CustomerName `.
466- * Inserts a copy of `Orders [1 ]` before `Orders [0 ]`.
467-
468- ::: code language = " json" source = " jsonpatch/snippets/copy.json" :::
469-
470- ## The test operation
471-
472- If the value at the location indicated by `path ` is different from the value provided in `value `, the request fails . In that case , the whole PATCH request fails even if all other operations in the patch document would otherwise succeed .
473-
474- The `test ` operation is commonly used to prevent an update when there's a concurrency conflict.
475-
476- The following sample patch document has no effect if the initial value of `CustomerName ` is "John ", because the test fails :
477-
478- ::: code language = " json" source = " jsonpatch/snippets/test-fail.json" :::
479-
480- ## Get the code
481-
482- [View or download sample code ](https :// github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/web-api/jsonpatch/samples). ([How to download](xref:index#how-to-download-a-sample)).
483-
484- To test the sample , run the app and send HTTP requests with the following settings :
485-
486- * URL : `http :// localhost:{port}/jsonpatch/jsonpatchwithmodelstate`
487- * HTTP method : `PATCH `
488- * Header : `Content - Type : application / json - patch + json `
489- * Body : Copy and paste one of the JSON patch document samples from the * JSON * project folder .
490-
491- ## Additional resources
492-
493- * [IETF RFC 5789 PATCH method specification ](https :// tools.ietf.org/html/rfc5789)
494- * [IETF RFC 6902 JSON Patch specification ](https :// tools.ietf.org/html/rfc6902)
495- * [IETF RFC 6901 JSON Patch path format spec ](https :// tools.ietf.org/html/rfc6901)
496- * [ASP .NET Core JSON Patch source code ](https :// github.com/dotnet/AspNetCore/tree/main/src/Features/JsonPatch/src)
497-
498- ::: moniker - end
258+ [ !INCLUDE[ ] ( ~/web-api/jsonpatch/includes/jsonpatch9.md )]
0 commit comments