【问题标题】:Override Required data attribute in mvc覆盖 mvc 中的必需数据属性
【发布时间】:2016-11-03 16:57:29
【问题描述】:

我正在 asp.net 中创建一个 mvc 应用程序。我已经在这个成员上创建了带有 dataAttribute 必需的 viewModel,以便在我将模型发布到我的控制器时获得验证消息。这工作正常。

现在我想重写 Validate 方法,以便为 errorMessage 指定翻译。我正在使用自定义框架来获取密钥的翻译。

我必须重写所需的 dataAttribute 才能使其与富有表现力的注释一起使用。

这里是代码

视图模型

public class SocietyInformationViewModel
{
    [Required(ErrorMessage = "5614")]
    public string Name { get; set; }
}

我把 translationKey 放在我的 ErrorMessage 中

之后,我创建了一个自定义 ModelValidator 和一个自定义 ModelValidatorProvider

模型验证器

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

现在我在 applicationStart 上调用 global.asax 中的 RegisterModelProviders

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

当这样做时,在执行时,我遇到了以下异常

不显眼的客户端验证规则中的验证类型名称必须是唯一的。多次看到以下验证类型:必需

所以我在网上搜索,发现这个 article 与 cmets 说我必须修改我的 web.config 并将 ClientValidationEnabled 键设置为 false。我做到了,错误消失了,但我的 modelValidor 不再被调用...

我有点迷茫,欢迎任何帮助

====== 更新=======

在stack上看了很多,发现在使用Ninject的时候,会添加NinjectDataAnnotationsModelValidatorProvider。这就是我收到消息的原因

多次看到以下验证类型:必需

所以我尝试删除 NinjectDataAnnotationsModelValidatorProvider 但我找不到任何解决方案。

====== 更新 2 =======

为了解决之前的问题,我在 github 上下载了 Ninject.Web.Mvc 项目并将其包含在我的解决方案中。然后,我删除了这一行(从 MvcModule.cs 中)

this.Kernel.Bind<ModelValidatorProvider>().To<NinjectDataAnnotationsModelValidatorProvider>();

我知道这不是最好的解决方案,但它是我找到的唯一解决方案

【问题讨论】:

  • 为什么不直接使用资源文件?
  • 就像我说的,我使用自定义框架来获取翻译。

标签: c# asp.net-mvc validation


【解决方案1】:

如果多个提供者提供相同的验证器,它将多次注册相同的规则,这就是导致错误的原因。

试试这个:

private void RegisterModelProviders()
{
    var provider = new LocalizableDataAnnotationsModelValidatorProvider();
    ModelValidatorProviders.Providers.Add(provider);
    DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
    provider.AddImplicitRequiredValidator = false;
}

【讨论】:

  • 我没有provider.AddImplicitRequiredValidator = false; 所以我尝试把它放在构造函数public LocalizableDataAnnotationsModelValidatorProvider() : base() { AddImplicitRequiredAttributeForValueTypes = false; } 中,但这不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 2015-11-04
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多