0

I used to implement multi field required validation using this link MVC3 Validating Multiple Fields As A Single Property

But it did not work at my end.

Below is the code I used.

Javascript

    $.validator.addMethod('multifield', function (value, element, params) {
    var properties = params.propertyname.split(',');
    var isValid = false;
    var count = 0;
    for (var i = 0; i < properties.length; i++) {
        var property = properties[i];
        if ($('#' + property).val() != "") {
            count++;
        }
    }
    if (properties.length == count) {
        isValid = true;
    }
    return isValid;
}, '');

$.validator.unobtrusive.adapters.add('multifield', ['propertyname'], function (options) {
    options.rules['multifield'] = options.params;
    options.messages['multifield'] = options.message;
}
);

Class

  public class Customer
    {
       public string AreaCode { get; set; }
      [MultiFieldRequired(new string[2] { "AreaCode", "PhoneNumber" }, ErrorMessage = "Please enter a phone number")]
       public string PhoneNumber { get; set; }
    }

    public class MultiFieldRequiredAttribute : ValidationAttribute, IClientValidatable
{
    string propertyName;
    private readonly string[] _fields;

    public MultiFieldRequiredAttribute(string[] fields)
    {
        _fields = fields;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        foreach (string field in _fields)
        {
            propertyName = field;
            PropertyInfo property = validationContext.ObjectType.GetProperty(field);
            if (property == null)
                return new ValidationResult(string.Format("Property '{0}' is undefined.", field));

            var fieldValue = property.GetValue(validationContext.ObjectInstance, null);

            if (fieldValue == null || String.IsNullOrEmpty(fieldValue.ToString()))
                return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName));
        }

        return ValidationResult.Success;
    }

     public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        // The value we set here are needed by the jQuery adapter
        ModelClientValidationRule multifield = new ModelClientValidationRule();
        multifield.ErrorMessage = this.ErrorMessage;
        multifield.ValidationType = "multifield"; // This is the name the jQuery validator will use
        //"otherpropertyname" is the name of the jQuery parameter for the adapter, must be LOWERCASE!
        multifield.ValidationParameters.Add("propertyname", string.Join(",", _fields));

        yield return multifield;
    }
}

View

@using (Html.BeginForm("Add", "Home", FormMethod.Post, new { @class = "form-inline" }))
    {


    <div class="editor-label">
        @Html.LabelFor(model => model.AreaCode)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.AreaCode)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.PhoneNumber)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.PhoneNumber)
        @Html.ValidationMessageFor(model => model.PhoneNumber)
    </div>
          <button type="submit" tabindex="19" class="form-control btn btn-primary" style="float: right; margin-left: 8px; margin-right: 10px;">Submit</button>
    }
Community
  • 1
  • 1
Gaurav123
  • 5,059
  • 6
  • 51
  • 81
  • What is not working - client side or server side validation or both? You have implemented `IClientValidatable` but have not shown your scripts to add the rules to the `$.validator` which are necessary for client side validation –  Sep 05 '16 at 10:45
  • Both server side and client side didn't work. Also I don't know about #.validator changes that I need to do in javascript – Gaurav123 Sep 05 '16 at 13:01
  • To understand what you need for client side validation, refer [The Complete Guide To Validation In ASP.NET MVC 3 - Part 2](http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2). But its not really clear what your wanting to do. If your wanting to have a Required validation attribute on `PhoneNumber` that also ensure that `AreaCode` has a value then you should one attribute applied to `PhoneNumber` only and that attribute accepts a parameter for the nae of the other property. –  Sep 05 '16 at 13:11
  • And it should be `return ValidationResult.Success;` (not `return null;`) –  Sep 05 '16 at 13:12
  • I have added javascript code as well...could you please find the issue and resolve the same now – Gaurav123 Sep 07 '16 at 09:38
  • Your scripts have no relationship to the code in your `ValidationAttribute` - all its doing is checking the the the value of the current control is not `null`. And you not using the value of `propertyName` (and in any case, your never assign a value to `propertyName` so it would be `null` anyway) –  Sep 07 '16 at 10:13
  • I added ``multifield.ValidationParameters.Add("propertyname", propertyName); `` to add value in property name.. Could you please help in javascript code..I don't know what to write there ... – Gaurav123 Sep 07 '16 at 10:17
  • But the value of `propertyName` is `null` (you never set it), and you never use it in the script anyway. As I noted before, there is no point doing this - your adding a validation attribute to `AreaCode`, but then ignoring it. You should have one attribute applied to `PhoneNumber` (say) `[RequiredWith("AreaCode")]` and that attribute is responsible for testing that both `PhoneNumber` and `AreaCode` are not null –  Sep 07 '16 at 10:24
  • I have removed the attribute and u r right, propertyname is coming as null. but when I try server side it contains values from ``propertyName = field;`` If you can please correct the changes wherever you think is wrong... – Gaurav123 Sep 07 '16 at 10:32
  • No time now, but I'll add an answer based on my previous comments tomorrow. –  Sep 07 '16 at 10:35

2 Answers2

1

The answer you linked to and the code you have based it on does not make a lot of sense. Applying a validation attribute to your AreaCode property without including an associated @Html.ValidationMessageFor() is pointless.

If you want a validation message associated with PhoneNumber that will display a Please enter a phone number error if it's empty, and to display a Please also enter an Area Code if its not empty but the AreaCode value is, then you need an attribute that is applied only to the PhoneNumber property, and that attribute needs to accept a parameter for the other property name.

Model

public string AreaCode { get; set; }
[Required(ErrorMessage = "Please enter a phone number")]
[RequiredWith("AreaCode", ErrorMessage = "Please also enter an Area Code")]
public string PhoneNumber { get; set; }

Validation attribute

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class RequiredWithAttribute : ValidationAttribute, IClientValidatable
{
    private const string _DefaultErrorMessage = "The {0} is also required.";
    private readonly string _OtherPropertyName;

    public RequiredWithAttribute(string otherPropertyName)
    {
        if (string.IsNullOrEmpty(otherPropertyName))
        {
            throw new ArgumentNullException("otherPropertyName");
        }
        _OtherPropertyName = otherPropertyName;
        ErrorMessage = _DefaultErrorMessage;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            var otherProperty = validationContext.ObjectInstance.GetType().GetProperty(_OtherPropertyName);
            var otherPropertyValue = otherProperty.GetValue(validationContext.ObjectInstance, null);
            if (otherPropertyValue == null)
            {
                return new ValidationResult(string.Format(ErrorMessageString, _OtherPropertyName));
            }
        }
        return ValidationResult.Success;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(_OtherPropertyName),
            ValidationType = "requiredwith",
        };
        rule.ValidationParameters.Add("dependentproperty", _OtherPropertyName);
        yield return rule;
    }
}

And add the following scripts

<script type="text/javascript">
    // General function to get the associated element
    myValidation = {
        getDependantProperyID: function (validationElement, dependantProperty) {
            if (document.getElementById(dependantProperty)) {
                return dependantProperty;
            }
            var name = validationElement.name;
            var index = name.lastIndexOf(".") + 1;
            dependantProperty = (name.substr(0, index) + dependantProperty).replace(/[\.\[\]]/g, "_");
            if (document.getElementById(dependantProperty)) {
                return dependantProperty;
            }
            return null;
        }
    }

    $.validator.addMethod("requiredwith", function (value, element, params) {
        var dependantControl = $('#' + params.dependentproperty);
        return dependantControl.val() !== '';
    });

    $.validator.unobtrusive.adapters.add("requiredwith", ["dependentproperty"], function (options) {
        var element = options.element;
        var dependentproperty = options.params.dependentproperty;
        dependentproperty = myValidation.getDependantProperyID(element, dependentproperty);
        options.rules['requiredwith'] = {
            dependentproperty: dependentproperty
        };
        options.messages['requiredwith'] = options.message;
    });

</script>
0

If I m not wrong MultiFieldRequired is used above class name which was explain in below stackoverflow link earlier: MVC3 Validating Multiple Fields As A Single Property

You can also try below method in model.Also Add namespace in

model

=====================

using System.Web.Mvc; 

=====================

 public class Customer
    {
        //...other fields here
         [Remote("ValidateAreaPhoneNumber","Home",AdditionalFields="PhoneNumber",ErrorMessage="Please enter a phone number")]

        public string AreaCode { get; set; }

        public string PhoneNumber { get; set; }
    }

You may write the method named

ValidateAreaPhoneNumber

in ur

Home Controller

as below:

public JsonResult ValidateAreaPhoneNumber(string PhoneNumber)
{

    //True:False--- action that implement to check PhoneNumber uniqueness

      return false;//Always return false to display error message
}
Community
  • 1
  • 1
Hina Khuman
  • 757
  • 3
  • 14
  • 41