ASP.NET MVC 2 には、一連のフィールドを含む Linq to sql クラスがあります。現在、別のフィールドに特定の (列挙型) 値がある場合、フィールドの 1 つが必要です。
これまでのところ、属性として列挙型を使用できるカスタム検証属性を作成しましたが、次のようには言えません。EnumValue = this.OtherField
どうすればいいですか?
ASP.NET MVC 2 には、一連のフィールドを含む Linq to sql クラスがあります。現在、別のフィールドに特定の (列挙型) 値がある場合、フィールドの 1 つが必要です。
これまでのところ、属性として列挙型を使用できるカスタム検証属性を作成しましたが、次のようには言えません。EnumValue = this.OtherField
どうすればいいですか?
MVC2 には、DataAnnotations を機能させる方法を示すサンプルの "PropertiesMustMatchAttribute" が付属しており、.NET 3.5 と .NET 4.0 の両方で機能するはずです。そのサンプル コードは次のようになります。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute
{
private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";
private readonly object _typeId = new object();
public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
: base(_defaultErrorMessage)
{
OriginalProperty = originalProperty;
ConfirmProperty = confirmProperty;
}
public string ConfirmProperty
{
get;
private set;
}
public string OriginalProperty
{
get;
private set;
}
public override object TypeId
{
get
{
return _typeId;
}
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
OriginalProperty, ConfirmProperty);
}
public override bool IsValid(object value)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
// ignore case for the following
object originalValue = properties.Find(OriginalProperty, true).GetValue(value);
object confirmValue = properties.Find(ConfirmProperty, true).GetValue(value);
return Object.Equals(originalValue, confirmValue);
}
}
その属性を使用するときは、モデル クラスのプロパティに配置するのではなく、クラス自体に配置します。
[PropertiesMustMatch("NewPassword", "ConfirmPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public class ChangePasswordModel
{
public string NewPassword { get; set; }
public string ConfirmPassword { get; set; }
}
カスタム属性で「IsValid」が呼び出されると、モデル インスタンス全体が渡されるため、依存プロパティの値をそのまま取得できます。このパターンに従って、より一般的な比較属性を簡単に作成できます。