Validation is a topic that comes up quite frequently. One concern is how to honor DRY (don’t repeat yourself) principles and create a framework that is reusable across layers. There are some very robust and tested frameworks out there, but sometimes they might be more than what you are looking for. In this post, I’ll show you how to build a standalone validation library that can be shared between Silverlight and the server, then integrated via MEF and PRISM for fluent validation.
Rules and Violations
First things first. We need to lay down the validation framework. One technique I’ve learned when working with Silverlight is to build your main classes as Silverlight classes first, so they take advantage of the “lower denominator.” Class libraries built in Silverlight are then easily shared on the server – the easiest, “out of the box” way is to create a mirrored .NET project and link the classes.
I suspect when a rule is violated, it might pertain to more than one property, so I created a rule violation to look like this:
public class RuleViolation { public RuleViolation(string message, IEnumerable<string> properties) { Message = message; Properties = properties; } public string Message { get; private set; } public IEnumerable<string> Properties { get; private set; } }
Next, we need to define what a validation rule looks like. What I want to do is define various rules and tag them with MEF to export, and have a centralized place to request and execute the rules. The interface I decided to go with looks like this:
public interface IValidationRule { IEnumerable<RuleViolation> Validate(string propertyName, object propertyValue); IEnumerable<RuleViolation> Validate(string propertyName, object propertyValue, Dictionary<string,object> parameters); }
We can simply pass a property and a value, possibly with additional parameters, and receive a list of violations. The parameters dictionary is one place some might complain. Instead of having fine-grained validations that each have different signatures, I like to compromise and use an open interface. I can still type it somewhat (I’ll show you how) but I prefer the flexibility of requesting the common interface over keeping track of all of the various method signatures.
Defining Rules
To explain what I mean, let’s build two validation rules, one that takes parameters, and one that doesn’t. Here is a rule that says, “this is required.” First, we’ll create a base validation class to take care of common tasks so our actual rules are easier to implement:
public abstract class BaseRule : IValidationRule { private readonly List<RuleViolation> _violations = new List<RuleViolation>(); protected void AddViolation(string message, string property) { AddViolation(message, new[] { property }); } protected void AddViolation(string message, IEnumerable<string> property) { var violation = new RuleViolation(message, property); _violations.Add(violation); } protected abstract void _Validate(string propertyName, object propertyValue, Dictionary<string,object> parameters); public IEnumerable<RuleViolation> Validate(string propertyName, object propertyValue) { return Validate(propertyName, propertyValue, null); } public IEnumerable<RuleViolation> Validate(string propertyName, object propertyValue, Dictionary<string, object> parameters) { _violations.Clear(); _Validate(propertyName, propertyValue, parameters); return new List<RuleViolation>(_violations); } }
Let’s get one assumption out the way. This code is not thread-safe. You’ll notice I’m using state on the class to handle the validation, by clearing the collection, then calling the derived class, and finally returning the result. If two threads entered this class, there would be an issue.
You might want to add the extra plumbing to make it thread safe, and that’s fine by me. I personally am not planning to execute anywhere other than within my view model getters and setters. I’m only validating as the result of user input (except in my testing, of course, where I can control this by creating new instances) which is via databinding. That means that if I code this correctly, any validations will actually only come in one thread: the main UI thread.
Here’s what a required value looks like:
public class ValueIsRequired : BaseRule { protected override void _Validate(string propertyName, object propertyValue, Dictionary<string,object> dictionary) { if (propertyValue == null || string.IsNullOrEmpty(propertyValue.ToString())) { AddViolation("Value is required.", propertyName); } } }
Notice that I’m ignoring the dictionary. When checking to see if only alpha characters are in a string (such as a title, for example) I might want to make it optional whether or not to allow spaces in between characters. Here’s a rule that takes in an optional parameter:
public class ValueOnlyContainsAlpha : BaseRule { private const string PATTERN = @"[^a-zA-Z]"; private const string PATTERNWITHSPACE = @"[^a-zA-Z ]"; public const string ALLOW_SPACE = "AllowSpace"; protected override void _Validate(string propertyName, object propertyValue, Dictionary<string,object> dictionary) { if (propertyValue is string && Regex.IsMatch(propertyValue.ToString().Trim(), dictionary.GetParameter<bool>(ALLOW_SPACE) ? PATTERNWITHSPACE : PATTERN)) { AddViolation("Value must be alpha only.", propertyName); } } }
(We could extend that a little more and have a separate message to define spaces or not … this is just here to illustrate the point.) If you’re wondering about the GetParameter
method, I extended the dictionary like this:
public static T GetParameter<T>(this Dictionary<string, object> dictionary, string parameterName) { return dictionary == null ? default(T) : dictionary.ContainsKey(parameterName) ? (T) dictionary[parameterName] : default(T); }
This is just a convenience to cast the value or get the default if it is not in the dictionary.
Exporting Rules
The idea with rules is that it should be easy to export them to the system so a centralized location can pass them out. In this case, I can bind validations later in the game but whatever is using the validations must be aware of the type of the rule. To me, that makes perfect sense – a range validation doesn’t make sense unless I know there is a range validation rule.
Let’s create an export attribute and some metadata for the rule, and we’ll just export them by type:
[MetadataAttribute] [AttributeUsage(AttributeTargets.Class,AllowMultiple = false)] public class ExportRuleAttribute : ExportAttribute { public ExportRuleAttribute(Type ruleType) : base(typeof(IValidationRule)) { Rule = ruleType; } public Type Rule { get; set; } } public interface IExportRuleMetadata { Type Rule { get; } }
Now I can export my rules like this:
[ExportRule(typeof(ValueIsRequired))] public class ValueIsRequired : BaseRule
We need to “catch” the rules somewhere. I’ll create a signature that mirrors the validation signature, with a factory:
public interface IValidationFactory { IEnumerable<RuleViolation> ValidateThat<T>(string propertyName, object propertyValue) where T : IValidationRule; IEnumerable<RuleViolation> ValidateThat<T>(string propertyName, object propertyValue, Dictionary<string,object> parameters) where T : IValidationRule; }
Here is where the fluent interface starts to creep in. Notice these are not just method names, but names that are starting to make a statement (“validate that …”). Let’s implement this with MEF:
[Export(typeof(IValidationFactory))] public class ValidationFactory : IValidationFactory { [ImportMany(AllowRecomposition = true)] public Lazy<IValidationRule,IExportRuleMetadata>[] Rules { get; set; } private IValidationRule GetRule<T>() where T: IValidationRule { return (from rules in Rules where rules.Metadata.Rule.Equals(typeof (T)) select rules.Value).FirstOrDefault(); } public IEnumerable<RuleViolation> ValidateThat<T>(string propertyName, object propertyValue) where T : IValidationRule { return GetRule<T>().Validate(propertyName, propertyValue); } public IEnumerable<RuleViolation> ValidateThat<T>(string propertyName, object propertyValue, Dictionary<string, object> parameters) where T : IValidationRule { return GetRule<T>().Validate(propertyName, propertyValue, parameters); } }
We capture all of the rules. When the client requests to “validate that…” we’ll fetch the type and pass through the parameters.
Fluent Interface
Before I hook this in, I want to add a few extension methods to make the interface more fluent. Remember how I mentioned I’m using a dictionary for additional parameters, but I can type it somewhat? You saw the example in the alpha with the optional spaces. I can send in a parameter that is “true” for allowing spaces. Let’s make it easier to pass that parameter, so our interface can look like this:
Validator.ValidateThat<ValueOnlyContainsAlpha>(propertyName,value,ValueOnlyContainsAlpha.ALLOW_SPACE.AsParameterWithValue(true));
That makes it a little easier to read without making a dictionary, adding the values, etc. In fact, we’ll also want to extend this (for example, if we need a minimum and maximum range) so I’ll also add an extension for additional parameters. The goal is to do this:
Validator.ValidateThat<ValueIsInRange>(propertyName ,value ,ValueIsInRange.MIN.AsParameterWithValue(1) .WithParameter(ValueIsInRange.MAX,10));
Here’s what the extension methods look like:
public static Dictionary<string, object> AsParameterWithValue(this string parameterName, object parameterValue) { return new Dictionary<string, object> {{parameterName, parameterValue}}; } public static Dictionary<string, object> WithParameter(this Dictionary<string, object> dictionary, string parameterName, object parameterValue) { dictionary.Add(parameterName, parameterValue); return dictionary; }
The last extension I want to create for our fluent interface is to allow chaining of validations. In most situations, you’ll have more than one validation. Because validations return an enumeration of violations, it is easy enough to combine them by merging their results. Here’s what the goal is:
var violations = Validator.ValidateThat<ValueIsRequired>(propertyName,value) .AndAlso(()=>Validator.ValidateThat<ValueOnlyContainsAlpha>(propertyName ,value ,ValueOnlyContainsAlpha.ALLOW_SPACE.AsParameterWithValue(true)));
We accomplish the merge like this:
public static IEnumerable<RuleViolation> AndAlso(this IEnumerable<RuleViolation> source, Func<IEnumerable<RuleViolation>> target) { var list = new List<RuleViolation>(source); list.AddRange(target()); return list; }
Using PRISM to Host the Validations
Now the validation project can easily be shared/linked to .NET and used for server-side validation. We’re more concerned with the immediate UI feedback. How does this engine integrate with Model-View-ViewModel?
PRISM provides MVVM guidance in their preview 4. Download it here. There is a base MVVM class in the MVVM quickstart that implements helpers for notify property changed events as well as IDataErrorInfo
, a standard means for identifying validation errors. John Papa discusses this interface here.
What we want to do is hook into the supplied class and make it easy to validate. The reference implementation already has methods for setting and clearing errors against properties, so we just want to provide a validation “front-end” to hook into this feature.
First, we’ll expose our validation factory by importing it into the base view model class:
[Import] public IValidationFactory Validator { get; set; }
Next, we’ll supply a method that derived view models can use to hook into validations:
protected virtual void WithValidationFor<T>(Expression<Func<T>> propertyExpression, IEnumerable<RuleViolation> violations) { var propertyName = ExtractPropertyName(propertyExpression); var hasViolations = false; foreach(var violation in violations) { hasViolations = true; SetError(propertyName, violation.Message); } if (!hasViolations) { ClearErrors(propertyName); } }
Very simple – we simply parse the validations, and if any exist, we set them on the property, otherwise we reset them.
Putting it All Together
I’m not supplying full source on purpose – obviously not everyone will use the PRISM reference implementation for a solution and may have another framework they’d prefer to use, and the intent here is educational. In this example, I can validate that a name is required and must be alpha only (with spaces) like this on a view model derived from the base:
private string _name; public string Name { get { return _name; } set { _name = value; RaisePropertyChanged(() => Name); var propertyName = ExtractPropertyName(() => Name); WithValidationFor(()=>Name, Validator.ValidateThat<ValueIsRequired>(propertyName,value) .AndAlso( ()=>Validator.ValidateThat<ValueOnlyContainsAlpha>(propertyName,value,ValueOnlyContainsAlpha.ALLOW_SPACE.AsParameterWithValue(true)))); } }
And there you have it: a (somewhat) fluent interface for validation that sits on top of PRISM’s MVVM quickstart guidance.
PUT MICROSOFT AZURE TO WORK
We tackle the ongoing challenges of running in Azure.
We were one of the first Microsoft Cloud Solution Providers (CSPs), we are Cloud OS Network (COSN) certified with many production environments on the Microsoft Cloud Platform including Azure Certified for Hybrid deployments leveraging private and public clouds.
We know how to make Azure work for you.
Architected to
meet your needs.
We build solutions to address your individual business objectives with an eye to sustained technology innovation.
Deployed
flawlessly.
We manage the entire lifecycle from start to finish to ensure no surprises and allow you to focus on your business.
Operated reliably
24x7x365.
We only engineer and deploy environments which can be managed and maintained for you by our team of experts 24x7x365.
20 years of experience makes us a trusted partner you can count on.
We have developed a core methodology to ensure we accurately capture your needs and translate them into the best solution possible. This process gives you the peace of mind that your cloud investment will be aligned with the return you seek. We can be counted on to bring our industry experience and real-world best practices to operate Azure environments.
Our methodology involves 4 steps:
Assess > Migrate > Re-Platform > Operate
Moving into the cloud is not a one time event. With every customer engagement, we deliver a structured approach as follows:
Assess:
Rely on our team to map your existing environment to a corresponding Azure cloud.
Migrate:
Easily move from your existing environment to a public or private Azure cloud.
Re-platform:
Understand how to transform your applications to better take advantage of Azure capabilities.
Operate:
Our team actively manages all maintenance and optimization to keep your environment running at its best.
Azure Environments Managed by Atmosera
We help you determine how best to run your applications in the deployment best suited for their unique requirements.
24
Regions
‘+$15B
Invested by Microsoft
6
Regions for US Government
The Power of Microsoft’s
Hybrid Platform
Microsoft is the only hyperscaler to offer a true hybrid solution with the flexibility to run applications using private or public clouds — and the ability to move between them.
Atmosera has the skills and expertise necessary to help you architect, deploy and operate integrated hybrid cloud solutions based on Microsoft’s Azure stack and microservices.
Azure Certified for
Hybrid Cloud
Atmosera has developed core competencies and intellectual property to take full advantage of all Azure has to offer.
All Atmosera Azure services receive the “Azure Certified for Hybrid Cloud” designation which confirms it passed Microsoft’s rigorous validation process under the Cloud OS Network (COSN) program. Customers benefit from knowing that their solution was carefully planned and executed using best practices and proven methods.
Not Sure How to Get Started?
Atmosera Azure pre-configured solutions can help.
We find many customers are not sure how to get started.
We developed a series of pre-configured solutions around specific use cases common for many customers.
You can take advantage of thoroughly tested and optimized solutions and accelerate the return on your cloud investment.