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".

kwv84
  • 943
  • 3
  • 11
  • 25
  • 3
    You can use RegExes see http://stackoverflow.com/questions/8244572/dataannotations-validation-regular-expression-in-asp-net-mvc-4-razor-view – MajkeloDev Oct 07 '15 at 08:19
  • you can also create custom validation attribute https://www.youtube.com/watch?v=vcX8WW4fL1s – vijay shiyani Oct 07 '15 at 08:27

4 Answers4

45

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);
    }
}
Simon Wosko
  • 551
  • 1
  • 4
  • 3
  • For AllowableValues?.Contains() I had better luck with AllowableValues?.Any(). I love this solution, Simon! – ClaytonQ Dec 18 '20 at 14:21
  • 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. – Jan Jul 16 '21 at 14:37
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");
        }
    }
}
kwv84
  • 943
  • 3
  • 11
  • 25
11

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; }
tletle
  • 696
  • 6
  • 7
4
[Required]
[RegularExpression("value1|value2|value3|...", ErrorMessage = "YourMessageHere")]
public string Gender { get; set; }
splinter.cell
  • 113
  • 1
  • 7