2014-07-23 89 views
1

我有小數2級的參數爲我的模型如下MVC3自定義驗證屬性:是比較有效的最小值和最大值

public class Range 
{ 
    public decimal MinimumValue { get; set; } 
    public decimal MaximumValue { get; set; } 
} 

是否可以進行自定義驗證這兩個參數,其中:

  • 驗證爲MinimmumValue(必須小於MaximumValue)
  • 驗證爲MaximumValue(必須大於MinimumValue更大)
+0

你使用什麼樣的驗證?數據註釋屬性? –

+0

哦是的數據註釋 –

回答

0

我做了一個自定義屬性來驗證一個字段,如果複選框被選中。如果複選框沒有被選中,則該字段是必需的,否則該字段不是必需的。我可以使用這段代碼來適應並檢查一個字段是否比其他字段更偉大。 您也可以使用數據註釋擴展。有關數據註解擴展here

public class RequiredIf : ConditionalValidationAttribute 
{ 
    protected override string ValidationName 
    { 
     get { return "requiredif"; } 
    } 

    public RequiredIf(string dependentProperty, object targetValue) 
     : base(new RequiredAttribute(), dependentProperty, targetValue) 
    { 
    } 

    protected override IDictionary<string, object> GetExtraValidationParameters() 
    { 
     return new Dictionary<string, object> 
        { 
         { "rule", "required" } 
        }; 
    } 
} 


[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)] 
public abstract class ConditionalValidationAttribute : ValidationAttribute, IClientValidatable 
{ 
    protected readonly ValidationAttribute InnerAttribute; 
    public string DependentProperty { get; set; } 
    public object TargetValue { get; set; } 
    protected abstract string ValidationName { get; } 

    protected virtual IDictionary<string, object> GetExtraValidationParameters() 
    { 
     return new Dictionary<string, object>(); 
    } 

    protected ConditionalValidationAttribute(ValidationAttribute innerAttribute, string dependentProperty, object targetValue) 
    { 
     this.InnerAttribute = innerAttribute; 
     this.DependentProperty = dependentProperty; 
     this.TargetValue = targetValue; 
    } 

    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); 

      // compare the value against the target value 
      if ((dependentvalue == null && this.TargetValue == null) || (dependentvalue != null && dependentvalue.Equals(this.TargetValue))) 
      { 
       // match => means we should try validating this field 
       if (!InnerAttribute.IsValid(value)) 
       { 
        // validation failed - return an error 
        return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName }); 
       } 
      } 
     } 
     return ValidationResult.Success; 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule() 
     { 
      ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), 
      ValidationType = ValidationName, 
     }; 
     string depProp = BuildDependentPropertyId(metadata, context as ViewContext); 
     // find the value on the control we depend on; if it's a bool, format it javascript style 
     string targetValue = (this.TargetValue ?? "").ToString(); 
     if (this.TargetValue.GetType() == typeof(bool)) 
     { 
      targetValue = targetValue.ToLower(); 
     } 
     rule.ValidationParameters.Add("dependentproperty", depProp); 
     rule.ValidationParameters.Add("targetvalue", targetValue); 
     // Add the extra params, if any 
     foreach (var param in GetExtraValidationParameters()) 
     { 
      rule.ValidationParameters.Add(param); 
     } 
     yield return rule; 
    } 

    private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext) 
    { 
     string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty); 
     // 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. 
     var thisField = metadata.PropertyName + "_"; 
     if (depProp.StartsWith(thisField)) 
     { 
      depProp = depProp.Substring(thisField.Length); 
     } 
     return depProp; 
    } 
} 
+0

但是如果讓我說我想使用數據註釋,結構會不同嗎? –

+0

什麼結構?使用就像一個正常的註釋。你會把[RequiredIf]屬性。在這個例子中,你可以像下面這樣使用:[RequiredIf(「OnRequest」,true,ErrorMessageResourceName =「ValueRequired」,ErrorMessageResourceType = typeof(Resources.Propertie))] –

2

有很多有關創建自定義屬性驗證,但這裏的文章的更多信息,它是如何可以看你的情況的例子:

public class GreaterThanAttribute : ValidationAttribute 
{ 
    public string PropertyNameToCompare { get; set; } 

    public GreaterThanAttribute(string propertyNameToCompare) 
    { 
     PropertyNameToCompare = propertyNameToCompare; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var propertyToCompare = validationContext.ObjectType.GetProperty(PropertyNameToCompare); 
     if (propertyToCompare == null) 
     { 
      return new ValidationResult(
       string.Format("Invalid property name '{0}'", PropertyNameToCompare)); 
     } 
     var valueToCompare = propertyToCompare.GetValue(validationContext.ObjectInstance, null); 

     bool valid; 

     if (value is decimal && valueToCompare is decimal) 
     { 
      valid = ((decimal) value) > ((decimal) valueToCompare); 
     } 
     //TODO: Other types 
     else 
     { 
      return new ValidationResult("Compared properties should be numeric and of the same type."); 
     } 

     if (valid) 
     { 
      return ValidationResult.Success; 
     } 

     return new ValidationResult(
      string.Format("{0} must be greater than {1}", 
       validationContext.DisplayName, PropertyNameToCompare)); 
    } 
} 

我不我非常喜歡我開始檢查房產類型的地方,但我不知道是否有可能使它更好。

當然你也需要實現GreaterThanAttribute