• 学习笔记验证控件


    作为程序员, 永远别指望用户按照规则进行输入, 比较理想的状况是在客户端浏览器和服务器端进行双重验证. 通常在客户端浏览器进行非功能性的常规验证, 如: 非空验证、范围验证及输入格式验证等, 而在服务器端进行功能性验证, 如: 检查账户是否存在, 检查用户权限等. 客户端浏览器的验证一般通过JavaScript实现, 验证过程与服务器无关, 在客户端浏览器验证通过后, 才将请求参数发送到服务器, 由服务端再次进行验证.微软的ASP.NET验证框架实现了客户端浏览器和服务器的双重验证.

    1. IValidator接口: ---ErrorMessage属性、IsValid属性、Validate()方法
    验证控件的核心是IValidator接口(System.Web.UI下), 其中有三个重要的成员: ErrorMessage属性、IsValid属性及Validate()方法, 执行validate方法后, 将设置IsValid属性.

    2. BaseValidator抽象类:
    为方便使用, ASP.NET通过实现了IValidator接口的抽象类BaseValidator为我们提供了大量的属性和方法.其中比较重要的属性有:
    ErrorMessage: 设置错误信息.
    IsValid: 验证结果.
    ControlToValidate: 对那个控件进行验证(通过ID查找)
    Display: 错误信息的显示方式, 有static、dynamic、none三中, static提前占位, 而dynamic不提前占位; none表示不在验证控件中显示, 通常配合BaseValiddator的Text属性, 将错误信息显示在ValidationSummary中.
    Text: 如果设置了Text, 验证控件将只显示Text内容, 而ErrorMessage的信息将放到ValidationSummary中显示.
    ValidationGrop: 只验证同一组的页面对象, 建议一开始就设置好分组.
    EnableClientScript: 是否启用客户端验证
    SetFocusOnError: 自动将焦点移到未通过验证的空间内.

    3. ASP.NET验证控件:
    RequiredFieldValidator: 检查用户是否输入, 除此控件外, 其他控件无输入时将默认不检查, 直接通过.
    RegularExpressionValidator: 使用正则表达式进行输入内容的验证.
        正则表达式内容:
        元数据: a
        [a,b,c]: abc任选一个, 如果可选项很多, 可用[a-z]
        \w: 大写字母、小写字母、0-9;   \W: 非大写字母、小写字母和0-9之外的字符;   \w\W: 所有字符
        \d: 0-9;   \D: 非0-9的字符
        \s: 空白
        数量词: ?表示0-1个;   +表示1-n个;   *表示0-n个;  {m,n}表示最少m个, 最多n个
        (): 分组
    CompareValidator: 用来比较两个绑定控件的内容. 需要通过Operator指定比较方式, 还需要通过Type指定比较的数据类型.
    RangeValidator: 判断内容是否在指定范围, 通过MaximumValue和MinimumValue指定最大和最小值, 也需要通过Type指定数据类型.
    CustomValidator: 自定义验证, 既可以在客户端浏览器验证也可以在服务器验证.客户端验证需要通过ClientValidationFunction属性设置验证用的JavaScript脚本函数名, 服务器端验证需要通过控件的ServerValidate事件来完成.
        .aspx文件中, 客户端浏览器验证的JavaScript脚本函数的形式如下:
        function ClientValidate(source,clientside_arguments)
        {

        }
        .cs文件中, 服务器端验证时ServerValidate事件的处理方法, 验证结果需要通过参数args.IsValid属性向验证框架返回结果, args.IsValid默认true;
        protected void ServerValidate(object source, ServerValidateEventArgs args)
        {

        }
    ValidationSummary: 收集页面上的验证信息并统一显示, 还可以通过ValidationGroup属性显示一组验证信息.
    注意: 按钮上有一个默认开启的属性CausesValidation, 表示该按钮是否激发验证, 如果该按钮通被包含在同一个ValidationGroup中, 则只进行该组中控件的验证.

    4. 服务器端验证的时机:
    页面对象有11个事件, 有两个非常重要的时间点(博客里有那张图): 一个是在Page_InitComplete --- Page_PreLoad之间, 完成控件的视图状态的读取以及请求参数到控件属性的赋值操作; 第二个是在Page_Load --- Page_LoadComplete之间, 完成服务器端请求参数处理和控件事件登记、通过页面对象的Validate()方法验证控件, 并通过其IsValid属性获得结果、控件事件的执行.
    服务器端验证时通过ServerValidate事件来完成的, 所以验证时机是在Page_Load事件之后, 控件事件之前执行. 页面上会有一个验证控件集合Page.Validators, 当执行服务器验证时, 遍历该集合, 改变页面对象的IsValid属性. 如果我们希望提前验证, 需要手动调用this.Validate()方法.

    //default.aspx代码

    代码
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <title>Untitled Page</title>
    <style type="text/css">
    .style1
    {
    95%;
    height: 216px;
    }
    .style5
    {
    }
    .style6
    {
    57px;
    }
    </style>
    </head>
    <body>
    <form id="form1" runat="server">
    <div style="text-align:center;">
    <div style=" 500px; height:500px; background-color:Silver; text-align:left; margin-top: 20; padding: 10px 0px 0px 30px; margin-top:4%" >

    <table class="style1">
    <tr>
    <td class="style6">
    <label for="txt_username">用户名: </label>
    </td>
    <td class="style5">
    <asp:TextBox ID="txt_username" runat="server" Width="209px"></asp:TextBox>
    </td>
    <td>
    <asp:RequiredFieldValidator ID="validator_rqeField_username" runat="server"
    ControlToValidate
    ="txt_username" Display="Dynamic" ErrorMessage="用户名不能为空"></asp:RequiredFieldValidator>
    <asp:CustomValidator ID="validator_custom_username" runat="server"
    ErrorMessage
    ="用户名已存在" ControlToValidate="txt_username"></asp:CustomValidator>
    </td>
    </tr>
    <tr>
    <td class="style6">
    <label for="txt_password">密 码: </label>
    </td>
    <td class="style5">
    <asp:TextBox ID="txt_password" runat="server" Width="209px" TextMode="Password"></asp:TextBox>
    </td>
    <td>
    <asp:RequiredFieldValidator ID="validator_rqeField_password" runat="server"
    ControlToValidate
    ="txt_password" ErrorMessage="密码不能为空"></asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td class="style6">
    <label for="txt_confirm">确 认: </label>
    </td>
    <td class="style5">
    <asp:TextBox ID="txt_confirm" runat="server" Width="209px" TextMode="Password"></asp:TextBox>
    </td>
    <td>
    <asp:RequiredFieldValidator ID="validator_rqe_confirm" runat="server"
    Display
    ="Dynamic" ErrorMessage="确认密码不能为空" ControlToValidate="txt_confirm"></asp:RequiredFieldValidator>
    <asp:CompareValidator ID="validator_compto_conpass" runat="server"
    ControlToCompare
    ="txt_password" ControlToValidate="txt_confirm"
    Display
    ="Dynamic" ErrorMessage="密码不一致"></asp:CompareValidator>
    </td>
    </tr>
    <tr>
    <td class="style6">
    <label for="txt_email">邮 箱: </label>
    </td>
    <td class="style5">
    <asp:TextBox ID="txt_email" runat="server" Width="209px"></asp:TextBox>
    </td>
    <td>
    <asp:RequiredFieldValidator ID="validator_rqeField_email" runat="server"
    ControlToValidate
    ="txt_email" Display="Dynamic" ErrorMessage="邮箱不能为空"></asp:RequiredFieldValidator>
    <asp:RegularExpressionValidator ID="validator_regx_email" runat="server"
    ControlToValidate
    ="txt_email" Display="Dynamic" ErrorMessage="邮件格式错误"
    ValidationExpression
    ="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"></asp:RegularExpressionValidator>
    </td>
    </tr>
    <tr>
    <td class="style6">
    <label for="txt_birth">生 日: </label>
    </td>
    <td class="style5">
    <asp:TextBox ID="txt_birth" runat="server" Width="209px"></asp:TextBox>
    </td>
    <td>
    <asp:RangeValidator ID="validator_range_birth" runat="server"
    ControlToValidate
    ="txt_birth" ErrorMessage="日期格式错误" Type="Date"></asp:RangeValidator>
    </td>
    </tr>
    <tr>
    <td class="style6">
    验证码:
    </td>
    <td class="style5" colspan="2">
    <asp:Image ID="Image1" runat="server" ImageUrl="~/DynamicCode.ashx" />
    </td>
    </tr>
    <tr>
    <td class="style6">
    输入验证码:
    </td>
    <td class="style5" colspan="2">
    <asp:TextBox ID="txt_dcode" runat="server" Width="210px"></asp:TextBox>
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
    ErrorMessage
    ="验证码不能为空" Display="Dynamic" ControlToValidate="txt_dcode"></asp:RequiredFieldValidator>
    <asp:CustomValidator ID="Validator_Dcode" runat="server"
    ErrorMessage
    ="验证码错误" ControlToValidate="txt_dcode" Display="Dynamic"
    onservervalidate
    ="Validator_Dcode_ServerValidate"></asp:CustomValidator>
    </td>
    </tr>
    <tr>
    <td colspan="3">
    <asp:LinkButton ID="lbtn_reguser" runat="server" onclick="lbtn_reguser_Click">注 册</asp:LinkButton>
    <asp:LinkButton ID="ltbn_forgetpass" runat="server">忘记密码?</asp:LinkButton>
    </td>
    </tr>
    </table>

    </div>
    </div>
    </form>
    </body>
    </html>

    //default.aspx.cs代码

    代码
    using System;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml.Linq;

    public partial class _Default : System.Web.UI.Page
    {
    protected void Page_Init(object sender, EventArgs e)
    {
    this.validator_range_birth.MaximumValue = DateTime.Now.ToShortDateString();
    this.validator_range_birth.MinimumValue = DateTime.Now.AddYears(-150).ToShortDateString();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
    if (this.IsPostBack)
    {
    //this.Validate(); //手动调用验证方法
    }

    }
    protected void lbtn_reguser_Click(object sender, EventArgs e)
    {
    if (this.IsValid) //当所有页面对象验证通过后, 将设置Page的IsValid属性, 验证通过
    {
    DAL.CalendarUser calendaruser
    = new DAL.CalendarUser();

    //初始birthday为空, 当串不为空时转换
    DateTime? birthday = null;
    if (!string.IsNullOrEmpty(this.txt_birth.Text))
    {
    birthday
    = DateTime.Parse(this.txt_birth.Text);
    }

    //int a = calendaruser.CreateUser(this.txt_username.Text, this.txt_password.Text, this.txt_email.Text, birthday);
    int exist = calendaruser.CreateUserByProc(this.txt_username.Text, this.txt_password.Text, this.txt_email.Text, birthday);

    if (exist != 0)
    {
    this.validator_custom_username.IsValid = false; //这里使用验证控件上的IsValid属性
    }
    }
    }
    protected void Validator_Dcode_ServerValidate(object source, ServerValidateEventArgs args)
    {
    //每次复位Validator状态
    args.IsValid = false;

    #region Cookie
    //HttpCookie hc = this.Request.Cookies["Dcode"];
    //if (hc != null)
    //{
    // string rqtcode = hc.Value.ToString();
    // //if(rqtcode == args.Value)
    // if (rqtcode == this.txt_dcode.Text)
    // {
    // args.IsValid = true; //这里必须用args.IsValid, 不能用this.validator_dcode.isvalid = true, 因为最后args.IsValid会覆盖掉this.validator_dcode.IsValid, 分析在最后
    // }
    //}
    //else
    //{
    // args.IsValid = false;
    //}
    #endregion

    #region Session
    if (this.Session["Dycode"] != null)
    {
    string num = this.Session["Dycode"] as string;
    if (num == this.txt_dcode.Text)
    {
    args.IsValid
    = true;
    }
    else
    {
    args.IsValid
    = false;
    }
    }

    #endregion
    }
    }

    //DynamicCode.ashx代码

    代码
    <%@ WebHandler Language="C#" Class="DynamicCode" %>

    using System;
    using System.Web;

    //使用Session记得在ashx中, 添加IRequiresSessionState的接口, 而aspx文件默认就是支持的
    public class DynamicCode : IHttpHandler,System.Web.SessionState.IRequiresSessionState {

    public void ProcessRequest (HttpContext context) {
    //context.Response.ContentType = "text/plain";
    //context.Response.Write("Hello World");
    context.Response.ContentType = "image/jpeg";

    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

    //随机数生成器
    Random ran = new Random();
    int rannum = ran.Next(10000, 100000);

    //创建位图文件
    System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(300, 80);

    //在位图文件上画画, 需要创建与图片画板相关的画图器
    using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
    {
    //用Graphic对象清空背景
    g.Clear(System.Drawing.Color.DarkGreen);

    //花矩形框
    g.DrawRectangle(new System.Drawing.Pen(System.Drawing.Brushes.Blue,3),0,0,bitmap.Width-1,bitmap.Height-1);

    //StringFormat对象, 用来保存数字位置, 在数字矩形的绘图区域中
    System.Drawing.StringFormat sf = new System.Drawing.StringFormat();
    sf.Alignment
    = System.Drawing.StringAlignment.Center;
    sf.LineAlignment
    = System.Drawing.StringAlignment.Center;

    //画数字, RectangleF用来确定显示数字的矩形区域
    g.DrawString(rannum.ToString(),
    new System.Drawing.Font("黑体", 50),
    System.Drawing.Brushes.Black,
    new System.Drawing.RectangleF(0, 0, bitmap.Width, bitmap.Height),
    sf);

    //画横线
    for (int i = 0; i < 80; i++)
    {
    g.DrawLine(
    new System.Drawing.Pen(System.Drawing.Brushes.Black),
    ran.Next(
    0, bitmap.Width),
    ran.Next(
    0, bitmap.Height),
    ran.Next(
    0, bitmap.Width),
    ran.Next(
    0, bitmap.Height));
    }

    //将数字保存到Cookie中
    //HttpCookie hc = new HttpCookie("Dcode");
    //hc.Value = rannum.ToString();
    //context.Response.Cookies.Add(hc); //保存到cookie中去, 但是没有页面对象, 所以需要通过context

    //将数字保存到Session中
    context.Session["DyCode"] = rannum.ToString();
    }

    //保存图片到response, 注意: 这里是一般处理程序, 没有页面对象, 所以只能用context
    bitmap.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    }

    public bool IsReusable {
    get {
    return false;
    }
    }

    }

    对args.IsValid和this.validator_dcode.IsValid的分析:
    args是ServerVlidate事件处理方法的参数, 而this.validator_dcode.IsValid是验证控件上的IsValid属性.
    这里又涉及到事件, 上边说过验证事件的处理是在Page_Load事件 --- Page_LoadComplete事件之间, 并且在控件事件之前. 顺便复习下事件, 事件仅仅是个有特殊的委托变量, 该委托变量指向堆中的一个委托对象 ---> 委托对象用来封装方法或函数, 以使我们可以达到传递方法的目的 ---> 但是封装完的方法仅仅是个地址(函数指针), C#不允许直接操作指针 ---> 所以提供了通过"变量名(参数列表)"的方式来调用方法 ---> 也就是"事件(参数列表)" ---> 而调一个空的方法又没有意义, 所以在类中又定义了一个事件触发方法, 判断事件上有方法时(非空)才触发事件. 触发方法格式如下:
    protected void On事件名(EventArgs e)
    {
        if(事件名 != null)
        {
            事件名(this,e);   //调用委托绑定的方法
        }
    }
    于是我们知道可以通过"事件(参数列表)"来调用, 而绑定的方法就是我们页面CS文件中的SerVerValidate(object source, ServerValidateEventArgs args). 当控件上触发这个事件时, 与该控件相关的信息都封装在了ServerValidateEventArgs类型的对象args中, 所以我们的事件处理方法中使用的属性都是从args对象里边来的, 当处理方法完成后, 将会根据args对象的结果信息修改控件上的属性, 包括this.validator_dcode.IsValid属性, ErrorMessage的赋值等工作, 因此最终会改掉this.validator_dcode.IsValid属性的值.

  • 相关阅读:
    Spring Boot 使用actuator监控与管理
    Spring Boot入门
    mysql中update语句的锁
    LinkedList深入学习
    23种设计模式学习之享元模式
    23种设计模式学习之桥接模式
    23种设计模式学习之外观模式
    23种设计模式学习之代理模式
    23种设计模式学习之装饰者模式
    23种设计模式学习之适配器模式
  • 原文地址:https://www.cnblogs.com/cs_net/p/1875320.html
Copyright © 2020-2023  润新知