Я попробовал ответ Махмуда, но он не сработал для меня без нескольких изменений. Добавив это в качестве ответа, я могу дать код, который помог в случае, если он кому-то поможет, но в полной мере благодарю Махмуда Хбубати - я проголосовал за ваш ответ.
В моей ситуации у меня был базовый класс DTO со свойством DbGeography, которое требовалось для проекта MVC, в котором использовались пользовательские EditorTemplate и DisplayTemplate для типа DbGeography. Но для публикации модели в контроллере Web API я хотел добавить поля широты / долготы в подкласс этого DTO, который будет использоваться для создания и установки экземпляра класса DbGeography для установки значения в свойстве DbGeography. Проблема заключалась в том, что я не мог сделать свойство DbGeography не обязательным только для подкласса.
Когда в конструктор было передано логическое значение с использованием подхода Махмуда, мне никогда не удавалось переопределить значение по умолчанию. Это может быть связано с тем, что я использую Web API и регистрирую атрибут с использованием фабричного подхода, как показано ниже (в методе Global.asax.cs Application_Start):
DataAnnotationsModelValidationFactory factory = (p, a) => new DataAnnotationsModelValidator(
new List<ModelValidatorProvider>(), new RequiredExAttribute()
);
DataAnnotationsModelValidatorProvider provider = new DataAnnotationsModelValidatorProvider();
provider.RegisterAdapterFactory(typeof(RequiredExAttribute), factory);
Мне пришлось изменить класс атрибута на это:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
...
public class RequiredExAttribute : RequiredAttribute
{
public bool IsRequired { get; set; }
public override bool IsValid(object value)
{
if (IsRequired)
return base.IsValid(value);
else
{
return true;
}
}
public override bool RequiresValidationContext
{
get
{
return IsRequired;
}
}
}
public class RequiredExAttributeAdapter : RequiredAttributeAdapter
{
public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute)
: base(metadata, context, attribute) { }
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
if (((RequiredExAttribute)Attribute).IsRequired)// required -> return normal required rules
return base.GetClientValidationRules();
else// not required -> return empty rules list
return new List<ModelClientValidationRule>();
}
}
Базовый класс:
[RequiredEx(IsRequired = true)]
public virtual DbGeography Location { get; set; }
Подкласс:
[RequiredEx(IsRequired = false)]
public override DbGeography Location { get; set; }
[Required]
public decimal Latitude { get; set; }
[Required]
public decimal Longitude { get; set; }
Обратите внимание, я использовал тот же метод, что и Махмуд, для регистрации атрибута в моем проекте MVC:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter));