File: DataAnnotations\CreditCardAttribute.cs
Project: ndp\fx\src\xsp\system\DataAnnotations\System.ComponentModel.DataAnnotations.csproj (System.ComponentModel.DataAnnotations)
namespace System.ComponentModel.DataAnnotations {
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Resources;
    using System.Linq;
 
    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
    public sealed class CreditCardAttribute : DataTypeAttribute {
        public CreditCardAttribute()
            : base(DataType.CreditCard) {
 
            // DevDiv 468241: set DefaultErrorMessage not ErrorMessage, allowing user to set
            // ErrorMessageResourceType and ErrorMessageResourceName to use localized messages.
            DefaultErrorMessage = DataAnnotationsResources.CreditCardAttribute_Invalid;
        }
 
        public override bool IsValid(object value) {
            if (value == null) {
                return true;
            }
 
            string ccValue = value as string;
            if (ccValue == null) {
                return false;
            }
            ccValue = ccValue.Replace("-", "");
            ccValue = ccValue.Replace(" ", "");
 
            int checksum = 0;
            bool evenDigit = false;
 
            // http://www.beachnet.com/~hstiles/cardtype.html
            foreach (char digit in ccValue.Reverse()) {
                if (digit < '0' || digit > '9') {
                    return false;
                }
 
                int digitValue = (digit - '0') * (evenDigit ? 2 : 1);
                evenDigit = !evenDigit;
 
                while (digitValue > 0) {
                    checksum += digitValue % 10;
                    digitValue /= 10;
                }
            }
 
            return (checksum % 10) == 0;
        }
    }
}