demoshop

demo, trying to be the best_

這次來到第二種自訂驗證的方法 SingleVal,其實這裡說的這些都是屬於前端驗證的方法,後端是很隨意的 讓我們來假設一下,今天 demo小鋪開放註冊會員,但是不希望有任何人註冊有關於 demo 這個名字,如果使用上一篇文章介紹的 AddBool 方式來寫,當哪一天要改成 「demoshop」 或是 「demo小鋪」的時候就會有很多地方要改,但是明明驗證邏輯是一樣的只是驗證的比對值不同,所以可以利用所謂的 AddSingleVal 方法來擴充驗證,要比對的值使用參數傳入,驗證的邏輯則是固定,這樣子就可以運用到多個情境,以下就是介紹

●依序前文的範例,這次我們也同樣在 ValidateAttribute 資料夾中建立一個新類別,取名為 【NoIsAttribute】


●這次我們已經知道需要驗證前端了,因此直接繼承 ValidationAttribute 和 IClientValidatable ,Code會長這樣

public class NoIsAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// 禁止輸入的值
    /// </summary>
    public string Input { get; set; }

    //因為此驗證不可能不輸入要禁止的值,所以利用建構式來強迫輸入
    public NoIsAttribute(string input)
    {
        this.Input = input;
    }

    public override bool IsValid(object value)
    {
        //要不要輸入與此驗證無關
        if (value == null)
            return true;

        //如果輸入的值是字串才做判斷
        if (value is string)
        {
            //輸入值與欄位值相同就報錯
            if (Input.Contains(value.ToString()))
                return false;
        }
        return true;
    }
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule rule = new ModelClientValidationRule
        {
            ValidationType = "nois",
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
        };
        //此參數一定要是小寫!
        rule.ValidationParameters["input"] = Input;

        yield return rule;
    }
}

注意事項rule.ValidationParameters的名稱一定要是小寫


●再來實作前端的 JS

<script type="text/javascript">
    $.validator.addMethod("nois", function (value, element, param) {
        if (value == false) {
            return true;
        }
        if (value.indexOf(param) != -1) {
            return false;
        }
        else {
            return true;
        }
    });
    $.validator.unobtrusive.adapters.addSingleVal("nois", "input");
</script>

注意事項邏輯與後端驗證相同,只是寫法改成了 javascript ,要注意的是因為此類型的驗證是有參數的,所以參數要註冊進去因此這次使用了addSingleVal 方法,第一個參數就是此 Method 名,第二個參數需要與後端的 rule.ValidationParameters名稱相同。


●接者前進到 RegisterModel Class 將 UserName 欄位的驗證改成如下(為了方便測試)

[Required]
[NoIs("demo",ErrorMessage="請使用別的名稱")]
[Display(Name = "User name")]
public string UserName { get; set; }

●再來就是到註冊頁面測試效果囉


demo廢言初步的擴充完成,但立刻會遇到一個問題,是否可以一次判斷多個禁止的值,這當然是可以完成的,而且要用習慣來完成,什麼叫做習慣?通常大家應該都很習慣多個值用逗點分隔吧,因此就利用這習慣來實作多個禁止值的擴充吧。

 

●回到 NoIsAttribute 調整 Code

public class NoIsAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// 禁止輸入的值
    /// </summary>
    public string[] Input { get; set; }

    //因為此驗證不可能不輸入要禁止的值,所以利用建構式來強迫輸入
    public NoIsAttribute(string input)
    {
        //檢查是否有包含分隔符號
        if (input.IndexOf(",") > -1)
            //有的話就切吧
            this.Input = input.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
        else
            //沒有的話就新增一個字串陣列塞過去
            this.Input = new string[] { input };
    }

    public override bool IsValid(object value)
    {
        //要不要輸入與此驗證無關
        if (value == null)
            return true;

        //如果輸入的值是字串才做判斷
        if (value is string)
        {
            //輸入值與欄位值相同就報錯
            if (Input.Contains(value.ToString()))
                return false;
        }
        return true;
    }
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        ModelClientValidationRule rule = new ModelClientValidationRule
        {
            ValidationType = "nois",
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
        };
        //此參數一定要是小寫!
        rule.ValidationParameters["input"] = string.Join(",", Input);

        yield return rule;
    }
}

●前端驗證也需要調整

<script type="text/javascript">
    $.validator.addMethod("nois", function (value, element, param) {
        if (value == false) {
            return true;
        }
        var validateState = true;
        var paramarr = param.split(',');
        $.each(paramarr, function (i, n) {
            if (value==n) {
                validateState = false;
                return;
            }
        });
        return validateState;
    });
    $.validator.unobtrusive.adapters.addSingleVal("nois", "input");
</script>

●再前往 RegisterModel Class 將 UserName 欄位的驗證改成如下

[Required]
[NoIs("demo,小鋪",ErrorMessage="請使用別的名稱")]
[Display(Name = "User name")]
public string UserName { get; set; }

●然後您就可以到註冊頁測試了,當使用者打了 「demo」 或是 「小鋪」 就會被限制囉,當然因為這驗證已經將變數抽了出來,所以如果需要套用在別的屬性上面也相當的容易,比如現在也將 Email 加上不可以輸入(123@123.com)的驗證

[Required]
[DataType(DataType.EmailAddress)]
[NoIs("123@123.com", ErrorMessage = "Email太假")]
[Display(Name = "Email")]
public string Email { get; set; }


demo廢言可以輸入參數以後彈性的確是增加了許多,不過擴充驗證規則還沒寫完哩,下一篇將介紹另一種大小值的驗證擴充法。

回應討論