How to put conditional Required Attribute into class property to work with WEB API?
I just want to put conditional Required Attribute which is work with WEB API
Example
public sealed class EmployeeModel
{
[Required]
public int CategoryId{ get; set; }
public string Email{ get; set; } // If CategoryId == 1 then it is required
}
I am using Model State validation via (ActionFilterAttribute)
You can implement your own ValidationAttribute
. Perhaps something like this:
public class RequireWhenCategoryAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var employee = (EmployeeModel) validationContext.ObjectInstance;
if (employee.CategoryId == 1)
return ValidationResult.Success;
var emailStr = value as string;
return string.IsNullOrWhiteSpace(emailStr)
? new ValidationResult("Value is required.")
: ValidationResult.Success;
}
}
public sealed class EmployeeModel
{
[Required]
public int CategoryId { get; set; }
[RequireWhenCategory]
public string Email { get; set; } // If CategoryId == 1 then it is required
}
This is just a sample. It may have casting issues, and I'm not sure this is the best approach to solve this problem.
Here's my 2 cents. It will give you a nice message like "AssigneeId is required for the current AssigneeType value Salesman" It works for enums too.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
public class RequiredForAnyAttribute : ValidationAttribute
{
/// <summary>
/// Values of the <see cref="PropertyName"/> that will trigger the validation
/// </summary>
public string[] Values { get; set; }
/// <summary>
/// Independent property name
/// </summary>
public string PropertyName { get; set; }
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var model = validationContext.ObjectInstance;
if (model == null || Values == null)
{
return ValidationResult.Success;
}
var currentValue = model.GetType().GetProperty(PropertyName)?.GetValue(model, null)?.ToString();
if (Values.Contains(currentValue) && value == null)
{
var propertyInfo = validationContext.ObjectType.GetProperty(validationContext.MemberName);
return new ValidationResult($"{propertyInfo.Name} is required for the current {PropertyName} value {currentValue}");
}
return ValidationResult.Success;
}
}
Use it like this
public class SaveModel {
[Required]
public AssigneeType? AssigneeType { get; set; }
[RequiredForAny(Values = new[] { nameof(AssigneeType.Salesman) }, PropertyName = nameof(AssigneeType))]
public Guid? AssigneeId { get; set; }
}