IHttphandler之“验证码”服务器控件

同样,先看下我们的web.config文件:

<httpHandlers>
      <add verb="*" path="*.yy" type="Identify.LandpyHttpHander,Identify"/>
 </httpHandlers>

首先提个问题大家见过后缀名为“yy”的文件吗,呵呵,这里实际上是使用了一个小技巧。利用IHttphandler来实现服务器端控件的事件,当点击控件时,发送一个“*.yy”路径的请求,从而实现Identify.LandpyHttpHander处理并返回客户端。

下面上代码:

using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Text;
using  System.Web;
using  System.Web.UI;
using  System.Web.UI.WebControls;

using  System.Web.SessionState;

namespace  Identify
{
    [DefaultProperty(
" Text " )]
    [ToolboxData(
" <{0}:LandpyIdentityControl runat=server></{0}:LandpyIdentityControl> " )]
    
public   class  LandpyIdentityControl : WebControl
    {
        [Bindable(
true )]
        [Category(
" Appearance " )]
        [DefaultValue(
"" )]
        [Localizable(
true )]
        
public   string  Text
        {
            
get
            {
                String s 
=  (String)ViewState[ " Text " ];
                
return  ((s  ==   null ?  String.Empty : s);
            }

            
set
            {
                ViewState[
" Text " =  value;
            }
        }

        
internal   static   int  _wordLength;

        [Description(
" 验证码长度 " )]
        
public   int  WordLength
        {
            
get  {  return  LandpyIdentityControl._wordLength; }
            
set
            {
                LandpyIdentityControl._wordLength 
=  value;

            }
        }

        
internal   static   string  _value;

        [Description(
" 验证码内容 " )]
        
public   string  Value
        {
            
get  {  return  LandpyIdentityControl._value; }
        }

        
protected   override   void  RenderContents(HtmlTextWriter output)
        {
            
// output.Write(Text);           
        }

        
public  LandpyIdentityControl()
            : 
base (HtmlTextWriterTag.Img) // 重写父类的构造(输出流的HTML标记设置为图像类型)
        { }

        
protected   override   void  AddAttributesToRender(HtmlTextWriter writer)
        {
            
base .AddAttributesToRender(writer);
            writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, 
" pointer " );
            writer.AddAttribute(
" onclick " " this.src='img.yy?id='+Math.random() " );
            writer.AddAttribute(HtmlTextWriterAttribute.Src, 
" img.yy " );
            writer.AddAttribute(
" alt " " 点击刷新 " );
        }
    }
}

下面是处理类:

using  System;
using  System.Collections.Generic;
using  System.Text;
using  System.Web;
using  System.Web.UI.WebControls;
using  System.Web.UI;
using  System.Web.SessionState;
using  System.Drawing;
using  System.IO;

namespace  Identify
{
    
public   class  LandpyHttpHander : IHttpHandler, IRequiresSessionState
    {
        
///   <summary>
        
///  返回验证码字符
        
///   </summary>
        
///   <param name="codeCount"> 验证码长度 </param>
        
///   <returns></returns>
         private   string  GetRandomNumberString( int  codeCount)
        {
            
string  strChoice  =   " 2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z " ;
            
string [] strResult  =  strChoice.Split( new  Char[] {  ' , '  });
            
string  strReturn  =   "" ;
            Random rnd 
=   new  Random();
            
for  ( int  i  =   0 ; i  <  codeCount; i ++ )
            {
                
int  j  =  rnd.Next(strResult.Length);
                strReturn 
=  strReturn  +  strResult[j].ToString();
            }
            
return  strReturn;
        }

        
private  Color GetColor()
        {
            
return  Color.Black;
        }

        
private  Bitmap CreateImage( string  str_AuthCode)
        {
            
int  width  =  str_AuthCode.Length  *   21 ;
            
int  height  =   30 ;
            Random rad 
=   new  Random();
            Bitmap bmp 
=   new  Bitmap(width, height);
            Graphics grp 
=  Graphics.FromImage(bmp); //  在图片上绘制图形
            grp.Clear(Color.LightGreen);
            grp.DrawRectangle(
new  Pen(Color.DarkGreen,  1 ),  0 0 , width  -   1 , height  -   1 );
            
// 画图片的背景噪音线
             for  ( int  i  =   0 ; i  <   15 ; i ++ )
            {
                
int  x1  =  rad.Next(width);
                
int  x2  =  rad.Next(width);
                
int  y1  =  rad.Next(height);
                
int  y2  =  rad.Next(height);

                grp.DrawLine(
new  Pen(Color.Black), x1, y1, x2, y2);
            }
            
// 画图片的前景噪音点
             for  ( int  i  =   0 ; i  <   100 ; i ++ )
            {
                
int  x  =  rad.Next(width);
                
int  y  =  rad.Next(height);

                bmp.SetPixel(x, y, Color.Black);
            }
            Font f 
=   new  Font( " 宋体 " 20 , FontStyle.Bold);
            Brush br 
=   new  SolidBrush(Color.Black);
            
for  ( int  i  =   0 ; i  <  str_AuthCode.Length; i ++ )
            {
                
string  s  =  str_AuthCode.Substring(i,  1 );
                Point p 
=   new  Point(i  *   20   +  rad.Next( 3 ), rad.Next( 3 +   1 );
                grp.DrawString(s, f, br, p);
            }
            grp.Dispose();
            
return  bmp;

        }

        
///   <summary>
        
///  是否可以处理远程的HTTP请求
        
///   </summary>
         public   bool  IsReusable
        {
            
get  {  return   true ; }
        }

        
///   <summary>
        
///  将验证码图片发送给WEB浏览器
        
///   </summary>
        
///   <param name="context"></param>
         public   void  ProcessRequest(HttpContext context)
        {
            
int  size  =  LandpyIdentityControl._wordLength;  // Int32.Parse((String)context.Session["Size"]);
            MemoryStream ms  =   new  MemoryStream();
            
string  NumStr  =  GetRandomNumberString(size);
            LandpyIdentityControl._value 
=  NumStr;
            
// context.Session.Add("value", NumStr); // 将验证码字符保存到session里面
            Bitmap theBitmap  =  CreateImage(NumStr);
            theBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
            context.Response.ClearContent();
            context.Response.ContentType 
=   " image/jpeg " // 需要输出图象信息 要修改HTTP头为jpeg类型 
            context.Response.BinaryWrite(ms.ToArray()); 
            theBitmap.Dispose();
            ms.Close();
            ms.Dispose();
            context.Response.End();
        }

    }
}

其中验证码图片的生成随便copy了下,实际就是GDI+实现DrawString方法。如果对GDI+有了解相信会很容易理解的。

这样“验证码”服务器控件就OK了,如果要使用,引入相应的Dll,设置下web.config,设置下控件的字符个数就可以使用了,很简单。

在设计视图中,自定义服务器控件的属性可以赋初始值。比如我们的控件属性:

[Description("验证码长度")]
        public int WordLength
        {
            get { return LandpyIdentityControl._wordLength; }
            set
            {
                LandpyIdentityControl._wordLength = value;

            }
        }

可以设置验证码的长度。

另外,自定义控件是从WebControl继承,可以重写很多方法,比如RenderControl,RenderContents,AddAttributesToRender等,各个方法的作用可以查阅相关资料,本文不再说明。其中,对于UI来说RenderXXXX一系列方法是很重要的,如同Winfrom程序中的OnPrint方法一样。

快去做自己喜欢的控件吧:)

 

你可能感兴趣的:(handler)