Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access viewmodel's property value in custom validation attribute to alter messages?

The viewmodel has many string properties like Sample as below. My requirement is to show different validation messages depending on a bool flag in my viewmodel. That flag is IsProposer property as mentioned below:

[SampleAttribute(true, "bla prop", "foo add driver")]       
public string Sample { get; set; }

public bool IsProposer { get; set; }

I thought to create a validation attribute so that I can just place it on all my string properties (required validation). And then depending on the value of that boolean flag, I will pass the msg accordingly. My custom validation attribute is as follows:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class SampleAttribute : RequiredAttribute
    {
        protected string ProposerErrorMessage { get; set; }
        protected string AdditionalDriverErrorMessage { get; set; }
        protected bool IsProposer { get; set; }
        public SampleAttribute(bool isProposer, string propmsg, string adddrivermsg)
        {
            ProposerErrorMessage = propmsg;
            IsProposer = isProposer;
            AdditionalDriverErrorMessage = adddrivermsg;

        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (IsValid(value))
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult(IsProposer ? ProposerErrorMessage : AdditionalDriverErrorMessage);
            }
        }
    }

Now the issue is, as you can see I am just passing true as first parameter for the attribute. Here, I need to pass the Isproposer property's value from the viewmodel instance so that I can then act accordingly. How can I access it?

like image 544
Siddharth Pandey Avatar asked Sep 19 '13 14:09

Siddharth Pandey


1 Answers

I solved my problem by creating a attribute like this:

 /// <summary>
    /// This validation attribute is an extension to RequiredAttribute that can be used to choose either of the two 
    /// validation messages depending on a property in the context of same model.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public class RequiredExtensionAttribute : RequiredAttribute
    {
        private string _errorMessageIfTruthy;
        private string _errorMessageIfFalsy; 
        private string _dependentProperty;

        public RequiredExtensionAttribute(string dependentproperty, string errorMessageIfTruthy, string errorMessageIfFalsy)
        {
            _errorMessageIfTruthy = errorMessageIfTruthy;
            _dependentProperty = dependentproperty;
            _errorMessageIfFalsy = errorMessageIfFalsy;

        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var propertyTestedInfo = validationContext.ObjectType.GetProperty(this._dependentProperty);
            if (propertyTestedInfo == null)
            {
                return new ValidationResult(string.Format("unknown property {0}", this._dependentProperty));
            }

            var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null);

            if (IsValid(value))
            {
                return ValidationResult.Success;
            }
            else
            {
                return new ValidationResult((bool)propertyTestedValue ? _errorMessageIfTruthy : _errorMessageIfFalsy);
            }
        }
    }

This can now be used in models like:

[RequiredExtensionAttribute("IsProposerViewModel", "Please select your employment status.", "Please select this driver's employment status")]       
public string EmploymentStatus { get; set; }
public bool IsProposerViewModel { get; set; }

-where the first parameter for attribute is the IsProposerViewModel, the dependent value.

like image 160
Siddharth Pandey Avatar answered Oct 30 '22 09:10

Siddharth Pandey