[英]ASP.NET MVC4 Unobtrusive validation localization
Problem: 问题:
I have issues getting the default messages to be localized for implicit [Required] attributes using unobtrusive jquery validation. 我有问题使用不显眼的jquery验证将默认消息本地化为隐式[Required]属性。 I do not want to put [Required] on every int (and other non-nullable types) in my model and the ressource file associated.
我不想在我的模型中的每个int(和其他非可空类型)和相关的ressource文件中放置[Required]。 I am wondering if anyone has tested the ASP.NET MVC4 Dev Preview and noticed the same issue?
我想知道是否有人测试过ASP.NET MVC4 Dev Preview并注意到同样的问题? When I look at the mvc code it clearly seems like it should work.
当我看到mvc代码时,它看起来应该很有效。
Attempted solution: 尝试解决方案:
Added in the global.asax: 在global.asax中添加:
DefaultModelBinder.ResourceClassKey = "ErrorMessages";
Have a resource file called "ErrorMessages.resx" and "ErrorMessages.fr.resx" in the global resources with PropertyValueInvalid and PropertyValueRequired. 在PropertyValueInvalid和PropertyValueRequired的全局资源中有一个名为“ErrorMessages.resx”和“ErrorMessages.fr.resx”的资源文件。
Interesting information: 有趣的信息:
A good thing I have noticed is that they fixed the "Field must be a number" or "Field must be a date" from being hard coded in an internal sealed class. 我注意到的一件好事是,他们修改了“字段必须是数字”或“字段必须是日期”,而不是在内部密封类中进行硬编码。
ClientDataTypeModelValidatorProvider.ResourceClassKey = "ErrorMessages";
Does work if you have a resource file called "ErrorMessages.resx" and "ErrorMessages.fr.resx" in the global ressources folder and FieldMustBeNumeric/FieldMustBeDate 如果在全局ressources文件夹和FieldMustBeNumeric / FieldMustBeDate中有一个名为“ErrorMessages.resx”和“ErrorMessages.fr.resx”的资源文件,则可以工作吗?
I know this is old, but to get localised messages into the metadata is to subclass DataAnnotationsModelValidator and override GetClientValidationRules and Validate to supply your own messages. 我知道这是旧的,但是要将本地化消息放入元数据中,要将DataAnnotationsModelValidator子类化,并覆盖GetClientValidationRules和Validate以提供您自己的消息。
You register the adapter using DataAnnotationsModelValidatorProvider.RegisterAdapterFactory. 您使用DataAnnotationsModelValidatorProvider.RegisterAdapterFactory注册适配器。
I built a wrapper factory builder to create the factory delegate. 我构建了一个包装工厂构建器来创建工厂委托。 The out parameter is here as I use this inside a loop as I discover all adapters in the assembly via reflection, so I need to get the attribute type for each adapter in order to call RegisterAdpaterFactory.
out参数在这里,因为我在循环中使用它,因为我通过反射发现程序集中的所有适配器,所以我需要获取每个适配器的属性类型以调用RegisterAdpaterFactory。 I could have inlined the registration but I do other stuff after this using the adapter/attribute information
我可以内联注册,但在此之后我使用适配器/属性信息做其他事情
public static class ModelValidationFactory
{
/// <summary>
/// Builds a Lamda expression with the Func<ModelMetadata, ControllerContext, ValidationAttribute, ModelValidator> 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;
}
}
This also works in MVC3, and i think MVC2 as well. 这也适用于MVC3,我也认为MVC2。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.