У меня есть модель с 4 свойствами, которые имеют тип string. Я знаю, что вы можете проверить длину одного свойства, используя аннотацию 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;
}
}
а затем вы можете иметь модель представления и украсить ее одним из своих свойств:
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; }
}
Ваша модель должна реализовать интерфейс 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; }
Фон:
Требуется подтверждение модели для обеспечения того, чтобы полученные нами данные были действительными и правильными, чтобы мы могли продолжить обработку с этими данными. Мы можем проверить модель в методе действий. Встроенными атрибутами проверки являются 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 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 = "Er bestaat al een afbeelding met deze naam")]
Обратите внимание, что требуется сообщение об ошибке, иначе ошибка будет пустой.
Немного поздно ответить, но для тех, кто ищет. Вы можете легко сделать это, используя дополнительное свойство с аннотацией данных:
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")
делать это в представлении может пригодиться, если вы хотите сделать локализацию.
Надеюсь, это поможет!