Silverlight and WCF RIA Services (6–Validation)

One of the strengths of WCF RIA Services is in its capabilities around the application of common validation logic on both the client tier and the service tier.

If I take the simplest route to create a new Silverlight+RIA Services project as in File | New Project;

image

and then make sure that I “switch on” RIA Services;

image

and then add a new Entity Data Model for my Northwind database to the generated web application project;

image

generating that model from the database with just a couple of tables into it (Categories and Products);

image

giving me a nice small model;

image

and then basing a Domain Service on that model, using Visual Studio to add another new item (Domain Service class) into my web application project;

image

and in the wizard that pops up to generate the skeleton bits of service-side code for me I enable editing for my Product entity set but not for my Category entity set and I also ask Visual Studio to generate metadata classes for me as in the dialog below;

image

then, with all that done, Visual studio will generate for me service-side classes relating to my DomainService (ProductService) and it will also generate the metadata classes that I asked for which look like;

  [MetadataTypeAttribute(typeof(Category.CategoryMetadata))]
  public partial class Category
  {

    // This class allows you to attach custom attributes to properties
    // of the Category class.
    //
    internal sealed class CategoryMetadata
    {

      // Metadata classes are not meant to be instantiated.
      private CategoryMetadata()
      {
      }

      public int CategoryID { get; set; }

      public string CategoryName { get; set; }

      public string Description { get; set; }

      public byte[] Picture { get; set; }

      public EntityCollection<Product> Products { get; set; }
    }
  }

  // The MetadataTypeAttribute identifies ProductMetadata as the class
  // that carries additional metadata for the Product class.
  [MetadataTypeAttribute(typeof(Product.ProductMetadata))]
  public partial class Product
  {

    // This class allows you to attach custom attributes to properties
    // of the Product class.
    //
    // For example, the following marks the Xyz property as a
    // required property and specifies the format for valid values:
    internal sealed class ProductMetadata
    {

      // Metadata classes are not meant to be instantiated.
      private ProductMetadata()
      {
      }

      public Category Category { get; set; }

      public Nullable<int> CategoryID { get; set; }

      public bool Discontinued { get; set; }

      public int ProductID { get; set; }

      public string ProductName { get; set; }

      public string QuantityPerUnit { get; set; }

      public Nullable<short> ReorderLevel { get; set; }

      public Nullable<int> SupplierID { get; set; }

      public Nullable<decimal> UnitPrice { get; set; }

      public Nullable<short> UnitsInStock { get; set; }

      public Nullable<short> UnitsOnOrder { get; set; }
    }
  }

If you’ve not looked at these metadata classes before then they show up in a bunch of places in use in the modern .NET Framework.

They reside in System.ComponentModel.DataAnnotations where there are a number of annotations (i.e. .NET attributes) that you can apply to types in order to state their declarative validation requirements. So, something like;

  public class MyEntity
  {
    [Required]
    [Range(1, 1000000)]
    public int MyIdentifier { get; set; }
  }

states that my MyIdentifier property is both required and that it has a range of 1 to 1 million.

Now, that works well but it’s impossible to add these kinds of declarative attributes to a type if either;

  • you don’t own the type and so don’t have the source for it to add them to
  • the type gets (re)generated by a tool so you can’t keep adding the attributes over and over

and so the MetadataTypeAttribute which we see in the RIA Services generated code up above is being used to define a class which contributes this kind of metadata to another class. The “metadata” (or “buddy”) class.

In our particular example, the Product class has a MetadataType attribute applied to it which states that the generated nested class Product.ProductMetadata can also contribute metadata to the Product class itself which is being generated for me by the Entity Framework generation process.

Following that through, I can apply a validation attribute such as this Range attribute below to the ProductMetadata property called UnitsOnOrder and the implication is that I want to apply that Range attribute to the UnitsOnOrder property of Product;

internal sealed class ProductMetadata
{
  // ... 

  [Range(0, 100)]
  public Nullable<short> UnitsOnOrder { get; set; }
}

There are a number of pre-canned validation attributes in System.ComponentModel.DataAnnotations such as;

  • Range
  • Required
  • RegularExpression
  • StringLength
  • etc.

all of which are derived from ValidationAttribute.

Now, with my Range attribute applied on the service-side, let’s imagine that I have some client code that tries to create a new product like this sketched client-side code below does;

      ProductContext context = new ProductContext();

      Product newProduct = new Product()
      {
        CategoryID = 1, // hard code
        SupplierID = 1, // hard code
        ProductName = "Test Product",
        UnitsOnOrder = 101
      };

      context.Products.Add(newProduct);

      context.SubmitChanges(
        submitOperation =>
        {
          if (submitOperation.HasError)
          {
            MessageBox.Show(submitOperation.Error.Message);
          }
        }, 
        null);

Attempting to insert an invalid product like this ( invalid because of the 101 units on order ) is going to result in errors being returned from the call to SubmitChanges and running the code gives me;

image

In this case, the invalid data never made it to the service. To me, there’s 3 different aspects to how this invalid data can be “caught”;

  1. It can be caught on the client when we call SubmitChanges()
  2. It can be caught by the service when a SubmitChanges() call arrives on the service-side
  3. It can be caught on the client long before we ever call SubmitChanges()

Validation Around SubmitChanges()

My attempt to call SubmitChanges() never left the client side because a ChangeSet was constructed ( containing my single insert of a single invalid Product ) and then that ChangeSet was validated and the failed validation result is immediately returned to the client rather than wasting a trip to the service.

What if I apply some validation logic that’s a little more custom?

As a starting example, I can replace my Range attribute with a CustomValidation attribute like this one;

  [MetadataTypeAttribute(typeof(Product.ProductMetadata))]
  public partial class Product
  {
    internal sealed class ProductMetadata
    {      
      // snip...

      [CustomValidation(typeof(MyValidator), "ValidateUnitsOnOrder")]
      public Nullable<short> UnitsOnOrder { get; set; }
    }
  }

Now, I have a choice about how I build the type MyValidator on the service-side. I can either put it into a regular code file and, in that case, the validation will only be applied on the service-side. So, if I write MyValidator as;

  public class MyValidator
  {
    public static ValidationResult ValidateUnitsOnOrder(short value, ValidationContext context)
    {
      ValidationResult result =
        (value >= 0.0 && value <= 100.0) ? 
          ValidationResult.Success :
          new ValidationResult("UnitsOnOrder is out of range 0 to 100");

      return (result);
    }
  }

and then re-run my original client side code against this then the validation will not happen on the client because the code generation process has not copied the MyValidator type to the client and nor has it generated the CustomValidation attribute on the Product’s UnitsOnOrder property.

Consequently, the call to SubmitChanges() will cross the network and rely on the service-side to do the validation.

When that call reaches the service-side, my DomainService (ProductService) will get instantiated and then it will go through its lifecycle (see previous post) of;

Initialize->Submit->AuthorizeChangeSet->ValidateChangeSet

and when my ChangeSet hits that ValidateChangeSet() method, the base class implementation will essentially use the System.ComponentModel.DataAnnotations.Validator class to validate the entities which in my case will cause a validation failure.

Once again the end result is that I get an error back to my call to SubmitChanges but this one actually came from the service-side unlike the previous example where there was no need to invoke the service.

If I want my new custom validation to occur down on the client, I can easily arrange for the MyValidator type to be shared with the client. I just rename its source-code file to include a .shared as in;

image

and now the code generation process will work differently and make sure that on the client side two additional things happen;

  1. The type MyValidator is copied to the client side and is built into the application there.
  2. The same CustomValidation attribute will also be applied to the UnitsOnOrder of the Product entity

so now now when I run my client-side code I’ll get validation once again on the client and the service-side will never be invoked.

There are other ways of doing custom validation. On the service-side, I could alter the definition of my Product metadata class so that it looked something like;

  [MetadataTypeAttribute(typeof(Product.ProductMetadata))]
  [CustomValidation(typeof(MyValidator), "ValidateProduct")]
  public partial class Product
  {
    internal sealed class ProductMetadata
    {
	// snip - no attribute now on UnitsOnOrder

    }
  }

and then I can change the definition of the MyValidator type;

public class MyValidator
  {
    public static ValidationResult ValidateProduct(Product product, 
      ValidationContext context)
    {
      ValidationResult result = ValidationResult.Success;

      if ((product.UnitsOnOrder <= 0.0) || (product.UnitsOnOrder >= 100.0))
      {
        // we can check more than just the one field here
        result = product.UnitsInStock > 10.0 ?
          new ValidationResult("Too many products in stock") :
          ValidationResult.Success;
      }
      return (result);
    }
  }

in order to validate the whole Product instance rather than just one property on it. As the ( rather contrived ) example shows, this lets me do cross-field validation.

Once again, if I place this into a file with a .shared.cs extension on it then it will run both client and service-side whereas if I place it in a file without a .shared.cs extension then it will only run client side.

If I only want the validation to run service-side then another option is to remove the CustomValidation attribute from my Product class and, instead, modify my DomainService itself.

If I find my ProductService and modify its InsertProduct method to include a CustomValidation attribute as below;

  [EnableClientAccess()]
  public class ProductService : LinqToEntitiesDomainService<NorthwindEntities>
  {
    //snip

    [CustomValidation(typeof(MyValidator), "ValidateProduct")]
    public void InsertProduct(Product product)
    {
      if ((product.EntityState != EntityState.Detached))
      {
        this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
      }
      else
      {
        this.ObjectContext.Products.AddObject(product);
      }
    }

    // snip
  }

then I get that same custom validation of my Product instance but, in this case, that’s only on the service-side and it’s only for Insert operations because that’s the only place where I have applied the attribute. Clearly, I could also apply it to Update and Delete or have different validators plugged in on those operations if I wanted that flexibility.

Another option about applying custom validation is to build my own class derived from ValidationAttribute in order to have my own library of custom validation attributes. As an again, contrived, example I might build an attribute such as this one which makes a fairly weak attempt to ensure that a numeric value is an even number;

public class EvenNumberAttribute : ValidationAttribute
  {
    // This is interesting. On the service-side I could override IsValid as below 
    // (albeit with hacky code).
    //
    // However, this override doesn't seem to exist in the Silverlight libraries
    // so if I share this code with the client then it won't compile there.
    // Hence, I choose to override the "other" IsValid method as that exists
    // in both places.
 
    //public override bool IsValid(object value)
    //{
    //  return ((int)value % 2 == 0);
    //}

    protected override ValidationResult IsValid(object value, 
      ValidationContext validationContext)
    {
      // one line of code disguising lots of implementation problems
      return ((short)value % 2 == 0 ?
        ValidationResult.Success :
        new ValidationResult("Value must be even"));
    }
  }

and I could then apply that on my ProductMetadata class to something like UnitsOnOrder;

  [MetadataTypeAttribute(typeof(Product.ProductMetadata))]  
  public partial class Product
  {

    internal sealed class ProductMetadata
    {
      // snip
   
      [EvenNumber]
      public Nullable<short> UnitsOnOrder { get; set; }
    }
  }

and, once again, if I put the code for my EvenNumberAttribute into a file with a .shared.cs extension then it will be run on both the client and the service side whereas if I don’t have a .shared.cs extension then it will only apply on the service side. 

Validation Before SubmitChanges()

If I revert back to my original setup and fragment of client-side code, reproduced below, which was being validated by a model which had a Range attribute on the UnitsOnOrder property;

      ProductContext context = new ProductContext();

      Product newProduct = new Product()
      {
        CategoryID = 1, // hard code
        SupplierID = 1, // hard code
        ProductName = "Test Product",
        UnitsOnOrder = 101
      };

      context.Products.Add(newProduct);

      context.SubmitChanges(
        submitOperation =>
        {
          if (submitOperation.HasError)
          {
            MessageBox.Show(submitOperation.Error.Message);
          }
        }, 
        null);

then it’s worth nothing that the Product that I create and populate is invalid from the point at which I set the UnitsOnOrder to a value of 101 and the entity itself “knows” that it is invalid from that point.

This is because the client-side generated Product class derives from Entity and is code-generated such that every property setter calls the base class ValidateProperty() method every time the property value changes.

What does ValidateProperty do? Ultimately it ends up in a call to Validator.ValidateProperty from System.ComponentModel.DataAnnotations and it’s that method which will perform the validation based on the validation attributes that it “sees”.

Consequently, as soon as the call to the UnitsOnOrder property setter has completed, the Entity will already be marked as invalid and I could have checked for validation results by doing something like;

    Product newProduct = new Product()
      {
        CategoryID = 1, // hard code
        SupplierID = 1, // hard code
        ProductName = "Test Product",
        UnitsOnOrder = 101
      };

      // is my entity already in error?
      if ((newProduct.ValidationErrors != null) &&
        (newProduct.ValidationErrors.Count > 0))
      {
        foreach (ValidationResult result in newProduct.ValidationErrors)
        {
          string error = string.Format("Property [{0}] has problem [{1}]",
            result.MemberNames.First(), // ?
            result.ErrorMessage);

          MessageBox.Show(error, "Error", MessageBoxButton.OK);
        }
      }

which displays a MessageBox showing that the Entity knew that it had errors as soon as the property had been set to an invalid value and long before I got anywhere near to calling SubmitChanges() on the DomainContext.

But, in Silverlight this would be a pretty lame way of gathering up the validation problems and reporting them to the UI because the Entity base class implements INotifyDataErrorInfo and so it is fully capable of returning validation errors to the UI ( both synchronously and asynchronously ).

If I create the most basic of UIs around this data;

    <Grid
        x:Name="LayoutRoot"
        Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition
                Width="Auto" />
            <ColumnDefinition
                Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition
                Height="Auto" />
            <RowDefinition
                Height="Auto" />
        </Grid.RowDefinitions>
        <sdk:Label
            Content="Product Name:"
            Grid.Column="0"
            HorizontalAlignment="Left"
            Margin="3"
            VerticalAlignment="Center" />
        <TextBox
            Grid.Column="1"
            Height="23"
            HorizontalAlignment="Left"
            Margin="3"
            Name="productNameTextBox"
            Text="{Binding Path=ProductName, Mode=TwoWay, NotifyOnValidationError=true}"
            VerticalAlignment="Center"
            Width="120" />
        <sdk:Label
            Content="Unit Price:"
            Grid.Column="0"
            Grid.Row="1"
            HorizontalAlignment="Left"
            Margin="3"
            VerticalAlignment="Center" />
        <TextBox
            Grid.Column="1"
            Grid.Row="1"
            Height="23"
            HorizontalAlignment="Left"
            Margin="3"
            Name="unitPriceTextBox"
            Text="{Binding Path=UnitPrice, Mode=TwoWay, NotifyOnValidationError=true}"
            VerticalAlignment="Center"
            Width="120" />
        <sdk:Label
            Content="Units On Order:"
            Grid.Column="0"
            Grid.Row="2"
            HorizontalAlignment="Left"
            Margin="3"
            VerticalAlignment="Center" />
        <TextBox
            Grid.Column="1"
            Grid.Row="2"
            Height="23"
            HorizontalAlignment="Left"
            Margin="3"
            Name="unitsOnOrderTextBox"
            Text="{Binding Path=UnitsOnOrder, Mode=TwoWay, NotifyOnValidationError=true}"
            VerticalAlignment="Center"
            Width="120" />
    </Grid>

which is only picking out 3 of the available properties (ProductName, UnitPrice and UnitsOnOrder) and if I then have code which sets up a DataContext with an invalid Product;

 Product newProduct = new Product()
      {
        CategoryID = 1, // hard code
        SupplierID = 1, // hard code
        ProductName = "Test Product",
        UnitsOnOrder = 101
      };
      this.DataContext = newProduct;      

then, because of INotifyDataErrorInfo and because I set the NotifyOnValidationError on my bindings then the validation problem will show up immediately in the UI;

image

and I could also drop a validation summary onto the same form to display that information and, just by virtue of putting that ValidationSummary into the same parent container (in this case, a Grid) it picks up the validation problems as in;

image

Now, I could have some kind of “Submit Changes” button that enabled/disabled itself based on the HasValidationErrors property of my Entity (or I could do something more complex and have a SubmitChanges ICommand that did a similar thing) as in;

        <Button
            Grid.Row="1"
            Content="Submit Changes"
            IsEnabled="{Binding HasValidationErrors,Converter={StaticResource negateConverter}}" />

where negateConverter is just a converter that flips over a boolean value and so that’s nice because it means that my UI won’t let my SubmitChanges call execute if the underlying Entity has validation problems.

That’s going to work out “ok” if I am doing per property validation because the generated Entity-derived class on the client side calls Entity.ValidateProperty every time a property changes.

But what if I have custom validation on the Product type itself. For instance, what if I have this routine that wants to validate a whole Product instance rather than just a single numeric property value?

 public class ProductValidator
  {
    public static ValidationResult ValidateProduct(Product product,
      ValidationContext context)
    {
      ValidationResult result = ValidationResult.Success;

      // note, not handling nulls
      if ((product.UnitPrice * product.UnitsOnOrder) > 1000.0m)
      {
        result = new ValidationResult("Can not have more than 1000.0 on order");
      }
      return(result);
    }
  }

and I make sure this is available to the client-side by putting it into a .shared.cs file and I associate it in my service-side metadata code with the Product type as in;

[MetadataTypeAttribute(typeof(Product.ProductMetadata))]
  [CustomValidation(typeof(ProductValidator), "ValidateProduct")]
  public partial class Product
  {

then what happens client side when I have a UnitPrice, UnitsOnOrder combination that results in > 1000.0?

Nothing.

Why? Because nothing in the framework is going to attempt to validate the whole Entity instance. There is nothing in the generated setters that will cause this validation to run. So, what I see in my UI is;

image

Now if I actually make a call to DomainContext.SubmitChanges then it will validate the Entity and that will fail. That is, if I put some code behind my “Submit Changes” button like;

ProductContext ctx = new ProductContext();

      ctx.Products.Add((Product)this.DataContext);

      ctx.SubmitChanges(callback =>
        {
          if (callback.HasError)
          {
            callback.MarkErrorAsHandled();
          }
        }, null);

then I see that my validation is being called on the client-side and that it is failing. However, my UI still doesn’t display anything.

Why? Because the errors that I’m raising from my validation routine are not being associated with any particular property of the Entity. They are being associated with the “whole entity”. The interface INotifyDataErrorInfo associates the [null/string.empty] property name with errors that are meant to relate to the “whole object”.

However, the bindings that I have set up in my UI are only set up to look for validation problems with particular properties (ProductName, UnitPrice, UnitsOnOrder).

If I want to get validation problems for the “whole object” displayed in the UI then (AFAIK) I need to have a binding that is interested in the “whole object” such as below on line 4;

    <Grid>
	<!-- snip -->

        <Grid DataContext="{Binding .,NotifyOnValidationError=True}">

	    <!-- snip -- >

            <TextBox
                Grid.Column="1"
                Height="23"
                HorizontalAlignment="Left"
                Margin="3"
                Name="productNameTextBox"
                Text="{Binding Path=ProductName, Mode=TwoWay, NotifyOnValidationError=true}"
                VerticalAlignment="Center"
                Width="120" />

	    <!-- snip -- >

        </Grid>
        
        <Button
            Grid.Row="1"
            Content="Submit Changes"
            IsEnabled="{Binding HasValidationErrors,Converter={StaticResource negateConverter}}"
            Click="Button_Click" />
        
        <sdk:ValidationSummary
                Grid.ColumnSpan="2"
                Grid.Row="2"
                Name="validationSummary1" />
    </Grid>

notice that the Grid binding its own DataContext back to its own DataContext doesn’t really achieve anything other than to switch on the NotifyOnValidationError and that causes my UI to do the right thing in the sense of;

image

Ok – so I can get my “whole entity” validation errors to show up on the screen but only after I call DomainContext.SubmitChanges or execute equivalent code – I think equivalent code might be something like;

List<ValidationResult> validationResults = new List<ValidationResult>();

      if (!Validator.TryValidateObject(
        this.DataContext,
        new ValidationContext(this.DataContext, null, null),
        validationResults))
      {
        Entity entity = (Entity)this.DataContext;

        foreach (var item in validationResults)
        {
          entity.ValidationErrors.Add(item);
        }
      }

which left me wondering whether there’s some way I can force this sort of code to run whenever my UnitPrice or UnitsOnOrder property value change in order to avoid having to call SubmitChanges to find out about those validation errors.

I think the short answer is “sort of” Smile

Some routes that I tried or at least thought about;

  1. I can’t (AFAIK) interfere with the code generation process so I don’t think there’s anything that I can do to force the whole entity to be validated when those 2 properties change by that route.
  2. I figured that I might try to hack together a custom validation attribute which didn’t actually do any validation but, instead, tried to get the whole entity validated and then I could drop that attribute onto the 2 related properties so that they would force the revalidation of the whole entity.

I tried to sketch out (2) above. The “trick” is that I can only get my code invoked as a result of a code-generated call which calls Entity.ValidateProperty and passes the prospective property value which has not yet been set on the underlying object instance. So perhaps I can sketch out an attribute like;

  public class InvalidatesEntityAttribute : ValidationAttribute
  {
    /// <summary>
    /// this whole thing is a sketch.
    /// </summary>
    protected override ValidationResult IsValid(object value, 
      ValidationContext validationContext)
    {
      List<ValidationResult> results = new List<ValidationResult>();

      validationContext.Items.Add("proposedValue", value);
     
      bool valid = Validator.TryValidateObject(
        validationContext.ObjectInstance, 
        validationContext,
        results,
        false);

      validationContext.Items.Remove("proposedValue");

      // We assume that if valid is false then we have some results
      return (valid ? ValidationResult.Success : results[0]);
    }
  }

and note that this is really just trying to call TryValidateObject which will call any “whole entity validation” that I have associated with my entity and it also tries (hack!) to pass down a hint in the ValidationContext.Items collection of what the proposed new value for the property is. I could drop that attribute onto my UnitsOnOrder and UnitPrice properties;

  [MetadataTypeAttribute(typeof(Product.ProductMetadata))]
  [CustomValidation(typeof(ProductValidator), "ValidateProduct")]
  public partial class Product
  {
    internal sealed class ProductMetadata
    {
      // Metadata classes are not meant to be instantiated.
      private ProductMetadata()
      {
      }

      public Category Category { get; set; }

      public Nullable<int> CategoryID { get; set; }

      public bool Discontinued { get; set; }

      public int ProductID { get; set; }

      public string ProductName { get; set; }

      public string QuantityPerUnit { get; set; }

      public Nullable<short> ReorderLevel { get; set; }

      public Nullable<int> SupplierID { get; set; }

      [InvalidatesEntity]
      public Nullable<decimal> UnitPrice { get; set; }

      public Nullable<short> UnitsInStock { get; set; }
      
      [InvalidatesEntity]
      [Range(1,100)]
      public Nullable<short> UnitsOnOrder { get; set; }
    }

and then I drop into a not-too-pleasant ValidateProduct routine on my ProductValidator class;

 

  public class ProductValidator
  {
    public static ValidationResult ValidateProduct(Product product,
      ValidationContext context)
    {
      ValidationResult result = ValidationResult.Success;

      decimal? unitPriceValue = product.UnitPrice;
      short? unitsOnOrderValue = product.UnitsOnOrder;

      if (!string.IsNullOrEmpty(context.MemberName))
      {
        object proposedValue = null;

        if (context.Items.TryGetValue("proposedValue", out proposedValue))
        {
          // this validation call has come from a generated property setter
          // so we need to make sure we're validating the right value. things
          // get ugly here...
          switch (context.MemberName)
          {
            case "UnitPrice":
              unitPriceValue = (decimal?)proposedValue;
              break;
            case "UnitsOnOrder":
              unitsOnOrderValue = (short?)proposedValue;
              break;
            default:
              break;
          }
        }
      }

      // note, not handling nulls
      if (unitPriceValue.HasValue && unitsOnOrderValue.HasValue)
      {
        if ((unitPriceValue.Value * unitsOnOrderValue.Value) > 1000.0m)
        {
          result = new ValidationResult("Can not have more than 1000.0 on order",
            new string[] { "UnitPrice", "UnitsOnOrder" });
        }
      }
      return (result);
    }
  }

and you’ll notice that this is trying in a very brittle way to do the right thing in that it is trying to serve two purposes';

 

  1. Whole entity validation when called from a place like SubmitChanges when it is ok to inspect the actual value of the two properties UnitPrice/UnitsOnOrder on the instance.
  2. Whole entity validation when called from a generated property setter when there is a changed property value still “in flight” and we have to try and figure out which property it is and what the value is going to be.

That’s about the best I managed in that particular scenario – no doubt someone will come along and tell me there’s a much better way of approaching it ( that’s fine by me Smile ).

This post has got a little long so I’ll draw a line on it at this point – lots of options around validation here…