Some time ago, I needed to implement a mechanism for an API to update an entity without using JsonPatchDocument. The reason was that the user of the API didn’t want to necessarily use JSON to use the patch method. But user might want to use XML, Message Pack or any other format. What I needed was to apply some change to an entity based on the DTO that was passed in. Let see what exactly HTTP patch suppose to do. Quote from restcookbook.
The HTTP methods PATCH can be used to update partial resources. For instance, when you only need to update one field of the resource, PUTting a complete resource representation might be cumbersome and utilizes more bandwidth
What I ended up with was two approach to solve this. First approach take a set of PatchDto object and based on that decipher what should be changed. In Second approach our method take a DTO, look for the properties that are populated. Then it’s going to update just those properties and leave the rest intact. One of the flaw of this approach is that it can’t do all of the expected Patch operations. Patch normally should be able to do Add, Remove, Replace, Copy, Move and Test on properties of an object. But I didn’t need all of that. Due to the problem with the second approach, I chose to use the first approach. But I’m going to introduce both, it might be useful to somebody.
First Approach: Using Patch Dto
The first approach that I’m going to show you uses a custom Dto called
PatchDto. Pretty simple, here’s what it looks like.
If we want to patch an entity, we need to send a collection of PatchDto. PatchDto has a property called
PropertyName which determine which property we’re going to update. It also has a property named
PropertyValue which is the value of of the property which we want to update.
Suppose we have an entity like below and we want to update it.
We can send something like this to our API. Note that this is just an example in Json. Our API doesn’t care, it only needs the objects.
Before I get into the implementation of patch, here’s how our API method looks like.
As you can see our action method takes an id. It then makes a query based on that id and retrieves the book. Then we send that book along with the
PatchDto to the
ApplyPatchAsync method. Note that currently our patch method doesn’t meet all the requirements of the formal patch. It can only changes a value, or delete a value (set it to null). Finally we get to the actual patch method and its implementation detail.
In this method the type
EntityEntry has a method called
SetValues. This method needs a dictionary of property names and the respective values which we build with our patch method. Finally we set the state of the entry as modified and save the changes. Also note that the property names are case sensitive.
Second Approach: Using A Normal Dto
This approach is not as straightforward the the first approach. I don’t recommend using this approach but I think in some situations it might be the way to go. In this implementation we only send the id and the Dto. We only fill the property of the Dto that we need to change and our method picks up these properties and apply them to our entity. Here’s how our action method might look like.
To achieve that first we need some methods to help us determine what property has value.
In the above code excerpt, the
IsNullOrEmpty method helps us determine if the current value is null or empty. It does that without knowing the actual type. The
Cast method dynamically cast one type to another type. Finally the
GetFilledProperties method get the properties that has value and return them as an array of string. Our patch method would look like something like this.
Here we first get the properties that needs updating. Then we set the id for the dto, which is irrelevant (I do it because IEntity’s Id is read only). Then I map the dto to an entity and attach that entity to the db context. Finally we set the modified state on the entity property one by one. This method of doing things obviously has its problems and I need to develop it further. But what I like about this approach is its convenience. We just new up a dto and fill only those properties that we want updated. But one major problem with it is that we can’t set a property to null.
In this post I described two methods for apply patch to a resource. The first way which involved filling a custom Dto which describe what needs to be changed. With second approach we pass in a ordinary DTO to determine what property should be included in our update. These two approaches has their problems, but I think they can be used when we don’t want the fully fledged functionality of
JsonPatchDocument. But we need something that has some of those characteristics. If you need a working sample for what I’ve just explained, you can find it here.