1

Basically there are two things which are important for me. The first one is already answered in the same way I would've done it (How to model a RESTful API with inheritance?). The RESTful design is easier to maintain when realized like:

GET /animals # get all animals POST /animals # create a dog or cat GET /animals/123 # get animal 123 

Instead of:

GET /dogs # get all dogs POST /dogs # create a dog GET /dogs/123 # get dog 123 GET /cats # get all cats POST /cats # create a cat GET /cats/123 # get cat 123 

I don't know how to setup a proper way of deserializing the following code into for example an object of type dog. I tend to get confused since most people advice on creating only an /animals POST endpoint instead of /animals/dog POST, but don't provide a direct solution to this.

The solutions I've found are:

  • TypeNameHandling.Auto (not secure unless custom serializer?)

  • Custom JsonConverter which also needs a custom implementation to tell which fields are in the derived classes as far as I'm concerned

  • JsonSubTypes(typeof(...)) annotation. This also needs including of fields from the derived classes in the custom mapping.

In the end I want to achieve the following. If this means this 'generic' solution in the end is not worth it, that's also an answer for me.

 [HttpPost] public async Task<ActionResult> Add(Animal animal) { // repo.add(animal); } 
5
  • show your classes aka your code, the object themselves would be able to handle it depending on what your code looks like, class -> BaseAnimal -> property bool HasFur. The serialized version would look like same as if it was in one class and wouldn't know about any base classes, you can then deserialize to the specific animal, you would have to deserialize to animal, then you could ask at run-time, what type of animal and then cast to that type. So you would perhaps need to deserialize twice, once to get the type of animal then to deserialize to that animal. Commented Dec 10, 2019 at 9:50
  • But the problem is to do this directly from the controller. I used the typical 'animal' base class and 'dog', 'cat' derived class example. For me it is regardless the properties the derived classes have. Commented Dec 10, 2019 at 10:24
  • i think i get what your saying, but the answer in the link you quoted was the best, from what i can see.. you need to split api calls into the way they are doing it... where the animal call, exposes what calls you can then call... like what they doing in your link, the answer is demonstrating this. Commented Dec 10, 2019 at 11:24
  • 1
    Yes I could also not figure out another way to do it but I was interested in what people generally do. So it seems that there will be (a lot) derived resources. Thanks for your input :) Commented Dec 10, 2019 at 12:20
  • marked up i agree, would be interesting if there are some more ways of approaching this. Commented Dec 11, 2019 at 7:37

1 Answer 1

1

Why not use the Route attribute?

So your route would look like

POST animals/dog 

All you need to do is the following:

[HttpPost] [Route("dog")] public Task<IActionResult> AddDog(Dog dog) 

That will produce the route

localhost:PORT/animals/dog 

That way its all contained in the one controller and the URIs are coming off of the central animals one.

Due to the way that things get serialised I don't think there is a way you can just post a generic Animal and it know to go to a dog or cat. You would need to write a custom deserialiser for that

Sign up to request clarification or add additional context in comments.

4 Comments

It is suggested by the article I followed to make only one endpoint which posts 'any' animal. The frontend is actually sending a dog with it's corresponding properties. My question is about realizing it so I can use POST animals/.
Ah I get what you're meaning now! Sorry mate! What I would do is put a property into the base class like Type or something and in the controller method when the base class has been deserialised you can check for that Type property IE Dog or Cat. From there you can get the request stream and just re-deserialise into the correct abstraction.
I was already afraid of this. What you suggest is probably a good solution, but I was hoping for something easier or more readable. Thanks for your input. I will mark your answer as solved since I think this is just a better way to solve the problem in the end. Eventhough it will result in some more endpoints.
Why not check out GraphQL? It provides a single end point and behind the scenes does checks to see where the data should be processed/gotten from and in what way?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.