Skip to content
Matthieu MEZIL (MSFT) edited this page May 31, 2015 · 7 revisions

In the edmx, we can define some metadata such as Nullable and MaxLength which are, by default, imported from the Database.

WAQS provides a way to very easily use them in UI validation.

However, it's sometimes not enough.

Think about addresses for example. Some countries use regions. Some others do not.
So Region property is nullable in Database and so in the edmx.
But if you want to send a letter in the US, you know that you have to set the region.

So, obviously, edmx metadata are not enough sometimes.

WAQS provides a way to define metadata for MaxLength, MinLength, MaxValue, MinValue, Pattern and Nullable.

With WAQS, these metadata are not constants only.
Indeed it is possible to define them for conditions.

So, in addition of the edmx metadata, we will use these specifications:

OrderDetailSpecifications

public static void DefineMetadata()
{
    Metadata<OrderDetail>.DefineMinValue(c => c.Discount, 0);
    Metadata<OrderDetail>.DefineMaxValue(c => c.Discount, 1);
}

CustomerSpecifications

public static void DefineMetadata()
{
    Metadata<Customer>.IsNullable(c => c.Region, c => c.Country != "USA");
    Metadata<Customer>.DefinePattern(c => c.PostalCode, c => c.Country == "USA" ? "^[0-9]{5}(?:-[0-9]{4})?$" : 
                                                         c.Country == "France" ? @"^(?:\d{2}|(?:2(?:A|B)))\d{3}$" : 
                                                         null);
}

To use metadata, you must use a static method name DefineMetadata are you have to use the Metadata class inside.

Note that contrary to calculated properties, metadata do not allow properties of another entity (using navigation properties).

Now, after a new WAQS / Update Solution Generated Code we are able to use these metadata in the client UI. Ex:

<TextBox Text="{Binding Customer.PostalCode}" 
         MaxLength="{Binding Customer.PostalCodeMaxLength}" 
         controls:ErrorsBehaviors.Errors="{Binding Customer.PostalCodeErrors}" />

Get the new version of the CustomersWindow using metadata.

Now if you have some errors, you will have (by default) something like this:

Then if you save with errors, you have an error from the server.

However, if you want to first check before saving, you have an optional parameter validate to SaveChangesAsync method:

try
{
    await _context.SaveChangesAsync(validate:true);
}
catch(ErrorException e)
{
    System.Windows.MessageBox.Show(String.Join(Environment.NewLine, e.Errors.OrderByDescending(er => er.Criticity).Select(er => er.Message))); // this is not good for an MVVM point of view
}

Note that as previously, this code is not good for an MVVM point of view but it is better for pedagogy.
You will see later how to respect MVVM pattern using WAQS.

You can get the final source code here.