0

I want to set the data annotation (display) of a field based on a variable or function:

public class InputModel
{            
    [Required]
    [StringLength(100, ErrorMessage = VARIABLE or FUNCTION())]
    [Display(Name = "Password - must use at least 12 characters")]
    [DataType(DataType.Password)]
    public string Password { get; set; }
}

How do you set data annotation programmatically?

InputModel.DataAnnotation.Display = "Foo";

How would you set the data annotation in the model to a variable or function?

poke
  • 369,085
  • 72
  • 557
  • 602
Barry MSIH
  • 3,525
  • 5
  • 32
  • 53
  • 1
    I do not understand how you see the Display Attribute related to the EF? Anyway, if you want to programmatically access the Atrribute, I would suggest you look into reflection. – Aldert Aug 05 '18 at 13:39
  • Attributes applied to members are "baked in" at compile time, you can't modify them once compiled. – Bradley Uffner Aug 05 '18 at 14:45

3 Answers3

0

You may derive a class (e.g. MyStringLenghtAttribute) from StringLengthAttribute and override the IsValid.

Prakash Dale
  • 526
  • 3
  • 7
0

You must extend DataAnnotationsModelValidatorProvider and override GetValidators method.

DataAnnotationsModelValidatorProvider loops through all the validation attributes using reflection to validate.

You can get access to all the attributes in the GetValidators methods and make changes to the validation attributes.

However you must register your custom DataAnnotationsModelValidatorProvider class in the application start like below.

protected void Application_Start()
    {
        ModelValidatorProviders.Providers.Add(new CustomMetadataValidationProvider());

        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);
    }

see below discussion for more details.

DataAnnotations dynamically attaching attributes

PNDev
  • 590
  • 1
  • 8
  • 23
0

StringLength is an ValidationAttribute which does not accept Variable or Function as constructor parameter.

If you want to custom StringLength error message, you could follow steps below:

  1. Custom ValidationAttribute

     public class StringError : StringLengthAttribute
     {
    private ErrorProvider _error;
    private string _key;
    public StringError(int maxlength, string key):base(maxlength)
    {
        _key = key;
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        _error = (ErrorProvider)validationContext.GetService(typeof(ErrorProvider));
    
        return base.IsValid(value, validationContext);
    }
    public override string FormatErrorMessage(string name)
    {
        if (_error != null)
        {
            return _error.Error(_key);
        }
        return base.FormatErrorMessage(name);   
    }
    }
    
  2. Define ErrorProvider to set and get ErrorMessage

        public class ErrorProvider
        {
    private Dictionary<string, string> _errorDic = new Dictionary<string, string>();
    
    public void AddOrUpdateError(string key, string value)
    {
        _errorDic[key] = value;
        //_errorDic.TryAdd(key,value);
    }
    public string Error(string key)
    {
        string value = null;
        _errorDic.TryGetValue(key, out value);
        return value;
    }
    }
    
  3. Resigter ErrorProvider

        services.AddSingleton<ErrorProvider>();
    
  4. Set the ErrorMessage value

        [HttpPost("SetKey")]
    public IActionResult SetKey([FromForm]string key,[FromForm]string value)
    {
        _errorProvider.AddOrUpdateError(key, value);
        return Ok();
    }
    [HttpPost("CustomAttribute")]
    public IActionResult CustomAttribute(InputModel input)
    {
        return Ok();
    }
    
    1. InputModel

         public class InputModel
        {
           [StringError(3, "Password")]
           public string Password { get; set; }
      
         }
      
Edward
  • 28,296
  • 11
  • 76
  • 121