Question

I have written an attribute before, but I I have not written a validation attribute before. I am seriously confused about how it all works together. I have read most of the tutorials online about how to go about accomplishing this. But I am left with a couple of questions to ponder.

Keep in mind that I am trying to write a requiredIf attribute that will only call a remote function if a certain Jquery variable is set... which incidentally is a variable that is pulled from view state... I guess I could make that part of my view model. But I digress

1) The C# code is slightly confusing. I know my attribute should extend the ValidationAttribute, IClientValidatable class and interface respectively. But I am a little confused about what each of the overidden methods should be doing? I am trying to write a requiredIf, how does overwriting these methods help me accomplish this goal?

2) If the variable is not there, I simply don't want the remote function to attempt to validate the field. I don't want any message to pop up on my form. Alot of the tutorials seem to revolve around that.

3) I am confused about what I need to do with the jquery to add this function to the view... What do I need to add to the JQuery to get this thing to work... It seems like a lot of extra coding when I could simply just type up a jquery function that did the same thing with just the same ore less coding... I know it also adds server side validation which is good. But still...

Here is what I have for my jquery side of this equation...

(function ($) {
    $validator.unobtrusive.adapters.addSingleVal("requiredifattribute", "Dependent");
    $validator.addMethod("requiredifattribute", function (value, element, params) {
        if (!this.optional(element)) {
            var otherProp = $('#' + params)
            return (otherProp.val() != value);
        }
        return true;
    })
}(jQuery));

Here is my Attribute (which is basically carbon copied out of one the required if tutorials... I know I need to customize it more, but once I get a better idea of what every piece is doing I will do that...

[AttributeUsage(AttributeTargets.Property)]
public class RequiredIfAttribute  : ValidationAttribute, IClientValidatable {
    private const string errorMessage = "The {0} is required.";
    //public string 
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentProperty { get; set; }
    public object TargetValue { get; set; }

    public RequiredIfAttribute(string dependentProperty, object targetValue){
        this.DependentProperty = dependentProperty;
        this.TargetValue = targetValue;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
        var field = validationContext.ObjectInstance.GetType().GetProperty(DependentProperty);
        if (field != null) {
            var dependentValue = field.GetValue(validationContext.ObjectInstance, null);
            if ((dependentValue == null && TargetValue == null) || (dependentValue.Equals(TargetValue))) {
                if (!innerAttribute.IsValid(value))
                    return new ValidationResult(ErrorMessage);
            }
        }
        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
        ModelClientValidationRule modelClientValidationRule = new ModelClientValidationRule {
            ErrorMessage = FormatErrorMessage(metadata.DisplayName),
            ValidationType = "requiredifattribute"
        };
        modelClientValidationRule.ValidationParameters.Add("dependent", DependentProperty);
        yield return modelClientValidationRule;
    }
}

UPDATE: What I have simply isn't working

Here is how a property in my model is anotated with the above attribute

    [RequiredIf("isFlagSet", true)]
    [Remote("ValidateHosFin", "EditEncounter", AdditionalFields = "hospitalFin, encflag", ErrorMessage = "Got Damn this is complex!")]
    [MinLength(6)]
    public string HostpitalFinNumber { get; set; }

The value in my view that I was trying to key this validation on is set up like so...

   ViewData["ADDENCOREDITTEMP"] = encflag;
   if (encflag == "AddEnc"){
       isFlagSet = true;
   }

I embed it into my page like so...

@Html.Hidden("isFlagSet", isFlagSet, new { id = "isFlagSet"}) 

I can't get my form to submit... The person who said he just tried this and got it to work, could you post the code?

Was it helpful?

Solution

Model:

public class X
{
    [RequiredIf("y", "y", ErrorMessage = "y is not y")]
    public string x { get; set; }

    public string y { get; set; }
}

View:

@using(Html.BeginForm())
{
    @Html.ValidationSummary()

    @Html.TextBoxFor(m => m.x)
    @Html.TextBoxFor(m => m.y)

    <input type="submit"/>
}

I assume your validation fails on the server side? do you have isFlagSet property in your view model?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top