3

Is there any data annotation for the allowed values in ASP.NET MVC Core? Since there is no enum in SQL server I am not able to migrate my class with enum field in it to the database. I want to give possible/allowed values to the field in the class. Is there any way to do this?

    public class Employee
    {
        [Key]
        public int ID { get; set; }

        [Required]
        public string Name { get; set; }

        [Required]
        public string Status { get; set; }

    }

I want to provide Active and Inactive as the only possible values to the Status field.

Adi
  • 405
  • 1
  • 7
  • 13
  • if you aren't presenting this as a drop down list, you can add a check constraint to your database. https://stackoverflow.com/a/11981892/2084315 – ps2goat Dec 09 '19 at 16:46
  • If you only have two options, I would store this as a Boolean. You could have a read-only property that return the value as a string if you really need it. If you had 3 values, then the enum would be an other table with a foreign key. – the_lotus Dec 09 '19 at 19:44

3 Answers3

6

you can also do this using a regular expression as below:

[Required]
[RegularExpression("Active|Inactive", ErrorMessage = "Invalid Status")]
 public string Status { get; set; }

More details can by found here

Aris
  • 4,643
  • 1
  • 41
  • 38
5

As @ps2goat mentioned, you could use a check constraint on your database. However, for the model coming into the API you probably still want to provide validation there. Ideally you will do what you can, within reason, to prevent bad data from ever getting to the data layer. You don't mention whether you're using an n-tier architecture, or if your controller is directly referencing the data model. Either way, I believe this custom attribute can be used either at the API layer or on the entity model.

This is a good answer that explains how to create a custom validation attribute. It's an old answer, but it still applies to .Net Core. And here is an answer for a custom validation attribute in .Net Core. It basically looks like this:

public class EmployeeStatusAttribute : ValidationAttribute
{
    private string[] _allowedValues;

    public EmployeeStatusAttribute(string[] allowedValues)
    {
        _allowedValues = allowedValues;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var employee = value as Employee;
        if (_allowedValues.Contains(employee.Status))
        {
            return ValidationResult.Success;
        }
        return new ValidationResult(`{employee.Status} is not a valid status`);
    }
}

Then in your model:

public class Employee
{
    ...

    [EmployeeStatus("Active", "Inactive")]
    public string Status { get; set; }

    ...
}
Matt U
  • 4,970
  • 9
  • 28
  • 1
    Good answer, but I believe in constructor you wanted to write `_allowedValues = allowedValues;` instead of `_args = allowedValues;` – Max Dec 09 '19 at 19:32
  • 1
    Oops, thanks @Max! I updated my answer. I had initially called it `_args` and forgot to change that instance of it. – Matt U Dec 09 '19 at 20:16
  • I have another following question on this. How can I access this in the dropdown in view? – Adi Jan 09 '20 at 17:26
1

In .NET 8 Preview 2 you can use the AllowedValues attribute for that.

[Required]
[AllowedValues("Active", "Inactive")]
public string Status { get; set; }

For more info: https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-2/#allowedvaluesattribute-and-deniedvaluesattribute.

Misha Zaslavsky
  • 8,414
  • 11
  • 70
  • 116