2012-02-29 112 views
0

カスタム属性を使用して長いフォームで検証を行っています。受信フィールドの1つは、ユーザーが対応するデータベースフィールドに対して複数の値を設定できるようにするために使用している長い一連のチェックボックスです(私はMultiSelectListを使用できると知っていますが、私はそれらの大きなファンではありません)。次に、データベースにロードする前に、ActionResultのPOSTメソッド内のさまざまなチェックボックスの値を単一の文字列にアセンブルします。その部分はうまくいく。MVC 3複数のチェックボックスのカスタム検証属性

しかし、少なくとも1つのチェックボックスをオンにしていることを確認する必要があります(つまり、データベースの値自体をnullにすることはできません)。だから私は、各チェックボックスの存在を探して、少なくとも1つが存在する場合は、検証を渡すカスタム検証属性を書いた。ここで私は、検証自体のために書いたコードは次のとおりです。

public class ConfirmLAAttribute : ValidationAttribute 
{ 
    public ConfirmLAAttribute() 
    { 
    } 

    protected override ValidationResult IsValid(Object value, ValidationContext validationContext) 
    { 
     string lAppTest = String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAShade") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAArticulation") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAMassing") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAScreening") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LARock") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAEdging") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAWindbreak") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAGroundcover") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LANaturalizing") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAOrchard") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LATopiary") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAHerb") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LAContainer") != null) ? "X" : String.Empty; 
     lAppTest += (validationContext.ObjectType.GetProperty("LABog") != null) ? "X" : String.Empty; 

     if (String.IsNullOrEmpty(lAppTest)) { 
      return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
     } 
     return ValidationResult.Success; 
    } 
} 

私はビューモデルの属性として検証を呼んでいる:

[ConfirmLA(ErrorMessage = "You must select at least one Landscape Application!")] 
public string Landscape_Application { get; set; } 

ビューモデルでのHTMLコードは、単にの繰り返しであります:

<input type="checkbox" name="LAAccent" value="true" /> Accent/Feature<br /> 

テーブルの内側(つまり、この15回、各チェックボックスに1つ)です。

問題は、これが常にエラーを投げていることです。検証コード自体の内部でデバッグしましたが、プロパティ名でチェックボックスを認識していません。つまり、チェックボックスがオンになっていても、次のいずれかが返されます。

lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty; 

私はさらに、チェックされた値が、ActionResultのFormCollectionに確実に存在することを確認しました。それは、GetPropertyメソッドがプロパティ名でこれらのチェックボックスを見つけられないのと同じように、構文が間違っているかのようです。私はここで間違って何をしていますか?

答えて

4

変更あなたのビューモデルを使用すると、選択したすべての値は、プロパティLandscapeServicesに追加されます提出ヒットすると

[Required(ErrorMessage = "You must select at least one Landscape Application!")] 
public ICollection<string> LandscapeServices { get; set; } 

<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAAccent" /> Accent/Feature<br /> 
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAShade" /> Accent/Feature<br /> 
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAArticulation" /> Accent/Feature<br /> 
/*etc etc*/ 

であるためにあなたのHTMLを変更することが。

これはサーバー側の検証にのみ有効です。クライアント側の検証が必要な場合は、独自のjavascript検証関数を使用してRequiredに拡張機能を作成する必要があります。

EDIT - SO answer

$(function(){ 
    $.validator.addMethod('required_group', function(value, element) { 
     var $module = $(element).parents('form'); 
     return $module.find('input.checkbox:checked').length; 
    }, 'Select at least one Service please'); 
    $.validator.addClassRules('required-checkbox', { 'required_group' : true }); 
+0

から、クライアント側の検証についてScubaSteveさんのコメント@対処する私は、「[]の文字列」に、この小さな(変更「ICollectionを」を微調整し、ビューモデルを渡されたことを確認しなければなりませんでしたPOST ActionResultの引数として)、あなたは私を最適なソリューションに置きます。また、処理側を "foreach"ループに変換することで、 "受信側"のコードを短くすることができました。ありがとう、それは華麗でした! – Sylver

+0

これはサーバー側の検証にも機能しますが、通常と同様にクライアント側の検証は自動的には追加されません。 – ScubaSteve

+0

@ScubaSteve質問は質問者に任せておく必要があります。 – heads5150

0

クライアント側の検証を実行しない限り、この属性は使用しません。代わりに、私はあなたのモデルをIValidatableObjectから派生させ、そのIsValidメソッドで検証を行います。はるかに簡単で、遅い拘束はありません。

関連する問題