How about a custom validation attribute with client validation enabled (so you get both client and server validation)? The solution below uses jQuery unobtrusive validation. To use this you will need to give all your buttons specific names and pass the name to the validation attribute. The button will also need to have a value of some sort so it can be posted back (so the server side code can test it, i.e. <input type="submit" name="myButton" value="1" />
). I haven't tested this code, so I'm not sure if it runs out of the box. You may need to make some mods:
The validation attribute for your model:
public class RequiredIfButtonClickedAttribute : ValidationAttribute, IClientValidatable
{
private RequiredAttribute _innerAttribute = new RequiredAttribute();
public string ButtonName { get; set; }
public RequiredIfButtonClickedAttribute(string buttonName)
{
ButtonName = buttonName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if ((value == null && !string.IsNullOrEmpty(HttpContext.Current.Request.Form[ButtonName])))
{
if (!_innerAttribute.IsValid(value))
{
return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
}
}
return ValidationResult.Success;
}
#region IClientValidatable Members
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule() { ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), ValidationType = "requiredifbuttonclicked" };
rule.ValidationParameters.Add("buttonname", ButtonName);
yield return rule;
}
#endregion
}
The client script:
/// <reference path="jquery-1.4.4-vsdoc.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
// When a button is clicked remove the clicked button class from all buttons and add it to the on that was clicked
$(":submit").click(function () {
$(":submit").removeClass('clickedButton');
$(this).addClass('clickedButton');
});
$.validator.addMethod('requiredifbuttonclicked',
function (value, element, parameters) {
// if the condition is true, reuse the existing
// required field validator functionality
if ($(".clickedButton").val("name") === parameters['buttonname'])
return $.validator.methods.required.call(
this, value, element, parameters);
return true;
}
);
$.validator.unobtrusive.adapters.add(
'requiredifbuttonclicked',
['buttonname'],
function (options) {
options.rules['requiredifbuttonclicked'] = {
buttonname: options.params['buttonname']
};
options.messages['requiredifbuttonclicked'] = options.message;
});
And use it like this:
[RequiredIfButtonClicked("myButtonName")]
public string Name { get; set; }
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…