Validation

Angular 2 Template Driven Validation

Last week’s post covered model driven validation in Angular 2 and this week I will be looking at template driven validation. Template driven validation provides a simplified way to add validation without the need to directly use a control group. This is a great way to get up and running for simple form cases, and maybe more complex ones as well. I haven’t hit a case yet that wouldn’t work with either validation style.

Building a Template Form with Validation

I started with a simple form that contains labels and inputs for entering a name and email address that are bound to corresponding values in the associated model.

<form>
   <div class="form-group">
     <label for="name">Name</label>
     <input type="text" class="form-control" [(ngModel)]="name">
   </div>
   <div class="form-group">
     <label for="name">Email</label>
     <input type="text" class="form-control" [(ngModel)]="email">
   </div>
</form>

The next example is the same form with validation added.

<form #contactForm="ngForm">
   <div class="form-group">
     <label for="name">Name</label>
     <input type="text" class="form-control" ngControl="name" #nameControl="ngForm" [(ngModel)]="name" required minlength="3">
     <div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.required">Name is required</div>
     <div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.minlength">Min Length</div>
   </div>
   <div class="form-group">
     <label for="name">Email</label>
     <input type="text" class="form-control" ngControl="email" #emailControl="ngForm" [(ngModel)]="email" required>
     <div [hidden]="emailControl.valid || !emailControl.errors || !emailControl.errors.required">Email is required</div>
   </div>
</form>

The first change you will notice is that the form now has a name assigned using #contactForm=”ngForm”. In this case the name is not used, but it could be used to disable a submit button if any of the inputs the form contained didn’t have valid values. I am sure there are a lot more use cases as well.

On the inputs that need validation a controls name is assigned via ngControl=”name” and a name is assigned using #nameControl=”ngForm”. I had some trouble withe assigning names to my inputs at first I keep getting the following.

EXCEPTION: Cannot assign to a reference or variable!

The cause of the issue was that I was trying to use #name for the control name which was already a property on the model. Once I changed to #nameControl all worked fine.

For the input for name above required minlength=”3″ tells the Angular form that the input is required and must be at least three characters in length.

Displaying Validation

For the name input you can see that it has two divs used to show specific messages based on which validation condition failed.

<div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.required">Name is required</div>
<div [hidden]="nameControl.valid || !nameControl.errors || !nameControl.errors.minlength">Min Length</div>

I am not sure why, but when using the template style validation I had to check !nameControl.errors in addition to the specific error like !nameControl.errors.required or I would get an exception when the page tried to load. If your control doesn’t have more than a single validation then nameControl.valid would be a sufficient condition for showing validation messages.

Custom Validators

I am going to use the same email validator from last week with a few changes so can be used from a template. The following is the full class.

import {Control, NG_VALIDATORS, Validator} from '@angular/common';
import {Directive, Provider, forwardRef} from '@angular/core';

const EMAIL_VALIDATOR = new Provider(NG_VALIDATORS, { useExisting: forwardRef(() => EmailValidator), multi: true });

@Directive({
    selector: '[emailValidator]',
    providers: [EMAIL_VALIDATOR]
})
export class EmailValidator implements Validator {
    validate(control: Control): {[key: string]: any} {
        const emailRegexp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
        if (control.value !== null && control.value !== "" && (control.value.length <= 5 || !emailRegexp.test(control.value))) {
            return { "email": true };
        }
        return null;
    }
}

The biggest difference is the @Directive decorator. The selector is the attribute that will be used to mark that an input needs to pass the specified validation. I am not 100% sure of the specifics of the provider, but the above works. This is another topic I need to explore more.

Using a Custom Validator

First in the model the validator must be imported.

import {EmailValidator} from './email-validator';

Then the validator needs to be added to the directives section of the @Component decorator.

@Component({
    selector: 'contact-detail',
    templateUrl: 'contact.detail.html',
    directives: [
        EmailValidator
    ],
    providers: [
        HTTP_PROVIDERS
    ]
})

To use in the view just add the emailValidator selector to the proper input.

<input type="text" class="form-control" ngControl="email" #emailControl="ngForm" [(ngModel)]="email" required emailValidator>

Finally add a div to display the error.

<div [hidden]="emailControl.valid || !emailControl.errors || !emailControl.errors.email">Email is invalid</div>

Wrapping Up

Using template driven validation you can quickly get a form validated without having to make changes outside of your template (unless you are using a custom validator). Angular 2 offers a lot of options when it comes to validation and where it should be put.

Angular 2 Template Driven Validation Read More »

Angular 2 Model Driven Validation

In this post a couple of weeks ago I covered Aurelia’s new validation plugin and I thought it would be good to see what Angular 2 has to offer validation wise. Angular’s offering is vastly different that Aurelia. Angular can use model driven or template driven validations. This post is going to look at the model driven style.

Forms

Angular forms is the framework’s way to handle groups of data entry that need support for data binding and validation among other things.

Building a Form with Validation

The first step to building a model driven form is import the classes that will be needed.

import {FormBuilder, ControlGroup, Validators} from '@angular/common';

Next add a variable for control group and setup the control group in the constructor of the class.

public contactForm: ControlGroup;

constructor(formBuilder: FormBuilder) {
    this.contactForm = formBuilder.group({
        name: ["", Validators.compose([Validators.required, Validators.minLength(3)])],
        email: ["", Validators.required]
    });
}

The above uses FormBuilder to define a name property that is required with a minimum length of three characters and an email property that is required. Later in the post I will add better email validation via customer validator.

Angular 2 only comes with required, minimum length, max length and pattern (match given regex) validators out of the box. Thankfully custom validators are pretty easy to implement.

Using a From with a View

Now that the form is setup the view needs to utilize it. The following is the code form the view.

<form class="form-horizontal" [ngFormModel]="contactForm">
  <div class="form-group">
      <label class="control-label">Name</label>
      <input type="text" ngControl="name" #name="ngForm" class="form-control">
      <div [hidden]="name.valid || name.pristine || !name.errors.required">Required</div>
      <div [hidden]="name.valid || name.pristine || !name.errors.minlength">Min Length</div>
  </div>
  <div class="form-group">
      <label class="control-label">Email</label>
      <input type="email" ngControl="email" #email="ngForm" class="form-control">
      <div [hidden]="email.valid || email.pristine || !email.errors.required">Required</div>
  </div>
</form>

First notice in the form tag [ngFormModel]=”contactForm” is used to bind the form to the control group crated in the model.

Instead of [(ngModel)]=”name” we use ngControl=”name” to bind the input box to the name control in the control group that was crated using the form builder above. #name=”ngForm” defines name as a variable that can be used later.

<div [hidden]=”name.valid || name.pristine || !name.errors.required”>Required</div>  is used to display validation errors to the user. This code is just saying to hide the div if name is valid or pristine (not changed by the user)  or if the validation error is not because the field is required. While this style works I much prefer Aurelia as it handles the extra work needed to automatically display validation errors.

Custom Validators

As I mention above I am going to show you a custom validator that can be used to better handle email validation. Most of this validation I found in a search but unfortunately I forgot to save the URL so I can’t link to the exact source. The following is the complete code for a custom email validator.

import {Control} from '@angular/common';

export class EmailValidator {
    static email(control: Control) {
        const emailRegexp = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;

        if (control.value !== "" && (control.value.length <= 5 || !emailRegexp.test(control.value))) {
            return { "email": true };
        }

        return null;
    }
}

Note that returning null means that validation passed.

Using a Custom Validator in a Model

First the custom validator needs to be imported.

import {EmailValidator} from './email.validator';

Now the validator can be used in the classes form builder.

this.contactForm = formBuilder.group({
    name: ["", Validators.compose([Validators.required, Validators.minLength(3)])],
    email: ["", Validators.compose([Validators.required, EmailValidator.email])]
});

Notices that the email control is now using Validators.compose which is used to apply multiple validations to a single control.

Using a Custom Validator in a View

Now the view just has to be changed to show the user that the reason for the failed validation is an invalid email address.

<div class="form-group">
    <label class="control-label">Email</label>
    <input type="email" ngControl="email" #email="ngForm" class="form-control">
    <div [hidden]="email.valid || email.pristine || !email.errors.required">Required</div>
    <div [hidden]="email.valid || email.pristine || !email.errors.email">Invalid address</div>
</div>

Note that the entry in errors will match the return value from the custom validator. I had issues trying to use the minimum length validator because I was trying to use minLength instead of minlength. If you are having trouble with validation message showing up that would be the first thing to check.

Wrapping Up

That covers the basics of model driven validation in Angular 2. Be on the look out for a post in the future that covers the same concepts but using a template driven approach. I also wanted to point out this post by Pascal Precht and this post by David Den Toom which helped me a lot in writing this post.

Angular 2 Model Driven Validation Read More »

Aurelia Validation the Replacement Library

The post from last week on Aurelia Validation is now useless as this blog post from the Aurelia team states validation has been completely overhauled. This post is going to feel very similar to last weeks, but using the new validation library. The details on adding a main.js will match exactly from last weeks post, but is being included to make sure the examples in this post are complete.

Installation

Validation in Aurelia is provided using a plugin in which must be installed before being used. Make sure you have npm and jspm installed. For more information on getting up and running with Aurelia check out this post that will guide you through the process and links to a Github repo with matching code.

From the console execute this command jspm install aurelia-validatejs to download and install the files needed for validation.

In order to load plugins a named Aurelia-App is need to allow more control of the bootstrapping process. In Views/Home/Aurelia.cshtml make the following change.

Before:
<div aurelia-app>

After:
<div aurelia-app="main">

Now that this Aurelia application has been named “main” Aurelia will look for a matching main.js file and call its configure function during the bootstrapping process. Here is the main.js I am using. Note that the validation plugin in is being loaded. For my project main.js is located in wwwroot/Aurelia.

export function configure(aurelia) {
    aurelia.use
      .standardConfiguration()
      .developmentLogging()
      .pluginin('aurelia-validatejs');

    aurelia.start().then(() => aurelia.setRoot());
}

Usage

The first step in using validation is to add its import to the top of the class that will be using it.

import {ValidationEngine, Validator, required, email} from 'aurelia-validatejs';

Next setup the validation rules using decorators and inject validation via the constructor and set up the validation rules. The plugin also supports a fluent style of adding validation to property, but I ran into issues getting it working so I just stuck with decorators for this post.

static inject() { return [Validator]; }

@required 
Name = '';

@required 
@email 
Email = '';

constructor(validator) {
    this.reporter = ValidationEngine.getValidationReporter(this);
}

The above makes sure that Name is required and that email is required and conforms to the rule of what an email address. This is only a small sample of the built in validations provided by check out this page for a sample of the other provided validations.

Show Validation Failures in a View

The validation plugin in provides a way to display validation messages with the appropriate field. The following is a part of a view that contains name and email address that are bound to the properties from above.

<form>
    <div class="form-group">
        <label>Name</label>
        <input type="text" value.bind="Name & validate" class="form-control">
    </div>
    <div class="form-group">
        <label>Email</label>
        <input type="email" value.bind="Email & validate" class="form-control">
    </div>
</form>

By adding & validate as part of the value bind statement the plug in knows where the validation messages show be shown.

Warning

If you run into a “Cannot read property ‘bindingContext’ of null” when trying to implement the new validation plugin make sure your class constructor contains:

this.reporter = ValidationEngine.getValidationReporter(this);

From what I can tell this requirement will be temporary. This is an alpha release of the overhaul and has a few rough edges such as the binding context gotcha and the fluent API issues I mentioned above. With the track record of the Aurelia team I am sure the issues I hit will be resolved quickly.

Aurelia Validation the Replacement Library Read More »

Aurelia Validation

Update: this post is now out of date an updated version can be found here.

Client side validation is an important part of client side frameworks and can provide users with immediate feedback as well as check away to stop before posting data to the server. This post is going to look at validation with in Aurelia.

Installation

Validation in Aurelia is provided using a plugin in which must be installed before being used. Make sure you have npm and jspm installed. For more information on getting up and running with Aurelia check out this post that will guide you through the process and links to a Github repo with matching code.

From the console execute this command jspm install aurelia-validation to download and install the files needed for validation.

In order to load plugins a named Aurelia-App is need to allow more control of the bootstrapping process. In Views/Home/Aurelia.cshtml make the following change.

Before:
<div aurelia-app>

After:
<div aurelia-app="main">

Now that this Aurelia application has been named “main” Aurelia will look for a matching main.js file and call its configure function during the bootstrapping process. Here is the main.js I am using. Note that the validation plugin in is being loaded. For my project main.js is located in wwwroot/Aurelia.

export function configure(aurelia) {
    aurelia.use
      .standardConfiguration()
      .developmentLogging()
      .pluginin('aurelia-validation');

    aurelia.start().then(a => a.setRoot());
}

Usage

The first step in using validation is to add its import to the top of the class that will be using it.

import {Validation} from 'aurelia-validation';

Next the inject validation via the constructor and set up the validation rules.

static inject() { return [Validation]; }
constructor(validation) {
    this.Name = '';
    this.Email = '';
    this.validation = validation.on(this)
        .ensure('Name').isNotEmpty().hasLengthBetween(3, 50)
        .ensure('Email').isNotEmpty().isEmail();
}

The above makes sure that Name is required and has a length between 3 and 50 characters and that email is required and conforms to the rule of what an email address contain. This is only a small sample of the built in validations provided by check out this page for a demo of the other provided validations.

Show Validation Failures in a View

The validation plugin in provides a custom attribute that will loop all nested child elements and display validation messages with the appropriate field. The following is a part of a view that contains name and email address that are bound to the properties from above.

<form role="form" validate.bind="validation">
    <div class="form-group">
        <label>Name</label>
        <input type="text" value.bind="Name"placeholder="name" class="form-control">
    </div>
    <div class="form-group">
        <label>Email</label>
        <input type="email" value.bind="Email" placeholder="email" class="form-control">
    </div>
</form>

You can see that the validate custom attribute is bound to the validation property of the class defined above. Since the controls are in a form group the validation plugin is able to infer where bound field is show validation errors in the appropriate area. Check out this page for more details on visualization of validation errors. The default visualization is based on Twitter Bootstrap, but that can be changed the details of which can be found here.

Issues

Unfortunately I ran into some problems with trying to implement validation in a more complex situation dealing with an object that is replaced via binding. I doubt this is a problem with Aurelia. If anyone has any experience with validation on objects that are fully replaced via binding please let me know. Expect a blog post once I get my issue figured out.

Aurelia Validation Read More »

ASP.NET Core User Options and Custom Validators

Last week’s post looked at ASP.NET Core’s password options and custom validators and this week I am going to cover the built-in user options as well as writing custom user validators.

User Options

Just as last week I am going to start off showing the default registration of identity with ASP.NET Core’s built in dependency injection which is found in the ConfigureServices function of the Startup class.

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

Using the same overload of  AddIdentity  as last week which accepts an IdentityOptions there are two built-in user options for AllowedUserNameCharacters and RequireUniqueEmail. The following example shows both options.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
     options.User.AllowedUserNameCharacters = "abcom@.";
     options.User.RequireUniqueEmail = true;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

When using AllowedUserNameCharacters make sure to include all the characters needed to make up a valid email address. My first test I left out the @ symbol and couldn’t create an account.

Custom User Validtors

The above built-in user validation options are pretty limited, but this just reflects that validation on users has standardized on email addresses for the most part. In the case that you require more specialized user validation the AddUserValidator extension to IdentityBuilder can be used in the AddIdentity chain to add custom validation based on the IUserValidator interface.

The only function on this interface is ValidateAsync. The following is an example user validator that limits users to a specific set of domains. For this example the domains are part of the validator class, but if this is something actually needed I would recommend storing the domains in a different way such as in a database or configuration.

public class UserDomainValidator<TUser> : IUserValidator<TUser> 
       where TUser : IdentityUser
{
    private readonly List<string> _allowedDomains = new List<string>
    {
        "elanderson.net",
        "test.com"
    };

    public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, 
                                              TUser user)
    {
        if (_allowedDomains.Any(allowed => 
               user.Email.EndsWith(allowed, StringComparison.CurrentCultureIgnoreCase)))
        {
            return Task.FromResult(IdentityResult.Success);
        }

        return Task.FromResult(
                 IdentityResult.Failed(new IdentityError
                 {
                     Code = "InvalidDomain",
                     Description = "Domain is invalid."
                 }));
    }
}

If the user’s email address doesn’t end with one of the domains in _allowedDomains the user will fail validation and the reason will be added to the list of identity validation errors which end up being show to the user. This validation is on the server side.

The following is what identity registration looks like with the user options and custom user validation.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.User.AllowedUserNameCharacters = "abccom.";
    options.User.RequireUniqueEmail = true;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddUserValidator<UserDomainValidator<ApplicationUser>>();

Wrapping Up

Following the above you can see how easy it to add any custom user validation that might be needed. It is also nice that adding custom validation on user and passwords are very similar.

ASP.NET Core User Options and Custom Validators Read More »

ASP.NET Core Password Options and Custom Validators

ASP.NET Core provides a lot of identity feature out of the box when individual user accounts is selected during project creation. Using the default settings a user’s password is required to be at least 6 characters and contain a number, a lower case letter, an uppercase letter and a special character. This post is going to cover changing the the above options as well as creating custom validators.

Password Options

The following is the default registration of identity in the ConfigureServices  function of the Startup  class with the default settings mentioned above.

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

AddIdentity  can accept options part of which allows control over the basic characteristics of what is required for user passwords. Here is the same AddIdentity but with all the options for passwords listed.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

All the options do what you would expect. One thing to note is if you change the required length by setting options.Password.RequiredLength then the new setting will only be validated on post back to the server, which is the case of most password validation anyway, but for pre-post validation on length then the string length data annotation needs to be updated on RegisterViewModel.Password, ResetPasswordViewModel.Password, ChangePasswordViewModel.NewPassword and SetPasswordViewModel.NewPassword.

Custom Password Validators

The above is great for changing simple aspects of password validation, but we all know password rules for organizations are not always simple enough to be covered by the above. Thankfully Microsoft has provided the AddPasswordValidator  extension method to the IdentityBuilder class which is what is returned by AddIdentity.

AddPasswordValidator takes a type that implements IPasswordValidator. The custom validator only has to implement the  ValidateAsync defined by IPasswordValidator. The following validator checks to make sure that all the characters of the password are not the same and returns an IdentityResult based on the conditions passing. Forgive the contrived example, but I wanted to keep the class as simple as possible.

public class SameCharacterPasswordValidator<TUser>: IPasswordValidator<TUser> 
       where TUser : class
{
    public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, 
                                              TUser user, 
                                              string password)
    {
        return Task.FromResult(password.Distinct().Count() == 1 ? 
            IdentityResult.Failed(new IdentityError
            {
                Code = "SameChar",
                Description = "Passwords cannot be all the same character."
            }) : 
            IdentityResult.Success);
    }
}

If validation failed is the result then is added to the list of validation messages the user sees just like with the built in password validations.

Here is registration of identity with the custom password validation which is on the last line.

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonLetterOrDigit = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddPasswordValidator<SameCharacterPasswordValidator<ApplicationUser>>();

Potential Use

Imagine you have a requirement to make sure a user doesn’t reuse the same password for a period of time. This would be a great place for a custom password validator. You could use dependency injection to get reference to a history of password hashes and use that to verify the user is not repeating the same password. Of course would have to first write the password hash history.

ASP.NET Core Password Options and Custom Validators Read More »

Multi-property Custom Validation Attributes

I am going to expand on last week’s Simple Custom Validation Attributes with custom validation attributes that need to look at more than a single property of a model. Again using the contact application example, lets say that if a contact has a country of USA then state and zip code are required.

As before we have class which inherits from ValidationAttribute. IsValid is still overridden, but it is a different overload than the previous example that provides access to the ValidationContext, which in our case is the contact model that is being validated.

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;

public class ValidCountryRequired : ValidationAttribute
{
    private readonly string _countryProperty;
    private readonly string[] _requriedByCountries;

    public ValidCountryRequired(string countryProperty,
                                string[] requriedByCountries)
    {
        _countryProperty = countryProperty;
        _requriedByCountries = requriedByCountries;
    }

    protected override ValidationResult IsValid(object value,
                                                ValidationContext context)
    {
        PropertyInfo propertyInfo;
        propertyInfo = context.ObjectType.GetProperty(_countryProperty);
        if (propertyInfo == null)
        {
            return new ValidationResult(_countryProperty +
                                        " does not exist");
        }

        var country = propertyInfo.GetValue(context.ObjectInstance, null);

        if (_requriedByCountries.Contains(country.ToString()) &&
            (value == null ||
             String.IsNullOrWhiteSpace(value.ToString())))
        {
            return new ValidationResult(context.DisplayName +
                                        " is requried for contacts from " +
                                        country);
        }

        return null;
    }
}

For this example I have added a constructor that takes the name of the country property in the model being validated and a string array of the countries that need to make sure the state and zip code are filled in. Both parameters are stored in class level variables for use in the IsValid function.

The IsValid function is still where all the work takes place. The overload of IsValid we are working with provides the value of the property being validated and the validation context that validation is running for. The validation context will allow us to access other properties on the model being validated.

The first step to checking a different property than the one being validated is to get the property info from the validation context by using context.ObjectType.GetProperty and passing the property name that was passed in via the constructor. If GetProperty returns null then the context did not contain the property that was expected. In this case a new ValidationResult is returned with a message that the expected country property was not found.

Using the property info for the country property we can call GetValue with context.ObjectInstance to get the contact’s country. If that country is found in the string array of countries that require the property being validated then a check is run to make sure the property has a value and is not blank.

If the property does not have a value then a new ValidationResult is returned with an error message. If the property does have a value then null is returned indicating that the property is valid.

Example usage from my contact model:

[ValidCountryRequired("Country", new[] { "USA" })]
public string State { get; set; }
[Display(Name = "Zip Code")]
[ValidCountryRequired("Country", new[] { "USA" })]
public string ZipCode { get; set; }

One other thing to note is the usage of context.DisplayName when creating the ValidationResult. By using display name in the message the ZipCode property will show as “Zip Code” in the message returned.

Multi-property Custom Validation Attributes Read More »

Simple Custom Validation Attributes

Last week I did an overview of  Data Annotations. This week I am going to expand on data annotations by giving an example of a very simple custom validation attribute.

Sticking with my contact application theme lets say that I only wanted to allow contacts from a very small list of countries. The .Net framework does not have a built in validation attribute to cover this scenario which means I would need to create my own custom validation attribute to fill this need.

To create a custom validation attribute all you need is a class that inherits from ValidationAttribute and overrides the IsValid function.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class ValidCountry : ValidationAttribute
{
    private readonly List<string> validCountries = new List<string>
    {
        "USA",
        "Canada",
        "Mexico"
    }; 

    public override bool IsValid(object value)
    {
        return value != null &&
               !validCountries.Contains((string)value);
    }
}

When validation for a property is performed the IsValid function of all the property’s validation attributes are run. The IsValid function is called with the value of the property being validated which will have to be cast to the type needed for validation. In my country example value is being cast to string and used see if the value is found in a list of valid countries.

Any property with the ValidCountry attribute would not validate unless the property was set to USA, Canada or Mexico. This is a contrived example, but it does give you an idea of how easy it is to add your own custom validation attributes.

Simple Custom Validation Attributes Read More »

Data Annotations

Validation via data annotations in .NET is a great feature that is simple to implement. Here is an example model class that is using data annotations.

using System.ComponentModel.DataAnnotations;

namespace Contacts.Models
{
    public class Contact
    {
        [Required]
        [StringLength(50, MinimumLength = 4)]
        public string Name { get; set; }
        [StringLength(2)]
        public string State { get; set; }
        [Display(Name = "Zip Code")]
        [StringLength(10)]
        public string ZipCode { get; set; }
    }
}

First step in using data annotations is to add a using statement for the System.ComponentModel.DataAnnotations namespace. This namespace allows you to add validation attributes to the properties that require validation and contains helper classes to run validate on attributed models.

In the example above Required, StringLength and Display are all validation attributes. For the most part the attributes are self-explanatory, but be aware most attributes also have options to give you more control of the validation. For example required attribute has an AllowEmptyStrings property that if set to true will allow an empty string to pass validation. String length is another example which has options for minimum and maximum lengths for the property being validated.

This is just a small sample of the built-in attributes that exist. Other built-in attributes range  from credit card and email address validation to file extension and range validation. If a built-in validation does not meet your needs then a custom attribute a can be created by deriving from ValidationAttribue.

MVC has a lot of great functionality built around data annotations. For instance as long as a client has JavaScript turned a form will not allow submission until the model passes all the validation conditions. On the server-side inside of a controller to run validation all it takes is to run ModelState.IsValid.

With winforms the story is not quite as simple, but still pretty straight forward. The following is a simple example of calling validation on a model.

private void ValidationExample()
{
    var contact = new Contact { Name = "Bob", State = "TN" };

    var context = new ValidationContext(contact);
    var errors = new List<ValidationResult>();

    if (!Validator.TryValidateObject(contact, context, errors))
    {
        foreach (ValidationResult result in errors)
        {
            //act on error
        }
    }
}

Validator.TryValidateObject takes the model to be validated, a validation context (created with the model to validate) and an empty list of type ValidationResult. The function call returns false if any properties fail validation. In the example above the validation would fail since name only contains three characters the minimum length is set to four characters.

Data Annotations Read More »