I'm creating an mvc app in asp.net. I've created viewModel with dataAttribute Required on this member, in order to get Validation message when I post my model to my controller. This is working fine.
Now I want to override the Validate method in order to specify a translation for the errorMessage. I'm working with a custom framework to get translation for a key.
I have to override the Required dataAttribute in order to get it working with expressive annotation.
Here is the code
ViewModel
public class SocietyInformationViewModel
{
[Required(ErrorMessage = "5614")]
public string Name { get; set; }
}
I put the translationKey in my ErrorMessage
After that, I've created a custom ModelValidator and a custom ModelValidatorProvider
ModelValidator
public class LocalizableDataAnnotationsModelValidator : ModelValidator
{
private ModelValidator _innerValidator;
private ModelMetadata _metadata;
public LocalizableDataAnnotationsModelValidator(ModelValidator innerValidator, ModelMetadata metadata, ControllerContext controllerContext)
: base(metadata, controllerContext)
{
_innerValidator = innerValidator;
_metadata = metadata;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
Service.TranslationService LocalizationManager = new Service.TranslationService();
// execute the inner validation which doesn't have localization
var results = _innerValidator.Validate(container);
// convert the error message (which should be the localization resource key) to the localized value through the ILocalizationResourceProvider
return results.Select((result) =>
{
string message = result.Message;
int key = 0;
if (Int32.TryParse(result.Message, out key))
message = LocalizationManager.Get(key, "");
return new ModelValidationResult() { Message = string.Format(message, _metadata.DisplayName) };
});
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
Service.TranslationService LocalizationManager = new Service.TranslationService();
var somerules = _innerValidator.GetClientValidationRules().ToList();
foreach (var rule in somerules)
{
int key = 0;
if (rule.ErrorMessage != null && rule.ErrorMessage.Length >= 3 && rule.ErrorMessage.Length <= 5 && Int32.TryParse(rule.ErrorMessage, out key))
rule.ErrorMessage = LocalizationManager.Get(key, "");
}
return somerules;
}
}
ModelValidatorProvider
public class LocalizableDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
public LocalizableDataAnnotationsModelValidatorProvider()
: base()
{
}
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var validators = base.GetValidators(metadata, context, attributes);
var cnt = validators.Count();
var result = new List<LocalizableDataAnnotationsModelValidator>();
foreach (var validator in validators)
{
result.Add(new LocalizableDataAnnotationsModelValidator(validator, metadata, context));
}
return result;
}
}
And now I call the RegisterModelProviders in the global.asax on applicationStart
private void RegisterModelProviders()
{
// register the model metadata provider
//ModelMetadataProviders.Current = new LocalizableDataAnnotationsModelMetadataProvider();
//// register the model validation provider
var provider = ModelValidatorProviders.Providers.Where(p => p.GetType() == typeof(DataAnnotationsModelValidatorProvider)).FirstOrDefault();
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
if (provider != null)
{
ModelValidatorProviders.Providers.Remove(provider);
}
//ModelValidatorProviders.Providers.Clear();
provider = new LocalizableDataAnnotationsModelValidatorProvider();
ModelValidatorProviders.Providers.Add(provider);
}
When doing like this, on execution, I've got the following exception
Validation type names in unobtrusive client validation rules must be unique. The following validation type was seen more than once: required
So I search on the web and I found this article with comments that say that I've to modify my web.config and set to false the ClientValidationEnabled key. I did it, and the error was gone, but my modelValidor is no more called...
I'm a little bit lost, any help is welcome
====== Update =======
After looking a lot on stack, I found that when using Ninject, it'will add NinjectDataAnnotationsModelValidatorProvider. That why I've got the message
The following validation type was seen more than once: required
So I try to remove NinjectDataAnnotationsModelValidatorProvider but I can't find any solution for that.
====== Update 2 =======
In order to fix previous problems, I download Ninject.Web.Mvc project on github and include it in my solution. Then, I remove this line (from the MvcModule.cs)
this.Kernel.Bind<ModelValidatorProvider>().To<NinjectDataAnnotationsModelValidatorProvider>();
I know it's not the best solution, but it's the only one that I've found