<html>
<head>
 
    <script language="VB" runat=server>        Sub ValidateBtn_OnClick(sender As Object, e As EventArgs)
            If (Page.IsValid) Then
               lblOutput.Text = "页有效!"
            Else
               lblOutput.Text = "页无效!:-("
            End If
        End Sub        Sub ServerValidate (sender As Object, value As ServerValidateEventArgs)            Try
                Dim num As Int32 = Int32.Parse(value.Value)                If num Mod 2 = 0 Then
                    value.IsValid = True
                    Exit Sub
                End If
            Catch E As Exception
                ' Do Nothing
            End Try
            value.IsValid = False
        End Sub   </script></head>
<body><h3><font face="宋体">CustomValidator 示例</font></h3><form runat="server">    <asp:Label id=lblOutput runat="server"
        Text="输入一个偶数:"
        Font-Name="宋体"
        Font-Size="10.5pt" /><br>    <p>    <asp:TextBox id=Text1 runat="server" />    &nbsp&nbsp    <asp:CustomValidator id="CustomValidator1" runat="server"
        ControlToValidate="Text1"
        OnServerValidate="ServerValidate"
        Display="Static"
        Font-Name="verdana" Font-Size="10pt">
           不是偶数!
    </asp:CustomValidator>    <p>    <asp:Button text="验证" onclick="ValidateBtn_OnClick" runat="server" /></form></body>
</html>

解决方案 »

  1.   

    Introduction
    A while ago I started working on converting an eCommerce payment gateway's (DataCash) COM server to a native .NET assembly using their XML API. Once I had got a basic version working I decided to produce a simple web form to test it out, and so opened it up for all comers (and received some very generous donations from CP members -- thanks guys :). As part of this web form I wanted to include support to check that users had entered a card number, expiration date etc., and then wanted to extend it further to include support for checking that the card number was valid before issuing a request to the payment gateway's server. This is the result, a drop-in replacement for any of the other validation controls.Incidentally, you can see a demo of the validator in use (as well as the card payment gateway assembly) at the following address: https://ssl500.securepod.com/oobaloo/DataCash/, besides this you may also be interested in the everything you ever wanted to know about CC's guide.Before getting into any of the implementation details here is a simple UML class diagram to show the rough layout of the Control.The diagram is missing information about parameter types since its not essential to understanding the model. For those who are not familiar with UML, it shows a specialisation relationship between the BaseValidator and CreditCardValidator classes - an is a relationship - demonstrating inheritance from BaseValidator to the more specialised CreditCardValidator class. New with the third incarnation of the control is the AcceptedCardTypes property which is used to specify what types of card should pass the validation using the CardType enumeration.The control includes support for validating card numbers in two ways. Firstly, through checking the card number using Luhn's formula, the details of which are included in the next part of the article. Secondly, the card type itself is examined, and the length is checked. The card type can be determined through a prefix and each type has a specified length, by examining these an additional level of control can be added - the types of card to accept. The method that implements this is IsValidCardType, and whether this is used during the validation is set by the ValidateCardType property. The main way the card number is going to be validated is through Luhn's formula, so firstly a little bit of background information and a demo of how the validation is performed.Luhn's Formula
    公式如下:
    Double the value of alternating digits
    The first step is to double each of the alternating digits in the number. But the trick is to start with the second digit from the right and work backwards. Say we have a credit card number 1234 5678 1234 5670. We'll start with the rightmost number 7, double it, and then do the same for every other digit. 
    1234 5678 1234 5670This will give us the following values.7 x 2 = 14
    5 x 2 = 10
    3 x 2 = 6
    .

    etc. 
    Add the separate digits of all the products
    Now we'll the separate digits of all the products, and come up with a final sum. 
    (1 + 4) + (1 + 0) + 6 + 2 + (1 + 4) + (1 + 0) + 6 + 2 = 28Be sure to add the digits, not just the number.Add the unaffected digits
    Now we'll go back to the original number and add all the digits that we didn't double. We'll still start from the right, but this time we'll start from the rightmost number. 
    1234 5678 1234 5670
    0 + 6 + 4 + 2 + 8 + 6 + 4 + 2 = 32Add the results and divide by 10 
    Finally, we'll add both the results and divide the answer by 10. 28 + 32 = 6060 is evenly divided by 10, so the credit card number is well formed and ready for further processing.
      

  2.   

    代码如下:private static bool ValidateCardNumber( string cardNumber )
    {
        try 
        {
            // Array to contain individual numbers
            System.Collections.ArrayList CheckNumbers = new ArrayList();
            // So, get length of card
            int CardLength = cardNumber.Length;
        
            // Double the value of alternate digits, starting with the second digit
            // from the right, i.e. back to front.
            // Loop through starting at the end
            for (int i = CardLength-2; i >= 0; i = i - 2)
            {
                // Now read the contents at each index, this
                // can then be stored as an array of integers            // Double the number returned
                CheckNumbers.Add( Int32.Parse(cardNumber[i].ToString())*2 );
            }        int CheckSum = 0;    // Will hold the total sum of all checksum digits
                
            // Second stage, add separate digits of all products
            for (int iCount = 0; iCount <= CheckNumbers.Count-1; iCount++)
            {
                int _count = 0;    // will hold the sum of the digits            // determine if current number has more than one digit
                if ((int)CheckNumbers[iCount] > 9)
                {
                    int _numLength = ((int)CheckNumbers[iCount]).ToString().Length;
                    // add count to each digit
                    for (int x = 0; x < _numLength; x++)
                    {
                        _count = _count + Int32.Parse( 
                              ((int)CheckNumbers[iCount]).ToString()[x].ToString() );
                    }
                }
                else
                {
                    // single digit, just add it by itself
                    _count = (int)CheckNumbers[iCount];   
                }
                CheckSum = CheckSum + _count;    // add sum to the total sum
            }
            // Stage 3, add the unaffected digits
            // Add all the digits that we didn't double still starting from the
            // right but this time we'll start from the rightmost number with 
            // alternating digits
            int OriginalSum = 0;
            for (int y = CardLength-1; y >= 0; y = y - 2)
            {
                OriginalSum = OriginalSum + Int32.Parse(cardNumber[y].ToString());
            }        // Perform the final calculation, if the sum Mod 10 results in 0 then
            // it's valid, otherwise its false.
            return (((OriginalSum+CheckSum)%10)==0);
        }
        catch
        {
            return false;
        }
    }//最后
    protected override bool EvaluateIsValid()
    {
        if (_validateCardType)    // should the length be validated also?
        {
            // Check the length, if the length is fine then validate the
            // card number
            if (IsValidCardType(_creditCardTextBox.Text))
                return ValidateCardNumber( _creditCardTextBox.Text );
            else
                return false;        // Invalid length
        }
        else
            // Check that the text box contains a valid number using 
            // the ValidateCardNumber method
            return ValidateCardNumber( _creditCardTextBox.Text );
    }
      

  3.   

    一时找不到简单的例子,这个例子相对复杂了,将就看吧。先建立一个包含customervalidate的类,用来检查信用卡的,继承的是一个包含require validate 的类,它们祖先都是一般的textbox。
    注意那句:this.Custom.ClientValidationFunction = "checkCredit";它指定了一个client端的检查函数。
    public class CreditTextBox : RequiredTextBox 
    {
    private CustomValidator _Custom = new CustomValidator();
    public CustomValidator Custom 
    {
    get { return _Custom; }
    }
    protected override void OnInit(EventArgs e) 
    {
    base.OnInit(e);
    this.Attributes["MultiValidate"] = "true";
    this.Custom.ControlToValidate = this.ID;
    this.Custom.ErrorMessage = "please enter a valid credit card  number";
    this.Custom.Display = ValidatorDisplay.None;
    this.Custom.ID = this.ID + "CustomValidator";
    this.Custom.ClientValidationFunction = "checkCredit";
    this.Controls.Add(Custom);
    }
    protected override void Render(HtmlTextWriter writer) 
    {
    base.Render(writer);
    this.Custom.RenderControl(writer);
    }
    }
      

  4.   

    用法:
    <%@ Register TagPrefix="etier" Namespace="Etier" Assembly="CreditCardValidator" %>
    <etier:CreditCardValidator
      Id="MyValidator"
      ControlToValidate="CardNumber"
      ErrorMessage="Please enter a valid credit card number"
      Display="none"
      RunAt="server"
      EnableClientScript="False"
      ValidateCardType="True"
      AcceptedCardTypes="Amex, VISA, MasterCard"
    />说明:
    _cardTypes 为信用卡内类型
    Flags, Serializable]
        public enum CardType
        {
            MasterCard    = 0x0001,
            VISA        = 0x0002,
            Amex        = 0x0004,
            DinersClub    = 0x0008,
            enRoute        = 0x0010,
            Discover    = 0x0020,
            JCB            = 0x0040,
            Unknown        = 0x0080,
            All            = CardType.Amex | CardType.DinersClub | 
                             CardType.Discover | CardType.Discover |
                             CardType.enRoute | CardType.JCB | 
                             CardType.MasterCard | CardType.VISA
        }
      

  5.   

    关键是那个函数的参数,必需是 source, agruments,返回值放在arguments.IsValid,看下面的程序:
    function checkCredit(source, arguments) {
     arguments.IsValid = isValidCreditCard(arguments.Value, "Visa");
    }
    isValidCreditCard是实际检查的函数,输入框的值在arguments.Value。
      

  6.   

    最后检查生成的client端code,注意最后的validator里面,clientvalidationfunction="checkCredit"。
    <input name="Service:payment:CreditCardNumber" type="text" maxlength="19" size="25" id="Service_payment_CreditCardNumber" class="Required" MultiValidate="true" /><span id="Service_payment_CreditCardNumberRequireValidator" controltovalidate="Service_payment_CreditCardNumber" errormessage="please enter this field" display="None" evaluationfunction="RequiredFieldValidatorEvaluateIsValid" initialvalue="" style="color:Red;display:none;"></span><span id="Service_payment_CreditCardNumberCustomValidator" controltovalidate="Service_payment_CreditCardNumber" errormessage="please enter a valid credit card  number" display="None" evaluationfunction="CustomValidatorEvaluateIsValid" clientvalidationfunction="checkCredit" style="color:Red;display:none;"></span>
      

  7.   

    server端的我就没提了,很多高手们已经给了很多例子了。