29

I'm working on a Web API 2 project. besides the requirement that some properties are required, some only can have specific values. One option is that I could try to save the model to the database (EF6) and create some logic while saving, but I think it is better to validate if the correct value is set before I make a call to the database. Does data annotations provide an attribute like Range but then for specific string values like in the example below? Or do I have to write my own validator attribute?

public class Person {
    public int PersonID { get; set; }

    [Required]
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [StringRange("M","F")]
    public string Gender { get; set; }
}

In the above example, when a post is done to the controller, the only values to accept are "M" or "F".

2

4 Answers 4

48

In case anyone stumbles upon this thread in the future, I took it a little further and added a public string array property accepting the allowable values in the validation filter. This will allow you to provide a collection of valid strings in the attribute decorator.

This way, you now have a generic reusable attribute you can use anytime to limit a model string property to a predefined set of values. Since it's a validation attribute, you can decorate it with a more informative error message as well.

Example Usage:

public class Person {
    [StringRange(AllowableValues = new[] { "M", "F" }, ErrorMessage = "Gender must be either 'M' or 'F'.")]
    public string Gender { get;set; }
}

String Attribute:

public class StringRangeAttribute : ValidationAttribute
{
    public string[] AllowableValues { get; set; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (AllowableValues?.Contains(value?.ToString()) == true)
        {
            return ValidationResult.Success;
        }

        var msg = $"Please enter one of the allowable values: {string.Join(", ", (AllowableValues ?? new string[] { "No allowable values found" }))}.";
        return new ValidationResult(msg);
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

For AllowableValues?.Contains() I had better luck with AllowableValues?.Any(). I love this solution, Simon!
ErrorMessage defined in the attribute is ignored and instead the content of msg variable is displayed when you do not enter any of the allowable values.
16

To validate the Gender property I've created a custom validation attribute by creating a new class (attribute):

using System;
using System.Collections.Generic;
using System.Web;
using System.ComponentModel.DataAnnotations;    

namespace MyProject.Models.Validation
{

    public class StringRangeAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {

            if(value.ToString() == "M" || value.ToString() == "F")
            {
                return ValidationResult.Success;
            }


            return new ValidationResult("Please enter a correct value");
        }
    }
}

Comments

12

you can use reqular expression like this:

[RegularExpression("M|F", ErrorMessage = "The Gender must be either 'M' or 'F' only.")]
public string Gender { get; set; }

but in my api it will show error message when i passed data so you can add

[StringLength(1, MinimumLength = 1, ErrorMessage = "The Gender must be 1 characters.")]

final code:

[StringLength(1, MinimumLength = 1, ErrorMessage = "The Gender must be 1 characters.")]
[RegularExpression("M|F", ErrorMessage = "The Gender must be either 'M' or 'F' only.")]
public string Gender { get; set; }

2 Comments

Nice. Quick 'n' dirty, and ideal for my present project!
What else if you have passed m|f. It will get failed. What need to add in lower case two get it pass ?
5
[Required]
[RegularExpression("value1|value2|value3|...", ErrorMessage = "YourMessageHere")]
public string Gender { get; set; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.