0

I am trying to validate a form submit BUT i want to validate a property ONLY if another property is set to true.

my two properties:

[DisplayName(Translations.Education.IsFeaturette)]
public  bool IsFeaturette { get; set; }

[DisplayName(Translations.Education.AddFeaturetteFor)]
[CusomValidatorForFeaturettes(IsFeaturette)]
public string[] Featurettes { get; set; }

custom annotation:

public class CusomValidatorForFeaturettes: ValidationAttribute
{
    private readonly bool _IsFeatturette;
    public CusomValidatorForFeaturettes(bool isFeatturette): base("NOT OK")
    {
        _IsFeatturette = isFeatturette;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value == null && _IsFeatturette )
        {
            var errorMessage = FormatErrorMessage(validationContext.DisplayName);
            return new ValidationResult(errorMessage);

        }
        return ValidationResult.Success;
    }
}

Basiclly if isfeature is true then Featurettes MUST have a value!

Error im getting:

An object reference is required for the non-static field, method, or property 'EducationViewModel.IsFeaturette'

I can not make this property static cuz that would give me problems since this property is set with enityframework and I don't wish to change any of this. How can I accomplish this without making the property static?

ThunD3eR
  • 3,216
  • 5
  • 50
  • 94
  • Consider using [foolproof](http://foolproof.codeplex.com/) conditional attributes, including their `[RequiredIfTrue]` attribute which will give you both client side and server side validation –  May 24 '16 at 22:32
  • thanks for the tip, However i would like to avoid using frameworks at this time. Do you know how can solve is like this? – ThunD3eR May 24 '16 at 22:40
  • You cant pass a property as a parameter to the attribute - it needs to be a `string` (a constant value) - in your case `[CusomValidatorForFeaturettes("IsFeaturette")]` to indicate the name of the 'other' property. –  May 24 '16 at 23:04

1 Answers1

2

Attributes are added to the metadata of the assembly at compile-time, and therefore its parameters must be known at compile-time. The error is generated because the your passing the value of a property (bool IsFeaturette) to the attribute which is not static (it could be true or false at run-time).

Instead, pass a string indicating the name of the property to compare, and in the method, use reflection to get the value of the property.

public  bool IsFeaturette { get; set; }

[CusomValidatorForFeaturettes("IsFeaturette")]
public string[] Featurettes { get; set; }

and modify the validation attribute to

public class CusomValidatorForFeaturettes: ValidationAttribute
{
    private readonly string _OtherProperty;

    public CusomValidatorForFeaturettes(string otherProperty): base("NOT OK")
    {
        _OtherProperty = otherProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // Get the dependent property 
        var otherProperty = validationContext.ObjectInstance.GetType().GetProperty(_OtherProperty);
        // Get the value of the dependent property 
        var otherPropertyValue = otherProperty.GetValue(validationContext.ObjectInstance, null);
        ......

You can then convert otherPropertyValue to bool and do your conditional check.

I also recommend you read The Complete Guide to Validation in ASP.NET-MVC-3 Part-2 to better understand how to implement a validation attribute, including how to implement IClientValidatable so that you get both server and client side validation. I also recommend you rename the method to (say) RequiredIfTrueAttribute to better reflect what it is doing.

Note also that foolproof have a good range of validation attributes for use in MVC.

And as a final note, your current implementation is specific to a dependency on one property (the value of IsFeaturette), which is pointless for a validation attribute - you would have been better off just checking the values in the controller and adding a ModelStateError. The code above means that you can pass in any property name (so long as that property was typeof bool) which is what a validation attribute should allow.

  • A minor point (appreciate this is an old answer) but instead of passing the property name and using reflection you can just cast the validationContext.ObjectInstance into the type and get the property values directly. – Tim Rutter Jan 10 '23 at 12:28