Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JsonPatchDocument Access ICollection

I'm trying to replace an object in a list using JsonPatchDocument but get an exception when I try and access a member of the collection with the correct path, here is my code:

    var oppfour = new Operation<Application>("replace", "/comments/0", "", obj);

    var contractResolver = new DefaultContractResolver();
    var operations = new List<Operation<Application>>();

    operations.Add(operation);
    operations.Add(opptwo);
    operations.Add(oppthree);
    operations.Add(oppfour);

    var patchJson = new JsonPatchDocument<Application>(operations, contractResolver);

    try
    {
        patchJson.ApplyTo(app);
    }

the data model I'm trying to access looks like this for Application:

public class Application: BaseEntity
{
    public virtual ICollection<Comment> Comments { get; set; }
}

Here is the exception:

Microsoft.AspNetCore.JsonPatch.Exceptions.JsonPatchException: The target location specified by path segment '0' was not found.

How can I set the path to replace something at a specific point in the collection?

like image 419
Adam Weitzman Avatar asked Jun 15 '17 16:06

Adam Weitzman


1 Answers

A little bit of an aged question, but... JsonPatch dictates that it needs a determinant path to operate on an element. In the case of an array, that means specifying the ordinal for the member to update (or "-" for add). Under the covers, JsonPatchDocument implements a list adapter to take care of resolving the item to update from the path. To determine if it should apply a list adapter, it checks for anything that can be cast as IList.

Now with EF, it's typical to implement child collections as ICollection:

public virtual ICollection<ChildObject> Children { get; set; }

But if we take a look at inheritance, we find that IList implements ICollection, which implements IEnumerable. Here's a quick read on the topic: https://medium.com/@kunaltandon.kt/ienumerable-vs-icollection-vs-ilist-vs-iqueryable-in-c-2101351453db

But what it boils down to is that IList adds the integer indexing that JsonPatch requires. So there's no way to get the ordinal on an ICollection. End of story.

Now EF isn't going to complain if you implement your child collections as List, or even IList - as long as it supports ICollection, EF is happy an you could apply your JsonPatch without issue. However, one thing to consider is that, unless you're specifically issuing ordered queries, you result should be considered non-deterministic. Because of that, applying an integer index is a lie.

If you do decent database design and put keys and indices on tables, the probability is that it will only be a dirty little white lie, rather than a scandalous affair. But that's your call to make.

like image 93
Byron Gray Avatar answered Oct 06 '22 18:10

Byron Gray