6

问题:

我在使用不显眼的 jquery 验证为隐式 [Required] 属性本地化默认消息时遇到问题。我不想将 [Required] 放在我的模型和关联的资源文件中的每个 int (和其他不可为空的类型)上。我想知道是否有人测试过 ASP.NET MVC4 Dev Preview 并注意到同样的问题?当我查看 mvc 代码时,它显然应该可以工作。

尝试的解决方案:

在 global.asax 中添加:

DefaultModelBinder.ResourceClassKey = "ErrorMessages";

在具有 PropertyValueInvalid 和 PropertyValueRequired 的全局资源中有一个名为“ErrorMessages.resx”和“ErrorMessages.fr.resx”的资源文件。

有趣的信息:

我注意到的一件好事是,他们修复了“字段必须是数字”或“字段必须是日期”在内部密封类中的硬编码。

ClientDataTypeModelValidatorProvider.ResourceClassKey = "ErrorMessages"; 

如果您在全局资源文件夹和 FieldMustBeNumeric/FieldMustBeDate 中有一个名为“ErrorMessages.resx”和“ErrorMessages.fr.resx”的资源文件,则可以使用

4

1 回答 1

2

我知道这很旧,但是要将本地化消息放入元数据中,需要继承 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 也是如此。

于 2012-09-25T03:52:23.940 回答