Reputation: 32515
Basically, if I have a collection of objects, how can I apply a validation attribute to each item in the collection (such as MaxLengthAttribute
)?
public class Foo
{
public ICollection<string> Bars { get; set; }
}
For example, how can I ensure that Bars contains strings that validate against a max length of 256?
Update:
I understand how to apply a validation attribute on a single property, but the question is asking how to apply it on objects within a collection.
public class Foo
{
[StringLength(256)] // This is obvious
public string Bar { get; set; }
// How do you apply the necessary attribute to each object in the collection!
public ICollection<string> Bars { get; set; }
}
Upvotes: 5
Views: 2382
Reputation: 13448
I know this question is kinda old, but maybe someone comes along looking for answers.
I'm not aware of a generic way to apply attributes to collection items, but for the specific string length example I used the following:
public class StringEnumerationLengthValidationAttribute : StringLengthAttribute
{
public StringEnumerationLengthValidationAttribute(int maximumLength)
: base(maximumLength)
{ }
public override bool RequiresValidationContext { get { return true; } }
public override bool IsValid(object value)
{ return false; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var e1 = value as IEnumerable<string>;
if (e1 != null) return IsEnumerationValid(e1, validationContext);
return ValidationResult.Success; // what if applied to something else than IEnumerable<string> or it is null?
}
protected ValidationResult IsEnumerationValid(IEnumerable<string> coll, ValidationContext validationContext)
{
foreach (var item in coll)
{
// utilize the actual StringLengthAttribute to validate the items
if (!base.IsValid(item) || (MinimumLength > 0 && item == null))
{
return new ValidationResult(base.FormatErrorMessage(validationContext.DisplayName));
}
}
return ValidationResult.Success;
}
}
Apply as follows, to require 4-10 characters for each collection item:
[StringEnumerationLengthValidation(10, MinimumLength=4)]
public ICollection<string> Sample { get; set; }
Upvotes: 2
Reputation: 4647
OK I found a pretty nice article explaining some useful info about this:
Here is some suggested code that would make the Bars member of Foo do what you want.
public class Foo
{
public ValidatedStringCollection Bars = new ValidatedStringCollection(10);
}
public class ValidatedStringCollection : Collection<string>
{
int _maxStringLength;
public ValidatedStringCollection(int MaxStringLength)
{
_maxStringLength = MaxStringLength;
}
protected override void InsertItem(int index, string item)
{
if (item.Length > _maxStringLength)
{
throw new ArgumentException(String.Format("Length of string \"{0}\" is beyond the maximum of {1}.", item, _maxStringLength));
}
base.InsertItem(index, item);
}
}
class Program
{
static void Main(string[] args)
{
Foo x = new Foo();
x.Bars.Add("A");
x.Bars.Add("CCCCCDDDDD");
//x.Bars.Add("This string is longer than 10 and will throw an exception if uncommented.");
foreach (string item in x.Bars)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
The linked article has several suggestions including overriding the other methods on the collection, implementing events conditionally, etc. This should hopefully cover you.
Upvotes: 1
Reputation: 4647
Take a look at the data annotation functionality:
Does this work for you?
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public class Foo
{
[StringLength(256)]
public ICollection<string> Bars { get; set; }
}
Upvotes: -1