Есть две части этого.Во-первых, вы должны написать обязательный атрибут, который требуется, только если другое свойство соответствует вашим критериям.
Вам нужно будет сделать что-то вроде:
public class RequiredComparerAttribute : RequiredAttribute
{
public OtherProperty { get; set; }
public override bool IsValid(object value)
{
// TODO: use reflection to validate other property as PropertyInfo
// or validate it's value after it is decided to be valid
foreach (ValidationAttribute va in property
.GetCustomAttributes(typeof(ValidationAttribute), true)
.OfType<ValidationAttribute>())
{
if (!va.IsValid(value))
{
return false; // not required
}
}
return true; // required
}
}
Затем в Application_Start вGlobal.asax, вам нужно зарегистрировать валидатор, который вы можете просто повторно использовать валидатор RequiredAttribute:
DataAnnotationsModelValidatorProvider
.RegisterAdapter(typeof(RequiredComparerAttribute),
typeof(RequiredAttributeAdapter));
Если вы хотите добавить свой собственный валидатор, вам придется написать собственный валидатор.У Фила Хаака есть пример в его блоге: http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx
Редактировать: посмотрите на CompareAttribute в .NET Reflector, чтобы понять, как получить значение OtherProperty.CompareAttribute также реализует IClientValidatable
для предоставления тех правил проверки, которые необходимы на стороне клиента.
Я не думаю, что CompareAttribute будет работать для вас, потому что вы должны проверить, что значение требуется на основе содержимого другого свойства, а не сравнивать равенство двух свойств.
Edit2: Что делает поставщик проверки?
Он добавляет правила в форму и предоставляет сообщения для этих правил.Вы можете точно увидеть, как RequiredAttributeAdapter
делает это, загрузив исходный код MVC 3.Чтобы понять, что он делает на стороне клиента, вы можете открыть страницу MVC 3 в Google Chrome, нажать CTRL + SHIFT + J, чтобы открыть окно инструментов разработчика, и ввести:
$('form:first').data().unobtrusiveValidation.options
Объект правил внутриoptions определяет, как проверять каждый элемент, а объект сообщения указывает сообщение об ошибке, которое будет отображаться для каждой ошибки проверки.
Edit3: Полный пример
После ответа на этот вопросЯ написал сообщение в блоге с полным примером создания пользовательского атрибута на клиенте (ненавязчивая проверка) и на сервере.Сообщение в блоге здесь .Этот пример относится к атрибуту «содержит», но его довольно легко изменить, чтобы он стал обязательным для сравнения.