开发者

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

开发者 https://www.devze.com 2023-03-27 06:07 出处:网络
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 to have to dec

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 to have to decorate every datetime property in all my models with a regex.

Is there way I can my custom TemplateEditor add the appropriate unobstrusive tags when it renders the textbox for it?


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


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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号