Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

relationships routing and fetching - what is the status and plans for that? #36

Open
cnolewajka opened this issue Jan 17, 2017 · 2 comments

Comments

@cnolewajka
Copy link

As per jsonapi spec:
http://jsonapi.org/format/#fetching-relationships

I tried to fetch related resources using /articles/id/relationships/author in the given example and it seems it couldn't get it work.

I tried to look at the implementation, add missing routing, etc. It looks like the current NJSONAPICORE doesn't account for that part of the spec.

If I am mistaken, would someone be kind and help me out with example?

If I am right, could we start a discussion on how to best implement it? I would willingly contribute towards the implementation.
The questions would be:

  • for /articles/id/relationships/author example, which controller should handle that?
  • in that case, would it be better to return Article object or Person object?
  • in this scenario, it looks like the entire resource object shouldn't be serialized, but only the resource identifier object; how to best pass that information to JsonApiTransformer implementation?

JSONAPICORE for the moment is by far the best implementation of the JSONAPI I found. It would be great to add that missing piece, and I will gladly contribute. If we can agree on approach related to the above questions, I guess I could plan quite a few hours pretty soon.

Thanks,
Cezary

@brainwipe
Copy link
Owner

Hi Cezary, thank you for your issue. You're quite right, NJsonApiCore doesn't support the fetching/updating of relationships and that is a pain! It's going to become critical at our company soon so I think it's wise we start with a discussion. I think it's more than a few hours work!

The articles controller handles the request for the anything that is /articles/*.

As per the json:api spec,

GET /articles/1/relationships/comments HTTP/1.1
Accept: application/vnd.api+json 

Response is:

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json

{
  "links": {
    "self": "/articles/1/relationships/author",
    "related": "/articles/1/author"
  },
  "data": {
    "type": "people",
    "id": "12"
  }
}

As you can see it is a relationship object.

Responsibilities

To help us find a solution, let's specify the responsibilities.

  • .NET MVC is responsible for joining the route with the controller. It is also responsible for de/serializing JSON but that happens invisibly using JSON.NET so we'll assume we can ignore that for now.
  • The Programmer who is implementing the API is responsible for talking to and updating the storage.
  • NJsonApiCore is responsible for the correct formatting in each direction and providing the Programmer with a Delta that they can apply to an entity loaded from storage. This is done in two places, on Request and on Response.

That should be enough for now, we can add to that later if need be. Let's look at the different operations.

GET Relationship

On the Response, NJsonApiCore needs to create the relationship object (it's not the responsibility of the programmer). To do that it needs the resource. The Programmer needs to get that from storage and to do that the Programmer needs a method on the MVC controller.

I don't like that the programmer creating a GET method for each relationship. The Programmer shouldn't care. So instead, NJsonApiCore should hijack the Request and call the controller method that is registered for GET. It takes the resource that the GET method returned and instead of serializing the whole resource, it serializes just the relationship that's been asked for and sends that back.

The Programmer isn't doing any more work in this case as they already have a GET method that returns the requested resource.

PATCH/POST/DELETE

This is more open to conversation. In this case, the Programmer needs to do some work. A relationship between two objects in storage needs to change. There are two options: new controller methods for each relationship and change or update the Delta<T> to include relationships so that existing POST controller methods that the Programmer has created will work.

The change to Delta<T> will need to be carefully done. It may not be possible for the Delta<T> class to make the relationship changes automatically because those relationships might well have storage concerns. The Programmer might need to be involved somewhere.

As an aside, I'm not in love with the Delta<T> class, it's very complex as it is and it's going to need to do a lot of work.

How does that sound so far?

@cnolewajka
Copy link
Author

Thanks for extensive reply.

Let's concentrate on the GET first. I would like to consider this scenarios:

  • we have multiple relationships, and fetching/creating them all, might be creating unnecessary load on the storage system or CPU. therefore, we shouldn't be forced to fetch the entire resource, when I need only a particular relationship; therefore, I should only need to retrieve and build the related resource that was requested, not necessarily the root resource; I shouldn't even be fetching attributes for the root resource;

  • should it work with nested relationships too? or jsonapi does not allow nested relationships?

  • filtering should work with those scenarios as well, let's say I need to retrieve related resource filtered by some condition; the ?filter[resource.attribute]=value would be nice (that should work I think in your proposal as well, just making sure)

For the above to work, programmer needs to be aware that only a related resource was requested.
Therefore, in the only get method, I need to do some if/elses and most probably call separate private methods to action this (that are not controller's actions as such).
We might equally have a few GET action methods for the more specific routes and instead of trying to do the logic of route analysis ourselves, and complicate the process of streaming out, just let's allow MVC to handle this. If I return on the controller the resource of the appropriate type, it will stream out properly (like if I request /articles/id/relationships/comments/id in the article controller, it serialises properly (with some etra attributes that shouldn't be there by jsonapi.org docs, but I guess that is easy to resolve).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants