EntLib 5.0 VAB: Validate on PropertyChanged with Silverlight 5/wCF RIA Services

Topics: Silverlight Integration Pack, Validation Application Block
Dec 20, 2012 at 8:13 PM

Hello

Is there a sample implementation available for validating on PropertyChanged event with Enterprise Library 5.0, Silverlight Integration and WCF RIA Services?

I implemented EntLib VAB on client side by inheriting my ViewModel from ValidatingModel, but what are the next steps? In the StockTrader implementation, I can’t see it.

In my sample below, the validation on the property “Title” works perfect, but there’s no effect if I try to validate an object like CustomerDTO, especially if I try to validate only a single property (e.g. Email) of the customer object or even a hierarchical object (e.g. address properties).

There is a ValidateOnPropertyChanged method, but how should I have to use it?

Thanks a lot, kind regards
Christian

 

 

My sample:

    public class MainViewModel : ValidatingModel
    {
        [StringLengthValidator(10)]
        public string Title
        {
            get { return GetProperty(() => Title); }
            set { SetProperty(() => Title, value); }
        }

        [ObjectValidator]
        [ObjectValidator("WarningRuleset", Ruleset = "WarningRuleset")]
        public CustomerDTO Customer
        {
            get { return GetProperty(() => Customer); }
            set { SetProperty(() => Customer, value); }
        }
    }




    [MetadataType(typeof(CustomerDTO.CustomerMetaData))]
    public partial class CustomerDTO
    {
        internal class CustomerMetaData
        {
            [StringLengthValidator(50)]
            public string Email { get; set; }
        }
    }

Dec 24, 2012 at 6:56 AM
Edited Dec 24, 2012 at 6:56 AM

Enterprise Library Validation Attributes extend DataAnnotations so they should be invoked (and validation run) during the validation.  What it looks like to me is that you have specified a RuleSet on your object.  What is the behavior if you remove the RuleSet?  Does it now behave as expected?

I would recommend reading The Validation Application Block -- there is a lot of good information there.  I think this is what you are seeing:

There are some limitations with regards to using the Validation Application Block attributes, however. Since the DataAnnotations Validation class does not allow you to specify a rule set when validating, any Validation Application Block attribute with a rule set specified will be ignored by the DataAnnotationsValidator class.

--
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to 

Jan 2, 2013 at 10:30 AM

Hi,

thanks for you feedback.

I read this documentation and removed the rulesets, but it still not works as expected. It only validates the EntLib Attributes on a manual "Validate"-request, not automatically within RIA Service validation.

Do you have a sample where the combination Silverlight/RIA Services/EntLib works? This would be a great help for me to analyze it.

Kind regards
Christian

Jan 3, 2013 at 1:27 PM

I see what you mean.  Firstly, if a ruleset name is specified then validation is not run; also, only the first validation error is returned.

It looks like validation is being run but Enterprise Library is not setting the MemberName on the ValidationResult which causes RIA Services to not display the ValidationResult message.

Here is the applicable Enterprise Library Code in ValueValidatorAttribute.cs:

    protected override DAValidationResult IsValid(object value, ValidationContext context)
    {
        if (!string.IsNullOrEmpty(this.Ruleset))
        {
            return DAValidationResult.Success;
        }

        var validator = DoCreateValidator(null, null, null, null);
        var results = validator.Validate(value);

        return results.IsValid
                ? DAValidationResult.Success
                : new DAValidationResult(results.First().Message);
    }

DAValidationResult is System.ComponentModel.DataAnnotations.ValidationResult.  Note that only the message is passed in.  When RIA Services goes to add the error messages it matches on the MemberName and if the MemberName does not match it is not added to the results.

If I make a small change to pass in the MemberName from the context then validation works:

    protected override DAValidationResult IsValid(object value, ValidationContext context)
    {
        if (!string.IsNullOrEmpty(this.Ruleset))
        {
            return DAValidationResult.Success;
        }

        var validator = DoCreateValidator(null, null, null, null);
        var results = validator.Validate(value);

        string[] memberNames = null;

        if (context != null)
        {
            memberNames = new string[] { context.MemberName };
        }

        return results.IsValid
                ? DAValidationResult.Success
                : new DAValidationResult(results.First().Message, memberNames);
    }

This looks like a bug but I haven't verified if this change would have other implications (although, I don't think so).  

Unfortunately, I think modifying the Enterprise Library Source code to reflect the above looks like the only way to truly resolve this.  The other alternatives are to manually invoke validation and set the error messages.  E.g. you could create a client side (Silverlight) partial class that extends the generated System.ServiceModel.DomainServices.Client.Entity classes and overrides the ValidateProperty method.

--
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to