ASP.NET MVC4 內建驗證遇到DateTime 型別的 Bug
- 2012-07-22
- 26939
- 0
- ASP.NET MVC3 驗證介紹實作與擴充
- 版本
- 4
如果你已經開始使用了 MVC4 而且很不巧的你會使用到 IE6、7、8 那你就會踩到這個雷,demo 一直很鼓吹各位開發 MVC 的朋友要使用 MVC 內建的驗證機制來簡化整個網站表單驗證的部份,當然有雷也必須要和各位誠實稟告,今天要說的就是日期驗證的雷。
為了方便直接使用內建樣本來示範,所以各位也可以直接開一個新的 ASP.NET MVC4 來玩玩看。
首先還是要使用到「Models」資料夾內的「AccountModels.cs」這個 Model物件,點開它,新增一個屬性
public class RegisterModel { [Required] [Display(Name = "User name")] public string UserName { get; set; } public DateTime TestData { get; set; } [Required] [DataType(DataType.EmailAddress)] [Display(Name = "Email address")] public string Email { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } }
以上的範例中新增了一個名稱為「TestData」的屬性,型別為 DateTime 而且沒給任何的驗證
再進到「Views」→「Account」→「Register.cshtml」加上剛剛的 testData
@model MvcApplication1.Models.RegisterModel @{ ViewBag.Title = "Register"; } <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>Create a new account.</h2> </hgroup> <p class="message-info">Passwords must be at least @Membership.MinRequiredPasswordLength characters long. </p> @using (Html.BeginForm()) { @Html.ValidationSummary() <fieldset> <legend>Registration Form</legend> <ol> <li> @Html.LabelFor(m => m.TestData) @Html.TextBoxFor(m => m.TestData) </li> <li> @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName) </li> <li> @Html.LabelFor(m => m.Email) @Html.TextBoxFor(m => m.Email) </li> <li> @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password) </li> <li> @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword) </li> </ol> <input type="submit" value="Register" /> </fieldset> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
編譯後到頁面去看看吧,進入到註冊頁(畫面右上角)
看到上圖,輸入了很正確的 2012-09-01 卻被驗證檔掉,這是因為 jquery.validate 的格式驗證擋住的,所以我們要來看看 jquery.validate 驗證了什麼。
開啟了 jquery.validate.js 搜尋「dateISO」第四個就是我們要看的驗證,但是我們要看的是它上面的「date」(因為 date 太多了不好找所以改找 dateISO)
// http://docs.jquery.com/Plugins/Validation/Methods/date date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); },
看起來這驗證十分的對,那到底是為什麼會出問題呢?
原來在 IE 678 的世界 newData('2012-09-01') 是會返回 NaN 的,所以導致驗證失敗
你可以用IE 678 來玩玩看下面這塊
既然知道了原因,那就避開它吧,直接改使用格式的驗證來判斷即可(反正如果真的錯了值也寫不進去 SQL ...)
return this.optional(element) || (/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value));
雖然說上方的改法就可以正常通過了(如果你日期格式不同請自行調整)但是直接去改 jquery.validate 是非常不明智的行為,當你動手改了以後,你就沒有能力升級了,所以這裡要運用一個小技巧,新增一個 js 檔案,命名為 jquery.validate.plus.js ,在裡面就這樣寫
jQuery.validator.methods.date = function (value, element) { return this.optional(element) || (/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value)); }
載入 js 的順序只要是這樣就可以成功的利用另一個 js 檔案擴充或覆寫原本的方法
<script type="text/javascript" src="/Scripts/jquery.validate.js"></script> <script type="text/javascript" src="/Scripts/jquery.validate.plus.js"></script>
以上的步驟流程完成後就可以通過 日期的前端驗證了,如果你還有遇到其他的問題,再留言吧
回應討論