Thursday, December 17, 2009

All Validation Techniques in ASP.NET MVC

Authors and editors: Sergey Khalipsky, Aleksandr Sliborsky
In the first article (Validation Techniques Comparison) we just considered the most useful and the best techniques that could be used for validation implementation in ASP.NET MVC.
We don’t want to deprive you of a pleasure of doing all this by yourself, so we will just give you a direction and some samples of implementation and let you dig deeper .
So, today’s agenda is:
  1. Manual validation in Model Binder and Controllers (client validation type 1 and server validation type 1)
  2. DataAnnotations (client validation type 2, server validation type 2);
  3. Custom Validation engine implementation (client validation type 1, server validation type 2);
  4. Spring Validation Framework usage on a server, manual validation on a client (client validation type 1, server validation type 3)
  5. Spring Validation Framework usage on a server, DataAnnotations + manual validation on a client (it’s a mix from several points from previous review);
  6. xVal Validation Framework
Let’s start fingerscrossed

Manual validation in ModelBinders and Controllers

When we started working with ASP.NET MVC some time ago it was almost the only solution we could implement. It’s obvious and could be ascribed to the brute-force approaches family.
The essence of this approach is that you just male your validation completely manually in controllers and everything is in your hands: from how to define validators (actually you don’t have them – you just right rules as a code) to how to show validation errors and how to merge server-side and client-side validators.
Whereas it’s the simplest solution to start from it’s not a good practice for real projects – too much of coding, less code reuse, mixing of logic or binding and validation. It could lead to some kind of mess in code and horror in the future maintenance.
So, just don’t keep in in your mind and move forward.

DataAnnotations

It’s a built-in validation provided along with ASP.NET MVC. And this approach is widely boosted on the Internet as a default validation solution for ASP.NET MVC projects.
Additional information about this approach and good its description could be easily found, and these articles could be good starting points:
Validation with the Data Annotation
DataAnnotations and ASP.NET MVC
ASP.NET MVC Tip #43 – Use Data Annotation Validators
We also bought that on one of our projects and had started implementation with DataAnnotations and, what was the surprise smile_omg, almost immediately had faced with the following problems:
  1. Shortage of validators.
  2. Relations between validators are hardcoded;
  3. There is no possibility to define group of validators or dependencies between some validators.
  4. It’s not easy to extend the framework with new validators.
All these disadvantages led to that we duplicated complex validation on client instead of just using attributes and server validation was dispersed across several places (it could be model metadata, ModelBinders and Controllers). Also if you add localization to such application then string resources could be also separated and deconcentrated across several places of the projects.

Custom Validation implementation

ASP.NET MVC provides good extensibility point since Version 2 Preview 1. Unfortunately, there is not much documentation about this approach but this question on stackoverflow - ASP.NET MVC 2 - Implementing custom Metadata and Validator Providers – could be a good starting point.
So, if you have some time you can definitely implement your custom solution where you will develop all the things you need, any kind of validation, integration, interface and so on and so force. And may be you even will be in time with your project. Or at least validation part of the project. My decision was to wait a little bit for third-party implementations or at least some templates that will allow me to just extend them not doing all the work from scratch.

Spring Validation Framework

As I already wrote Spring.Net Validation Framework (http://www.springframework.net/doc-latest/reference/html/validation.html) is a standard de-facto in our company for many reasons. And I still don’t want to argue about this choice. (But, I’d be glad to hear something new about other validation frameworks and may be I will agree with you later).
So we tried to integrate ASP.NET MVC and Spring.Net. And, wow, it’s possible and easy!
Firstly, we tried to implement the integration through Validation and Metadata Providers. But, unfortunately they are oriented to step-by-step validation of the object’s properties. That is bad, because it doesn’t allow us to use all the power of validation framework and not in-line with it.
Then we used OnActionExecuting method in the following way:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// 1. Need to validate model only for the post requests
if (filterContext.HttpContext.Request.HttpMethod == "POST")
{
// 2. We pass through the parameters of actions to obtain objects for validation.
foreach (KeyValuePair<string, object> keyValue in filterContext.ActionParameters)
{
// 3. Obtain validator by its name.
BaseValidator validator =
SpringSingleton<BaseValidator>.GetInstance(keyValue.Value.GetType().Name + "Validator");
ValidationErrors validationErrors = new ValidationErrors();
// 4. Validating...
if (!validator.Validate(keyValue.Value, validationErrors))
{
// 5. Transform Spring validation errors into ModelValidationResult objects.
foreach (ModelValidationResult modelValidationResult in GetModelValidationResults(validationErrors))
{
// 6. Add error to the list of errors.
ModelState.AddModelError(Guid.NewGuid().ToString(), modelValidationResult.Message);
}
}
}
}
base.OnActionExecuting(filterContext);
}



Of course, it’s just a sketch. What we did:
  1. We decided to validate only the POST requests.
  2. We analyze an action on the subject of parameters it takes. Every parameter is considered as the object that could be validated. Thus we take every parameter and pass it through the validation cycle.
  3. Here is the simplest solution for validation :) Of course in a real-world project you should implement your own solution for obtaining validation rules by model (or by whatever else). We just define naming convention that validation rules are registered with names postfixed with “Validator” for every object.
  4. We ask validation engine to validate the object
  5. We transform Spring validation errors into standard built-in ModelValidationResult objects.
  6. And add these objects to the errors list.
So, you can get added evidence that it is easy and quick to implement such an integration. I think, it’s not much more complex for your favorite framework.
You will also need to implement a mechanism of making a choice of which object should be validated on which actions and by what rules (steps 2 and 3). There are several variants that are possible:
  • You can mark a model that this model should be validated;
  • Mark an action, that some of its parameters (models) should be validated (and additionally you can define – by which validator);
  • Mark a controller for more flexible validation;
  • Move configuration and links specification into separate configuration file (e.g. XML-file)
The final decision is up to you. And we will leave you here to let you think about it and move forward to the next possibility.

Spring Validation + DataAnnotations

Previous solutions will force us to use manually written validation on client (or some other framework). And here an interesting question arises: how many complex checks do we have? If we have not many of them then why should be spend our implementing the functionality which we could easily get from standard implementation (I mean DataAnnotation). We have not more than 30% of complex validation rules from the overall quantity of valiadtors to be implemented. Please, agree, all we are too lazy to implement the rest of them (70%!) manually.
So we have decided to try DataAnnotation only for the client validation and Spring Validation Framework for the server one.
And this mix is our choice and recommended solution – it’s easy to define server rules using XML definitions or code (use what you want, Spring allows you to do it) and to define the most of client checks using attributes not Java Script thumbs_up

xVal Validation Framework

On one of our projects we tried to use xVal Validation Framework.
It is an interesting solution, an interesting framework.
Actually, it was…
Why so? ASP.NET MVC 2 provides very similar mechanisms to what xVal provides. If you are going to use ASP.NET MVC 2 on your project then all the possibilities which are provided by xVal now are provided by ASP.NET MVC infrastructure: DataAnnotations, IRulesProvider (analogue is ValidatorProvider + MetadataProvider). Correspondingly, there is no much sense to use xVal for the projects based on ASP.NET MVC 2.
But still it’s a good framework anyway :)

Resume

We have tried several options. All these options are described in this article. And we have found that Spring Validation Framework + Data Annotations + jQuery is the most powerful, flexible and time-saving choice on our projects.
Your choice is definitely could differ from our one. And we’d like to here your arguments and to see your implementation ideas.
Enjoy your job!
kick it on DotNetKicks.com
DZone:http://www.dzone.com/links/validation_techniques_in_aspnet_mvc.html

1 comment:

admax said...

Can you explain spring.net + data annotations solution? Did you implement validator/metadata provider?