xVal build against newes Castle Components Validator with language support

May 21, 2010 at 10:32 AM
Edited May 21, 2010 at 12:20 PM

I've make a build against newest Castle Validator and wired everything up in my MVC project as always. After launching app in VS2010 i'v checked bin directory and desired Castle.Components.Validator.dll was in place with satellite assemblies in subdirectories. I tried to change current UI culture but nothing work and only default/neutral culture messages are showing. It seems to ResourceManager involved in CachedValidationRegistry that should show all satellite assemblies has some troubles. I make it work by manually loading specified satellite assembly from file placed in /LANG/ dir but it is ResourceManager default functionality to do this job.

Do I have to make any special steps to get it work?

Simple code test from Global.axax Begin Request method

Thread.CurrentThread.CurrentUICulture = new CultureInfo( "pl" );

Thread.CurrentThread.CurrentCulture = new CultureInfo( "pl-PL" );

var alibs = AppDomain.CurrentDomain.GetAssemblies();

main assembly plus satellite assemblies are in this list (PublicKeyToken for culture assemblies is null, culture property is set with languages)

var resourceManager = new ResourceManager( "Castle.Components.Validator.Messages", typeof( ValidatorRunner ).Assembly );

var resourceString = resourceManager.GetString( "same_as_invalid" );

resource string is always from neutral culture - English language

May 21, 2010 at 8:27 PM
Edited May 21, 2010 at 11:21 PM

I've finaly get it work.

I have some conclusions:

  • language resources from original Castle.Components.Validator assembly does not work
  • Messages.XX.resx files copied to my Assembly and put to CachedValidationRegistry work
  • because it is CACHEDValidationRegistry it parse rules only for first time when field validation is involved so it's not possible to wired it up on App Start and change Current Cultrue in App BeginRequest
  • the BIGGEST conclusion is that javascript language messages doesn't work for CastleValidation because messages form resource files are threated as custom messages

Code change:

In CastleValidatorRulesProvider

        private IEnumerable<Rule> ConvertToXValRules(IValidator val)
            var rules = ruleEmitters.EmitRules(val);
            if (!string.IsNullOrEmpty(val.ErrorMessage))
                foreach (var rule in rules)
                    rule.ErrorMessage = val.ErrorMessage;
            return rules;

should be

        private IEnumerable<Rule> ConvertToXValRules(IValidator val) {
            var rules = ruleEmitters.EmitRules(val);
            if (!string.IsNullOrEmpty(val.ErrorMessage))
                foreach (var rule in rules)
                    rule.ErrorMessage = MessageIfSpecified(val.ErrorMessage);
            return rules;
	private static string MessageIfSpecified( string message ) {
		// We don't want to display the default {validator.*} messages
		if( ( message != null ) && !message.StartsWith( "castlevalidator." ) ) {
			return message;

		return null;

 And in CachedValidationRegistry

		public string GetStringFromResource(string key)
			if (resourceManager != null)
				ResourceSet resourceSet = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentCulture, true, true);
				string result = resourceSet.GetString(key);
				if (result != null)
					return "castlevalidator." + result;
			ResourceSet defaultResourceSetForCurrentThread =
				defaultResourceManager.GetResourceSet( Thread.CurrentThread.CurrentCulture, true, true );

			return "castlevalidator." + defaultResourceSetForCurrentThread.GetString(key);

For now i've only changed ConvertToXValRulesto this rule.ErrorMessage = null; and javascript language messages work.