Передача настраиваемых параметров в ValidationAttribute
Я построил настраиваемый атрибут ValidationAttribute, чтобы я мог проверять уникальные адреса электронной почты в своей системе. Тем не менее, я хотел бы каким-то образом передать пользовательский параметр, чтобы добавить к моей проверке еще больше логики.
public class UniqueEmailAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
//I need the original value here so I won't validate if it hasn't changed.
return value != null && Validation.IsEmailUnique(value.ToString());
}
}
Ответы
Ответ 1
Как это?
public class StringLengthValidatorNullable : ValidationAttribute
{
public int MinStringLength { get; set; }
public int MaxStringLength { get; set; }
public override bool IsValid(object value)
{
if (value == null)
{
return false;
}
var length = value.ToString().Length;
if (length < MinStringLength || length >= MaxStringLength)
{
return false;
}
return true;
}
}
Использование:
[StringLengthValidatorNullable(MinStringLength = 1, MaxStringLength = 16)]
public string Name {get; set;}
Ответ 2
Имел аналогичное требование, когда мне приходилось передавать значение в пользовательский атрибут.
Проблема здесь в том, что атрибуты атрибутов не позволяют переменные.
Вы получаете ошибку времени компиляции:
Ссылка на объект требуется для нестатического поля, метода или Свойство
Вот как я смог это сделать:
В контроллере
[FineGrainAuthorization]
public class SomeABCController : Controller
{
public int SomeId { get { return 1; } }
}
В атрибуте
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FineGrainAuthorizationAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
ControllerBase callingController = filterContext.Controller;
var someIdProperty = callingController.GetType().GetProperties().Where(t => t.Name.Equals("SomeId")).First();
int someId = (int) someIdProperty.GetValue(callingController, null);
}
}
Помните, что строка внутри .Name.Equals("SomeId")
должна совпадать с объявлением public int SomeId
Ответ 3
Вы также можете передать параметры, которые являются другими свойствами в той же модели.
Создайте собственный атрибут проверки:
public class SomeValidationAttribute : ValidationAttribute
{
//A property to hold the name of the one you're going to use.
public string OtherProperty { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//Get the value of the property using reflection.
var otherProperty = validationContext.ObjectType.GetProperty(OtherProperty);
var otherPropertyValue = (bool)otherProperty.GetValue(validationContext.ObjectInstance, null);
if (value != null && otherPropertyValue)
{
return ValidationResult.Success;
}
return new ValidationResult("Invalid property message.");
}
}
Затем передайте имя свойства, которое вы собираетесь использовать.
public class RequestModel
{
public bool SomeProperty { get; set; }
[SomeValidation(OtherProperty = "SomeProperty")]
public DateTime? StartDate { get; set; }
}
Ответ 4
Я бы предложил что-то вроде @Oliver (что бы я сделал, во всяком случае), но потом я заметил, что вы не хотите передавать константы.
Как насчет чего-то подобного?
public static class MyConfig
{
public static int MinStringLength { get; set; }
public static int MaxStringLength { get; set; }
public static SomeObject otherConfigObject { get; set; }
}
А затем доступ MyConfig.MinStringLength
к проверке?
Я соглашусь, что это не слишком красиво.