0

I'm trying to hook up some server side validation so there is some sort of last line of defense so bad data doesn't get through. One of my fields depends on a boolean value. If the boolean is true then the int value must be 0. If it is false then it has to between 1 and 7. This is what I have so far but it's not working.

[ValidApplicationPrimary(ComplianceProfile= NFlagComplianceProfile)]
[Column("APPLICATION_PRIMARY")]
public int ApplicationPrimary { get; set; }

[Required]
[Column("NFLAG_COMPLIANCE_PROFILE")]
public bool NFlagComplianceProfile { get; set; }

public class ValidApplicationPrimary : ValidationAttribute
    {
        public Boolean ComplianceProfile { get; set; } 

        public override bool IsValid(object value)
        {
            if (ComplianceProfile)//If they have a compliance profile the value of Application Primary should be 0
            {
                if (((Int32)value) == 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (((Int32)value) > 0 && ((Int32)value)<=7) //If Application primary is between 1 and 7 then it is true
            {
                return true;
            }
            else //Outside that range its false
                return false;

        }

I keep getting this error

Error   3   An object reference is required for the non-static field, method, or property 'EntityFrameworkTable.NFlagComplianceProfile.get'
ryan miller
  • 105
  • 1
  • 9

3 Answers3

2

You can't reference other properties in that way. If you have .NET 4 or higher you can do something like this:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ValidApplicationPrimary : ValidationAttribute
{
  private const string DefaultErrorMessage = "If {0} is false, {1} must be 1-7.";

  public bool ComplianceProfile { get; private set; }

  public override string FormatErrorMessage(string name)
  {
    return string.Format(ErrorMessageString, name, ComplianceProfile );
  }

  protected override ValidationResult IsValid(object value, 
                        ValidationContext validationContext)
  {
    if (value != null)
    {
      var complianceProfile= validationContext.ObjectInstance.GetType()
                         .GetProperty(ComplianceProfile);

      var complianceProfileValue= complianceProfile
                    .GetValue(validationContext.ObjectInstance, null);

        if (complianceProfileValue)//If they have a compliance profile the value of Application Primary should be 0
        {
            if (((Int32)value) == 0)
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
            }
        }
        else if (((Int32)value) > 0 && ((Int32)value)<=7) //If Application primary is between 1 and 7 then it is true
        {
            return ValidationResult.Success;
        }
        else //Outside that range its false
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));


    }

    return ValidationResult.Success;
  }        
}

Usage:

[ValidApplicationPrimary("ComplianceProfile")]
[Column("APPLICATION_PRIMARY")]
public int ApplicationPrimary { get; set; }

This article describes it in detail: http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2

Steve Greene
  • 12,029
  • 1
  • 33
  • 54
  • That looks interesting and I might have to try that but I also found this website and taking some stuff from there worked for me http://www.binaryintellect.net/articles/55bef03e-3d41-4a0a-b874-78b7c7a9ce36.aspx , which I will post as an answer as well so others can see. – ryan miller Jul 09 '15 at 16:02
  • Looking at the two answers it appears they use roughly the same concept – ryan miller Jul 09 '15 at 16:05
  • Yes, similar. Note that the devtrends article also shows how you can achieve client side validation. – Steve Greene Jul 09 '15 at 16:13
1

If you haven't already, you should consider using Jeremy Skinner's FluentValidation. Very lightweight and will simplify your validation rules significantly.

FluentValidation github

Once you have your initial set up and model decorated, you would place your rules in your validator's constructor. You can even define custom validation methods to conditionally apply validation rules. This is explained in more detail in the docs.

public class ObjectValidator : AbstractValidator<YourObject>
{    
    public ObjectValidator(){
      RuleFor(x => x.ApplicationPrimary).Equal(0).When(x => x.NFlagComplianceProfile);
      RuleFor(x => x.ApplicationPrimary).InclusiveBetween(1, 7).When(x => !x.NFlagComplianceProfile);    
    }
}

You would decorate your model like this

[Validator(typeof(ObjectValidator))]
public class YourObject
{
   public int ApplicationPrimary { get; set; }

   public bool NFlagComplianceProfile { get; set; }
}
JDupont
  • 1,352
  • 10
  • 14
0
 public class ValidApplicationPrimary : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            Boolean flag = false;
            Object instance = validationContext.ObjectInstance;
            Type type = instance.GetType();
            PropertyInfo property = type.GetProperty("NFlagComplianceProfile");
            Object propertyValue = property.GetValue(instance);

            switch (Convert.ToInt32(propertyValue))
            {
                case 1:
                    if(Convert.ToInt32(value) == 0)
                    {
                        flag = true;
                    }
                    break;
                case 0:
                    if(Convert.ToInt32(value) >0 && Convert.ToInt32(value)<8)
                    {
                        flag = true;
                    }
                    break;
                default:
                    flag = false;
                    break;
            }
            if(!flag)
            {
                ValidationResult result = new ValidationResult("");
                return result;
            }
            else
            {
                return null;
            }


        }

http://www.binaryintellect.net/articles/55bef03e-3d41-4a0a-b874-78b7c7a9ce36.aspx

This seems to be working for me. There are some kinks but the few different scenarios I tried appeared to work correctly.

ryan miller
  • 105
  • 1
  • 9