2011-02-08 10 views
31

2つのフィールドを比較するカスタムValidationAttributeを作成するにはどうすればよいですか?これは一般的な「パスワードの入力」、「パスワードの確認」のシナリオです。私は2つのフィールドが等しいことを確認し、物事を一貫させるために、DataAnnotationsを介して検証を実装したいと考えています。DataAnnotationsを使用して2つのモデルプロパティを比較する

だから、擬似コードで、私は次のようなものを実装する方法を探しています:

public class SignUpModel 
{ 
    [Required] 
    [Display(Name = "Password")] 
    public string Password { get; set; } 

    [Required] 
    [Display(Name = "Re-type Password")] 
    [Compare(CompareField = Password, ErrorMessage = "Passwords do not match")] 
    public string PasswordConfirm { get; set; } 
} 

public class CompareAttribute : ValidationAttribute 
{ 
    public CompareAttribute(object propertyToCompare) 
    { 
     // ?? 
    } 

    public override bool IsValid(object value) 
    { 
     // ?? 
    } 
} 

そこで問題は、どのように私はValidationAttributeを[比較]コーディングしますか?

答えて

25

これを行うASP.NET MVC 3フレームワークにCompareAttributeがあります。 ASP.NET MVC 2を使用し、.Net 4.0をターゲットにしている場合、ASP.NET MVC 3ソースコードの実装を見ることができます。

3

カスタム検証属性を使用して、個々のプロパティではなくモデルに適用できます。ここではexampleをご覧ください。

7

これはダーリンの答えの長いバージョンです:

public class CustomAttribute : ValidationAttribute 
{  
    public override bool IsValid(object value) 
    { 
     if (value.GetType() == typeof(Foo)) 
     { 
      Foo bar = (Foo)value; 
      //compare the properties and return the result 
     } 

     throw new InvalidOperationException("This attribute is only valid for Foo objects"); 
    } 
} 

と使用方法:

[MetadataType(typeof(FooMD))] 
public partial class Foo 
{ 
    ... functions ... 
} 

[Custom] 
public class FooMD 
{ 
    ... other data annotations ... 
} 

エラーは、プロジェクトの参照がSystem.Webのことを確認します@Html.ValidationSummary(false)

42

に表示されます。 mvc v3.xxxxx。

using System.Web.Mvc; 

次に、あなたのコードは次のようなものでなければなりません。 。 。 。

[Required(ErrorMessage = "This field is required.")]  
public string NewPassword { get; set; } 

[Required(ErrorMessage = "This field is required.")] 
[Compare(nameof(NewPassword), ErrorMessage = "Passwords don't match.")] 
public string RepeatPassword { get; set; } 
+2

あなた自身に第二の特性のために必要な属性を保存することができます。 –

+1

C#6.0以降、プロパティ名として "magic strings"を使用する代わりに、 'nameof'キーワードを使用できるようになりました。これにより、強く型付けされたプロパティ名を使用しているので、関連するプロパティのリファクタリングがより簡単になります(魔法の文字列を更新するのを忘れてしまいます)。プラス、コンパイラはあなたが1つを見逃してしまった場合は何とかエラーになるので、 "絶対に"できなくなります。 @ Janxの回答ごとの使用例:[CompareAttribute(nameof(NewPassword)、ErrorMessage = "パスワードが一致しません。") ' –

0

私はこの問題を見て、オブジェクトのプロパティが特定の値だった場合、正規表現を評価する検証属性を書き込もうとしていました。アドレスは、配送先住所だった場合、私の場合、私は私書箱が有効になってほしくありませんでしたので、これは私が思い付いたものです:

使用

[Required] 
public EAddressType addressType { get; set; } //Evaluate Validation attribute against this 

[EvaluateRegexIfPropEqualsValue(Constants.NOT_PO_BOX_REGEX, "addressType", EAddressType.Shipping, ErrorMessage = "Unable to ship to PO Boxes or APO addresses")] 
public String addressLine1 { get; set; } 

そして、ここでの検証属性のコードです:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] 
public class EvaluateRegexIfPropEqualsValue : ValidationAttribute 
{ 
    Regex _regex; 
    string _prop; 
    object _targetValue; 

    public EvaluateRegexIfPropEqualsValue(string regex, string prop, object value) 
    { 
     this._regex = new Regex(regex); 
     this._prop = prop; 
     this._targetValue = value; 
    } 

    bool PropertyContainsValue(Object obj) 
    { 
     var propertyInfo = obj.GetType().GetProperty(this._prop); 
     return (propertyInfo != null && this._targetValue.Equals(propertyInfo.GetValue(obj, null))); 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext obj) 
    { 
     if (this.PropertyContainsValue(obj.ObjectInstance) && value != null && !this._regex.IsMatch(value.ToString())) 
     { 
      return new ValidationResult(this.ErrorMessage); 
     } 
     return ValidationResult.Success; 
    } 
} 
2

君たちはMVC 4を使用している場合

パーシャルクラスimplimentのcomfirmemail pのより1 Metadataclassを作成してください..それはあなたのエラーを解決します。このコードを試してみてくださいロパティー。詳細は以下のコードを確認してください。あなたはすでに必要な実際には最初のプロパティとの比較を施行しているので、この場合は

using System; 
    using System.Collections.Generic; 
    using System.ComponentModel.DataAnnotations; 
    using StringlenghtMVC.Comman; 
    using System.Web.Mvc; 

using System.Collections; 

    [MetadataType(typeof(EmployeeMetaData))] //here we call metadeta class 
    public partial class Employee 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
     public string Email { get; set; } 
     public Nullable<int> Age { get; set; } 
     public string Gender { get; set; } 
     public Nullable<System.DateTime> HireDate { get; set; } 

     //[CompareAttribute("Email")] 
     public string ConfirmEmail { get; set; } 
    } 

    public class EmployeeMetaData 
    { 
     [StringLength(10, MinimumLength = 5)] 
     [Required] 
     //[RegularExpression(@"(([A-za-Z]+[\s]{1}[A-za-z]+))$", ErrorMessage = "Please enter Valid Name")] 
     public string Name { get; set; } 

     [Range(1, 100)] 
     public int Age { get; set; } 
     [CurrentDate] 
     [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)] 
     public DateTime HireDate { get; set; } 

     //[RegularExpression(@"^[\w-\._\%][email protected](?:[\w]{2,6}$")] 
     public string Email { get; set; } 

     [System.Web.Mvc.CompareAttribute("Email")] 
     public string ConfirmEmail { get; set; } 


    } 
関連する問題