ASP.NET MVC3 условная проверка вложенности модели для EditorTemplate
Предположим, у вас есть viewModel:
public class CreatePersonViewModel
{
[Required]
public bool HasDeliveryAddress {get;set;}
// Should only be validated when HasDeliveryAddress is true
[RequiredIf("HasDeliveryAddress", true)]
public Address Address { get; set; }
}
И модель Address
будет выглядеть так:
public class Address : IValidatableObject
{
[Required]
public string City { get; set; }
[Required]
public string HouseNr { get; set; }
[Required]
public string CountryCode { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string Street { get; set; }
#region IValidatableObject Members
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
string[] requiredFields;
var results = new List<ValidationResult>();
// some custom validations here (I removed them to keep it simple)
return results;
}
#endregion
}
Некоторые предложили бы создать модель представления для Address и добавить туда некоторую пользовательскую логику, но мне нужен экземпляр Address
перейти к моему EditorTemplate для адреса.
Основная проблема здесь заключается в том, что проверка адреса выполняется до проверки моей модели PersonViewModel, поэтому я не могу предотвратить ее.
Примечание: RequiredIfAttribute - это пользовательский атрибут, который делает то, что я хочу, для простых типов.
2 ответа
Было бы легко, если бы вы использовали FluentValidation.NET вместо DataAnnotations или IValidatableObject, которые довольно сильно ограничивают возможности проверки в сложных сценариях:
public class CreatePersonViewModelValidator : AbstractValidator<CreatePersonViewModel>
{
public CreatePersonViewModelValidator()
{
RuleFor(x => x.Address)
.SetValidator(new AddressValidator())
.When(x => x.HasDeliveryAddress);
}
}
У Саймона Инса есть альфа-версия Mvc.ValidationToolkit, которая, кажется, может делать то, что вы хотите.
Обновить
Насколько я понимаю, "проблема" заключается в классе DefaultModelBinder, который проверяет вашу модель на основе того, что, если он находит атрибут проверки, он спрашивает, является ли значение допустимым (на самом деле вполне разумным!), У него нет понятия иерархии., Для поддержки требуемой функциональности вам нужно написать пользовательское связующее звено модели, которое связывает, а затем проверяет, если необходимо, как определено вашей декларативной разметкой.
Если вы пишете такой класс, он может быть хорошим кандидатом на фьючерсы MVC.