2010-12-20 3 views
6

私はWebページフォームからデータを受け取るためのデータ転送オブジェクトを作成したASP.NET MVC 2プロジェクトを持っています。フォームには2つのグループのチェックボックスがあります。オブジェクトを検証して、各グループのチェックボックスの少なくとも1つがチェックされていることを確認します。少なくとも1つのチェックボックスがチェックされていることを確認するためのASP.NET MVCバリデーター

ユーザーがクライアント側の検証をハックすることができないように、サーバー側で検証を行っています。 (後でjQueryでクライアント側の検証を追加するのは簡単です。)

私の理解では、データ転送オブジェクトクラス用に独自のカスタムValidationAttributeを作成する必要がありますが、作成方法と使い方を理解できませんそれらのうちの少なくとも1つが真であることを確認するためにチェックボックスのプロパティの任意のリストを受け入れることができます。私は、このような属性を呼び出す必要があります推測しています:

[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()メソッドの結果を反映させる方法はありますか? –

答えて

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をチェックしていますが、RequiredAttributesとStringLengthAttributesがエラーメッセージを正しく生成していても、この属性のIsValid()メソッドは呼び出されません。また、どのように私はこれから私のビューに検証メッセージを得るだろうか? <%= Html.ValidationMessageFor(Model => Model.Set1Check1)%>、またはそのようなもの? –

+0

私の質問の前半の解決策を見つけました - クラスレベルの属性は、すべてのプロパティレベルの属性が渡されない限り呼び出されません。私はそれで生きることができます。しかし、私はまだビューにこの属性のエラーメッセージを取得する方法を検討しようとしています... –

+0

私の更新をご覧ください。 – Aliostad

0

あなたのDTOはあなたのViewModelを推測していますが、IDataErrorInfoをihertできます。 そして、あなたはまた(私はこれをコンパイルしていないに注意してください)このよう

//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; } } 
} 
関連する問題