Как добавить атрибут проверки в свойство модели в TemplateEditor в MVC3 - PullRequest
3 голосов
/ 12 августа 2011

У меня есть DateTime TemplateEditor, и я хотел бы добавить к нему проверку регулярного выражения. У меня есть атрибут RegularExpression, которым я могу украсить модель, но я не хочу украшать каждое свойство datetime во всех моих моделях с помощью регулярного выражения.

Есть ли способ, как мой пользовательский TemplateEditor может добавить соответствующие ненавязчивые теги, когда для него отображается текстовое поле?

Ответы [ 2 ]

3 голосов
/ 12 августа 2011

Вместо добавления вашего валидатора в шаблон, вы должны вставить свой валидатор, используя пользовательский ModelMetadataValidatorProvider.Сначала создайте свой класс ModelMetadataProvider:

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();
    }
}

Затем зарегистрируйте свой ModelMetadataValidatorProvider в Global.asax.cs в Application_Start.

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

Теперь, когда вы получаете доступ к модели, атрибут RegularExpressionAttribte будетбыть прикрепленным к каждому полю DateTime.Вы также можете расширить это для предоставления локализованного регулярного выражения DateTime и сообщения.

counsellorben

0 голосов
/ 12 августа 2011

Это просто уточняет (и устраняет пару небольших проблем) ответ Конселлорбена

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

и затем регистрирует его в global.asax следующим образом:

ModelValidatorProviders.Providers.Add(new ExtendedDataAnnotationsModelValidatorProvider());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...