フィールドのリストを含む検索オブジェクトがある場合、System.ComponentModel.DataAnnotations名前空間を使用して、検索のフィールドの少なくとも1つがnullまたは空でないことを検証するように設定できますか?つまり、すべてのフィールドはオプションですが、少なくとも1つは常に入力する必要があります。
このためのカスタムバリデーターを作成します。クライアント側の検証は提供されず、サーバー側のみが提供されます。
これが機能するには、値型がデフォルトで0
またはnullable
になるため、false
型を使用する必要があることに注意してください。
まず、新しいバリデーターを作成します。
using System.ComponentModel.DataAnnotations;
using System.Reflection;
// This is a class-level attribute, doesn't make sense at the property level
[AttributeUsage(AttributeTargets.Class)]
public class AtLeastOnePropertyAttribute : ValidationAttribute
{
// Have to override IsValid
public override bool IsValid(object value)
{
// Need to use reflection to get properties of "value"...
var typeInfo = value.GetType();
var propertyInfo = typeInfo.GetProperties();
foreach (var property in propertyInfo)
{
if (null != property.GetValue(value, null))
{
// We've found a property with a value
return true;
}
}
// All properties were null.
return false;
}
}
次に、これでモデルを装飾できます。
[AtLeastOneProperty(ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
}
次に、ModelState.IsValid
を呼び出すと、バリデーターが呼び出され、メッセージがビューのValidationSummaryに追加されます。
これを拡張して、戻ってくるプロパティのタイプを確認するか、必要に応じて検証に含める/検証から除外する属性を探すことができます-これは、検証しているタイプについて何も知らない汎用バリデーターを想定しています。
プロパティのグループ化をサポートするためにZhaphの回答を拡張しました。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AtLeastOnePropertyAttribute : ValidationAttribute
{
private string[] PropertyList { get; set; }
public AtLeastOnePropertyAttribute(params string[] propertyList)
{
this.PropertyList = propertyList;
}
//See http://stackoverflow.com/a/1365669
public override object TypeId
{
get
{
return this;
}
}
public override bool IsValid(object value)
{
PropertyInfo propertyInfo;
foreach (string propertyName in PropertyList)
{
propertyInfo = value.GetType().GetProperty(propertyName);
if (propertyInfo != null && propertyInfo.GetValue(value, null) != null)
{
return true;
}
}
return false;
}
}
使用法:
[AtLeastOneProperty("StringProp", "Id", "BoolProp", ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
}
また、2つ(またはそれ以上)のグループが必要な場合:
[AtLeastOneProperty("StringProp", "Id", ErrorMessage="You must supply at least one value")]
[AtLeastOneProperty("BoolProp", "BoolPropNew", ErrorMessage="You must supply at least one value")]
public class SimpleTest
{
public string StringProp { get; set; }
public int? Id { get; set; }
public bool? BoolProp { get; set; }
public bool? BoolPropNew { get; set; }
}
この質問はかなり古いものですが、.NET 3.5(私は信じています)の時点で、 IValidatableObject はトリッキーな検証状況に役立ちます。これを実装して、任意のビジネスルールを検証できます。この場合、次のようになります。
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(FieldOne) && string.IsNullOrWhiteSpace(FieldTwo))
yield return new ValidationResult("Must provide value for either FieldOne or FieldTwo.", new string[] { "FieldOne", "FieldTwo" });
}
アノテーションを付けずに.Netクラスに対して複雑な検証を行う場合は、 FluentValidation を参照するか、.Net 2.0の場合は FluentValidation for 2. を参照してください。