Create a gist now

Instantly share code, notes, and snippets.

MaximumWeightAttribute custom attribute - usage [MaximumWeight("PropertyName", "PropertyValue", MaxWeightInt)]
public class MaximumWeightAttribute : ValidationAttribute, IClientValidatable {
private const string ERRORMSG = "Weight must not exceed {0} lbs.";
public string DependentProperty { get; set; }
public string DependentValue { get; set; }
public int MaximumWeight { get; set; }
public MaximumWeightAttribute(string dependentProperty, string dependentValue, int maximumWeight) {
this.DependentProperty = dependentProperty;
this.DependentValue = dependentValue;
this.MaximumWeight = maximumWeight;
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
var rule = new ModelClientValidationRule() {
ErrorMessage = String.Format(ERRORMSG, this.MaximumWeight),
ValidationType = "maximumweight",
string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
rule.ValidationParameters.Add("dependentproperty", depProp);
rule.ValidationParameters.Add("dependentvalue", this.DependentValue);
rule.ValidationParameters.Add("weightvalue", this.MaximumWeight);
yield return rule;
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
// get a reference to the property this validation depends upon
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.DependentProperty);
if (field != null) {
// get the value of the dependent property
var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);
var weight = containerType.GetProperty(validationContext.DisplayName);
int weightvalue = (int)weight.GetValue(validationContext.ObjectInstance, null);
// compare the value against the target value
if (dependentvalue == this.DependentValue && weightvalue > this.MaximumWeight) {
// validation failed - return an error
return new ValidationResult(String.Format(ERRORMSG, this.MaximumWeight));
return ValidationResult.Success;
private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext) {
// build the ID of the property
string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
// unfortunately this will have the name of the current field appended to the beginning,
// because the TemplateInfo's context has had this fieldname appended to it. Instead, we
// want to get the context as though it was one level higher (i.e. outside the current property,
// which is the containing object (our Person), and hence the same level as the dependent property.
var thisField = metadata.PropertyName + "_";
if (depProp.StartsWith(thisField))
// strip it off again
depProp = depProp.Substring(thisField.Length);
return depProp;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment