Description
My solution has these projects:
- DAL = Modified Entity Framework
- DTO = Data Transfer objects that are able to validate themselves
- BL = Business Layer Services
- WEB = presentation Asp.net MVC application
DAL, BL and WEB all reference DTO which is great.
The process usually executes this way:
- A web request is made to the WEB
- WEB gets DTOs posted
- DTOs get automagically validated via custom ActionFilter
- validation errors are auto-collected
- (Validation is OK) WEB calls into BL providing DTOs
- BL calls into DAL by using DTOs (can either pass them through or just use them)
DTO Validation problem then...
My DTOs are able to validate themselves based on their own state (properties' values). But right now I'm presented with a problem when this is not the case. I need them to validate using BL (and consequently DAL).
My real-life example: User registers and WEB gets a User DTO that gets validated. The problematic part is username
validation. Its uniqueness should be checked against data store.
How am I supposed to do this?
There's additional info that all DTOs implement an interface (ie. User
DTO implements IUser
) for IoC purposes and TDD. Both are part of the DTO project.
Impossible tries
- I can't reference BL in DTO because I'll get circular reference.
Compilation error
- I can't create an additional DTO.Val project that would reference partial DTO classes and implement their validation there (they'd reference BL + DTO).
Partial classes can't span assemblies.
Possible tries
- Create a special
ActionFilter
that would validate object against external conditions. This one would be created within WEB project thus seeing DTO and BL that would be used here. - Put DTOs in BL and keep DTO interfaces as actual DTOs referenced by other projects and refactor all code to use interfaces instead of concrete classes.
- Don't handle external dependant validation and let external dependencies throw an exception - probably the worst solution to this issue
Resulting solution
I ended up using controller action filter that was able to validate object against external factors that can't be obtained from the object itself.
I created the filter that takes the name of the action parameter to check and validator type that will validate that particular parameter. Of course this validator has to implement certain interface to make it all reusable.
validator needs to implement this simple interface
It's a simple and effective solution to a seemingly complex problem.