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

Support POST requests to a to-many relationship link #353

Closed
avrittrohwer opened this issue Jul 25, 2018 · 1 comment · Fixed by #875
Closed

Support POST requests to a to-many relationship link #353

avrittrohwer opened this issue Jul 25, 2018 · 1 comment · Fixed by #875

Comments

@avrittrohwer
Copy link

As per the json:api spec (under the section linked at http://jsonapi.org/format/#crud-updating-relationships)

A server MUST respond to PATCH, POST, and DELETE requests to a URL from a to-many relationship link
...
If a client makes a POST request to a URL from a relationship link, the server MUST add the specified
members to the relationship unless they are already present. If a given type and id is already in the
relationship, the server MUST NOT add it again

@jaredcnance
Copy link
Contributor

jaredcnance commented Oct 28, 2018

Steps to Implementation

@maurei

For the most part, you can follow the PatchRelationshipsAsync path.

  • Define a new service layer interface ICreateRelationshipService (or better name). See the existing interfaces. This interface should also b implemented by IResourceCmdService.

  • Add dependency on the new interface to constructor of BaseJsonApiController:

public JsonApiController(
IJsonApiContext jsonApiContext,
IGetAllService<T, int> getAll = null,
IGetByIdService<T, int> getById = null,
IGetRelationshipService<T, int> getRelationship = null,
IGetRelationshipsService<T, int> getRelationships = null,
ICreateService<T, int> create = null,
IUpdateService<T, int> update = null,
IUpdateRelationshipService<T, int> updateRelationships = null,
IDeleteService<T, int> delete = null
) : base(jsonApiContext, getAll, getById, getRelationship, getRelationships, create, update, updateRelationships, delete) { }

  • Add PostRelationshipAsync to BaseJsonApiController that checks to see if the service is available and if so, forwards the request to the service layer and returns an HTTP 200 status code if successful.

  • Add PostRelationshipAsync method to JsonApiController similar to PatchRelationshipsAsync. This method should just be a stub to define the routing and then forward the call on to the base class.

[HttpPatch("{id}/relationships/{relationshipName}")]
public override async Task<IActionResult> PatchRelationshipsAsync(
TId id, string relationshipName, [FromBody] List<ResourceObject> relationships)
=> await base.PatchRelationshipsAsync(id, relationshipName, relationships);

  • Define the implementation of the method in the EntityResourceService. This should be pretty straightforward. We should lookup the resource and relationship on the ResourceGraph and ensure that it is a HasMany relationship. If not, I think we should return an HTTP 403 with a meaningful message.

  • The code that actually updates the resource in the database should be defined as a new method in the DefaultEntityRepository. The method should also be defined on the IEntityWriteRepository.

  • Add the new interface to auto discovery

internal static HashSet<Type> ServiceInterfaces = new HashSet<Type> {

  • Add the new interface to service registration

services.AddScoped(typeof(IEntityRepository<>), typeof(DefaultEntityRepository<>));
services.AddScoped(typeof(IEntityRepository<,>), typeof(DefaultEntityRepository<,>));
services.AddScoped(typeof(ICreateService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(ICreateService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IGetAllService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IGetAllService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IGetByIdService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IGetByIdService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IGetRelationshipService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IUpdateService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IUpdateService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IDeleteService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IDeleteService<,>), typeof(EntityResourceService<,>));
services.AddScoped(typeof(IResourceService<>), typeof(EntityResourceService<>));
services.AddScoped(typeof(IResourceService<,>), typeof(EntityResourceService<,>));

@maurei maurei added this to the v3.2.0 milestone Apr 24, 2019
@wisepotato wisepotato removed this from the v3.2.0 milestone Oct 9, 2019
@maurei maurei self-assigned this Sep 18, 2020
This was referenced Nov 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants