Click here to Skip to main content
15,887,746 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Say for example my model was

Year
Make
[RequiredIF(Year != null)
Model
[RequiredIF(Year != null and Make != null)
Trim

I am using .NET Core for the solution and have seen exampled for RequireIF but it only checks one field. I need multiple fields.

Thanks
Steve

What I have tried:

public class RequiredIfAttribute : ValidationAttribute
    {

        RequiredAttribute _innerAttribute = new RequiredAttribute();
        private string _dependentProperty { get; set; }
        private object _targetValue { get; set; }

        public RequiredIfAttribute(string dependentProperty, object targetValue)
        {
            this._dependentProperty = dependentProperty;
            this._targetValue = targetValue;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var field = validationContext.ObjectType.GetProperty(_dependentProperty);
            if (field != null)
            {
                var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
                if ((dependentValue == null && _targetValue == null) || (dependentValue.Equals(_targetValue)))
                {
                    if (!_innerAttribute.IsValid(value))
                    {
                        string name = validationContext.DisplayName;
                        return new ValidationResult(ErrorMessage = name + " Is required.");
                    }
                }
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult(FormatErrorMessage(_dependentProperty));
            }
        }
Posted
Updated 10-Jul-19 6:05am

The extended solution includes passing the field and required value. Here the attribute pass comma separated text to pass field and value. Each of these pairs is considered 'and'.

[RequiredIf(new string[] {"Year,1994", "Make,!null"})]


In the actual attribute, we parse the value pair and check if the value is required for the field.

public class RequiredIfAttribute : ValidationAttribute
    {
        private const string DefaultErrorMessageFormatString = "The {0} field is required.";
        private readonly string[] _dependentProperties;

        public RequiredIfAttribute(string[] dependentProperties)
        {
            _dependentProperties = dependentProperties;
            ErrorMessage = DefaultErrorMessageFormatString;
        }

        private bool IsValueRequired(string checkValue, Object currentValue)
        {
            if (checkValue.Equals("!null", StringComparison.InvariantCultureIgnoreCase))
            {
                return currentValue != null;
            }

            return checkValue.Equals(currentValue);
        }

        protected override ValidationResult IsValid(Object value, ValidationContext context)
        {
            Object instance = context.ObjectInstance;
            Type type = instance.GetType();
            bool valueRequired = false;

            foreach (string s in _dependentProperties)
            {
                var fieldValue = s.Split(',').ToList().Select(k => k.Trim()).ToArray();

                Object propertyValue = type.GetProperty(fieldValue[0]).GetValue(instance, null);

                valueRequired = IsValueRequired(fieldValue[1], propertyValue);
            }

            if (valueRequired)
            {
                return value != null
                    ? ValidationResult.Success
                    : new ValidationResult(context.DisplayName + " required. ");
            }
            return ValidationResult.Success;
        }
    }


Note that checking if the field has null value involves some string parsing. In the solution above, I am assuming 'And' operator for all the field value pairs. The above solution can be extended to add an equality operator.
 
Share this answer
 
Comments
smoro999 10-Jul-19 14:50pm    
Thanks this works. Appreciate the direction and help.
Benktesh Sharma 10-Jul-19 14:59pm    
Wonderful. Thanks.
Since you want multiple fields to be part of the validation attribute, it is much easier to pass an array of parameters to the constructor of the RequiredIf attribute and loop through the fields to make logic. I did something similar and here is the code.

For making simple, I used single constructor and thus I have to pass array even for a single field, but this can be changed.

For validating model, I am passing array of fields as below:
[RequiredIf(new string[] {"Year", "Make"})]


The IsValid method simply goes through the fields and checks. Null checking happens within the validation logic.

Let me know for any questions.


Here are the associated codes.

public String Year { get; set; }

[RequiredIf(new string[] {"Year"})]
public String Make { get; set; }

[RequiredIf(new string[] {"Year", "Make"})]
public String Model { get; set; }

public String Trim { get; set; }


public class RequiredIfAttribute : ValidationAttribute
   {
       private const string DefaultErrorMessageFormatString = "The {0} field is required.";
       private readonly string[] _dependentProperties;

       public RequiredIfAttribute(string[] dependentProperties)
       {
           _dependentProperties = dependentProperties;
           ErrorMessage = DefaultErrorMessageFormatString;
       }

       protected override ValidationResult IsValid(Object value, ValidationContext context)
       {
           Object instance = context.ObjectInstance;
           Type type = instance.GetType();

           foreach (string s in _dependentProperties)
           {
               Object propertyValue = type.GetProperty(s).GetValue(instance, null);
               if (propertyValue == null || value != null)
               {
                   return ValidationResult.Success;
               }
           }
           return new ValidationResult(context.DisplayName + " required. ");
       }
   }
 
Share this answer
 
Comments
smoro999 9-Jul-19 8:11am    
If I wanted to also have this work

[RequiredIF(Year == 2019 && Make != null)
Trim

Would like to be able to do conditional with and/or with actual values.

Thanks in advance.
Steve
Benktesh Sharma 10-Jul-19 11:13am    
Thanks Steve,
I am glad that the solution I provided helped you. To get a solution that you need, I believe we can extend the attribute to pass the values as well as the equality operator. Let me work a bit on this and provide you with something to get started. Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900