是否可以覆盖模型中属性的必需属性?
我很想知道是否可以覆盖模型上设置的[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);