0

one model property validation info/rules are available in the other properties of same model object. i have to validate the property values using other properties values.

Model class:-

    [FormatValidtion("Value", "Format", "MinLength", "MaxLength", ErrorMessage = "Please enter correct format")]
    public class Sample
    {        
        #region ModelProperties

        public string Id { get; set; }

        [Required(ErrorMessage = "Please Enter Value")]
        public string Value { get; set; }              

        public string Format { get; set; }

        public string MinLength { get; set; }

        public string MaxLength { get; set; }

        #endregion
    }

Model object looks like above.Here i have to validate Value property using the

  • Format ( Fomart Validation like email,phone & Date)

  • MinLength,MaxLength (Range validation) properties.

I know we can do this using custom validations like

  1. Create Custom class keeping ValidationAttribute as base
  2. Pass all these properties( Value ,Format,MinLength & MaxLength)
  3. Write switch case with Format property.
  4. Validate Format using Regex and do manual range validation or with dynamic Regex validation.

EDIT :- Added Custom Validation Class Code Here

Custom Validation Class:

[AttributeUsage(AttributeTargets.Class)]
public class FormatValidtion : ValidationAttribute
{

    public String Value { get; set; }
    public String Format { get; set; }
    public String MinLength { get; set; }
    public String MaxLength { get; set; }

    public FormatValidtion(String value, String format, String minLength, String maxLength)
    {
        Value = value;
        Format = format;
        MinLength = minLength;
        MaxLength = maxLength;
    }

    public override Boolean IsValid(Object value)
    {
        Type objectType = value.GetType();

        PropertyInfo[] neededProperties =
          objectType.GetProperties()
          .Where(p => p.Name == Value || p.Name == Format || p.Name == MinLength || p.Name == MaxLength)
          .ToArray();

        if (neededProperties.Count() != 4)
        {
            throw new ApplicationException("PropertiesMatchAttribute error on " + objectType.Name);
        }

        Boolean isMatched = true;

        switch (Convert.ToString(neededProperties[1].GetValue(value, null)))
        {
            case "Alpha":
                Regex regExAlpha = new Regex(@"/^[A-Za-z]+$/");
                if (!regExAlpha.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                {
                    isMatched = false;
                }
                break;
            case "Number":
                Regex regExNumber = new Regex(@"/^[0-9]+$/");
                if (!regExNumber.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                {
                    isMatched = false;
                }
                break;
            case "AlphaNum":
                Regex regExAlphaNum = new Regex(@"/^[a-zA-Z][a-zA-Z0-9]+$/");
                if (!regExAlphaNum.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                {
                    isMatched = false;
                }
                break;
            default:
                isMatched = false;
                break;
        }
        return isMatched;
    }    
}

This is working correctly at class level and showing validation messages through validation summary. But I want to modify the above code to do the following things.

  1. Validation should happen at property level or some how need to show error message at property level( using validationMessage helper class).
  2. Need to provide the specific error messages for each validation other than common error message.
  3. Range validation should happen.

Can anybody provide some thoughts around these?

User_MVC
  • 251
  • 2
  • 7
  • 21

2 Answers2

0

You could use IValidatableObject interface. When properly implemented, you can show property level and custom error messages.

Here's the question for further reading

Community
  • 1
  • 1
archil
  • 39,013
  • 7
  • 65
  • 82
  • Thanks for ur reply. Can you pls provide similar examples how to modify the above code? – User_MVC Jul 04 '13 at 08:20
  • Sorry, at the moment I've got no time : (. Did you read the link with similar question and explanations? – archil Jul 04 '13 at 08:53
0

I done with following code.

Model class:-

    [FormatValidtion("Value", "Format", "MinLength", "MaxLength")]
    public class Sample
    {
        #region ModelProperties

        public string Id { get; set; }

        [Required(ErrorMessage = "Please Enter Value")]
        public string Value { get; set; }

        public string Format { get; set; }

        public string MinLength { get; set; }

        public string MaxLength { get; set; }

        #endregion
    }

Custom Validation Class:-

[AttributeUsage(AttributeTargets.Class)]
    public class FormatValidtion : ValidationAttribute
    {

        public string Value { get; set; }
        public string Format { get; set; }
        public string MinLength { get; set; }
        public string MaxLength { get; set; }
        public string Format1 { get; set; }
        public string Value1 { get { return Value; } }

        public FormatValidtion(String value, String format, String minLength, String maxLength)
        {
            Value = value;
            Format = format;
            MinLength = minLength;
            MaxLength = maxLength;
        }

        public override Boolean IsValid(Object value)
        {
            Type objectType = value.GetType();

            PropertyInfo[] neededProperties =
              objectType.GetProperties()
              .Where(p => p.Name == Value || p.Name == Format || p.Name == MinLength || p.Name == MaxLength)
              .ToArray();

            if (neededProperties.Count() != 4)
            {
                throw new ApplicationException("PropertiesMatchAttribute error on " + objectType.Name);
            }

            Boolean isMatched = true;
            this.Format1 = Convert.ToString(neededProperties[1].GetValue(value, null));

            switch (Convert.ToString(neededProperties[1].GetValue(value, null)))
            {
                case "Alpha":
                    Regex regExAlpha = new Regex(@"/^[A-Za-z]+$/");
                    if (!regExAlpha.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                    {
                        isMatched = IsValidLength(Convert.ToString(neededProperties[0].GetValue(value, null)).Length, Convert.ToInt32(neededProperties[2].GetValue(value, null)), Convert.ToInt32(neededProperties[3].GetValue(value, null)));
                    }
                    break;
                case "Number":
                    Regex regExNumber = new Regex(@"/^[0-9]+$/");
                    if (!regExNumber.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                    {
                        isMatched = IsValidLength(Convert.ToString(neededProperties[0].GetValue(value, null)).Length, Convert.ToInt32(neededProperties[2].GetValue(value, null)), Convert.ToInt32(neededProperties[3].GetValue(value, null)));
                    }
                    break;
                case "AlphaNum":
                    Regex regExAlphaNum = new Regex(@"/^[a-zA-Z][a-zA-Z0-9]+$/");
                    if (!regExAlphaNum.IsMatch(Convert.ToString(neededProperties[0].GetValue(value, null))))
                    {
                        isMatched = IsValidLength(Convert.ToString(neededProperties[0].GetValue(value, null)).Length, Convert.ToInt32(neededProperties[2].GetValue(value, null)), Convert.ToInt32(neededProperties[3].GetValue(value, null)));
                    }
                    break;
                default:
                    isMatched = false;
                    break;
            }
            return isMatched;
        }

        /// range validation
        public bool IsValidLength(int valueLenght, int minLenght, int maxLenght)
        {
            if (valueLenght >= minLenght && valueLenght <= maxLenght)
                return true;
            return false;
        }

    }

Validation Adapter Class:-

public class FormatValidtionAdapter : DataAnnotationsModelValidator<FormatValidtion>
    {

        public FormatValidtionAdapter(ModelMetadata metadata, ControllerContext context, FormatValidtion attribute)
            : base(metadata, context, attribute)
        {
        }


       // To Provide Error messages dynamically depends on format.            
        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            string ErrorMessage = null;
            if (!Attribute.IsValid(Metadata.Model))
            {
                switch (Attribute.Format1)
                {
                    case "Alpha":
                        ErrorMessage = "Please enter alphabets only";
                        break;
                    case "Number":
                        ErrorMessage = "Please enter numbers only";
                        break;
                    case "AlphaNum":
                        ErrorMessage = "Please enter alphanumeric  only";
                        break;
                    default:
                        break;
                }
                yield return new ModelValidationResult
                {
                    Message = ErrorMessage,
                    MemberName = Attribute.Value1
                };
            }
        }
    }

Global.aspx.cs:-

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);

            DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(FormatValidtion), typeof(FormatValidtionAdapter));
        }
User_MVC
  • 251
  • 2
  • 7
  • 21