How to get interpolated message in NHibernate.Validator
I am trying to integrate NHibernate.Validator with ASP.NET MVC client side validation and the only problem I have found is that I simply cannot convert an uninterpreted message to human readable. I thought it would be a tricky task, but turned out to be the hardest part of client side validation. The main problem is that since it is not server side I only need the validation attributes that are in use and I don't actually have an instance or anything else.
Here are some excerpts from what I've already tried:
// Get the the default Message Interpolator from the Engine
IMessageInterpolator interp = _engine.Interpolator;
if (interp == null)
{
// It is null?? Oh, try to create a new one
interp = new NHibernate.Validator.Interpolator.DefaultMessageInterpolator();
}
// We need an instance of the object that needs to be validated, se we have to create one
object instance = Activator.CreateInstance(Metadata.ContainerType);
// we enumerate all attributes of the property. For example we have found a PatternAttribute
var a = attr as PatternAttribute;
// it seems that the default message interpolator doesn't work, unless initialized
if (interp is NHibernate.Validator.Interpolator.DefaultMessageInterpolator)
{
(interp as NHibernate.Validator.Interpolator.DefaultMessageInterpolator).Initialize(a);
}
// but even after it is initialized the following will throw a NullReferenceException, although all of the parameters are specified, and they are not null (except for the properties of the instance, which are all null, but this can't be changed)
var message = interp.Interpolate(new InterpolationInfo(Metadata.ContainerType, instance, PropertyName, a, interp, a.Message));
I know the above is pretty tricky code for a seemingly simple question, but I'm still left with no solution. Is there a way to get the interpolated string from NHValidator?
a source to share
Ok, so I know this is an old question, but I stumbled upon this while trying to do the same and it got me started, so I thought I'd give an answer.
I think the code in the question was on the right track, but there are a couple of problems. The interpolator hasn't been fully initialized with the details ResourceManager
and Culture
, and it doesn't seem to mean that you can only have one DefaultMessageInterpolator
for each validation attribute. Also, you don't need an instance of the object you are checking to get the interpolated message.
In the code in the question where you initialize the interpolator with an attribute value, you also need to initialize the interpolator with the details of ResourceManager
which one will be used.
This can be done using an overloaded method Initialize
on DefaultMessageInterpolator
, which has the following signature:
public void Initialize(ResourceManager messageBundle,
ResourceManager defaultMessageBundle,
CultureInfo culture)
The first parameter is the user-defined ResourceManager, if you want to use your resource file for error messages, you can pass null if you just want to use the default ResouceManager, the second parameter is the default ResourceManager - you can pass
new ResourceManager(
NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
Assembly.GetExecutingAssembly());
for this, the last parameter is the culture used (NHibernate.Validator comes with resource files with validation messages in multiple languages) - if you pass null to this it will just use CultureInfo.CurrentCulture
Finally, you can only have one DefaultMessageInterpolator
for each attribute, so you will need to create a new one DefaultMessageInterpolator
for each validation attribute. You can use DefaultMessageInterpolatorAggregator
to handle this, or just roll your own.
I hope this helps someone.
a source to share
Thanks for your help - I could move forward if I could. I just wanted to add that in addition to the first call to Initialize in the DefaultMessageInterpolator, which Stank illustrates, I also had to make a second excellent call to Initialize to fully initialize it (I was getting several Null Reference Exceptions using only the first call). My code looks like this:
string interpolatedMessage = "";
DefaultMessageInterpolator interpolator = new DefaultMessageInterpolator();
interpolator.Initialize(null,
new ResourceManager(
NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource,
Assembly.Load("NHibernate.Validator")),
CultureInfo.CurrentCulture);
interpolator.Initialize(attribute as Attribute);
if (attribute is IValidator && attribute is IRuleArgs)
{
IValidator validator = attribute as IValidator;
IRuleArgs ruleArgs = attribute as IRuleArgs;
InterpolationInfo interpolationInfo = new InterpolationInfo(
validatableType,
null,
propertyName,
validator,
interpolator,
ruleArgs.Message);
interpolatedMessage = interpolator.Interpolate(interpolationInfo);
}
a source to share