I am writing a custom MVC validation attribute that is dependent on another named property within the model. Implementing IClientValidatable
my code looks like this:
public IEnumerable<ModelClientValidationRule> GetClientValidationRules
(ModelMetadata metadata, ControllerContext context)
{
var name = metadata.DisplayName ?? metadata.PropertyName;
ModelClientValidationRule rule = new ModelClientValidationRule()
{ ErrorMessage = FormatErrorMessage(name), ValidationType = "mycustomvalidation" };
rule.ValidationParameters.Add("dependentproperty", dependentProperty);
yield return rule;
}
The trouble is that I am trying to use this in a list of elements. The dependent property is rendered in the view with a name of MyListOfObjects[0].DependentProperty
and the validation rule is rendered as data-val-mycustomvalidation-dependentproperty="DependentProperty"
How do I access the full name of the dependent property from within GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
so that it renders as data-val-mycustomvalidation-dependentproperty="MyListOfObjects[0].DependentProperty"
The model looks like this:
public class MyClass
{
public string SomeValue { get; set; }
public List<Item> MyListOfObjects { get; set; }
public class Item
{
[MyCustomValidation("DependentProperty")]
public int MyValidatedElement { get; set; }
public int DependentProperty { get; set; }
}
}
You do not need the fully qualified property name in the validation attribute, and you cannot determine it in any case because the validation context is (in your case) typeof Item
(the attribute has no context of of the parent MyClass
).
Where you do need the full name is in the client side script (when you add the adapter
to $.validator.unobtrusive
. The following script will return the id
attribute of the dependent property
myValidationNamespace = {
getDependantProperyID: function (validationElement, dependantProperty) {
if (document.getElementById(dependantProperty)) {
return dependantProperty;
}
var name = validationElement.name;
var index = name.lastIndexOf(".") + 1;
dependantProperty = (name.substr(0, index) + dependantProperty).replace(/[\.\[\]]/g, "_");
if (document.getElementById(dependantProperty)) {
return dependantProperty;
}
return null;
}
}
You can then use it when initializing client side validation
$.validator.unobtrusive.adapters.add("mycustomvalidation", ["dependentproperty"], function (options) {
var element = options.element;
var dependentproperty = options.params.dependentproperty;
dependentproperty = myValidationNamespace.getDependantProperyID(element, dependentproperty);
options.rules['mycustomvalidation'] = {
dependentproperty: dependentproperty
};
options.messages['mycustomvalidation'] = options.message;
});