How to add validation attribute to model property in TemplateEditor in MVC3

前端 未结 2 1096
悲哀的现实
悲哀的现实 2020-12-06 03:48

I have a DateTime TemplateEditor and I would like to add regex validation to it. I have a RegularExpression attribute that I could decorate the model with, but I dont want

相关标签:
2条回答
  • 2020-12-06 04:08

    Instead of adding your validator in the template, you should insert your validator using a custom ModelMetadataValidatorProvider. First, create your ModelMetadataProvider class:

    public class MyModelMetadataValidatorProvider : DataAnnotationsModelValidatorProvider
    {
    
        internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create;
        internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() {
            {
                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<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
        {
            List<ModelValidator> 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();
        }
    }
    

    Next, register your ModelMetadataValidatorProvider in Global.asax.cs in Application_Start.

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

    Now, when you access a model, a RegularExpressionAttribte will be attached to each DateTime field. You can also extend this to provide a localized DateTime regular expression and message.

    counsellorben

    0 讨论(0)
  • 2020-12-06 04:13

    This is just elaborating (and fixing a couple little problems) on Consellorben's answer

    public class ExtendedDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider
    {
        internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create;
        internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() 
        {
            {
                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<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> 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 a m/d/yyyy format" };
                            break;
                        case "Time":
                            regex = new RegularExpressionAttribute(RegExPatterns.Time) { ErrorMessage = "Invalid time. Please use a h:mm format" };
                            break;
                        default: //DateTime
                            regex = new RegularExpressionAttribute(RegExPatterns.DateAndTime) { ErrorMessage = "Invalid date / time. Please use a m/d/yyyy h:mm format" };
                            break;
                    }
    
                    if (!AttributeFactories.TryGetValue(regex.GetType(), out factory))
                        factory = DefaultAttributeFactory;
    
                    yield return factory(metadata, context, regex);
                }
            }
        }
    }
    

    and then register it in the global.asax like so:

    ModelValidatorProviders.Providers.Add(new ExtendedDataAnnotationsModelValidatorProvider());
    
    0 讨论(0)
提交回复
热议问题