Say I have a controller CatController
with actions for GET, POST and PUT. They all use the same Cat
resource which could look like this:
public class CatDto {
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public bool IsFriendly {get; set; }
}
However, the Name
and IsFriendly
properties should only be required when creating a new cat (POST), but optional when updating it (PUT) to allow updating only a single property.
The way I've handled this until now is simply having two classes, a CreateCat
and UpdateCat
which have the same properties but different data annotations. However I don't want to have to maintain two almost identical classes.
I could of course validate the model manually in each action, but data annotations are very useful for things like global model validators and automatic generation of Swagger schemas.
I'm also using the Swagger schema to automatically generate SDK's (using ApiMatic), and that results in having two duplicate classes generated (CreateCat
and UpdateCat
) for what really should only be a single resource (Cat
).
Is there an alternative way to achieve what I'm trying to do with only a single class?
Here is a simple description of all: POST is always for creating a resource ( does not matter if it was duplicated ) PUT is for checking if resource exists then update, else create new resource. PATCH is always for updating a resource.
Can I use POST instead of PUT method? Yes, you can.
POST method request gets input from the request body and query string. Data passed using the POST method will not visible in query parameters in browser URL. parameters of POST methods are not saved in browser history. There is no restriction in sending the length of data.
I prefer to keep separate models to be honest. You could have a base abstract ( or not ) model with all the common properties although this is not required and simply adds a third class. Is there a need for it? I'd say no.
There are slight differences between POST and PUT.Neither POST nor PUT require the Id property if you already have that in the PUT endpoint. This negates the need of checking if that Id in URL matches the Id in the model.
Your example does not make the difference visible, but in many cases there are fields you don't really want to update. For example let's say you have a Created and Updated date fields, you would not want to change your Created date via a PUT for example. The more data you have that you do not want to update via a PUT, the more obvious and worthwhile the differences between the models become.
In your case even with those 2 properties I would still create 2 different models, even if they are virtually the same, this sets the expectation on how the API works and creates a clear design in the mind of everyone else who is working on it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With