/// <inheritdoc />
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // RequiredAttribute marks a property as required by validation - this means that it
            // must have a non-null value on the model during validation.
            var requiredAttribute = context.Attributes.OfType <RequiredAttribute>().FirstOrDefault();

            if (requiredAttribute != null)
            {
                context.ValidationMetadata.IsRequired = true;
            }

            foreach (var attribute in context.Attributes.OfType <ValidationAttribute>())
            {
                // If another provider has already added this attribute, do not repeat it.
                // This will prevent attributes like RemoteAttribute (which implement ValidationAttribute and
                // IClientModelValidator) to be added to the ValidationMetadata twice.
                // This is to ensure we do not end up with duplication validation rules on the client side.
                if (!context.ValidationMetadata.ValidatorMetadata.Contains(attribute))
                {
                    context.ValidationMetadata.ValidatorMetadata.Add(attribute);
                }
            }
        }
Esempio n. 2
0
 public void CreateValidationMetadata(
     ValidationMetadataProviderContext context)
 {
     if (context.Key.ModelType.GetTypeInfo().IsValueType&&
         context.ValidationMetadata.ValidatorMetadata
         .Where(m => m.GetType() == typeof(RequiredAttribute)).Count() == 0)
     {
         context.ValidationMetadata.ValidatorMetadata.
         Add(new RequiredAttribute());
     }
     foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
     {
         ValidationAttribute tAttr = attribute as ValidationAttribute;
         if (tAttr != null /*&& tAttr.ErrorMessage == null */ && tAttr.ErrorMessageResourceName == null)
         {
             var name = tAttr.GetType().Name;
             if (resourceManager.GetString(name) != null)
             {
                 tAttr.ErrorMessageResourceType = resourceType;
                 tAttr.ErrorMessageResourceName = name;
                 tAttr.ErrorMessage             = null;
             }
         }
     }
 }
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     foreach (var attr in context.Attributes)
     {
         if (attr is ValidationAttribute validationAttr)
         {
             // If there is no custom message, try to find an adapter to set
             // the ErrorMessageResourceName property automatically.
             var hasNoCustomErrorMessage = string.IsNullOrWhiteSpace(validationAttr.ErrorMessage);
             var isDataTypeAttribute     = validationAttr is DataTypeAttribute;
             if (hasNoCustomErrorMessage || isDataTypeAttribute)
             {
                 foreach (var adapter in Adapters)
                 {
                     if (adapter.CanHandle(validationAttr))
                     {
                         validationAttr.ErrorMessageResourceType = ErrorMessageResourceType;
                         validationAttr.ErrorMessageResourceName = adapter.GetErrorMessageResourceName(validationAttr);
                         break;
                     }
                 }
             }
         }
     }
 }
Esempio n. 4
0
        /// <remarks>This will localize the default data annotations error message if it is exist, otherwise will try to look for a parameterized version.</remarks>
        /// <example>
        /// A property named 'UserName' that decorated with <see cref="RequiredAttribute"/> will be localized using
        /// "The {0} field is required." and "The UserName field is required." error messages.
        /// </example>
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            foreach (var metadata in context.ValidationMetadata.ValidatorMetadata)
            {
                if (metadata is ValidationAttribute attribute)
                {
                    var displayName = context.Attributes.OfType <DisplayAttribute>().FirstOrDefault()?.Name;
                    // Use DisplayName if present
                    var argument           = displayName ?? context.Key.Name;
                    var errorMessageString = attribute.ErrorMessage == null && attribute.ErrorMessageResourceName == null
                        ? attribute.FormatErrorMessage(argument)
                        : attribute.ErrorMessage;

                    // Localize the parameterized error message
                    var localizedString = _stringLocalizer[errorMessageString];

                    if (localizedString == errorMessageString)
                    {
                        // Localize the unparameterized error message
                        var unparameterizedErrorMessage = errorMessageString.Replace(argument, "{0}");
                        localizedString = _stringLocalizer[unparameterizedErrorMessage];
                    }

                    attribute.ErrorMessage = localizedString;
                }
            }
        }
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (!_hasOnlyMetadataBasedValidators)
            {
                return;
            }

            for (var i = 0; i < _validatorProviders.Length; i++)
            {
                var provider = _validatorProviders[i];
                if (provider.HasValidators(context.Key.ModelType, context.ValidationMetadata.ValidatorMetadata))
                {
                    context.ValidationMetadata.HasValidators = true;
                    return;
                }
            }

            if (context.ValidationMetadata.HasValidators == null)
            {
                context.ValidationMetadata.HasValidators = false;
            }
        }
            public void Should_not_update_ErrorMessageResource_of_ValidationAttribute_with_custom_ErrorMessage()
            {
                // Arrange
                var key         = new ModelMetadataIdentity();
                var myAttribute = new MyValidationAttribute
                {
                    ErrorMessage = "Some message"
                };
                var attributes = new ModelAttributes(new object[] { myAttribute });
                var context    = new ValidationMetadataProviderContext(key, attributes);

                MyMockAdapter
                .Setup(x => x.CanHandle(myAttribute))
                .Returns(true);
                MyMockAdapter
                .Setup(x => x.GetErrorMessageResourceName(myAttribute))
                .Returns("Whatever")
                .Verifiable();

                // Act
                ProvierUnderTest.CreateValidationMetadata(context);

                // Assert
                Assert.Null(myAttribute.ErrorMessageResourceName);
                Assert.Null(myAttribute.ErrorMessageResourceType);
                Assert.Equal("Some message", myAttribute.ErrorMessage);
                MyMockAdapter.Verify(
                    x => x.GetErrorMessageResourceName(myAttribute),
                    Times.Never
                    );
            }
Esempio n. 7
0
            public void CreateValidationMetadata(
                ValidationMetadataProviderContext context)
            {
                if (context.Key.ModelType.GetTypeInfo().IsValueType&&
                    context.ValidationMetadata.ValidatorMetadata.Where(m => m.GetType() == typeof(RequiredAttribute)).Count() == 0)
                {
                    context.ValidationMetadata.ValidatorMetadata.Add(new RequiredAttribute());
                }

                foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
                {
                    ValidationAttribute tAttr = attribute as ValidationAttribute;
                    if (tAttr != null && tAttr.ErrorMessageResourceName == null)
                    {
                        //何故かEmailAddressAttributeはErrorMessageがデフォルトでnullにならない。
                        if (tAttr.ErrorMessage == null || (attribute as EmailAddressAttribute != null && !string.IsNullOrEmpty(tAttr.ErrorMessage)))
                        {
                            var name = tAttr.GetType().Name;
                            if (resourceManager.GetString(name) != null)
                            {
                                tAttr.ErrorMessageResourceType = resourceType;
                                tAttr.ErrorMessageResourceName = name;
                                tAttr.ErrorMessage             = null;
                            }
                        }
                    }
                }
            }
Esempio n. 8
0
        public void CanCreateValidationMetadata()
        {
            var(key, attributes) = GetMockedDependencies();
            var context = new ValidationMetadataProviderContext(key, attributes);

            _compositeMetadataDetailsProvider.CreateValidationMetadata(context);
        }
Esempio n. 9
0
    public void CreateValidationMetadata_SetsHasValidatorsToTrue_IfProviderReturnsTrue()
    {
        // Arrange
        var metadataBasedModelValidatorProvider = new Mock <IMetadataBasedModelValidatorProvider>();

        metadataBasedModelValidatorProvider.Setup(p => p.HasValidators(typeof(object), It.IsAny <IList <object> >()))
        .Returns(true)
        .Verifiable();

        var validationProviders = new IModelValidatorProvider[]
        {
            new DefaultModelValidatorProvider(),
            metadataBasedModelValidatorProvider.Object,
        };
        var metadataProvider = new HasValidatorsValidationMetadataProvider(validationProviders);

        var key             = ModelMetadataIdentity.ForType(typeof(object));
        var modelAttributes = new ModelAttributes(new object[0], new object[0], new object[0]);
        var context         = new ValidationMetadataProviderContext(key, modelAttributes);

        // Act
        metadataProvider.CreateValidationMetadata(context);

        // Assert
        Assert.True(context.ValidationMetadata.HasValidators);
        metadataBasedModelValidatorProvider.Verify();
    }
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
            {
                var validationAttribute = attribute as ValidationAttribute;
                if (validationAttribute == null)
                {
                    continue;
                }

                // ignore custom error messages
                if (string.IsNullOrWhiteSpace(validationAttribute.ErrorMessage) == false)
                {
                    continue;
                }

                // only continue if ErrorMessageResourceName is set
                if (string.IsNullOrWhiteSpace(validationAttribute.ErrorMessageResourceName))
                {
                    continue;
                }

                // only continue if DefaultResourceAttribute is set on the container class
                var defaultResource = context.Key.ContainerType.GetCustomAttribute <DefaultResourceAttribute>();
                if (defaultResource == null)
                {
                    continue;
                }

                validationAttribute.ErrorMessageResourceType = defaultResource.ResourceType;
            }
        }
    public void CreateValidationMetadata(ValidationMetadataProviderContext context)
    {
        foreach (var attr in context.Attributes)
        {
            if (!(attr is ValidationAttribute validationAttr))
            {
                continue;
            }

            // Do nothing if custom error message or localization options are specified
            if (!(string.IsNullOrWhiteSpace(validationAttr.ErrorMessage) || attr is DataTypeAttribute))
            {
                continue;
            }
            if (!string.IsNullOrWhiteSpace(validationAttr.ErrorMessageResourceName) && validationAttr.ErrorMessageResourceType != null)
            {
                continue;
            }

            foreach (var adapter in Adapters)
            {
                if (adapter.CanHandle(validationAttr))
                {
                    validationAttr.ErrorMessageResourceType = ErrorMessageResourceType;
                    validationAttr.ErrorMessageResourceName = adapter.GetErrorMessageResourceName(validationAttr);
                    validationAttr.ErrorMessage             = null;
                    break;
                }
            }
        }
    }
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context.Attributes == null)
            {
                return;
            }

            foreach (var contextParameterAttribute in context.Attributes)
            {
                if (!(contextParameterAttribute is ValidationAttribute attribute))
                {
                    continue;
                }

                if (attribute.ErrorMessage != null)
                {
                    continue;
                }

                var message = _messages.Get(attribute.GetType());

                if (message != null)
                {
                    attribute.ErrorMessage = message;
                }
            }
        }
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     foreach (var builder in Builders)
     {
         builder.Apply(context);
     }
 }
Esempio n. 14
0
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     foreach (var bindingProvider in providers.OfType <IValidationMetadataProvider>())
     {
         bindingProvider.CreateValidationMetadata(context);
     }
 }
Esempio n. 15
0
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (Type != null)
            {
                if (Type.IsAssignableFrom(context.Key.ModelType))
                {
                    context.ValidationMetadata.ValidateChildren = false;
                }

                return;
            }

            if (FullTypeName != null)
            {
                if (IsMatchingName(context.Key.ModelType))
                {
                    context.ValidationMetadata.ValidateChildren = false;
                }

                return;
            }

            Debug.Fail("We shouldn't get here.");
        }
            public void Should_update_ErrorMessageResource_of_ValidationAttribute()
            {
                // Arrange
                var key         = new ModelMetadataIdentity();
                var myAttribute = new MyValidationAttribute();
                var attributes  = new ModelAttributes(new object[] { myAttribute });
                var context     = new ValidationMetadataProviderContext(key, attributes);
                var expectedErrorMessageResourceName = "SomeResourceName";

                MyMockAdapter
                .Setup(x => x.CanHandle(myAttribute))
                .Returns(true);
                MyMockAdapter
                .Setup(x => x.GetErrorMessageResourceName(myAttribute))
                .Returns(expectedErrorMessageResourceName);

                // Act
                ProvierUnderTest.CreateValidationMetadata(context);

                // Assert
                Assert.Equal(
                    expectedErrorMessageResourceName,
                    myAttribute.ErrorMessageResourceName
                    );
                Assert.Equal(
                    ProvierUnderTest.ErrorMessageResourceType,
                    myAttribute.ErrorMessageResourceType
                    );
            }
Esempio n. 17
0
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (context.Key.ContainerType != null && !context.Key.ContainerType.IsValueType)
            {
                var viewConfig = ServiceLocator.GetViewConfigure(context.Key.ContainerType);

                if (viewConfig != null && context.Key.Name.IsNotNullAndWhiteSpace())
                {
                    var descriptor = viewConfig.GetViewPortDescriptor(context.Key.Name);
                    if (descriptor != null)
                    {
                        descriptor.Validator.Each(v =>
                        {
                            v.DisplayName = descriptor.DisplayName;
                            if (v is RangeValidator)
                            {
                                RangeValidator valid = (RangeValidator)v;
                                RangeAttribute range = new RangeAttribute(valid.Min, valid.Max);
                                range.ErrorMessage   = valid.ErrorMessage;

                                context.ValidationMetadata.ValidatorMetadata.Add(range);
                            }
                            else if (v is RegularValidator)
                            {
                                RegularValidator valid             = (RegularValidator)v;
                                RegularExpressionAttribute regular = new RegularExpressionAttribute(valid.Expression);
                                regular.ErrorMessage = valid.ErrorMessage;
                                context.ValidationMetadata.ValidatorMetadata.Add(regular);
                            }
                            else if (v is RemoteValidator)
                            {
                                RemoteValidator valid  = (RemoteValidator)v;
                                RemoteAttribute remote = new RemoteAttribute(valid.Action, valid.Controller, valid.Area);
                                remote.ErrorMessage    = valid.ErrorMessage;
                                context.ValidationMetadata.ValidatorMetadata.Add(remote);
                            }
                            else if (v is RequiredValidator)
                            {
                                RequiredValidator valid    = (RequiredValidator)v;
                                RequiredAttribute required = new RequiredAttribute();
                                required.ErrorMessage      = valid.ErrorMessage;
                                context.ValidationMetadata.ValidatorMetadata.Add(required);
                            }
                            else if (v is StringLengthValidator)
                            {
                                StringLengthValidator valid        = (StringLengthValidator)v;
                                StringLengthAttribute stringLength = new StringLengthAttribute(valid.Max);
                                stringLength.ErrorMessage          = valid.ErrorMessage;
                                context.ValidationMetadata.ValidatorMetadata.Add(stringLength);
                            }
                        });
                    }
                }
            }
        }
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     NullCheckHelper.ArgumentCheckNull(context, nameof(ValidationMetadataProvider));
     if (context.Attributes.OfType <ClientRequiredAttribute>().Any())
     {
         context.ValidationMetadata.IsRequired = true;
     }
 }
 /// <inheritdoc />
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     if (MaybeUtils.IsMaybeType(context.Key.ModelType))
     {
         // Maybe<T> should be considered as a whole during validation. Prevent ASP.NET Core from validating
         // the children of a Maybe<T> instance.
         context.ValidationMetadata.ValidateChildren = false;
     }
 }
Esempio n. 20
0
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            // ignore non-properties and types that do not match some model base type
            if (context?.Key.ContainerType == null ||
                !_injectableType.IsAssignableFrom(context.Key.ContainerType))
            {
                return;
            }

            // In the code below I assume that expected use of ErrorMessage will be:
            // 1 - not set when it is ok to fill with the default translation from the resource file
            // 2 - set to a specific key in the resources file to override my defaults
            // 3 - never set to a final text value
            var propertyName = context.Key.Name;
            var modelName    = context.Key.ContainerType.Name;

            // sanity check
            if (string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(modelName))
            {
                return;
            }

            foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
            {
                if (attribute is ValidationAttribute tAttr)
                {
                    // at first, assume the text to be generic error
                    var errorName    = tAttr.GetType().Name;
                    var fallbackName = errorName + "_ValidationError";
                    // Will look for generic widely known resource keys like
                    // MaxLengthAttribute_ValidationError
                    // RangeAttribute_ValidationError
                    // EmailAddressAttribute_ValidationError
                    // RequiredAttribute_ValidationError
                    // etc.

                    // Treat errormessage as resource name, if it's set,
                    // otherwise assume default.
                    var name = tAttr.ErrorMessage ?? fallbackName;

                    // At first, attempt to retrieve model specific text
                    var localized = _stringLocalizer[name];

                    // Final attempt - default name from property alone
                    if (localized.ResourceNotFound) // missing key or prefilled text
                    {
                        localized = _stringLocalizer[fallbackName];
                    }

                    // If not found yet, then give up, leave initially determined name as it is
                    var text = localized.ResourceNotFound ? name : localized;

                    tAttr.ErrorMessage = text;
                }
            }
        }
 public void Apply(ValidationMetadataProviderContext context)
 {
     if (_key.Equals(context.Key))
     {
         foreach (var action in _validationActions)
         {
             action(context.ValidationMetadata);
         }
     }
 }
Esempio n. 22
0
 public void CreateValidationMetadata(ValidationMetadataProviderContext context)
 {
     if (context.Key.MetadataKind == ModelMetadataKind.Property)
     {
         foreach (var configurator in _provider.GetMetadataConfigurators(context.Key))
         {
             configurator.Configure(context.ValidationMetadata);
         }
     }
 }
Esempio n. 23
0
 public void CreateValidationMetadata(ValidationMetadataProviderContext context) =>
 // 201704042333AMA
 // ابتدا همه اتریبیوت ها دریافت کرده و از بین آنها
 // آنهایی که مربوط به اعتبارسنجی هستند را جدا می کنیم
 // سپس پراپرتی متن خطای آنها را تغییر می دهیم
 context
 .PropertyAttributes
 ?.Where(attribute => attribute is ValidationAttribute)
 ?.Cast <ValidationAttribute>()
 ?.ToList()
 ?.ForEach(att =>
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
            {
                if (attribute is not ValidationAttribute validationAttribute)
                {
                    continue;
                }

                validationAttribute.ErrorMessage = ValidationErrors.MapAttributeToConstant(validationAttribute);
            }
        }
Esempio n. 25
0
    public void CreateValidationMetadata(ValidationMetadataProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        foreach (var provider in _providers.OfType <IValidationMetadataProvider>())
        {
            provider.CreateValidationMetadata(context);
        }
    }
        private void UpdateErrorMessage(IStringLocalizer stringLocalizer, ValidationMetadataProviderContext context, ValidationAttribute attribute)
        {
            if (CanUpdateErrorMessage(attribute))
            {
                var propertyName  = context.Key.Name;
                var validatorName = attribute.GetValidatorName();

                attribute.ErrorMessage = propertyName != null
                    ? GetErrorMessageKey(stringLocalizer, propertyName, validatorName)
                    : validatorName;
            }
        }
Esempio n. 27
0
    internal static bool IsRequired(ValidationMetadataProviderContext context)
    {
        var nullabilityContext = new NullabilityInfoContext();
        var nullability = context.Key.MetadataKind switch
        {
            ModelMetadataKind.Parameter => nullabilityContext.Create(context.Key.ParameterInfo!),
            ModelMetadataKind.Property => nullabilityContext.Create(context.Key.PropertyInfo!),
            _ => null
        };
        var isOptional = nullability != null && nullability.ReadState != NullabilityState.NotNull;
        return !isOptional;
    }
}
        private void RecreateMetadata(ModelMetadataIdentity key, DefaultMetadataDetails details)
        {
            var validationContext = new ValidationMetadataProviderContext(key, details.ModelAttributes);
            var displayContext    = new DisplayMetadataProviderContext(key, details.ModelAttributes);
            var bindingContext    = new BindingMetadataProviderContext(key, details.ModelAttributes);

            DetailsProvider.CreateValidationMetadata(validationContext);
            DetailsProvider.CreateDisplayMetadata(displayContext);
            DetailsProvider.CreateBindingMetadata(bindingContext);
            details.ValidationMetadata = validationContext.ValidationMetadata;
            details.DisplayMetadata    = displayContext.DisplayMetadata;
            details.BindingMetadata    = bindingContext.BindingMetadata;
        }
Esempio n. 29
0
        public void CreateValidationMetadata(
            ValidationMetadataProviderContext context)
        {
            var metaData = context.ValidationMetadata.ValidatorMetadata;

            // int/Decimal/DateTime等の値型の場合、
            // 暗黙的に必須属性が追加されるので、そのメッセージも置き換え
            if (context.Key.ModelType.GetTypeInfo().IsValueType&&
                metaData.Where(m => m.GetType() == typeof(RequiredAttribute)).Count() == 0)
            {
                metaData.Add(new RequiredAttribute());
            }

            // 対象プロパティに紐づく全ての属性に対して処理
            foreach (var obj in metaData)
            {
                if (!(obj is ValidationAttribute attr))
                {
                    continue;
                }

                // リソースやメッセージが変更されている場合はそれを優先
                // (新旧メッセージが共にnullも「変更なし」とみなす)
                if (attr.ErrorMessageResourceName != null)
                {
                    continue;
                }
                Type   type           = attr.GetType();
                string message        = attr.ErrorMessage;
                string?defaultMessage = this.defaultMessageDic.GetValueOrDefault(type);
                if (!string.Equals(message, defaultMessage))
                {
                    continue;
                }

                // メッセージが既定から変更されておらず、
                // 対応するメッセージが未定義の場合は既定の動作に任せる
                string name       = RESOURCE_KEY_PREFIX + type.Name;
                string?newMessage = resourceManager.GetString(name);
                if (string.IsNullOrEmpty(newMessage))
                {
                    continue;
                }

                // メッセージが既定から変更されておらず、
                // 対応するメッセージが定義されている場合、それで上書き
                attr.ErrorMessageResourceType = resourceType;
                attr.ErrorMessageResourceName = name;
                attr.ErrorMessage             = null;
            }
        }
        public void CreateValidationMetadata(ValidationMetadataProviderContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // Add Required attribute to value types to simplify localization
            if (context.Key.ModelType.GetTypeInfo().IsValueType&& Nullable.GetUnderlyingType(context.Key.ModelType.GetTypeInfo()) == null && !context.ValidationMetadata.ValidatorMetadata.OfType <RequiredAttribute>().Any())
            {
                context.ValidationMetadata.ValidatorMetadata.Add(new RequiredAttribute());
            }

            foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
            {
                var validationAttribute = attribute as ValidationAttribute;
                if (validationAttribute == null)
                {
                    continue;                              // Not a validation attribute
                }
                // Do nothing if custom error message or localization options are specified
                if (!(string.IsNullOrWhiteSpace(validationAttribute.ErrorMessage) || attribute is DataTypeAttribute))
                {
                    continue;
                }
                if (!string.IsNullOrWhiteSpace(validationAttribute.ErrorMessageResourceName) && validationAttribute.ErrorMessageResourceType != null)
                {
                    continue;
                }

                // Get attribute name without the "Attribute" suffix
                var attributeName = validationAttribute.GetType().Name;
                if (attributeName.EndsWith(AttributeNameSuffix, StringComparison.Ordinal))
                {
                    attributeName = attributeName.Substring(0, attributeName.Length - AttributeNameSuffix.Length);
                }

                // Link to resource if exists
                var resourceKey = this._resourceManager.GetResourceKeyName(context.Key, attributeName);
                if (resourceKey != null)
                {
                    validationAttribute.ErrorMessageResourceType = this._resourceType;
                    validationAttribute.ErrorMessageResourceName = attributeName;
                    validationAttribute.ErrorMessage             = null;
                }
                else
                {
                    validationAttribute.ErrorMessage = $"Missing resource key for '{attributeName}'.";
                }
            }
        }