demoshop

demo, trying to be the best_

版本
3

此篇是自訂擴充驗證的最後一篇,先來說說什麼叫做「不等於驗證」此驗證就是和內建的 Compare 剛好相反,您可以自訂某一欄位的值不能與另一個欄位相同,應用層面也滿廣的,比如有個欄位要輸入親子關係,那A姓名就不能等於B姓名,而且這次介紹的是彈性最高的 addMethod 所以如果你有什麼很神奇的想法,這篇就是一定要學會的。

●一樣一開始就建立一個自訂的驗證規則出來吧,這次名稱就取為「NotequalToAttribute」

/// <summary>
/// 兩個欄位不能相等
/// </summary>
public sealed class NotEqualToAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// Gets the other property.
    /// </summary>
    public string OtherProperty { get; private set; }
    /// <summary>
    /// Initializes a new instance of the <see cref="NotEqualToAttribute"/> class.
    /// </summary>
    /// <param name="otherProperty">要比對的屬性名稱</param>
    public NotEqualToAttribute(string otherProperty)
    {
        OtherProperty = otherProperty;
    }

    /// <summary>
    /// 根據目前的驗證屬性,驗證指定的值。
    /// </summary>
    /// <param name="value">要驗證的值。</param>
    /// <param name="validationContext">有關驗證作業的內容資訊。</param>
    /// <returns>
    ///   <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult"/> 類別的執行個體。
    /// </returns>
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(OtherProperty);
        if (property == null)
        {
            return new ValidationResult(
                string.Format(
                    CultureInfo.CurrentCulture,
                    "{0} 不存在",
                    OtherProperty
                )
            );
        }
        var otherValue = property.GetValue(validationContext.ObjectInstance, null);
        if (object.Equals(value, otherValue))
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }

    /// <summary>
    /// 在類別中實作時,傳回該類別的用戶端驗證規則。
    /// </summary>
    /// <param name="metadata">模型中繼資料。</param>
    /// <param name="context">控制器內容。</param>
    /// <returns>
    /// 此驗證程式的用戶端驗證規則。
    /// </returns>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
            ValidationType = "notequalto",
        };
        rule.ValidationParameters["other"] = OtherProperty;
        yield return rule;
    }
}

這次有幾點比較不一樣,首先在第27行的時候,我們多傳入了一個「ValidationContext validationContext」參數,因為傳入了它,我們才可以利用反射去取得指定的欄位是否存在(指定欄位的時候使用弱型別所以少了這驗證就很容易發生拼錯、打錯而導致欄位不存在的錯誤),驗證存在後再利用反射取得輸入的值來做比對驗證。


●再來為了符合情境,我們要在「AccountModels.cs」內的「RegisterModel」新增屬性並且加上驗證

[NotEqualTo("UserName", ErrorMessage = "介紹人與Username不能相同")]
[Display(Name = "介紹人")]
public string Introducer { get; set; }

在本範例的設定是不可以輸入和 username 欄位的值相同


●來到 View 增加以下 Code

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

●接者擴充 js

<script type="text/javascript">
    jQuery.validator.addMethod('notEqualTo', function (value, element, param) {
        return this.optional(element) || value != $(param).val();
    });
    jQuery.validator.unobtrusive.adapters.add(
        'notequalto', ['other'], function (options) {
            options.rules['notEqualTo'] = '#' + options.params.other;
            if (options.message) {
                options.messages['notEqualTo'] = options.message;
            }
        });
</script>

●編譯過後再測試就可以看到效果了


demo廢言到目前為止前端驗證的擴充已經介紹完畢了,如果您還有什麼不是很瞭解用法的地方其實直接打開專案中的【jquery.validate.unobtrusive.js】檔案從第188行到第261行就有很明確的說明,相當的好上手,如果你有心想把 ASP.NET MVC3 寫好的話寫一套自己的驗證規則擴充是必須的,擴充的方法如您所見並不困難而且效果很好,如果在擴充的時候有什麼問題的話歡迎留言詢問,剩下的系列文大約剩下兩篇,有關於一些技巧的應用 demo 會盡量早點發出來的 

回應討論