如何在MVC3中的TemplateEditor中向模型属性添加validation属性

我有一个DateTime TemplateEditor,我想添加正则表达式validation。 我有一个RegularExpression属性,我可以用它来装饰模型,但我不想用一个正则表达式来装饰我所有模型中的每个datetime属性。

有没有办法让我的自定义TemplateEditor在为它呈现文本框时添加适当的不引人注意的标签?

您应该使用自定义ModelMetadataValidatorProvider插入validation器,而不是在模板中添加validation器。 首先,创建ModelMetadataProvider类:

 public class MyModelMetadataValidatorProvider : DataAnnotationsModelValidatorProvider { internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create; internal static Dictionary AttributeFactories = new Dictionary() { { typeof(RegularExpressionAttribute), (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute) } }; internal static ModelValidator Create(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) { return new DataAnnotationsModelValidator(metadata, context, attribute); } protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes) { List vals = base.GetValidators(metadata, context, attributes).ToList(); // inject our new validator if (metadata.ModelType.Name == "DateTime") { DataAnnotationsModelValidationFactory factory; RegularExpressionAttribute regex = new RegularExpressionAttribute( "^(((0?[1-9]|1[012])/(0?[1-9]|1\\d|2[0-8])|(0?[13456789]|1[012])/(29|30)|(0?[13578]|1[02])/31)/(19|[2-9]\\d)\\d{2}|0?2/29/((19|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00)))$"); regex.ErrorMessage = "Invalid date format"; if (!AttributeFactories.TryGetValue(regex.GetType(), out factory)) factory = DefaultAttributeFactory; vals.Add(factory(metadata, context, regex)); } return vals.AsEnumerable(); } } 

接下来,在Application_Start中的Global.asax.cs中注册ModelMetadataValidatorProvider。

  ModelValidatorProviders.Providers.Clear(); ModelValidatorProviders.Providers.Add(new MyModelMetadataValidatorProvider()); 

现在,当您访问模型时,RegularExpressionAttribte将附加到每个DateTime字段。 您还可以对此进行扩展以提供本地化的DateTime正则表达式和消息。

counsellorben

这只是在Consellorben的回答中详细阐述(并解决了一些小问题)

 public class ExtendedDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider { internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create; internal static Dictionary AttributeFactories = new Dictionary() { { typeof(RegularExpressionAttribute), (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute) } }; internal static ModelValidator Create(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) { return new DataAnnotationsModelValidator(metadata, context, attribute); } protected override IEnumerable GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable attributes) { if(!attributes.Any(i => i is RegularExpressionAttribute)) { if (typeof(DateTime).Equals(metadata.ModelType) || (metadata.ModelType.IsGenericType && typeof(DateTime).Equals(metadata.ModelType.GetGenericArguments()[0]))) { DataAnnotationsModelValidationFactory factory; RegularExpressionAttribute regex = null; switch (metadata.DataTypeName) { case "Date": regex = new RegularExpressionAttribute(RegExPatterns.Date) { ErrorMessage = "Invalid date. Please use am/d/yyyy format" }; break; case "Time": regex = new RegularExpressionAttribute(RegExPatterns.Time) { ErrorMessage = "Invalid time. Please use ah:mm format" }; break; default: //DateTime regex = new RegularExpressionAttribute(RegExPatterns.DateAndTime) { ErrorMessage = "Invalid date / time. Please use am/d/yyyy h:mm format" }; break; } if (!AttributeFactories.TryGetValue(regex.GetType(), out factory)) factory = DefaultAttributeFactory; yield return factory(metadata, context, regex); } } } } 

然后将其注册到global.asax中,如下所示:

 ModelValidatorProviders.Providers.Add(new ExtendedDataAnnotationsModelValidatorProvider());