Very often I am involved in discussions about “the right place” where to perform Data Validation. A lot of people do not approve the use of tools that checks automatically Data Validation attributes in the UI. This happens in Mvc, Silverlight +Ria services and in both Silverlight and Wpf if you use the Validation Toolkit for Wpf & Silverlight.
The main criticism is that, according to them, Validation needs to be performed in the Business Layer, not in the Presentation Layer. Performing validation in the presentation layer enforces a duplication of the procedure that needs to be repeated in other layers. Taken literally this observation appears fair. However, behind the above words there is the danger of confusing some concepts:
- Where performing the validation is different from when performing the validation. Moreover, we needs also to understand well what does where mean in object programming. For sure the Presentation layer is not where to perform the validation. However, the best time when to perform validation is when the flux of control is in the Presentation Layer, that is, immediately after the user input: this way we are able to help the user with an immediate feedback, and we eliminate immediately potentially dangerous requests that might be used for a denial of service attack.
Thus, the best solution is performing data validation when the flux of control is in the Presentation Layer by using rules defined in other Layers(where), and that the Presentation Layer is not aware of(it just enforces them, it doesn’t need to know anything about them). This is exactly what all tools that verify Data Annotations in the Presentation Layer do! - Performing validation when the flux of control is in the Presentation Layer may force to perform a second validation control at a later time either because immediately after the user input we might miss some information that is necessary to perform the validation, or because of security related issues. However, there is nothing bad in performing two validation controls if we are able to do this without duplicating code. Code duplication has a negative impact on software modifiability, but the duplication of the validation control creates no problems. Below I will show how we can avoid code duplication.
Once we cleared the way from sources of possible confusion and mistakes we can try an answer to the question: what is the best place where to define data validation rules?
Actually there is not a unique place where to put them! There are rules, whose best place is the Data Layer, other the Business Layer, and also the Presentation Layer. Data Layer scoped constraints are the ones imposed by some consistency rules of the database that might be not relevant to the application, Business Layer level constraints are all constraints imposed by Business rules(some of them are also encoded within the consistency rules of the data base). Maybe someone is surprised that there might be also Presentation Level Validation rules: later on I will show some examples.
However, before it is worth to point out that there are rules involving the very conceptual nature of data. Such rules cross the boundaries of layers and remain attached to the different representations that the same conceptual entity has in each layer. For instance, the E-Mail address of a Customer has always the same structure that is independent on how this conceptual entity is represented in the different layers. Maybe in the Presentation Layer we have no object representing a single customer and that the customer data are mixed with the ones of another conceptual entity…but notwithstanding this, if there is a Customer E-Mail it has the same structure it has in the Data or Business Layer.
Such rules can be defined in a common place and used by all Layers they are relevant to, avoiding code duplication.However, where do this cross Layers rules come from and how we can identify them?
In the Analysys stage of an application we typically prepare a Data Dictionary containing the definition of all terms and Data that are relevant to the application.Such definitions need to be considered in all Layers to ensure the coherence of the overall application. Thus, for instance, once we have defined the structure of an Address we need to use this structure in all Layers, otherwise we will not be able to translate it from the representation it has in one Layer to the representation it has into another Layer.
Well, now we have the answer: the cross Layers validation rules just translate the Data Dictionary property types definitions into procedures that enforce their structure. In other terms such Validation rules just translate constraints that are intrinsic in the data themselves, not Business rules: the structure of an E-Mail Address is independent of the use we do and is implicit in its definition. Such properties are typically property level validation rules, while Business rule more often involve constraints spanning several properties of an object.
To understand better how to proceed in practice let consider the case of the Address. We use the definition of address to write validation rules for different representations an address might have: 1) a single rule to be used when the address is represented as a single string and a some other rules for the case the address is represented as a complex structure(Country, street, etc). For the second representation we probably need several rules, one for each field, and a final check rule for the overall complex structure.
All validation rules obtained this way may be translated into validation attributes and put in a separate dll that is referenced by all Layers.
In a well structured application the Data Dictionary not only defines the structure of all conceptual entities but also name conventions, in order to make easier “to put the fingers” in the software, and to enforce coherence among all Layers. I suggest a convention for the name of the objects of the type Customer, CustomerBusiness, CustomerView, and the use of the same property names across all Layers.
Using the same property names for all properties related to the same conceptual entities allows the definition of common meta-classes to be used in all Layers. Thus, if we have a Data Layer Customer class and a DetailCustomer, and ShortCustomer classes passed from the Business Layer to the Presentation Layer, they can both take their property level Validation attributes from the same meta-class defined once and for all in the same dll that contains also the common Validation Attributes reference by all Layers. Properties defined in the meta-class that are not used in one of the target classes are simply not validated by the validation engine. The previous assertion is true for all property level attributes but the [Required] attribute that fails the Validation if it is not defined in the target class. Therefore I advice of avoiding to include it in the common meta-classes.
As a matter of fact the required attribute doesn’t translate an intrinsic constraint on the property it is applied to, but a requirement on the whole object that contains that property. For this reason we are not able to fit it among the common validation rules shared among all Layers. For instance, the fact that an OrderDate property is required in the business Layer doesn’t imply that it is necessarely required also in the Presentation Layer, because it might be provided from a source different from the user, for instance another procedure, or the computer clock.
Often the best time to check a Required attribute is when we are sure the object has been completely filled. However, this is not a general rule because we might want the user to insert a start and stop OrderDate to list all orders included in a time interval. This is an example of Presentation Layer scoped validation rule! In such a case we can use the [Required] attribute directly on some ViewModel property.In the cases where the Required check just translate an integrity constraint of the whole object that contains the property I propose to use an object level validation attribute that checks all required fields. Accordingly, I defined a similar object level attribute in my Mvc Controls Toolkit(see the RequiredFieldsAttribute here).
I promised to show some examples of Presentation Layer scoped validation rules. I already provided the example of the dates that defines the Orders to list. In general Validation rules on data that are used to define filtering criteria are often Presentation Layer scoped Validation rules.
Tags: Validation, Data Annotations, Data Validation, MVC Controls Toolkit