简体   繁体   中英

How to use mvc dataannotations to validate property value if other property is set to true?

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?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM