ASP.NET MVC4 Unobtrusive localization check

Problem:

I'm having trouble localizing the default messages for implicit attributes [Required] using an unobtrusive jquery validation. I do not want to put [Required] on each int (and other types that are not nullable) in my model and associated ressource file. I am wondering if any ASP.NET MVC4 Dev Preview project was tested and noticed the same problem? When I look at the mvc code, it clearly seems like it should work.

Attempted Solution:

Added to global.asax:

DefaultModelBinder.ResourceClassKey = "ErrorMessages"; 

Have a resource file named "ErrorMessages.resx" and "ErrorMessages.fr.resx" in the global resources with PropertyValueInvalid and PropertyValueRequired.

Interesting information:

It’s good that I noticed that they fixed “field must be a number” or “field must be a date” from hard coding in an internal private class.

 ClientDataTypeModelValidatorProvider.ResourceClassKey = "ErrorMessages"; 

Works if you have a resource file named "ErrorMessages.resx" and "ErrorMessages.fr.resx" in the global ressources folder and FieldMustBeNumeric / FieldMustBeDate

+6
source share
1 answer

I know this is old, but getting localized messages into metadata is a subclass of DataAnnotationsModelValidator and overriding GetClientValidationRules and Validate to provide your own messages.

You register the adapter using DataAnnotationsModelValidatorProvider.RegisterAdapterFactory.

I created a factory builder to create a factory delegate. The out parameter is here because I use this inside the loop when I discover all the adapters in the assembly through reflection, so I need to get the attribute type for each adapter to call RegisterAdpaterFactory. I could enable registration, but after that I do other things using adapter / attribute information

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

This also works in MVC3, and I think MVC2 too.

+2
source

Source: https://habr.com/ru/post/902786/


All Articles