问题
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>
}
回答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>
回答2:
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
}
来源:https://stackoverflow.com/questions/39325307/multifield-required-validation-is-not-working-in-client-side-in-mvc-5