ASP .Net MVC 3 unobtrusive custom client validation

前端 未结 2 514
花落未央
花落未央 2020-12-04 13:33

I have used the jquery validation plug in for a couple years now but this is my first effort to mixing with MVC 3 unobtrusive validation.

Information on the client s

相关标签:
2条回答
  • 2020-12-04 14:11

    Here's how you could proceed. First you need to write a custom validator attribute in order to ensure that the validation is enforced on the server side. You could use the one described in this blog post:

    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"
            };
        }
    }
    

    Notice that I've modified it to make it implement the IClientValidatable interface and added the GetClientValidationRules method which simply uses the same error message for client validation as the server side and provides an unique name for this validator that will be used by the jquery unobtrusive adapter. Now all that's left is to decorate your model property with this attribute:

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

    and in your view:

    <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 讨论(0)
  • 2020-12-04 14:12

    You need ValidateFor in addition to TextBoxFor. I can't tell from your question if you've already done that or not. You also need EnableClientValidation before the form.

    0 讨论(0)
提交回复
热议问题