Problem Statement:

I'm using custom validation attribute RequiredIf to validate some fields in my MVC-Razor application.Everything was working fine.But recently we noticed, application taking too much time to respond after spending some time with the application.When contacted Microsoft support team,they suggested to change the requiredIf, as the current one is making the application to respond slowly.So we modified the old RequiredIf with the new one.But the current RequiredIf is not triggering the model data annotations which were triggering earlier.What's wrong in the new RequiredIf attribute.

Any suggestion/answer would be highly appreciated.??

Old RequiredIf Code:

Codeproject link for more info: Codeproject

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
    public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
    {
        private readonly string defaultErrorMessageFormatString = "The {0} is required";
        public List<string> DependentProperties { get; private set; }
        public List<string> DependentValues { get; private set; }
        public string Props { get; private set; }
        public string Vals { get; private set; }
        public string RequiredFieldValue { get; private set; }

        //To avoid multiple rules with same name
        public static Dictionary<string, int> CountPerField;
        //Required if you want to use this attribute multiple times
        private readonly object typeId = new object();
        public override object TypeId
        {
            get { return typeId; }
        }

        public RequiredIfAttribute(string dependentProperties,
               string dependentValues = "", string requiredValue = "val")
        {
            if (string.IsNullOrWhiteSpace(dependentProperties))
            {
                throw new ArgumentNullException("dependentProperties");
            }
            string[] props = dependentProperties.Trim().Split(',');
            if (props != null && props.Length == 0)
            {
                throw new ArgumentException("Prameter Invalid:DependentProperties");
            }

            if (props.Contains("") || props.Contains(null))
            {
                throw new ArgumentException("Prameter Invalid:DependentProperties," +
                          "One of the Property Name is Empty");
            }

            string[] vals = null;
            if (!string.IsNullOrWhiteSpace(dependentValues))
                vals = dependentValues.Trim().Split(',');

            if (vals != null && vals.Length != props.Length)
            {
                throw new ArgumentException("Different Number " +
                      "Of DependentProperties And DependentValues");
            }

            DependentProperties = new List<string>();
            DependentProperties.AddRange(props);
            Props = dependentProperties.Trim();
            if (vals != null)
            {
                DependentValues = new List<string>();
                DependentValues.AddRange(vals);
                Vals = dependentValues.Trim();
            }

            if (requiredValue == "val")
                RequiredFieldValue = "val";
            else if (string.IsNullOrWhiteSpace(requiredValue))
            {
                RequiredFieldValue = string.Empty;
                defaultErrorMessageFormatString = "The {0} should not be given";
            }
            else
            {
                RequiredFieldValue = requiredValue;
                defaultErrorMessageFormatString =
                        "The {0} should be:" + RequiredFieldValue;
            }

            if (props.Length == 1)
            {
                if (vals != null)
                {
                    ErrorMessage = defaultErrorMessageFormatString +
                                   @", When " + props[0] + @" is ";
                    if (vals[0] == "val")
                        ErrorMessage += @" given";
                    else if (vals[0] == "")
                        ErrorMessage += @" not given";
                    else
                        ErrorMessage += vals[0];
                }
                else
                    ErrorMessage = defaultErrorMessageFormatString +
                                   @", When " + props[0] + @" is given";
            }
            else
            {
                if (vals != null)
                {
                    ErrorMessage = defaultErrorMessageFormatString +
                                   @", When " + dependentProperties + @" are: ";
                    foreach (string val in vals)
                    {
                        if (val == "val")
                            ErrorMessage += @"AnyValue,";
                        else if (val == "")
                            ErrorMessage += @"Empty,";
                        else
                            ErrorMessage += val + @",";
                    }
                    ErrorMessage = ErrorMessage.Remove(ErrorMessage.Length - 1);
                }
                else
                    ErrorMessage = defaultErrorMessageFormatString + @", When " +
                                   dependentProperties + @" are given";
            }
        }

        protected override ValidationResult IsValid(object value,
                           ValidationContext validationContext)
        {
            //Validate Dependent Property Values First
            for (int i = 0; i < DependentProperties.Count; i++)
            {
                var contextProp =
                  validationContext.ObjectInstance.GetType().
                  GetProperty(DependentProperties[i]);
                var contextPropVal = Convert.ToString(contextProp.GetValue(
                                             validationContext.ObjectInstance, null));

                var requiredPropVal = "val";
                if (DependentValues != null)
                    requiredPropVal = DependentValues[i];

                if (requiredPropVal ==
                       "val" && string.IsNullOrWhiteSpace(contextPropVal))
                    return ValidationResult.Success;
                else if (requiredPropVal == string.Empty &&
                            !string.IsNullOrWhiteSpace(contextPropVal))
                    return ValidationResult.Success;
                else if (requiredPropVal != string.Empty && requiredPropVal !=
                            "val" && requiredPropVal != contextPropVal)
                    return ValidationResult.Success;
            }

            string fieldVal = (value != null ? value.ToString() : string.Empty);

            if (RequiredFieldValue == "val" && fieldVal.Length == 0)
                return new ValidationResult(string.Format(
                           ErrorMessageString, validationContext.DisplayName));
            else if (RequiredFieldValue == string.Empty && fieldVal.Length != 0)
                return new ValidationResult(string.Format(
                           ErrorMessageString, validationContext.DisplayName));
            else if (RequiredFieldValue != string.Empty && RequiredFieldValue
                     != "val" && RequiredFieldValue != fieldVal)
                return new ValidationResult(string.Format(ErrorMessageString,
                                            validationContext.DisplayName));

            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(
               ModelMetadata metadata, ControllerContext context)
        {
            int count = 0;
            string key = metadata.ContainerType.FullName + "." + metadata.GetDisplayName();

            if (CountPerField == null)
                CountPerField = new Dictionary<string, int>();

            if (CountPerField.ContainsKey(key))
            {
                count = ++CountPerField[key];
            }
            else
                CountPerField.Add(key, count);

            yield return new RequiredIfValidationRule(string.Format(ErrorMessageString,
                  metadata.GetDisplayName()), RequiredFieldValue, Props, Vals, count);
        }
    }


    public class RequiredIfValidationRule : ModelClientValidationRule
    {
        public RequiredIfValidationRule(string errorMessage, string reqVal,
               string otherProperties, string otherValues, int count)
        {
            int i = 0;

            while (count > 26)
            {
                count -= 26;
                i++;
            }

            var tmp = count == 0 ? "" : Char.ConvertFromUtf32(96 + count);
            while (i > 0)
            {
                tmp += tmp;
                i--;
            }

            ErrorMessage = errorMessage;
            ValidationType = "requiredif" + tmp;
            ValidationParameters.Add("reqval", reqVal);
            ValidationParameters.Add("others", otherProperties);
            ValidationParameters.Add("values", otherValues);
        }
    }

New RequiredIf Code:

Stackoverflow link for more info : Stackoverflow

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
    private String PropertyName { get; set; }
    private Object DesiredValue { get; set; }
    private readonly RequiredAttribute _innerAttribute;

    public RequiredIfAttribute(String propertyName, Object desiredvalue)
    {
        PropertyName = propertyName;
        DesiredValue = desiredvalue;
        _innerAttribute = new RequiredAttribute();
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        if (context.ObjectInstance.GetType().GetProperty(PropertyName) != null)
        {
            var dependentValue =
                context.ObjectInstance.GetType().GetProperty(PropertyName).GetValue(context.ObjectInstance, null);

            if (dependentValue != null && dependentValue.ToString() == DesiredValue.ToString())
            {
                if (!_innerAttribute.IsValid(value))
                {
                    return new ValidationResult(FormatErrorMessage(context.DisplayName), new[] { context.MemberName });
                }
            }
        }
        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessageString,
            ValidationType = "requiredif",
        };
        // ReSharper disable once PossibleNullReferenceException
        rule.ValidationParameters["dependentproperty"] = (context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(PropertyName);
        rule.ValidationParameters["desiredvalue"] = DesiredValue is bool ? DesiredValue.ToString().ToLower() : DesiredValue;

        yield return rule;
    }


}

Related posts

Recent Viewed