Does there exist an enum validation attribute which validates a certain enum value?
Or should I do that manually:
if(viewModel.State == State.None) base.AddModelError("","wrong enum selected...");
How would you do that?
Enum:
public enum SomeEnum
{
Right = 1,
Wrong = 2,
Other = 3
}
ViewModel:
public class TestModel
{
[Range((int)(SomeEnum.Right), (int)(SomeEnum.Right), ErrorMessage = "Please select an Enum value")]
public SomeEnum Value { get; set; }
}
No other code needed. Enums are basically integers so you can use the Range attribute to validate them.
I would create my own validation attribute something like (untested):
public enum SomeEnum
{
Right,
Wrong
}
[AttributeUsage(AttributeTargets.Property)]
public sealed class EnumValueAttribute : ValidationAttribute
{
private const string DefaultErrorMessage = "Cannot be that value";
public SomeEnum EnumVal { get; private set; }
public EnumValueAttribute(SomeEnum enumVal)
: base(DefaultErrorMessage)
{
EnumVal = enumVal;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name, EnumVal);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var enumVal = (SomeEnum) Enum.Parse(typeof (SomeEnum), value.ToString());
if (enumVal != EnumVal)
{
return new ValidationResult(DefaultErrorMessage);
}
return ValidationResult.Success;
}
}
Usage:
public class TestModel
{
[EnumValue(SomeEnum.Right)]
public SomeEnum Value { get; set; }
}
UPDATED
So this is as generic as you can reasonably take it, I've not tested this code, but it does compile. Notice that I've assigned number values to the enums.
public enum SomeEnum
{
Right = 1,
Wrong = 2,
Other = 3
}
[AttributeUsage(AttributeTargets.Property)]
public sealed class DisallowEnumValueAttribute : ValidationAttribute
{
public object DissallowedEnum { get; private set; }
public Type EnumType { get; private set; }
public DisallowEnumValueAttribute(Type enumType, object dissallowedEnum)
{
if (!enumType.IsEnum)
throw new ArgumentException("Type must be an enum", "enumType");
DissallowedEnum = dissallowedEnum;
EnumType = enumType;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var disallowed = Convert.ChangeType(DissallowedEnum, EnumType);
var enumVal = Convert.ChangeType(value, EnumType);
if (disallowed == null || enumVal == null)
throw new Exception("Something is wrong"); //or return validation result
if (enumVal == disallowed)
{
return new ValidationResult("This value is not allowed");
}
return ValidationResult.Success;
}
}
public class TestModel
{
[DisallowEnumValue(typeof(SomeEnum), SomeEnum.Wrong)]
public SomeEnum Thing { get; set; }
}
My enum validation was like this and works in dataannotation validation
public enum CreatedBySelfOrOthersEnumValues
{
Self,
Others
}
public class CampaignRegisterValidationModel
{
[Required]
public string Name { get; set; }
[Required]
public CreatedBySelfOrOthersEnumValues CreatedForSelfOrOthers { get; set; }
[Required]
public int CountryCode { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
Then validating it
if (ModelState.IsValid)
{
}
[Required]public State? State { get; set; }and include only valid values inenum State(and if that enum is being used elsewhere, then use a view model). Alternatively you would need a custom validation attribute that accepts an array of valid (or invalid) names, something like[RequiredEnum(Exclude="None")]public State? State { get; set; }