首先,你需要比Compare attribute類似的方式來創建自己的驗證屬性。
在此屬性中,您將指定其他依賴屬性,並且錯誤消息將被格式化以考慮屬性顯示名稱。
的屬性看起來像這樣(我不是太驕傲關於它的名字和默認的錯誤消息!):
public class SelectOneValidationAttribute : ValidationAttribute, IClientValidatable
{
private const string DefaultErrorMessage = "Please enter '{0}' or '{1}'.";
private string _otherFieldName;
public SelectOneValidationAttribute(String otherFieldName)
: base(DefaultErrorMessage)
{
_otherFieldName = otherFieldName;
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, _otherFieldName);
}
protected override DataAnnotationsValidationResult IsValid(object value, ValidationContext validationContext)
{
PropertyInfo otherPropertyInfo = validationContext.ObjectType.GetProperty(_otherFieldName);
if (otherPropertyInfo == null)
{
return new DataAnnotationsValidationResult("Unknown property " + _otherFieldName);
}
string strValue = value == null ? null : value.ToString();
if(!String.IsNullOrEmpty(strValue))
//validation succeeds as this field has been populated
return null;
object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
string strOtherPropertyValue = otherPropertyValue == null ? null : otherPropertyValue.ToString();
if (!String.IsNullOrEmpty(strOtherPropertyValue))
//validation succeeds as the other field has been populated
return null;
else
//validation failed, none of the 2 fields were populated
return new DataAnnotationsValidationResult(DefaultErrorMessage);
}
//Create the data attributes for the client to use
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ValidationType = "selectone",
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
};
rule.ValidationParameters["otherfield"] = FormatPropertyForClientValidation(_otherFieldName);
yield return rule;
}
public static string FormatPropertyForClientValidation(string property)
{
return "*." + property;
}
}
所以,你可以用它在你的模型如:
public class YourModel
{
[SelectOneValidation("Phone")]
public string Mobile { get; set; }
[SelectOneValidation("Mobile")]
public string Phone { get; set; }
}
使用該代碼,錯誤消息「請輸入'Mobile'或'Phone'。」和「請輸入'電話'或'移動'。」將在服務器端驗證失敗時顯示。 (您可以設置相同的錯誤消息,例如「請輸入一個...」)
爲了添加客戶端驗證,您需要創建用於不顯眼驗證的適配器。 (請確保您添加它的地方不顯眼的驗證解析文檔之前,否則,你將需要手動解析它):
//Add an adaptor for our new jquery validator, that builds the optional parameters
//for our validation code (the other field to look at)
$.validator.unobtrusive.adapters.add("selectone", ["otherfield"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.otherfield,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];
setValidationValues(options, "selectone", element);
});
這是使用中的少數幾個不顯眼的驗證庫定義類的實用功能:
function setValidationValues(options, ruleName, value) {
options.rules[ruleName] = value;
if (options.message) {
options.messages[ruleName] = options.message;
}
}
function getModelPrefix(fieldName) {
return fieldName.substr(0, fieldName.lastIndexOf(".") + 1);
}
function appendModelPrefix(value, prefix) {
if (value.indexOf("*.") === 0) {
value = value.replace("*.", prefix);
}
return value;
}
最後我創建了一個新的驗證規則。這是因爲儘管所需的驗證允許設置過濾表達式,因此當該表達式評估爲true時,該字段僅被標記爲有效,請參見required validation,但我們需要對onBlur驗證應用類似的修復程序,而不是等於規則。
驗證方法應用等於驗證的所述修復,然後僅在其他相關字段上使用依賴選擇器調用所需的規則,因此只有在字段爲空且依賴項有空時,所需的驗證纔會返回false沒有被填滿。
$.validator.addMethod("selectone", function (value, element, param) {
// bind to the blur event of the target in order to revalidate whenever the target field is updated
// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
var otherField = $(param);
if (this.settings.onfocusout) {
otherField.unbind(".validate-selectone").bind("blur.validate-selectone", function() {
$(element).valid();
});
}
var otherFieldBlankFilter = ":input[name=" + otherField[0].name + "]:blank";
return $.validator.methods.required.call(this, value, element, otherFieldBlankFilter);
});
如果你不介意這件事,就好像你在表單提交僅在驗證,你可以只寫直接使用所需的規則的適配器:
$.validator.unobtrusive.adapters.add("selectone", ["otherfield"], function (options) {
var prefix = getModelPrefix(options.element.name),
other = options.params.otherfield,
fullOtherName = appendModelPrefix(other, prefix),
element = $(options.form).find(":input[name=" + fullOtherName + "]")[0];
setValidationValues(options, "required", ":input[name=" + fullOtherName + "]:blank");
});
與所有這到位,你的驗證應該工作。如果兩者均爲空,並且您嘗試提交,則兩個字段都將顯示錯誤消息。如果您隨後在其中一個地方輸入內容並將其標記出來,則應刪除這兩個錯誤消息。
您應該也可以根據需要調整它,因爲您可以修改驗證屬性,不顯眼的適配器和驗證規則。