As far as I know that ErrorMessage
, ErrorMessageResourceName
, and ErrorMessageResourceType
properties are not used by Validation Application Block. They are included in Validation Application Block 5.0, because VAB's BaseValidationAttribute
now inherits from System.ComponentModel.DataAnnotations.ValidationAttribute
. These properties are defined in DataAnnotations' ValidationAttribute
. By inheriting from DataAnnotations, the applications and frameworks can validate a model without having a dependency on VAB (such as the validation that ASP.NET MVC does for instance).
What you can do is use VAB's MessageTemplateResourceName
and MessageTemplateResourceType
and don't use any markers and use a text specific to the property. For instance, put this complete text in your resource: "Valideringsmeddelande för efternamn" (sorry if the translation is crappy; I used Google translate).
Update:
I did some digging around in the library and unfortunately there is no easy way around this. Below is the code for the GetMessage
method that is defined in the Validator
base class that is located in Microsoft.Practices.EnterpriseLibrary.Validation
.
protected internal virtual string GetMessage(
object objectToValidate, string key)
{
return string.Format(CultureInfo.CurrentCulture,
this.MessageTemplate,
new object[] { objectToValidate, key, this.Tag });
}
As you can see, the error message is generated using the MessageTemplate
as format string together with the objectToValidate
, key
, and Tag
as formatting arguments. The Tag
is a value that you can define in a ValidationAttribute
and is therefore static and can not be culture specific. When you are validating a property, the supplied key
will always be the name of that property. This name will be supplied by the framework by reflecting over the validated type.
You can make the name more user friendly and language specific, by defining a new Validator
and overriding the GetMessage
. This way you can fetch a culture dependent text based on the property name from a resource. The problem is however, that you will have to create a sub class for every validation attribute you wish to use and for each validation attribute you must inherit the supporting validator class. While this shouldn’t be that much code per attribute and per validator, it would still be very painful to maintain such a code base.
I think it would be easier to simply define the complete message including user friendly, language specific name in the resource.
Update 2:
I thought of something that might possibly help. When your application only has to be able to display a single language at a time, there may be a work around. This won't work for web applications were the displayed messages are localized based on the thread's current culture, but it might work for desktop applications were you can configure language specific texts in the application's configuration file.
When you define the validation rules in the application's configuration file (which is a model VAB supports), you can use the Tag attribute with a language specific string.
<validation>
<type name="Company.Application.Domain.Person"
defaultRuleset="Default"
assemblyName="Company.Application.Domain">
<ruleset name="Default">
<properties>
<property name="LastName">
<validator type="StringLengthValidator" tag="efternamn"
upperBound="30" lowerBound="1" lowerBoundType="Inclusive"
upperBoundType="Inclusive" negated="false"
messageTemplate="" messageTemplateResourceName=""
messageTemplateResourceType=""
name="String Length Validator" />
</property>
</properties>
</ruleset>
</type>
</validation>
Take a close look at the tag tag="efternamn"
. When you put the {2} placeholder in the format string in your resource, it will get replaced by the string defined in tag. In other words, this resource string:
Valideringsmeddelande för '{2}'
will result in this validation message:
Valideringsmeddelande för 'efternamn'
Of course for this to work, your configuration must be localized. This wouldn’t be a good solution for web applications.
But... you can also go one step further and build an IConfigurationSource
implementation that returns a ValidationSettings
instance that is based on the thread's current culture. In this scenario you will have to build the configuration in code. Here is an example of how to do this:
public class MyConfigurationSource : IConfigurationSource
{
private Dictionary<CultureInfo, ValidationSettings> settings =
new Dictionary<CultureInfo, ValidationSettings>();
public ConfigurationSection GetSection(string sectionName)
{
if (sectionName == ValidationSettings.SectionName)
{
var culture = CultureInfo.CurrentCulture;
lock (this.settings)
{
if (!this.settings.ContainsKey(culture))
{
this.settings[culture] =
this.BuildSettingsFor(culture);
}
return this.settings[culture];
}
}
return null;
}
private ValidationSettings BuildSettingsFor(CultureInfo culture)
{
// TODO: Build up your configuration here. Example:
new StringLengthValidatorData("LastName_Smaller100")
{
Tag = MyResources.GetValue(“Customer.LastName”, culture),
LowerBound = 1,
LowerBoundType = RangeBoundaryType.Inclusive,
UpperBound = 100,
UpperBoundType = RangeBoundaryType.Inclusive
}
}
}
You can supply an instance of that MyConfigurationSource
to the ValidationFactory
or, if you want better integration, hook up this type it in the VAB configuration.
Note however that building validation rules in code is currently a lot of work, especially because VAB does not (yet) have a decent fluent configuration API (I complained about this here). I'm in the process of writing an API that makes it much easier to do so (keep an eye on my blog for that).
Good luck.