4

I'm working on some code which use DataAnnotation attributes on viewmodels, and overrides some of the attributes programmatically under certain circumstances.

Changing ErrorMessage on various types of ValidationAttributes, no problem.

Changing DataFormatString on DisplayFormatAttributes, no problem.

Changing MinimumLength on a StringLengthAttribute, no problem. But.. MaximumLength does not have a public setter!?

Is there any reason why this one property stands out as having a private setter, when all around it are public? Is there any workaround I can use to programmatically change the maximum length of a StringLengthAttribute?

Carson63000
  • 4,215
  • 2
  • 24
  • 38
  • Thanks for the answers - however, what I ended up doing was implementing my own custom validation attribute, let's call it `MyStringLengthAttribute`, which was identical in function to the framework one, except with a public `MaximumLength` property. All works fine now. – Carson63000 Aug 23 '11 at 06:15

3 Answers3

3

Since the only public way to set the MaximumLength property is via the attribute constructor, there's no programmatic way to change it post-construction. You can always use private reflection to do what you need, assuming that you're running the code with sufficient trust. If you don't want to (or can't) go that route, another option would be to swap view models under the given conditions, rather than just updating the attributes as needed. Then you can just construct the needed attribute for each individual view model, and not worry about changing the attribute itself programmatically.

One final option is to actually write your own StringLength attribute. You can pretty easliy mimic the functionality of the built-in version, since its IsValid() method is really straightforward:

public override bool IsValid(object value)
{
    int num = (value == null) ? 0 : ((string)value).Length;
    return value == null || (num >= this.MinimumLength && num <= this.MaximumLength);
}

Mimicing that, but including a public setter on the MaximumLength property should get you what you need.

dlev
  • 48,024
  • 5
  • 125
  • 132
1

Assuming that you are using a custom ModelMetadataValidatorProvider, as I outlined at How to add validation attribute to model property in TemplateEditor in MVC3, in your override of the GetValidators method, you can iterate through the validators returned by the base method, remove the current StringLengthAttribute, and substitute your StringLengthAttribute, with the MaxLength value desired.

Community
  • 1
  • 1
counsellorben
  • 10,924
  • 3
  • 40
  • 38
  • I gave this idea a try, and in my custom ModelMetadataValidatorProvider, I can retrieve the `StringLengthAttributeAdapter` but its `Attribute` property is protected, so I can't get at the original attribute's minimum length and error message, to construct a new attribute with a different maximum length. – Carson63000 Aug 22 '11 at 04:50
0

Since this code is viewmodel specific have your ViewModel Implement the IValidateableObject interface and validate in there.


public IEnumerable Validate(ValidationContext validationContext)
{
    if (YourField.Length == 2)
    {
        yield return new ValidationResult("ut oh!!");
    }
}

Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71