Unable to display ErrorMessageResourceName with custom validation attribute
I've based myself upon this question to create a custom validation attribute with asp.net mvc3 and jquery validate :
I've updated it to work with a group of string properties instead of bool. Which works fine. But my issue comes when I use it with custom ErrorMessage the custom message is not displayed. And I cannot figure out why.
[RequiredOneFromGroup("PhoneGroup",
ErrorMessageResourceName = "PhoneGroup",
ErrorMessageResourceType = typeof(WizardStrings))]
public String Mobile { get; set; }
[RequiredOneFromGroup("PhoneGroup",
ErrorMessageResourceName = "PhoneGroup",
ErrorMessageResourceType = typeof(WizardStrings))]
public String Phone { get; set; }
Here's the custom validation attribute :
[AttributeUsage(AttributeTargets.Property)]
public class RequiredOneFromGroup : ValidationAttribute, IClientValidatable
{
public RequiredOneFromGroup(string groupName)
{
ErrorMessage = string.Format("You must select at least one value from group "{0}"", groupName);
GroupName = groupName;
}
public string GroupName { get; private set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
foreach (var property in GetGroupProperties(validationContext.ObjectType))
{
var propertyValue = (string)property.GetValue(validationContext.ObjectInstance, null);
if ( ! string.IsNullOrWhiteSpace(propertyValue))
{
// at least one property is true in this group => the model is valid
return null;
}
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
private IEnumerable<PropertyInfo> GetGroupProperties(Type type)
{
return
from property in type.GetProperties()
where property.PropertyType == typeof(string)
let attributes = property.GetCustomAttributes(typeof(RequiredOneFromGroup), false).OfType<RequiredOneFromGroup>()
where attributes.Count() > 0
from attribute in attributes
where attribute.GroupName == GroupName
select property;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage
};
rule.ValidationType = string.Format("group", GroupName.ToLower());
rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
yield return rule;
}
}
I've tried to remove the manual setting of the ErrorMessage but then I would get an empty error message. How can I retrieve the value of ErrorMessageResourceName that I specify in the Named Parameters of the model ? And how can I set it so the custom validation attribute display it ?
In your GetClientValidationRules
method replace:
var rule = new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage
};
with:
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};
Also get rid of the this.ErrorMessage = ...
line in your constructor. You cannot set both the ErrorMessage and use a ErrorMessageResourceName
and ErrorMessageResourceType
properties of a validation attribute. Those things are mutually exclusive.
Alright I was thinking that somehow because the custom validation attribute inherits from ValidationAttribute the ErrorMessage handling would be done naturally. That seems not to be the case though.
I've worked around this issue as follow :
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var groupProperties = GetGroupProperties(metadata.ContainerType).Select(p => p.Name);
var rule = new ModelClientValidationRule
{
// Replaced ErrorMessage with ErrorMessageString which
// will hold string value of ErrorMessageResourceName if there is
ErrorMessage = this.ErrorMessageString
};
rule.ValidationType = string.Format("group", GroupName.ToLower());
rule.ValidationParameters["propertynames"] = string.Join(",", groupProperties);
yield return rule;
}
链接地址: http://www.djcxy.com/p/9700.html