As announced in the previous post NHibernate.Validator (NHV for friends) has its own embedded configuration based on fluent-interface (Loquacious for friends). This new feature will be general-available with the next version NHV1.2.0.
The NHV configuration
As test and because the new configuration is “Loquacious” enough I’m going to expose some examples without explication.
Example 1:
var configure = new FluentConfiguration();
configure.Register(
Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.Namespace.Equals("Company.Product.YourNamespace"))
.ValidationDefinitions())
.SetDefaultValidatorMode(ValidatorMode.UseExternal);
ve = new ValidatorEngine();
ve.Configure(configure);
Example 2:
var configure = new FluentConfiguration();
configure.Register(
Assembly.Load("Company.Product")
.ValidationDefinitions()
.Where(t => t.Namespace.Equals("Company.Product.YourNamespace"))
)
.SetDefaultValidatorMode(ValidatorMode.UseExternal)
.IntegrateWithNHibernate.ApplyingDDLConstraints().And.RegisteringListeners();
ve = new ValidatorEngine();
ve.Configure(configure);
The only thing you can’t configure, using FluentConfiguration, is the SharedEngineProvider because it is configurable only trough application config (by the way, from what I saw on the NET, an explication about what is the SharedEngineProvider is needed).
For the configuration, I have add two extensions methods, both named ValidationDefinitions(), to Assembly and to IEnumerable<System.Type>.
The configuration of class validation
Example v1:
public AddressDef()
{
Define(x => x.Country)
.MaxLength(20).And
.NotNullable();
Define(x => x.floor)
.IncludedBetween(-2, 50).WithMessage("{floor.out.of.range}");
Define(x => x.Id)
.IncludedBetween(1, 2000);
Define(x => x.Line1)
.NotNullable();
Define(x => x.State)
.NotNullable().And
.MaxLength(3);
Define(x => x.Zip)
.NotNullable().And
.MaxLength(5).WithMessage("{long}").And
.MatchWith("[0-9]+");
Define(x => x.InternalValid)
.IsTrue();
}
What happen at design-time ? Some images are more clear than 100 words…
The first advantage of fluent-interface-configuration appear clear: a very little example is that you can’t define an integer property as not-nullable.
For instance validators here is the example using Attributes and its equivalent using fluent-configuration:
Example v2:[AssertAnimal]
public class Suricato
{
}
public class SuricatoDef:ValidationDef<Suricato>
{
public SuricatoDef()
{
ValidateInstance.Using(new AssertAnimalAttribute());
}
}
Extending constraints configuration
Who know NHV know that we have some country-specific validators. Country-specific-validator is a clear example about how extend the framework.
The follow is the implementation of NHibernate.Validator.Specific.It (validators available for Italy):
public static class ItLoquaciousExtensions
{
public static IRuleArgsOptions IsCodiceFiscale(this IStringConstraints definition)
{
return ((IConstraints)definition).AddWithFinalRuleArgOptions(new CodiceFiscaleAttribute());
}
public static IRuleArgsOptions IsPartitaIva(this IStringConstraints definition)
{
return ((IConstraints)definition).AddWithFinalRuleArgOptions(new PartitaIvaAttribute());
}
public static IRuleArgsOptions IsPartitaIva(this IIntegerConstraints definition)
{
return ((IConstraints)definition).AddWithFinalRuleArgOptions(new PartitaIvaAttribute());
}
}
And obviously, at design-time, it appear like this:
Conclusions
Sometimes NHV is not so well know by NHibernate users (NHV has 5% of NH downloads). If you are using some other validation framework, in applications where you are using NHibernate, you should check if the validator are initializing collections and relations (proxy)… perhaps we should write something else about how NHV work together with NHibernate.
Great job Fabio! I really like the final syntax.
ReplyDeleteGreat job !!!
ReplyDeleteBut I have one question ... :(
In our project we are using NHV. At the moment I have an issue because in different contexts I've to validate a entity accordingly. Fluent validation I thought is the solution also but it isn't so. Is it possible to have something similar myEntityInUpdateContext.GetValidationResultForRule(new ThisIsNonDefaultRegisteredValiRuleForThisEntity())
I would appreciate any sugestions
You can do it creating a new VE. BTW create a JIRA ticket with your request; the feature is easy to implements.
ReplyDeleteI apologise if this is a newbie question, but what is the recommended way to set the maximum field length. Which comes first; the database of the configuration?
ReplyDeleteThe way I see it, if you start with the database, then the configuration(mapping) should automatically know the maximum field length (for strings at least).
If you start with the configuration(mapping), I assume you can create the database creation script. So how do you handle a change in schema if there is data in your database?
Update the mapping and do some sort of export to genearte the alter script?
Is there a way to have .NET automatically set the field length on single line edits based on a nhibernate field length?
Thanks.
Bill.
Sir When I try to do Configuration following your blog it gives me error with .ValidationDefinitions()
ReplyDeleteThe Visual Studio Says
Error 4 'System.Reflection.Assembly' does not contain a definition for 'ValidationDefinitions' and no extension method 'ValidationDefinitions' accepting a first argument of type 'System.Reflection.Assembly' could be found (are you missing a using directive or an assembly reference?)
Please Help
Hi All,
DeleteI've followed above procedure to configure Nhibernate Validator in fluent way with nihibernate models. i'm able to configure successfully but not validating any of model & not giving error.
If i configure in Attribute way [means decorating properties instead writing in external file] is working fine & validating all properties as expected.
Same thing not happening if i do in fluent way.
please help me if you got anything to do configuration with external files.
Hi All,
ReplyDeleteI've above procedure to configure Nhibernate Validator in fluentway with nihibernate models. i'm able to configure successfully but not validating any of model & giving error.
If i configure in Attribute way [means decorating properties instead writing in external file] is working find & validating all properties as expected.
Samething not happening if i do with fluent way.
please any one help me to do configuration with external files.
thanks,
Sampath.
Hi All,
ReplyDeleteI've followed above procedure to configure Nhibernate Validator in fluent way with nihibernate models. i'm able to configure successfully but not validating any of model & not giving error.
If i configure in Attribute way [means decorating properties instead writing in external file] is working find & validating all properties as expected.
Same thing not happening if i do in fluent way.
please any one help me to do configuration with external files.
thanks,
Sampath.
Interesting Blog ! It Would be a Great If u Can Provide More details about It.Thank You.
ReplyDeletebunded fuel tank hire & used generator sales