2010-12-20 71 views
6

我有一個ASP.NET MVC 2項目,其中我創建了一個數據傳輸對象接收來自網頁形式的數據。該表格上有兩組複選框。我想驗證對象以確保每個組中至少有一個複選框被選中。一個ASP.NET MVC驗證器,以確保至少有一個複選框被選中

我在服務器端進行驗證,以便用戶無法繞過任何客戶端驗證。 (我稍後會用jQuery添加客戶端驗證;這很容易)。

我的理解是我必須爲我的數據傳輸對象類創建自己的自定義ValidationAttribute,但我不明白如何創建和使用一個可以接受複選框屬性的任意列表,以確保其中至少有一個是真實的。我猜我會叫這樣的屬性:

[AtLeastOneCheckbox("set1check1", "set1check2", "set1check3", 
    ErrorMessage = "You must check at least one checkbox in set 1.")] 
[AtLeastOneCheckbox("set2check1", "set2check2", "set2check3", "set2check4", "set2check5", 
    ErrorMessage = "You must check at least one checkbox in set 2.")] 
public class MyFormDTO 
{ 
    ... 
} 

將AtLeastOneCheckboxAttribute實行什麼樣的?

還是有不同的方式,我應該做這種驗證?

+0

另外,我不知道爲什麼微軟MVC是把我推到這個「屬性」驗證系統的一切。如果我使用由RequiredAttribute和StringLengthAttribute完成的檢查以及我放在每個屬性上的其他驗證屬性,然後我還將IsValid()方法添加到我的對象,該對象對此對象的屬性執行其他檢查以確定它是否有效,有沒有辦法讓ModelState反映我的IsValid()方法的結果? – 2010-12-20 17:53:48

回答

4

如果您有多個複選框組,您只需要多次定義該屬性。

[AttributeUsage(AttributeTargets.Class)] 
public class AtLeastOneCheckboxAttribute : ValidationAttribute 
{ 
    private string[] _checkboxNames; 

    public AtLeastOneCheckboxAttribute(params string[] checkboxNames) 
    { 
     _checkboxNames = checkboxNames; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var propertyInfos = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) 
      .Where(x=>_checkboxNames.Contains(x.Name)); 

     var values = propertyInfos.Select(x => x.GetGetMethod().Invoke(value, null)); 
     if (values.Any(x => Convert.ToBoolean(x))) 
      return ValidationResult.Success; 
     else 
     { 
      ErrorMessage = "At least one checkbox must be selected"; 
      return new ValidationResult(ErrorMessage); 
     } 
    } 
} 

UPDATE

因爲你已經發現了,類級別的驗證被稱爲只有在所有的屬性通過。爲了獲得錯誤,只需使用空字符串作爲密鑰

+0

我試過使用你的代碼,但它似乎沒有被調用。我在我的對象上設置AtLeastOneCheckboxAttribute,然後在控制器中檢查ModelState,但是該屬性的IsValid()方法永遠不會被調用,即使我的RequiredAttributes和StringLengthAttributes正確地生成了錯誤消息。另外 - 我怎麼會從這個驗證信息到我的視圖? <%= Html.ValidationMessageFor(Model => Model.Set1Check1)%>,或類似的東西? – 2010-12-20 18:10:26

+0

找到了我的問題的前半部分的解決方案 - 除非所有屬性級屬性都通過,否則顯然不會調用類級屬性。我可以忍受這一點。但我仍然試圖弄清楚如何將這個屬性的錯誤信息放入視圖中... – 2010-12-20 18:29:27

+0

請參閱我的更新。 – Aliostad 2010-12-20 18:59:28

0

你的DTO,這是我猜你的ViewModel可以ihert IDataErrorInfo。 然後,你可以做你的驗證這樣的(注意我沒編譯這個)

//I'm guessing you have a list of checkboxes 
IEnumerable<bool> checkBoxes1; 
IEnumerable<bool> checkBoxes2; 

public class MyFormDTO : IDataErrorInfo 
{ 
    public string this[string prop] 
    { 
     get 
     { 
      if(prop == "checkBoxes1") 
      { 
       if(checkBoxes1.Any(x => x == true)) 
       { 
        return "Error: You need to select atleast one checkbox from set1"; 
       } 
      } 
      else if(prop == "checkBoxes2") 
      { 
       if(checkBoxes2.Any(x => x == true)) 
       { 
        return "Error: You need to select atleast one checkbox from set2"; 
       } 
      } 
      return null; 
     } 
    } 
    public string Error { get { return null; } } 
} 
相關問題