ASP.NET MVC4 Ненавязчивая локализация проверки - PullRequest
6 голосов
/ 01 декабря 2011

Проблема:

У меня возникают проблемы с локализацией сообщений по умолчанию для неявных атрибутов [Required] с использованием ненавязчивой проверки jquery. Я не хочу помещать [Обязательный] для каждого типа int (и других типов, не обнуляемых) в моей модели и связанном файле ресурсов. Мне интересно, если кто-нибудь тестировал ASP.NET MVC4 Dev Preview и заметил ту же проблему? Когда я смотрю на код MVC, кажется, что он должен работать.

Попытка решения:

Добавлено в global.asax:

DefaultModelBinder.ResourceClassKey = "ErrorMessages";

Иметь файл ресурсов с именами «ErrorMessages.resx» и «ErrorMessages.fr.resx» в глобальных ресурсах с PropertyValueInvalid и PropertyValueRequired.

Интересная информация:

Хорошо, что я заметил, что они исправили «Поле должно быть числом» или «Поле должно быть датой» после того, как оно было жестко закодировано во внутреннем запечатанном классе.

ClientDataTypeModelValidatorProvider.ResourceClassKey = "ErrorMessages"; 

Работает, если у вас есть файл ресурсов с именами «ErrorMessages.resx» и «ErrorMessages.fr.resx» в папке глобальных ресурсов и FieldMustBeNumeric / FieldMustBeDate

1 Ответ

2 голосов
/ 25 сентября 2012

Я знаю, что это старая версия, но чтобы получить локализованные сообщения в метаданных, нужно создать подкласс DataAnnotationsModelValidator и переопределить GetClientValidationRules и Validate для предоставления ваших собственных сообщений.

Вы регистрируете адаптер с помощью DataAnnotationsModelValidatorProvider.RegisterAdapterFactory.

Я построил фабрику-упаковщик для создания фабричного делегата. Параметр out здесь, так как я использую его внутри цикла, когда я обнаруживаю все адаптеры в сборке с помощью отражения, поэтому мне нужно получить тип атрибута для каждого адаптера, чтобы вызвать RegisterAdpaterFactory. Я мог бы указать регистрацию, но я делаю другие вещи после этого, используя информацию об адаптере / атрибуте

public static class ModelValidationFactory
{
    /// <summary>
    /// Builds a Lamda expression with the Func&lt;ModelMetadata, ControllerContext, ValidationAttribute, ModelValidator&gt; signature
    /// to instantiate a strongly typed constructor.  This used by the <see cref="DataAnnotationsModelValidatorProvider.RegisterAdapterFactory"/>
    /// and used (ultimately) by <see cref="ModelValidatorProviderCollection.GetValidators"/> 
    /// </summary>
    /// <param name="adapterType">Adapter type, expecting subclass of <see cref="ValidatorResourceAdapterBase{TAttribute}"/> where T is one of the <see cref="ValidationAttribute"/> attributes</param>
    /// <param name="attrType">The <see cref="ValidationAttribute"/> generic argument for the adapter</param>
    /// <returns>The constructor invoker for the adapter. <see cref="DataAnnotationsModelValidationFactory"/></returns>
    public static DataAnnotationsModelValidationFactory BuildFactory(Type adapterType, out Type attrType)
    {
        attrType = adapterType.BaseType.GetGenericArguments()[0];

        ConstructorInfo ctor = adapterType.GetConstructor(new[] { typeof(ModelMetadata), typeof(ControllerContext), attrType });

        ParameterInfo[] paramsInfo = ctor.GetParameters();

        ParameterExpression modelMetadataParam = Expression.Parameter(typeof(ModelMetadata), "metadata");
        ParameterExpression contextParam = Expression.Parameter(typeof(ControllerContext), "context");
        ParameterExpression attributeParam = Expression.Parameter(typeof(ValidationAttribute), "attribute");

        Expression[] ctorCallArgs = new Expression[]
        {
            modelMetadataParam,
            contextParam,
            Expression.TypeAs( attributeParam, attrType )
        };

        NewExpression ctorInvoker = Expression.New(ctor, ctorCallArgs);

        // ( ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute ) => new {AdapterType}(metadata, context, ({AttrType})attribute)
        return Expression
            .Lambda(typeof(DataAnnotationsModelValidationFactory), ctorInvoker, modelMetadataParam, contextParam, attributeParam)
            .Compile()
            as DataAnnotationsModelValidationFactory;
    }
}

Это также работает в MVC3, и я думаю, что MVC2 также.

...