I am building an ASP.NET MVC project and going for the following Architecture:
- A Core project that has models, validation, dto, logic, etc.
- A ServiceStack API project that acts as my REST API
- An ASP.NET MVC Web project that is the UI
So, let's say I want to add a user. I define a NewUserInputModel
in the Core project. I give it some data annotations such as [Required]
. After doing this, the Web project will perform client side validation based on those annotations.
My question is about server side validation. I want to validate the NewUserInputModel
using the same rules that are being used on the client side, and I want to run that validation weather the NewUserInputModel
comes in from the API or the Web project.
I realize I could call ModelState.IsValid
from a Controller in the Web project - but I want to call that validation from the Core project so that all validation logic lives in Core. This way, no matter how this model gets to the Core logic, I always call the same validation. I don't want to leak a System.Web
reference into my Core project.
Is this a reasonable design? I think it is - but if something about it smells, I'd be happy to hear it.
Thanks in advance for any help.
I usually keep my view models in the Web project and do the input validation in the controller using the
ModelState
property. If this succeeds, I map them to domain models (which live in the Core layer) and send those to my services in the Service (could also be Core) layer. The service layer validates business rules and if it succeeds it calls a repository to perform the desired action and returns the result of the operation to the controller.Keeping your view models in the Web project also allows you to use MVC validation attributes such as
RemoteAttribute
.I'm not saying that your design smells, but I do think it's good to separate presentation logic from your Core layer.
Making a mixed Validation could be also useful, so mixing DataAnnotations with custom validations logic
This may be helpful http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2
I consider your approach to be good. Mapping one set of models to another could bring some bugs.
The code you are looking for is:
For details see http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationcontext.aspx or http://odetocode.com/blogs/scott/archive/2011/06/29/manual-validation-with-data-annotations.aspx
My approach to this by fast thinking is to do something like that. In business layer create
Now having a service example
Now in the controller you call the service and pass the validation messages to the view. It may be necessary to use ViewBag and pass the whole list. On the view you can highlight Info, Warning, Error. For example you could return some success message with Info type, or nothing at all and in the controller create success message.
Generally this approach is more coding, but more flexibility. Ideally service would validate everything, but for smaller projects to avoid validation duplication, as Henk Mollema stated in his answer, you could do user input validation through ViewModel and in service just validate just critical business rules.
ValidationMessageType may be an overkill as well, so it's possible to return just List from the service as error list and the empty list would mean success.