ASP.NET MVC4不显眼的验证本地化

Nic*_*CNB 6 c# asp.net-mvc .net-4.0 asp.net-mvc-4

问题:

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

尝试解决方案:

在global.asax中添加:

DefaultModelBinder.ResourceClassKey = "ErrorMessages";
Run Code Online (Sandbox Code Playgroud)

在与PropertyValueInvalid和PropertyValueRequired全球资源,被称为"ErrorMessages.resx"和"ErrorMessages.fr.resx"的资源文件.

有趣的信息:

我注意到的一件好事是,他们修改了"字段必须是数字"或"字段必须是日期",而不是在内部密封类中进行硬编码.

ClientDataTypeModelValidatorProvider.ResourceClassKey = "ErrorMessages"; 
Run Code Online (Sandbox Code Playgroud)

如果在全局ressources文件夹和FieldMustBeNumeric/FieldMustBeDate中有一个名为"ErrorMessages.resx"和"ErrorMessages.fr.resx"的资源文件,则可以工作吗?

Rob*_*ney 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这也适用于 MVC3,我认为 MVC2 也适用。