驗證出生日期確保年齡在指定區間。
public class AgeRangeAttribute : RangeAttribute, IClientValidatable
{
public AgeRangeAttribute(int minimum, int maximum) : base(minimum, maximum) { }
public override bool IsValid(object value)
{
DateTime birthDate = (DateTime)value;
DateTime age = new DateTime(DateTime.Now.Ticks - birthDate.Ticks);
return age.Year >= (int)Minimum && age.Year <= (int)Maximum;
}
public override string FormatErrorMessage(string name)
=> base.FormatErrorMessage("年齡"); // 固定顯示名稱
// 客戶端規則產生
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ValidationType = "agerange", // 對應 jQuery Validate 規則名稱
ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};
rule.ValidationParameters.Add("currentdate", DateTime.Today.ToString("dd-MM-yyyy"));
rule.ValidationParameters.Add("minage", Minimum);
rule.ValidationParameters.Add("maxage", Maximum);
yield return rule;
}
}
jQuery.validator.addMethod("agerange",
function (value, element, params) {
var minAge = params.minage;
var maxAge = params.maxage;
var literalCurrentDate = params.currentdate; // 格式 dd-MM-yyyy
var literalBirthDate = value; // 預期同格式
var currentParts = literalCurrentDate.split('-');
var birthParts = literalBirthDate.split('-');
var birthDate = new Date(birthParts[2], birthParts[1] - 1, birthParts[0]); // 月份 0-based
var currentDate = new Date(currentParts[2], currentParts[1] - 1, currentParts[0]);
var age = currentDate.getFullYear() - birthDate.getFullYear();
if (currentDate.getMonth() < birthDate.getMonth() ||
(currentDate.getMonth() == birthDate.getMonth() && currentDate.getDate() < birthDate.getDate()))
age--;
return age >= minAge && age <= maxAge;
});
// Unobtrusive 適配器
jQuery.validator.unobtrusive.adapters.add("agerange", ["currentdate", "minage", "maxage"], function (options) {
options.rules["agerange"] = {
currentdate: options.params.currentdate,
minage: options.params.minage,
maxage: options.params.maxage
};
options.messages["agerange"] = options.message;
});
@model DateTime
@Html.TextBoxFor(m => m, new { @class = "date-picker" })
@Html.ValidationMessageFor(m => m)
Model 屬性標註:[AgeRange(18, 65)] public DateTime BirthDate { get; set; }
ValidationAttribute 實作伺服器端 IsValid。IClientValidatable 介面,GetClientValidationRules 產生 ModelClientValidationRule(含 ValidationType、ErrorMessage、ValidationParameters)。jQuery.validator.addMethod 註冊驗證邏輯,參數對應 ValidationParameters。jQuery.validator.unobtrusive.adapters.add 註冊適配器,將 HTML data-val-* 屬性對應至規則參數與訊息。dd-MM-yyyy)。jquery.validate.js 與 jquery.validate.unobtrusive.js 之後載入。自訂驗證需雙端實作:伺服器端 ValidationAttribute 保證資料完整性,客戶端 jQuery Validate 提升使用者體驗。IClientValidatable 為橋樑,將參數透過 Unobtrusive JavaScript 傳遞至前端適配器。掌握此流程可建構任意複雜業務驗證規則。