ASP.NET MVC 3 Validation - 正则表达式验证RegularExpressionAttribute之日期验证

ASP.NET MVC 3中,正则表达式的验证属性是RegularExpressionAttribute。

问题:

日期格式进行Server端和Client端的验证


解决方案(1):

直接使用RegularExpressionAttribute,写正则表达式。

        [RegularExpression(@"Regular Expression Here", ErrorMessage = "Please input valid date format")]
        public String RegualarExpressionField { get; set; }

这样做的好处是比较直接,但当正则表达式比较复杂时,代码会显得并不怎么优雅。


解决方案(2)

从RegularExpressionAttribute直接派生出DateExpressionAttribute

    public class DateExpressionAttribute : RegularExpressionAttribute
    {
         public DateExpressionAttribute()
             : base("Date Regular Expression Here")
         {

         }
    }
较之方案(1)的做法,好处是能够把正则表达式封装起来,复用性更强(方案(1)中,每个日期验证都需要将正则表达式拷贝一遍,如此代码的维护工作量可想而知)。

建立一个测试model:

    public class TestModel
    {
        [DateExpression]
        public DateTime? DateField { get; set; }

        [RegularExpression(@"Regular Expression Here", ErrorMessage = "Please input valid date format")]
        public String RegualarExpressionField { get; set; }
    }

page:

    <div>
        <fieldset>
            <legend>Account Information</legend>

            <div class="editor-label">
                @Html.LabelFor(m => m.DateField)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.DateField)
                @Html.ValidationMessageFor(m => m.DateField)
            </div>

           <div class="editor-label">
                @Html.LabelFor(m => m.RegualarExpressionField)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(m => m.RegualarExpressionField)
                @Html.ValidationMessageFor(m => m.RegualarExpressionField)
            </div>

            <p>
                <input type="submit" value="go!" />
            </p>
        </fieldset>
    </div>

运行之后会发现两个问题:

①方案(2)中,客户端的验证没有被触发

②即使输入完全符合正则表达式的值,两个方案经Server端验证后,全部返回验证的错误信息

讨论:

问题①的原因:

我们在DateExpressionAttribute并没有实现IClientValidatable接口,故Client端的验证不会被触发;

修改类如下:

    public class DateExpressionAttribute : RegularExpressionAttribute, IClientValidatable
    {
         public DateExpressionAttribute()
             : base(@"Your date regular expression here")
         {

         }

         public override string FormatErrorMessage(string name)
         {
             return String.Format(CultureInfo.CurrentCulture,
               "The filed {0} should be a date", name);
         }

         public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
         {
             var name = metadata.GetDisplayName();
             var rule = new ModelClientValidationRegexRule(FormatErrorMessage(name), Pattern);
             yield return rule;
         }
    }
再次运行,方案(2)的客户端验证也可以成功触发了。


问题②的原因:
由于我们定义的两个字段都是DateTime类型,故从前台传到后台后,实际去进行验证的时间格式是DateTime(yyyy-MM-dd hh:mm:ss),所以正则表达式必然返回错误(几乎永远不可能通过)。另外,将Client端的验证关掉,输入abc后,返回的错误是"The value "abc" is not a valid value for DateField"。这个错误并不是正则表达式的验证错误,而是当试着把"abc"转换成DateTime类型的时候所抛出的错误,也就是说,你如果输入了无法转换成DateTime类型的值的话,验证是不会经过正则表达式那一端的。当你到达正则表达式验证的时候,输入的日期格式已经被转换成了DateTime了。

此时,可以考虑把DateExpression的Server端验证拿掉,最终代码如下:

    public class DateExpressionAttribute : RegularExpressionAttribute, IClientValidatable
    {
         public DateExpressionAttribute()
             : base(@"((^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(10|12|0?[13578])([-\/\._])(3[01]|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(11|0?[469])([-\/\._])(30|[12][0-9]|0?[1-9])$)|(^((1[8-9]\d{2})|([2-9]\d{3}))([-\/\._])(0?2)([-\/\._])(2[0-8]|1[0-9]|0?[1-9])$)|(^([2468][048]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([3579][26]00)([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][0][48])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][2468][048])([-\/\._])(0?2)([-\/\._])(29)$)|(^([1][89][13579][26])([-\/\._])(0?2)([-\/\._])(29)$)|(^([2-9][0-9][13579][26])([-\/\._])(0?2)([-\/\._])(29)$))")
         {

         }

         public override bool IsValid(object value)
         {
             return true;
         }

         public override string FormatErrorMessage(string name)
         {
             return String.Format(CultureInfo.CurrentCulture,
               "The filed {0} should be a date", name);
         }

         public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
         {
             var name = metadata.GetDisplayName();
             var rule = new ModelClientValidationRegexRule(FormatErrorMessage(name), Pattern);
             yield return rule;
         }
    }

若是仍需要加Server端的验证的话,另一个间接方法就是暂时用String来取得Date的值。这样一来不必经过DateTime类型的转化。即便输入了错误的格式,也能够进行Server端的验证,返回期望的错误消息。在Server端验证通过后,再手动将字符串转化为日期格式。


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值