Validation of domain model: how and where - asp.net-mvc

A typical EF+MVC system will have two or three levels of validation:
For ViewModel: input / physical validation (DataAnnotations, FluentValidation), in other words, length, null, range, regex, etc.
For Model: input / physical validation (repeat of 1 in case MVC is not used and data comes from another system, WCF, forms, etc.)
For Model: logical / "business rules" validation
I can't find best practices for validation of 2+3 for the actual Model / entities / domain / "business rules". We either:
put simple validation rules in an entity's property setter (but this is really messy)
hook into EF's SaveChanges(), and if an entity is in the Added or Modified state then trigger validation (which validates the entire entity at once)
This is hard to maintain. A lot of thought went into ViewModel validation, but for Model validation it is domain-specific and so it is for you to determine a creative solution, and mine is not that great.
Are there better ways to do this, or helpful tools (like maybe DataAnnotations or FluentValidation but for domain entities)?
Where is the best place to do model validation or to trigger the model's validation?

A typical MVC+EF system will have 3 layers, but they aren't what you're talking about.
Presentation Layer (input/output)
Business Layer (Logical layer)
Data Layer (model represents low-level data)
MVC provides validation for layer 1. EF provides validation for layer 3. There is no validation functionality provided by either MVC or EF for layer 2. If you want validation there, you have to do it yourself, or use a third party business object framework.
Validation in layers 1 and 3 are separate, even though in many cases they may have similar validation. The reason is that validation is accomplished in different ways, and with different requirements.
For example, you may have a field in your database that is nullable for data modeling or business logic reasons (let's say some data is pre-loaded and the user is required to update the field as part of the business process). The data layer says it's nullable, but you want your UI to make it required.
EDIT:
Simply put, the Data model should not be enforcing business rules. Therefore, you should not need any validation in the data model, other than to validate against the physical data model (ie, if the field is nullable, the data type in the model should nullable, otherwise not). In most cases, you physically cannot insert invalid (from the data models perspective) data because the code model will not allow it. The only exception to this is string variables, which can obviously overflow the size constraints of the physical model, but if that happens then an exception gets thrown anyways.
Your middle tier, the business layer, should be where you need to validate business rules (for example, that a customer purchase order must start with a letter). Neither MVC or Entity Framework, or WCF or whatever provide any way to do this validation.
There is a bit of a disconnect here, because the business rules should (in theory) drive the presentation layer validation. But, MVC has no built-in functionality to do that, though. So you end up duplicating your business rules in the UI.
There is at least one third party business object framework that tries to deal with this. CSLA. They provide a custom MVC model binder that ties in the business objects with the UI to do validation, but this is just using the built-in extendibility of MVC to do this.
So, if you don't want to use a dedicated business object framework, you are stuck either duplicating validation between UI and Business layer, or trying to figure out your own way to make your own business layer control UI validation.

Related

About patterns in MVC 3

It is common sense to keep business logic out of controllers. It is also common sense that database access logic should be on a repository, using a repository pattern, as described here: Repository Pattern
However, the repository pattern specifies only very simple low level database operations: Insert, Delete, Update, Select. People advise to keep validation logic out of it too. That is not a problem, since most of the validation can be put inside the model object itself. The problem comes when we need to make some kind of cross-validation, that is, a validation that needs to look on more than one instance of the same model object (for example, ensuring that a name is unique accross all instances of same object) or, even worse, when the validation logic needs to check two or more objects of different types. In this case, we have a real big hole: the business logic cannot be in controller, cannot be in the repository, cannot be in the object model itself (since the logic is not bound only to the object's properties). Where should this logic be? What is the best design pattern for this kind of requirement?
You can create a service layer as described here:
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
The problem here is that your design requires the UI to do validation based on business concerns.
The way to accomplish this is to abstract the validation into the business layer. Your business layer may have methods like ValidateUserIsUnique() and then your ui calls into this layer and receives a result, which is then used for validation.
In particular, for client-side validation MVC provides the RemoteValidationAttribute, but this will only do client-side validation. You will also need to do a server-side validation that calls the same (or a similar) function on the server.

How to unify validation across layers/tiers

In a typical MVC application we have validation that occurs in many different places. It might be client-side, in the controller, and then again at the data level. If you have a business layer, then there is additional validation there as well.
How do we unify all these so that we're not violating DRY, and causing support nightmares when validations change? A sub-question is how to enable dynamic validation based on the model across all layers.
For example: We may have a ViewModel that has data annotation attributes. In MVC2/3 this unifies client-side and controller validation, but does not help with the data model (unless you are using your data model as your view model, which isn't a good practice).
This means you have to add the same validations to the data model and business layers, duplicating it. What's more, the data model might have subtly different validation requirements than the view model (for instance, an entire data record might comprise several view models of a multi-step wizard. And only a complete record can be saved).
Some people add complex validation to the data model when using an ORM like EF or L2S with partial classes, which i'm not sure is the right path either. It works for apps that are primarily data oriented (data entry type apps), but would not work for apps that have more non-data business logic.
What I'd like is some way to either generate validation for all layers, or a way to hook into a single validation system. Does anything like that exist?
"Fluent Validation" provides better re-usability.
Please visit.
http://fluentvalidation.codeplex.com/
Re-usable documents for Fluent Validation.
http://fluentvalidation.codeplex.com/wikipage?title=CreatingAValidator&referringTitle=Documentation&ANCHOR#ReusingValidators
http://fluentvalidation.codeplex.com/wikipage?title=CreatingAValidator&referringTitle=Documentation&ANCHOR#Collections
Below one may be full fill your needs.
http://tnvalidate.codeplex.com/
I guess I really don't understand your answer since rarely is your data model, business model, and view model all the same. If they are, just use the data model and put the validation on it. The validations across all your layers are specific to the layer.
Example: Your ui should not contain business layer logic in case you ever change the ui layer, or create a new one.

Fluent Validation, Domain and ViewModels

I've been developing a web application with asp.net mvc, nhibernate and ddd concepts.
I've developed validations with Fluent Validation for my domain classes and it works fine. Well, now, I need a ViewModel to edit an entity in a View, soo, my question is, Do I need to create another validation class to validate my viewmodel? Or what should I do to get around this situation?
I ask it because I don't want to broke the DRY (don't repeat yourself) concetp.
Thanks!
Domain level validation, and View-Model validation are quite different imho (although they can have lots of overlap).
For instance, it may be perfectly allowable to have a certain field as null in your database, but require it's input on certain webforms. In this case you would check for null within the Model validation.
It would also be quite normal for multiple client applications to share the same Domain controllers (via WCF for example), but to possess different application validation logic.
If you use DataAnnotations in your view model you can get client-side javascript validation for free, so as a general rule, I always have a separate ViewModel from my Domain objects, even if it's a 1:1 mapping - I just use AutoMapper to translate between them. In addition to getting the client-side validation, it also reduces the clutter within the Domain validation.

MVC validation: where to validate?

We say that model validation at controllers layer is the correct place to validate all data we gonna operate with. In this case, if we change UI to another (remembering that our layers must be pretty decoupled) the new data validation principles are going to execute - in this case all our inner rules can be violated.
You may say that data models is the separate layer and that layer, but not UI, is the only place for validation. But in this case i found it more effective to validate data in the service or business objects layer, don't i?
In fact we have a number of objects corresponding to our domain object: db table record, linq2sql class, domain object class, viewmodel class. Should it be only one place to validate data model? Why should it be in (or close to) UI but not in the other layer? In my opinion, the validation must occur in the service layer - with all other busness logic. If i need to inform user about error as fast as possible, i'll use client validation in addition to main one. Thoughts? Thank you.
Data validation is the responsibility of the model. The best place to put validation rules in my opinion is as constraints in the database. Having constraints ensures that no incorrect data will ever be stored in the database, no matter how it is access. Unfortunately only basic constraints are suitable to express in the database.
The next place to put validation, when using linq-to-sql for data access, I is the extension methods on the entity classes. Then all code will have to pass through the validation.
To improve user experience, basic validation can be repeated in the UI, but that is just for user experience and to catch the most common mistakes early. On the web, using JavaScript validation is preferable. On rich clients the same code as the one called by the extension methods can sometimes be reused.
Always remember that any service exposed to a client, could be called by a malicious client that lacks the validation that the real client does. Never trust the client to do any kind of validation or security checks correctly.
1.It is validated at UI level because to reduce the one extra hit to server. (EnableClientSideValidation check). And its for basic validations only(like invalid input etc)
2.Many business validations are written in Business layer where they intact irrespective to the UI(WPF or MVC)
3.Usually we write UI validation in controller and specific to MVC.
4.You should keep the validation part as per the prefrences. like sometime we validate entity for unique constraint in such case I would prefer to write my validation attribute over the Entity itself.So at the time of insertion to the database it will be validated.
Also you can try to introduce another layer(new library) here for simplicity and decoupling approach,
This new layer will do, some validation which are not specific to UI and not specific to business logic. We will call it as App Services Layer which also actually helps you to interact with WCF like scenarios. So now your controller and WCF will interact with same layer and with same validation.
Data Validation should happen at the domain level. But UI validation errors should be caught without having to ask someone else downstream.

Proper way to validate model in ASP.NET MVC 2 and ViewModel apporach

I am writing an ASP.NET MVC 2 application using NHibernate and repository pattern. I have an assembly that contains my model (business entities), moreover in my web project I want to use flattened objects (possibly with additional properties/logic) as ViewModels.
These VMs contain UI-specific metadata (eg. DisplayAttribute used by Html.LabelFor() method).
The problem is that I don't know how to implement validation so that I don't repeat myself throughout various tiers (specifically validation rules are written once in Model and propagated to ViewModel).
I am using DataAnnotations on my ViewModel but this means no validation rules are imposed on the Model itself. One approach I am considering is deriving ViewModel objects from business entities adding new properties/overriding old ones, thus preserving validation metadata between the two however this is an ugly workaround.
I have seen Automapper project which helps to map properties, but I am not sure if it can handle ASP.NET MVC 2 validation metadata properly. Is it difficult to use custom validation framework in asp.net mvc 2?
Do you have any patterns that help to preserve DRY in regard to validation?
It is fine to repeat validation. Trick is to place it where it's appropriate.
In your case - at UI, validate UI logic (view model props must not be null, in correct format etc.), in business layer - validate business logic (account has money etc.).
Do not use DRY as an excuse to violate SRP! :P
View models are supposed to uncouple your business layer from presentation role.
Don't glue everything together again.
I guess Automapper can't handle that. :)

Resources