2015-02-23 112 views
0

我有以下POCO:如何驗證客戶端驗證中的雙變量規則?

public class CabinetItem 
{ 
    [Required] 
    [Display(...)] 
    public double Width { get; set; } 

    public double MinWidth { get; } 
} 

我試圖搞清楚的是我如何驗證WidthMinWidth較大時MinWidth可能是什麼嗎?最小寬度是一個依賴於櫥櫃項目的約束。注意:我還遺漏了一個MaxWidth來簡化這個問題。

+0

看看我的答案,它包括unobtrusivevalidation – sabotero 2015-02-23 17:09:36

回答

0

您可以創建一個CustomValidationAttribute

以此爲考試PLE:

public class GreaterThanAttribute : ValidationAttribute, IClientValidatable 
    { 
     private readonly string _testedPropertyName; 
     private readonly bool _allowEqualValues; 
     private readonly string _testedPropertyDisplayName; 

     public override string FormatErrorMessage(string displayName) 
     { 
      return string.Format(ErrorMessages.GreaterThan_Message, displayName, _testedPropertyDisplayName); 
     } 

     public GreaterThanAttribute(string testedPropertyName, Type resourceType, string testedPropertyDisplayNameKey, bool allowEqualValues = false) 
     { 
      _testedPropertyName = testedPropertyName; 
      _allowEqualValues = allowEqualValues; 
      var rm = new ResourceManager(resourceType); 
      _testedPropertyDisplayName = rm.GetString(testedPropertyDisplayNameKey);    
     } 

     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 
      var propertyTestedInfo = validationContext.ObjectType.GetProperty(_testedPropertyName); 

      if (propertyTestedInfo == null) 
      { 
       return new ValidationResult(string.Format("unknown property {0}", _testedPropertyName)); 
      } 

      var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null); 

      if (value == null || !(value is Decimal)) 
      { 
       return ValidationResult.Success; 
      } 

      if (propertyTestedValue == null || !(propertyTestedValue is Decimal)) 
      { 
       return ValidationResult.Success; 
      } 

      // Compare values 
      if ((Decimal)value >= (Decimal)propertyTestedValue) 
      { 
       if (_allowEqualValues && value == propertyTestedValue) 
       { 
        return ValidationResult.Success; 
       } 
       else if ((Decimal)value > (Decimal)propertyTestedValue) 
       { 
        return ValidationResult.Success; 
       } 
      } 

      return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
     } 

     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
     { 
      var rule = new ModelClientValidationRule 
      { 
       ErrorMessage = FormatErrorMessage(metadata.DisplayName), 
       ValidationType = "greaterthan" 
      }; 
      rule.ValidationParameters["propertytested"] = _testedPropertyName; 
      rule.ValidationParameters["allowequalvalues"] = _allowEqualValues; 
      yield return rule; 
     } 
    } 

您可以使用它像這樣:

public Decimal MyProperty1 { get; set; } 

[GreaterThanAttribute("MyProperty1", typeof(Strings), "Error_String")] 
public Decimal MyProperty2 { get; set; } 

[GreaterThanAttribute("MyProperty2", typeof(Strings), "Error_String")] 
public Decimal MyProperty3 { get; set; } 

,以及在客戶端,您可以添加此客戶端驗證:

jQuery.validator.unobtrusive.adapters.add('greaterthan', ['propertytested', 'allowequalvalues'], function (options) { 
      options.params["allowequalvalues"] = options.params["allowequalvalues"] === "True" || 
               options.params["allowequalvalues"] === "true" || 
               options.params["allowequalvalues"] === true ? true : false; 

      options.rules['greaterthan'] = options.params; 
      options.messages['greaterthan'] = options.message; 
     }); 
jQuery.validator.addMethod("greaterthan", function (value, element, params) {   
      var properyTestedvalue= $('input[name="' + params.propertytested + '"]').val(); 
      if (!value || !properyTestedvalue) return true; 
      return (params.allowequalvalues) ? parseFloat(properyTestedvalue) <= parseFloat(value) : parseFloat(properyTestedvalue) < parseFloat(value); 
     }, ''); 
+0

這可能會奏效。但是我沒有直接向客戶發送最大寬度。我是一個隱藏的價值。 – Jordan 2015-02-23 18:28:11

+0

以及'$('input [name =''+ params.propertytested +'「'')')即使是隱藏字段 – sabotero 2015-02-23 21:26:14

+0

,您也必須使用@ Html.HiddenFor(m => m.MinWith)'渲染隱藏的字段 – sabotero 2015-02-23 21:30:56

1

選項1:

foolproof NuGet包可能是你的情況是非常有用的。

安裝foolproof NuGet包,並使用其額外的有用的屬性如下所示:

public class CabinetItem 
{ 
    [Required] 
    [Display(...)] 
    [GreaterThan("MinWidth")] 
    public double Width { get; set; } 

    public double MinWidth { get; } 
} 

還有一些其他的功能,以及:

  • [是]
  • [EqualTo]
  • [NotEqualTo]
  • [GreaterThan]
  • [每種不超過]
  • [GreaterThanOrEqualTo]
  • [LessThanOrEqualTo]

資源:Is there a way through data annotations to verify that one date property is greater than or equal to another date property?

+0

您鏈接到的自定義驗證屬性僅適用於Silverlight。我相信MVC的模擬將是ValidationAttribute。如果情況並非如此,請糾正我。 – Jordan 2015-02-23 16:54:21

+0

我已經看到這個,但是這不需要回發到服務器來驗證?這是幕後的不顯眼的驗證嗎? – Jordan 2015-02-23 16:54:51

+0

是的,你是正確的第一個我會刪除它,但第二個不顯眼的ajax可以是任何獲取/發佈方法。請看看http://www.asp.net/mvc/overview/older-versions/creating-a-mvc-3-application-with-razor-and-unobtrusive-javascript – Tushar 2015-02-23 16:59:33