Tuesday, September 29, 2009 10:45 AM srkirkland

Using xVal with NHibernate Validator 1.2

This will be a quick and dirty post about how to get xVal 1.0 (http://xval.codeplex.com/) to work with the new NHibernate Validator 1.2beta (http://nhforge.org/media/p/7.aspx).

The problem is that xVal 1.0 ships with a NHibernate Validator (NHVal) Ruleset Provider which does not compile against the 1.2beta DLLs because of some API changes.  Meanwhile, S#arp Architecture uses NHVal 1.2 so using those Dlls is a requirement for me.

In the process of rewriting the NHVal ruleset provider I stripped out all XML rule definition support, so for my code to work you must be using NHVal attributes.

With those disclaimers, here is the code:

public class NHibernateValidatorRulesProvider : CachingRulesProvider
{
    private readonly ValidatorMode configMode;
    private readonly RuleEmitterList<IRuleArgs> ruleEmitters = new RuleEmitterList<IRuleArgs>();
 
    public NHibernateValidatorRulesProvider(ValidatorMode configMode)
    {
        this.configMode = configMode;
 
        ruleEmitters.AddSingle<LengthAttribute>(x => new StringLengthRule(x.Min, x.Max));
        ruleEmitters.AddSingle<MinAttribute>(x => new RangeRule(x.Value, null));
        ruleEmitters.AddSingle<MaxAttribute>(x => new RangeRule(null, x.Value));
        ruleEmitters.AddSingle<RangeAttribute>(x => new RangeRule(x.Min, x.Max));
        ruleEmitters.AddSingle<NotEmptyAttribute>(x => new RequiredRule());
        ruleEmitters.AddSingle<NotNullNotEmptyAttribute>(x => new RequiredRule());
        ruleEmitters.AddSingle<PatternAttribute>(x => new RegularExpressionRule(x.Regex, x.Flags));
        ruleEmitters.AddSingle<EmailAttribute>(x => new DataTypeRule(DataTypeRule.DataType.EmailAddress));
        ruleEmitters.AddSingle<DigitsAttribute>(MakeDigitsRule);
    }
 
    protected override RuleSet GetRulesFromTypeCore(Type type)
    {
        var classMapping = ClassMappingFactory.GetClassMapping(type, configMode);
 
        var rules = from member in type.GetMembers()
                    where member.MemberType == MemberTypes.Field || member.MemberType == MemberTypes.Property
                    from att in classMapping.GetMemberAttributes(member).OfType<IRuleArgs>()
                    // All NHibernate Validation validators attributes must implement this interface
                    from rule in ConvertToXValRules(att)
                    where rule != null
                    select new {MemberName = member.Name, Rule = rule};
 
        return new RuleSet(rules.ToLookup(x => x.MemberName, x => x.Rule));
    }
 
    private IEnumerable<Rule> ConvertToXValRules(IRuleArgs att)
    {
        foreach (var rule in ruleEmitters.EmitRules(att))
        {
            if (rule != null)
            {
                rule.ErrorMessage = MessageIfSpecified(att.Message);
                yield return rule;
            }
        }
    }
 
    private string MessageIfSpecified(string message)
    {
        // We don't want to display the default {validator.*} messages
        if ((message != null) && !message.StartsWith("{validator."))
            return message;
        return null;
    }
 
    private RegularExpressionRule MakeDigitsRule(DigitsAttribute att)
    {
        if (att == null) throw new ArgumentNullException("att");
        string pattern;
        if (att.FractionalDigits < 1)
            pattern = string.Format(@"\d{{0,{0}}}", att.IntegerDigits);
        else
            pattern = string.Format(@"\d{{0,{0}}}(\.\d{{1,{1}}})?", att.IntegerDigits, att.FractionalDigits);
        return new RegularExpressionRule(pattern);
    }
 
    private static class ClassMappingFactory
    {
        public static IClassMapping GetClassMapping(Type type, ValidatorMode mode)
        {
            const IClassMapping result = null;
 
            switch (mode)
            {
                case ValidatorMode.UseAttribute:
                    break;
                default:
                    throw new NotImplementedException("Only attributes are supported");
            }
 
            return result ?? new ReflectionClassMapping(type);
        }
    }
}

 

Now in the global.asax file, you just need to hook xVal and this class together like so:

xVal.ActiveRuleProviders.Providers.Add(
                new NHibernateValidatorRulesProvider(
                    ValidatorMode.UseAttribute));
 
Enjoy!
Filed under: , , , , ,

Comments

# Using xVal with NHibernate Validator 1.2 - Scott Kirkland

Tuesday, September 29, 2009 5:24 PM by DotNetShoutout

Thank you for submitting this cool story - Trackback from DotNetShoutout

# re: Using xVal with NHibernate Validator 1.2

Wednesday, September 30, 2009 11:24 AM by jbland

So did you provide an adapter to use xVal with S#arp ?

# Twitter Trackbacks for Using xVal with NHibernate Validator 1.2 - Scott's Blog [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 Using xVal with NHibernate Validator 1.2 - Scott's Blog         [asp.net]        on Topsy.com

# asp.net mvc validation framework -xVal

Thursday, October 01, 2009 12:25 AM by geff zhang

Steve Sanderson在codeplex上发布了一个asp.net mvc validation framework xVal ,并写一篇详细的文章介绍这个框架 xVal - a validation framework for ASP.NET MVC。xVal可以把客户端和服务端的验证机制结合起来。

# Validator教程

Saturday, October 10, 2009 4:00 AM by 永不言败

# Required Validator For NHibernate Validators

Thursday, October 15, 2009 1:46 PM by Scott's Blog

I’ve recently switched from the Enterprise Library Validation Application Block to using NHibernate Validators

# Required Validator For NHibernate Validators | I love .NET!

Thursday, October 15, 2009 2:51 PM by Required Validator For NHibernate Validators | I love .NET!

Pingback from  Required Validator For NHibernate Validators | I love .NET!

# re: Using xVal with NHibernate Validator 1.2

Monday, October 19, 2009 9:52 AM by Fabio Maulo

NHV has metadata. Metadata store the same info no matter which is the Validator.Mode. xVal conf. should read metadata instead attributes; If you need help I can help you. ping me.

# An xVal Provider For NHibernate Validator

Monday, November 02, 2009 1:13 PM by Scott's Blog

I wrote a post about a month ago about using xVal with NHibernate Validator 1.2 which solved a problem

# An xVal Provider For NHibernate Validator | I love .NET!

Monday, November 02, 2009 1:54 PM by An xVal Provider For NHibernate Validator | I love .NET!

Pingback from  An xVal Provider For NHibernate Validator | I love .NET!

# re: Using xVal with NHibernate Validator 1.2

Monday, October 11, 2010 12:50 AM by rex

xVal, It work on NHibernate Validator 1.2beta only. Is it work on NHibernate Validator 1.2 non beta ?

Leave a Comment

(required) 
(required) 
(optional)
(required)