demoshop

demo, trying to be the best_

ASP.NET MVC3 內建的錯誤訊息都十分的詳細,但我們自己擴充的都只會顯示【欄位 XX 無效。】這種沒啥用的錯誤訊息,因此本文會說明利用一些技巧來改變錯誤訊息的內容。

●在 Model Class 中加上驗證 Attribute 的時候,如果有設定 ErrorMessage 屬性,那錯誤的時候就可以顯示自定的錯誤

[Email(ErrorMessage="Email 格式錯誤")]
public string Email { get; set; }


●這樣當然是可以解決問題,但每次使用的時候都要輸入是很麻煩的(通常會被淪落為複製貼上,然後就錯誤百出...)因此應該改變預設的錯誤訊息,可以看到之前 demo 的自定驗證規則文章中對於 ModelClientValidationRule 的 ErrorMessage 都是會在包住 FormatErrorMessage方法

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    ModelClientValidationRule rule = new ModelClientValidationRule
    {
        ValidationType = "email",
        ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
    };
    yield return rule;
}

使用FormatErrorMessage() 就可以產生出 【欄位 xxxx 無效。】的錯誤訊息,但是使用者看到了無效並不知道為什麼,所以應該要改成使用者看的懂得訊息,不然這樣的錯誤訊息就沒什麼效用。

注意事項基於資安考量,錯誤訊息別設定的太明確,意思到就好。


●為了修改成更平易近人的錯誤提示,我們可以覆寫掉 FormatErrorMessage 這個方法

public override string FormatErrorMessage(string name)
{
    return this.ErrorMessage ?? string.Format("{0} 欄位請輸入正確的 Email", name);
}
  • this.ErrorMessage 是建立 ModelClass 的時候 驗證Attribute 輸入的那個 ErrorMessage。
  • ?? 是 C# 的特殊寫法,簡單說就是前面是 null 的話就傳回後面(?? 運算子 (C# 參考)

這樣子錯誤訊息就明確很多了


●當然對於可以輸入參數值的驗證也可以很簡單寫

public override string FormatErrorMessage(string name)
{
    /*
     * Input 這屬性本身是 字串陣列所以才這樣合併
     *
     * 請參考
     * ASP.NET MVC3 自訂驗證規則 帳號不能註冊為 demoshop !(使用 AddSingleVal 方法)
     * http://demo.tc/Post/688
     */
    return string.Format("{0} 欄位不可輸入 {1}", name, string.Join("、", this.Input));
}

 


demo廢言眼尖的朋友可能會發現在前幾篇的時候 demo 擴充前端驗證的 javascript 中好像都少了一個錯誤訊息的參數,這是因為使用了微軟佛心寫好的 jquery.validate.unobtrusive.js 這隻 js 中就有幫我們指定進去了(可以從第 134 行開始看),因此即使你在擴充前端的 javascript 中有寫錯誤訊息,預設的狀態一樣出不來,反而有可能導致前端驗證的錯誤訊息和後端驗證的錯誤訊息不同步,所以建議就維持預設吧。

 

注意事項上面有提到錯誤訊息不要設定的太明確這點, demo 想舉一個相當常見的例子,今天假設你來到了一個你曾經有註冊過會員的網站,但是因為你忘記密碼也忘了帳號,不過通常的使用者帳號都會有幾個輪流換假設你今天輸入了【test1】系統很明確的回應你【此帳號不存在】,那你就可以繼續猜【test2】直到系統回應【密碼錯誤!】的時候,就可以很明確的知道我是使用了【test2】註冊的,只需要專心猜密碼就好,這例子如果套用在【有心人士】身上的話,它就可以很輕易的知道這系統有哪些註冊的帳號,對於資安來說是不安全的,而且這也是很容易避免的,千萬要注意。

回應討論