是否可以覆盖模型中属性的必需属性?

我很想知道是否可以覆盖模型上设置的[Required]属性。 我相信这个问题最简单的解决方案,任何接受者?

取决于你究竟在做什么。 如果您正在使用子类,使用具有Required属性作为基础的模型,您可以执行以下操作:

使用new关键字重新定义属性,而不是覆盖它。

 public class BaseModel { [Required] public string RequiredProperty { get; set; } } public class DerivativeModel : BaseModel { new public string RequiredProperty { get; set; } } 

如果您只想绑定或validation模型,但跳过控制器中的Required属性,则可以执行以下操作:

 public ActionResult SomeAction() { var model = new BaseModel(); if (TryUpdateModel(model, null, null, new[] { "RequiredProperty" })) // fourth parameter is an array of properties (by name) that are excluded { // updated and validated correctly! return View(model); } // failed validation return View(model); } 

@HackedByChinese方法很好,但它包含一个问题

 public class BaseModel { [Required] public string RequiredProperty { get; set; } } public class DerivativeModel : BaseModel { new public string RequiredProperty { get; set; } } 

如果您在表单上使用DerivativeModel ,此代码会在ModelState EVEN中给出validation错误, override也不起作用,因此您无法通过覆盖或续订来删除Required属性,因此我找到了某种解决方法

 public class BaseModel { public virtual string RequiredProperty { get; set; } } public class DerivativeModel : BaseModel { [Required] public override string RequiredProperty { get; set; } } public class DerivativeModel2 : BaseModel { [Range(1, 10)] public override string RequiredProperty { get; set; } } 

我有一个没有validation属性和派生类的基本模型

您可以使用自定义validation属性(它可能来自RequiredAttribute):

  public class RequiredExAttribute : RequiredAttribute { public bool UseRequiredAttribute { get; protected set; } public RequiredExAttribute(bool IsRequired) { UseRequiredAttribute = IsRequired; } public override bool IsValid(object value) { if (UseRequiredAttribute) return base.IsValid(value); else { return true; } } public override bool RequiresValidationContext { get { return UseRequiredAttribute; } } } public class RequiredExAttributeAdapter : RequiredAttributeAdapter { public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute) : base(metadata, context, attribute) { } public override IEnumerable GetClientValidationRules() { if (((RequiredExAttribute)Attribute).UseRequiredAttribute)// required -> return normal required rules return base.GetClientValidationRules(); else// not required -> return empty rules list return new List(); } } 

然后使用以下代码行在Application_Start重新设置它:

  DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter)); 

我尝试了Mahmoud的答案,但如果没有一些变化,它对我没有用。 添加这个作为答案,所以我可以提供代码,以防万一它帮助其他人,但完全归功于Mahmoud Hboubati – 我已经赞成你的答案。

在我的情况下,我有一个基础DTO类,它具有一个MVC项目所需的DbGeography属性,该项目使用自定义EditorTemplate和DisplayTemplate作为DbGeography类型。 但是,为了将模型发布到Web API控制器,我希望将纬度/经度字段添加到该DTO的子类中,这将用于创建和设置DbGeography类的实例以在DbGeography属性上设置值。 问题是,我不能仅在子类上不需要DbGeography属性。

当使用Mahmoud的方法在构造函数中传递布尔值时,它似乎永远不会覆盖我的默认值。 这可能是因为我正在使用Web API并使用工厂方法注册属性,如下所示(在Global.asax.cs Application_Start方法中):

 DataAnnotationsModelValidationFactory factory = (p, a) => new DataAnnotationsModelValidator( new List(), 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 GetClientValidationRules() { if (((RequiredExAttribute)Attribute).IsRequired)// required -> return normal required rules return base.GetClientValidationRules(); else// not required -> return empty rules list return new List(); } } 

基类:

 [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; } 

注意,我使用与上面Mahmoud相同的方法在我的MVC项目中注册属性:

 DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter)); 

是的,可以使用MetadataType类,例如:

 [MetadataType(typeof(Base.Metadata))] public class Base { public string RequiredProperty { get; set; } public class Metadata { [Required] public string RequiredProperty { get; set; } } } [MetadataType(typeof(Derived.Metadata))] public class Derived : Base { public new class Metadata { } } 

并测试它:

 var type = typeof(Derived); var metadataType = typeof(Derived.Metadata); var provider = new AssociatedMetadataTypeTypeDescriptionProvider(type, metadataType); TypeDescriptor.AddProviderTransparent(provider, type); var instance = new Derived(); var results = new List(); Validator.TryValidateObject(instance, new ValidationContext(instance), results, true); Debug.Assert(results.Count == 0);