11

I'm using ASP.Net Web API and the Code First Entity Framework and from what I've read you should typically be exposing DTO objects rather than the entity objects directly in your action methods (according to http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-5).

So in one case I'm working on, to avoid the problem of "over-posting" as described in the link above I've created a DTO object with almost all the same properties as the model object. What I'm wondering however is do I need to duplicate all the same sets of validation attributes (eg. [Required], [Range(N,M)], etc. for both the DTO and model properties? Initially I was hoping not to (to avoid duplication) but you need the validation attributes on the DTO if you want to leverage the binding validation (ie. ModelState.IsValid) and on the main model if you want your database to be created with the appropriate constraints ([Required] -> not null, etc.)

Is there no better way?

Also, are there some attributes that Entity does use but the model binding validation does not use? For example, while [Range(n,m)] will clearly affect validation on some client input, does entity care about it at all (it doesn't seem to affect the created DB schema from what I can tell?)

1 Answer 1

8

The entities should only have the attributes which are actually having an impact on the database. The DTOs should not have any attributes for validation except for the DataMemberAttribute to define if a property is required and in which order it should be displayed etc. For OData you also have to set the KeyAttribute. The models should have the validation attributes. Because the DTOs and the models are probably almost identical you create for each dto which needs to be validated a model and just swap the dto's value to the model's object. Now you can validate it, if you are not using ValidationAttributes for the models you can validate them for example with FluentValidation

So long story short:

  • Entities only get the attributes which actually impact the database's schema

  • DTOs are simple objects with no validation logic, except for the DataMemberAttribute

  • Models should have the validation attributes (only if needed, not needed when using FluentValidation)

The workflow for POST will be: -> DTO comes in -> Swap dto to Model -> Validate the model -> Swap model to entity -> Store entity in database -> Use the updated entity and swap it to a new dto -> Return the dto

Greetings, Voltaic

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

11 Comments

"Swap dto to Model" then Validate the model, how will that work? With swap I guess you mean map dto to model? If yes the ModelState will still operate on the dto because this one is passed. Short story: Do you put Required attribute on your DTO`s ?
You can map the DTO to model by using AutoMapper or any other framework, or simply do it by hand. The Required attribute is used to ensure a state of the dto that you are willing to handle. The Model doesn't need the required attribute, just the DTO. You could write a base class for your models which holds the DTO as some kind of state and you can then just expose the DTO's properties as properties of the model.
If that's the case, then what is the strategy to transfer information about the underlying model to the client? If a field is invalid, it would be nice to know without hitting the server. I would argue that if the dto is used in an update operation then putting the validation or other business logic in the dto so the client can know in advance how to form the request.
You could define your validation rules for example with FluentValidation. The validator would check the model which is holding the DTO as its internal state. The developer which is using your client must and maybe should not know about the dto. A clean model, that has its own validator fits most of the needs we currently have. This is of course just one of multiple ways of handling such scenarios.
I disagree, sometimes it is common to use your DTOs as both input and output, DTO models are input of your controller actions and the validation is handled by the framework and you can check it with ModelState.IsValid.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.