Answer the question
In order to leave comments, you need to log in
How to properly create a DataAnnotations validator?
Good day to all! The problem is this. Created a validator based on the ValidationAttribute from the System.DataAnnotations namespace to validate class fields. There is a class with required fields that are marked with the Requred attribute. And also there are unmarked ones. The custom validator applies to both required and optional fields. If values for optional fields are not specified, then after validation it gives an error that these fields (not mandatory) are also required. In theory, non-mandatory fields should not be checked if it does not matter.
Here is the custom class:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class APIDataTypes : ValidationAttribute
{
public ApiDataType DataType { get; set; }
public APIDataTypes( ApiDataType DataType) : base()
{
this.DataType = DataType;
this.checkers = new Dictionary<ApiDataType, Func<string, bool>>()
{
{ApiDataType.UUID, (value) =>
{
ErrorMessage = "Некорректный идентификатор.";
string pattern = @"^[0-9A-Fa-f]{8}\-[0-9A-Fa-f]{4}\-[0-9A-Fa-f]{4}\-[0-9A-Fa-f]{4}\-[0-9A-Fa-f]{12}$";
return Regex.IsMatch(value, pattern);
}},
{ApiDataType.Coordinate, (value)=>
{
ErrorMessage = "Некорректные данные координат.";
string pattern = @"\d{1,3}\.\d+[;]\d{1,3}\.\d+";
return Regex.IsMatch(value, pattern);
}},
{ApiDataType.IMEI,(value) =>
{
ErrorMessage = "Некорректный IMEI";
string pattern = @"\d{2}\-\d{6}\-\d{6}";
return Regex.IsMatch(value, pattern);
}},
{
ApiDataType.PhoneNumber, (value) =>
{
ErrorMessage = "Некорректный номер. Номер должен состоять только из натуральных чисел. Количество символов должен быть от 12 до 15 шт.";
string pattern = @"\d{12,15}";
return Regex.IsMatch(value,pattern);
}},
{ApiDataType.Version, (value) =>
{
ErrorMessage = "Проверьте корректность данные о версии объекта";
Version version = new Version();
return Version.TryParse(value, out version);
}}
};
}
private Dictionary<ApiDataType, Func<string, bool>> checkers;
public override bool IsValid(object value)
{
return value == null ? false : checkers[this.DataType](value.ToString());
}
}
public enum ApiDataType
{
PhoneNumber,
UUID,
IMEI,
Coordinate,
Version
}
public class BeaconBindingModelUpdate
{
[Required]
[APIDataTypes ( ApiDataType.UUID )]
[Display ( Name = "Идентификатор устройства" )]
public Guid Id { get; set; }
[Required]
[APIDataTypes ( ApiDataType.UUID )]
[Display ( Name = "Идентификатор пользователья" )]
/// <summary>
/// Идентификатор пользователья
/// </summary>
public Guid UserId { get; set; }
[Display ( Name = "Идентификатор типа устройства в системе" )]
[APIDataTypes ( ApiDataType.UUID )]
/// <summary>
/// Идентификатор типа устройства в системе
/// </summary>
public Guid BeaconTypeId { get; set; }
[Display ( Name = "IMEI идентификатор устройства" )]
[APIDataTypes ( ApiDataType.IMEI )]
/// <summary>
/// IMEI идентификатор устройства
/// </summary>
public string IMEI { get; set; }
[Display ( Name = "Версия программного обеспечения" )]
[APIDataTypes ( ApiDataType.Version )]
/// <summary>
/// Версия программного обеспечения устройства
/// </summary>
public Version SoftwareVersion { get; set; }
[Display ( Name = "Версия устройства" )]
[APIDataTypes ( ApiDataType.Version )]
/// <summary>
/// Версия устройства
/// </summary>
public Version HardwareVersion { get; set; }
[Display ( Name = "Пароль установленный на устройстве" )]
[DataType ( DataType.Password )]
/// <summary>
/// Пароль установленный в устройстве
/// </summary>
public string DevicePassword { get; set; }
[Display ( Name = "Номер сим карты" )]
[APIDataTypes ( ApiDataType.PhoneNumber )]
/// <summary>
/// Номер сим карты который установлен в устройстве
/// </summary>
public string SimNumber { get; set; }
[APIDataTypes ( ApiDataType.IMEI )]
/// <summary>
/// IMEI идентификатор сим карты
/// </summary>
public string SimIMEI { get; set; }
}
Answer the question
In order to leave comments, you need to log in
1) metanit.com/sharp/mvc5
Глава 7. Метаданные и валидация модели
Аннотации данных для отображения свойств
Основы валидации
Атрибуты валидации
Валидация модели в контроллере
Отображение ошибок валидации
Создание собственной логики валидации
public class MovieViewModel : IValidatableObject
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string Genre { get; set; }
public int GenreId { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Producer { get; set; }
public DateTime ReleaseDate { get; set; }
public byte Rating { get; set; }
public string TrailerURI { get; set; }
public bool IsAvailable { get; set; }
public int NumberOfStocks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validator = new MovieViewModelValidator();
var result = validator.Validate(this);
return result.Errors.Select(item => new ValidationResult(item.ErrorMessage, new[] { item.PropertyName }));
}
}
public class MovieViewModelValidator : AbstractValidator<MovieViewModel>
{
public MovieViewModelValidator()
{
RuleFor(movie => movie.GenreId).GreaterThan(0)
.WithMessage("Select a Genre");
RuleFor(movie => movie.Director).NotEmpty().Length(1,100)
.WithMessage("Select a Director");
RuleFor(movie => movie.Writer).NotEmpty().Length(1,50)
.WithMessage("Select a writer");
RuleFor(movie => movie.Producer).NotEmpty().Length(1, 50)
.WithMessage("Select a producer");
RuleFor(movie => movie.Description).NotEmpty()
.WithMessage("Select a description");
RuleFor(movie => movie.Rating).InclusiveBetween((byte)0, (byte)5)
.WithMessage("Rating must be less than or equal to 5");
RuleFor(movie => movie.TrailerURI).NotEmpty().Must(ValidTrailerURI)
.WithMessage("Only Youtube Trailers are supported");
}
private bool ValidTrailerURI(string trailerURI)
{
return (!string.IsNullOrEmpty(trailerURI) && trailerURI.ToLower().StartsWith("https://www.youtube.com/watch?"));
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question