文字列型の4つのプロパティを持つモデルがあります。StringLengthアノテーションを使用して、単一のプロパティの長さを検証できることを知っています。ただし、4つのプロパティを組み合わせた長さを検証したいと思います。
データアノテーションでこれを行うMVCの方法は何ですか?
私はMVCが初めてで、自分のソリューションを作成する前に正しい方法でそれを実行したいので、これを求めています。
文字列型の4つのプロパティを持つモデルがあります。StringLengthアノテーションを使用して、単一のプロパティの長さを検証できることを知っています。ただし、4つのプロパティを組み合わせた長さを検証したいと思います。
データアノテーションでこれを行うMVCの方法は何ですか?
私はMVCが初めてで、自分のソリューションを作成する前に正しい方法でそれを実行したいので、これを求めています。
回答:
カスタム検証属性を書くことができます:
public class CombinedMinLengthAttribute: ValidationAttribute
{
public CombinedMinLengthAttribute(int minLength, params string[] propertyNames)
{
this.PropertyNames = propertyNames;
this.MinLength = minLength;
}
public string[] PropertyNames { get; private set; }
public int MinLength { get; private set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var properties = this.PropertyNames.Select(validationContext.ObjectType.GetProperty);
var values = properties.Select(p => p.GetValue(validationContext.ObjectInstance, null)).OfType<string>();
var totalLength = values.Sum(x => x.Length) + Convert.ToString(value).Length;
if (totalLength < this.MinLength)
{
return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
}
return null;
}
}
そして、あなたはビューモデルを持っていて、それでそのプロパティの1つを装飾するかもしれません:
public class MyViewModel
{
[CombinedMinLength(20, "Bar", "Baz", ErrorMessage = "The combined minimum length of the Foo, Bar and Baz properties should be longer than 20")]
public string Foo { get; set; }
public string Bar { get; set; }
public string Baz { get; set; }
}
this.RuleFor(x => x.Foo).Must((x, foo) => x.Foo.Length + x.Bar.Length + x.Baz.Length < 20).WithMessage("The combined minimum length of the Foo, Bar and Baz properties should be longer than 20");
。次に、データアノテーションを使用して記述する必要があるという私の回答のコードを見て、どちらを使用するかを教えてください。宣言的検証モデルは、命令型モデルと比較して非常に貧弱です。
IsValid
が呼び出されたときはvalidationContext
is nullです。私が間違ったことを何か考えていますか?:-(
モデルはインターフェースを実装する必要がありますIValidatableObject
。検証コードをValidate
メソッドに入れます:
public class MyModel : IValidatableObject
{
public string Title { get; set; }
public string Description { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Title == null)
yield return new ValidationResult("*", new [] { nameof(Title) });
if (Description == null)
yield return new ValidationResult("*", new [] { nameof(Description) });
}
}
注意してください:これはサーバー側の検証です。クライアント側では機能しません。検証はフォームの送信後にのみ実行されます。
ExpressiveAnnotationsはそのような可能性を提供します。
[Required]
[AssertThat("Length(FieldA) + Length(FieldB) + Length(FieldC) + Length(FieldD) > 50")]
public string FieldA { get; set; }
ダリンの答えを改善するには、少し短くすることができます:
public class UniqueFileName : ValidationAttribute
{
private readonly NewsService _newsService = new NewsService();
public override bool IsValid(object value)
{
if (value == null) { return false; }
var file = (HttpPostedFile) value;
return _newsService.IsFileNameUnique(file.FileName);
}
}
モデル:
[UniqueFileName(ErrorMessage = "This file name is not unique.")]
エラーメッセージが必要であることに注意してください。そうでない場合、エラーは空になります。
バックグラウンド:
モデルの検証は、受信した受信データが有効かつ正しいことを確認し、このデータを使用してさらに処理できるようにするために必要です。アクションメソッドでモデルを検証できます。組み込みの検証属性は、Compare、Range、RegularExpression、Required、StringLengthです。ただし、組み込み以外の検証属性が必要なシナリオがある場合があります。
カスタム検証属性
public class EmployeeModel
{
[Required]
[UniqueEmailAddress]
public string EmailAddress {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public int OrganizationId {get;set;}
}
カスタム検証属性を作成するには、このクラスをValidationAttributeから派生させる必要があります。
public class UniqueEmailAddress : ValidationAttribute
{
private IEmployeeRepository _employeeRepository;
[Inject]
public IEmployeeRepository EmployeeRepository
{
get { return _employeeRepository; }
set
{
_employeeRepository = value;
}
}
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
var model = (EmployeeModel)validationContext.ObjectInstance;
if(model.Field1 == null){
return new ValidationResult("Field1 is null");
}
if(model.Field2 == null){
return new ValidationResult("Field2 is null");
}
if(model.Field3 == null){
return new ValidationResult("Field3 is null");
}
return ValidationResult.Success;
}
}
お役に立てれば。乾杯!
参考文献
答えに少し遅れますが、誰が検索しているのか。データアノテーションで追加のプロパティを使用することにより、これを簡単に行うことができます。
public string foo { get; set; }
public string bar { get; set; }
[MinLength(20, ErrorMessage = "too short")]
public string foobar
{
get
{
return foo + bar;
}
}
それだけです。検証エラーも特定の場所に表示したい場合は、ビューにこれを追加できます。
@Html.ValidationMessage("foobar", "your combined text is too short")
ローカリゼーションを行う場合は、ビューでこれを行うと便利です。
お役に立てれば!