demoshop

demo, trying to be the best_

版本
4

如果你已經開始使用了 MVC4 而且很不巧的你會使用到 IE6、7、8 那你就會踩到這個雷,demo 一直很鼓吹各位開發 MVC 的朋友要使用 MVC 內建的驗證機制來簡化整個網站表單驗證的部份,當然有雷也必須要和各位誠實稟告,今天要說的就是日期驗證的雷。

demo廢言為了方便直接使用內建樣本來示範,所以各位也可以直接開一個新的 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>

以上的步驟流程完成後就可以通過 日期的前端驗證了,如果你還有遇到其他的問題,再留言吧

回應討論