REST is well-known and commonly used pattern for creating web APIs. There are many HTTP verbs, but the most frequently used for building REST services are:
- POST - create new item
- GET - read item
- PUT - update/replace item
- DELETE - delete item
These methods are usually enough for a client to make all operations with a resource. But what if the client wants to change only particular properties of a resource?
For demonstration scenario lets say we have following object and we want to change the weapon property to "Knife"
{
name: "James Bond"
age: "45"
weapon: "Gun"
}
Client code in pseudo-C#:
srcJson = GET {resourceUrl}
model = Json.Parse<UserModel>(srcJson)
model.weapon = "Knife"
dstJson = Json.Serialize(model)
PUT {resourceUrl}
That is the obvious solution - GET the resource, modify it and PUT it back to a server. Depending on your architecture and used languages this might have some drawbacks.
Imagine what happens when your UserModel is missing some properties. They will get lost and not send to the server in a PUT call. In case of default ASP.NET Core/C# setup they will be interpreted as a change to default values leading to a data loss.
JSON Patch
PUT call replaces whole object rather then performing partial resource update only. JSON Patch was created to modify the resource exactly as you want by sending list of operations rather then the object itself.
JSON PATCH request
[
{ op: "replace", path: "/weapon", value: "Knife" }
]
Implementation of JSON Patch is part of ASP.NET Core,
This structure allows full control of all properties of a resource including arrays, but also tends to be quite chatty and not very human writeable/readable.
JSON Merge Patch
If you are looking for something simpler then JSON Patch, there is other way.
JSON Merge Patch allows you to send changes in the form of original model. There is not a list of operations, but rather a patch object containing only changes that are merged with original resource on the server
JSON Merge patch
{
weapon: "Knife"
}
And the result will be
{
name: "James Bond"
age: "45"
weapon: "Knife"
}
JSON Merge patch is limited compared to full JSON Patch. You cannot remove a property (as missing property means "no change" rather then "remove") and also array operations are limited.
Morcatko.AspNetCore.JsonMergePatch
Using JSON Merge Patch in C# is not easy. C# is statically typed language and JSON Merge Patch format expects the exact opposite - it defines the operations by property (non)existence.
Morcatko.AspNetCore.JsonMergePatch is my implementation of JSON Merge Patch for ASP.NET Core. It is designed to fit nicely into ASP.NET Core architecture. Its API is same as API of full JSON patch. All you have to do to use it is to initialize it in your startup class and make an endpoint that accepts patch object.
// Startup.ConfigureServices
services
.AddMvc()
.AddJsonMergePatch();
// Controller
[HttpPatch]
[Consumes(JsonMergePatchDocument.ContentType)]
public void Patch(JsonMergePatchDocument<UserModel> patch)
{
...
patch.ApplyTo(backendModel);
...
}
That is it.
Notice the Consumes
attribute. You can use it together with full JSON Patch. Requests ContentType is a way how to distinquish betweens both versions.
In case you are using swagger to generate API documentation for your service you will need to add a DocumentFilter
to your swagger configuration - see github for more details
Morcatko / Morcatko.AspNetCore.JsonMergePatch
JsonMergePatch support for ASP.NET Core
JSON Merge Patch support for ASP.NET Core
- Morcatko.AspNetCore.JsonMergePatch (ASP.NET Core 2.x)
- Morcatko.AspNetCore.JsonMergePatch.NewtonsoftJson (ASP.NET Core 3+)
- Morcatko.AspNetCore.JsonMergePatch.SystemText (ASP.NET Core 3+)
- Morcatko.AspNetCore.JsonMergePatch.Document (ASP.NET Core 3+ - base package)
JSON Merge Patch
- RFC 7396
- performs partial resource update similar to JSON Patch
- Supports Swagger
- netstandard 2.0
C# object:
var backendModel = new Model()
{
Name = "James Bond"
Age = "45"
Weapon = "Gun"
}
JSON Merge Patch:
var mergePatch = new object() {
"Weapon": "Knife"
}
Resulting C# object:
var newObject = new Model() {
Name = "James Bond"
Age = "45"
Weapon = "Knife"
}
How to
See 2.1-testApp
, 3.0 testApp
or 6.0/testApp
for sample
- Install nuget (Use JsonMergePathch version same as your .NET) .
- ASP.NET Core 2.x Morcatko.AspNetCore.JsonMergePatch
- ASP.NET Core 3+ (Newtonsoft.Json)…
Top comments (0)