2011-01-28 36 views
17

Tôi đã sử dụng các jquery xác nhận cắm trong một vài năm nay nhưng đây là nỗ lực đầu tiên của tôi để trộn với MVC 3 unobtrusive xác nhận.ASP .Net MVC 3 unobtrusive khách hàng xác nhận khách hàng

Thông tin về phía khách hàng của mọi thứ nằm rải rác trên internet và thật khó để tìm thấy bất kỳ điều nào đủ sâu để giải thích cho những người chưa sử dụng nó. Tôi đã đốt cháy Google trong một giờ ngay bây giờ cho một ví dụ về cách tạo trình xác thực phía máy khách tùy chỉnh.

@Html.TextBoxFor(model => Model.CCPayment.CardNumber, new { @class = "textInput validateCreditCard", maxLength = "20" }) 

$(document).ready(function() { 
     jQuery.validator.unobtrusive.adapters.add('validateCreditCard', {}, function (value, element) { 
     alert('foo'); 
    }); 
}); 

nếu tôi chạy mã trên ở cuối chế độ xem thì hoàn toàn không có gì. Tôi thậm chí đã thử jquery.validator.addmethod() và vẫn không có gì. Tất cả các xác nhận phía khách hàng được phát ra từ chú thích xác thực mô hình của tôi đều hoạt động tốt.

<div class="ctrlHolder"> 
       <label> 
        <em>*</em> 
        Card Number: 
       </label> 
       @Html.TextBoxFor(model => Model.CCPayment.CardNumber, new { @class = "textInput validateCreditCard", maxLength = "20" }) 

       <p class="field-validation-valid formHint" data-valmsg-for="CCPayment.CardNumber"></p> 
      </div> 
+0

Bạn có bao gồm kịch bản "jquery.validate.unobtrusive.js" trong trang của bạn? – Chandu

+0

vâng ... tất cả các xác thực phía máy khách khác hoạt động, trong mô hình của tôi, tôi có một số chú thích tạo ra các trường bắt buộc và tất cả chúng đều hoạt động tốt. Tôi chỉ muốn thêm một phương thức xác thực tùy chỉnh để xác thực biểu mẫu. – JBeckton

Trả lời

26

Dưới đây là cách bạn có thể tiến hành. Trước tiên, bạn cần phải viết một thuộc tính validator tùy chỉnh để đảm bảo rằng việc xác thực được thực thi ở phía máy chủ. Bạn có thể sử dụng một trong những mô tả trong blog post này:

public class CreditCardAttribute : ValidationAttribute, IClientValidatable 
{ 
    private CardType _cardTypes; 
    public CardType AcceptedCardTypes 
    { 
     get { return _cardTypes; } 
     set { _cardTypes = value; } 
    } 

    public CreditCardAttribute() 
    { 
     _cardTypes = CardType.All; 
    } 

    public CreditCardAttribute(CardType AcceptedCardTypes) 
    { 
     _cardTypes = AcceptedCardTypes; 
    } 

    public override bool IsValid(object value) 
    { 
     var number = Convert.ToString(value); 

     if (String.IsNullOrEmpty(number)) 
      return true; 

     return IsValidType(number, _cardTypes) && IsValidNumber(number); 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return "The " + name + " field contains an invalid credit card number."; 
    } 

    public enum CardType 
    { 
     Unknown = 1, 
     Visa = 2, 
     MasterCard = 4, 
     Amex = 8, 
     Diners = 16, 

     All = CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners, 
     AllOrUnknown = CardType.Unknown | CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners 
    } 

    private bool IsValidType(string cardNumber, CardType cardType) 
    { 
     // Visa 
     if (Regex.IsMatch(cardNumber, "^(4)") 
      && ((cardType & CardType.Visa) != 0)) 
      return cardNumber.Length == 13 || cardNumber.Length == 16; 

     // MasterCard 
     if (Regex.IsMatch(cardNumber, "^(51|52|53|54|55)") 
      && ((cardType & CardType.MasterCard) != 0)) 
      return cardNumber.Length == 16; 

     // Amex 
     if (Regex.IsMatch(cardNumber, "^(34|37)") 
      && ((cardType & CardType.Amex) != 0)) 
      return cardNumber.Length == 15; 

     // Diners 
     if (Regex.IsMatch(cardNumber, "^(300|301|302|303|304|305|36|38)") 
      && ((cardType & CardType.Diners) != 0)) 
      return cardNumber.Length == 14; 

     //Unknown 
     if ((cardType & CardType.Unknown) != 0) 
      return true; 

     return false; 
    } 

    private bool IsValidNumber(string number) 
    { 
     int[] DELTAS = new int[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 0 }; 
     int checksum = 0; 
     char[] chars = number.ToCharArray(); 
     for (int i = chars.Length - 1; i > -1; i--) 
     { 
      int j = ((int)chars[i]) - 48; 
      checksum += j; 
      if (((i - chars.Length) % 2) == 0) 
       checksum += DELTAS[j]; 
     } 

     return ((checksum % 10) == 0); 
    } 

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

Chú ý rằng tôi đã sửa đổi nó để làm cho nó thực hiện các giao diện IClientValidatable và thêm GetClientValidationRules phương pháp mà chỉ đơn giản sử dụng các thông báo lỗi tương tự cho khách hàng xác nhận là phía máy chủ và cung cấp tên duy nhất cho trình xác thực này sẽ được sử dụng bởi bộ điều hợp không phô trương. Bây giờ tất cả những gì còn lại là để trang trí bất động sản mô hình của bạn với thuộc tính này:

[CreditCard(ErrorMessage = "Please enter a valid credit card number")] 
[Required] 
public string CardNumber { get; set; } 

và theo quan điểm của bạn:

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script> 
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script> 
<script type="text/javascript"> 
    $(function() { 
     jQuery.validator.unobtrusive.adapters.addBool('creditcard'); 
    }); 
</script> 

@using (Html.BeginForm()) 
{ 
    @Html.TextBoxFor(x => x.CardNumber) 
    @Html.ValidationMessageFor(x => x.CardNumber) 
    <input type="submit" value="OK" /> 
} 
+0

Darin, cảm ơn phản hồi chi tiết. Tôi đang sử dụng IValidatableObject trong mô hình của tôi chứ không phải là thuộc tính tùy chỉnh không có nghĩa là tôi không thể liên kết xác thực phía máy chủ và phía máy khách trừ khi tôi sử dụng các thuộc tính tùy chỉnh? – JBeckton

+0

Tôi không thể thêm xác thực ứng dụng khách tùy chỉnh với việc liên kết nó với xác thực phía máy chủ không? – JBeckton

+1

@ JBeckton, bạn có thể nhưng điều đó sẽ vô cùng vô dụng và một lỗ hổng bảo mật rất lớn. Để làm việc này, bạn sẽ cần có các thuộc tính HTML5 'data- *' thích hợp được phát ra trên hộp văn bản của bạn để bộ điều hợp hoạt động. Bạn nên thực hiện logic xác nhận của bạn ít nhất là trên máy chủ. Xác nhận phía khách hàng chỉ dành cho mục đích thẩm mỹ. –

2

Bạn cần ValidateFor ngoài TextBoxFor. Tôi không thể nói từ câu hỏi của bạn nếu bạn đã làm điều đó hay không. Bạn cũng cần EnableClientValidation trước biểu mẫu.

+0

EnableClientValidation được đặt trong web.config của tôi, tôi đã xóa các trình trợ giúp ValidatorFor vì chúng không cần thiết với xác thực không chính xác mvc 3 mới. thay vào đó tất cả những gì bạn cần là một phần tử html với một lớp của trường hợp xác thực hợp lệ – JBeckton

+1

Nếu bạn không có 'ValidateFor', thì bạn sẽ không thấy thông báo xác thực phía máy chủ. Trong MVC 2, xác thực phía máy khách sẽ không hoạt động nếu không có chúng. –

+0

ok Tôi đã nhận, nếu js bị tắt, tôi sẽ không thấy thông báo xác thực. Với được kích hoạt tôi nhìn thấy chúng, nhưng như là tin nhắn val phía khách hàng. – JBeckton

Các vấn đề liên quan