Click here to Skip to main content
15,881,600 members
Articles / Programming Languages / C# 5.0

Custom Validation Attribute – Contains

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
3 Aug 2015CPOL1 min read 5.6K   1  
Custom validation attribute - contains

Situation

I needed to create a custom validation attribute. More specifically, contains attribute.

I have a a few properties where I need to know if input value is valid and valid = value is contained in a list of allowed values.

For example:

property: title

allowed values: Mr, Mrs, Miss, Dr, etc.

So I created my own custom validation attribute:

C#
public class ContainsValidatorAttribute : ValidationAttribute
{
    public string[] AcceptedValues { get; set; }
    public override bool IsValid(object value)
    {
        string strValue = value as string;
        if (!AcceptedValues.Contains(strValue))
        {
            return false;
        }
        return true;
    }
}
 
//Usage:
[ContainsValidator(AcceptedValues = new[] { "Mr", "Mrs", "Miss", "Ms", "Dr" }, 
ErrorMessage = "Not a valid title")]
public string Title { get; set; }

This works great, but then I thought it would be much better to have all the values in one place rather than write them right into an attribute.

So I created a static helper class with all allowed values:

C#
public static class ValidatorHelper
{
    public static readonly string[] Titles = { "Mr", "Mrs", "Miss", "Ms", "Dr" };
    public static readonly string[] SmokerStatus = { "Yes", "No", "Ex"};
}

However, this will not work, because you cannot pass a static value into an attribute like this:

C#
[ContainsValidator(AcceptedValues = ValidatorHelper.Titles, ErrorMessage = "Not a valid title")]
public string Title { get; set; }

This will end with error even if you make string[] AcceptedValues static.

My Solution

C#
public class ContainsValidatorAttribute : ValidationAttribute
{
    public string AcceptedValuesKey { get; set; }
    public override bool IsValid(object value)
    {
        var strValue = (string) value;
        string[] values;
        ValidatorHelper.Dictionary.TryGetValue(AcceptedValuesKey, out values);
        return values != null && values.Contains(strValue);
    }
}

and store values in a dictionary:

C#
public static class ValidatorHelper
{
    public static readonly string[] Titles = { "Mr", "Mrs", "Miss", "Ms", "Dr" };
    public static readonly string[] SmokerStatus = { "Yes", "No", "Ex"};

    public const string TitleKey = "Title";
    public const string SmokerStatusKey = "Smoke";

    public static Dictionary<string, string[]> Dictionary = new Dictionary<string, string[]>()
    {
        {TitleKey, Titles},
        {SmokerStatusKey, SmokerStatus},
    };
}

Now you can store all values in one place and use dictionary to get allowed values.

C#
[ContainsValidator(AcceptedValuesKey = ValidatorHelper.TitleKey, ErrorMessage = "Not a valid title")]
public string Title { get; set; }

And here is the unit test.

C#
[TestClass]
    public class ContainsAttributeTest
    {
        [TestMethod]
        public void TestContainsAttribute()
        {
            var attr = new ContainsValidatorAttribute();
            attr.AcceptedValuesKey = ValidatorHelper.TitleKey;
            var result = attr.IsValid("Mr");

            Assert.AreEqual(true, result);
        }

        [TestMethod]
        public void TestContainsAttributeFailNull()
        {
            var attr = new ContainsValidatorAttribute();
            attr.AcceptedValuesKey = "invalid key";
            var result = attr.IsValid("Mr");

            Assert.AreEqual(false, result);
        }

        [TestMethod]
        public void TestContainsAttributeFailInvalidValue()
        {
            var attr = new ContainsValidatorAttribute();
            attr.AcceptedValuesKey = ValidatorHelper.TitleKey;
            var result = attr.IsValid("invalid");

            Assert.AreEqual(false, result);
        }
    }

Summary

This is not an ideal solution, but it is the only one I was able to come up with.

If you have any ideas on how to improve this solution, I would be grateful if you could share it with us in the comments.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --