Wednesday, March 16, 2011

Catcha in Asp.net C#

USe this Class To Generate Captcha  in Your Site

CaptchaControl.cs

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

namespace CaptchaControl
{
    public class CaptchaControl : System.Web.UI.WebControls.WebControl,
        IPostBackDataHandler, INamingContainer, IValidator

    {
        #region Public Properties

        [DefaultValue(50),
         Description("Specify the height of the captcha image"),
         Category("Appearance")]
        public int DrawHeight { get; set; }

        [DefaultValue(200),
         Description("Specify the width of the captcha image"),
         Category("Appearance")]
        public int DrawWidth { get; set; }

        [DefaultValue(50),
         Description("Number of characters to be printed"),
         Category("Appearance")]
        public int NumberOfChars { get; set; }

        [Description("States the validation state of the user. True if validated else false"),
         Category("Properties")]
        public bool IsValidated { get { return _isValidated; } }

        #endregion

        #region Private Variables
       
        private bool _isValidated = false;
        private CaptchaImage _captcha = new CaptchaImage();
        private string _previousGUID = string.Empty;
       
        #endregion

        #region WebControl Members

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            writer.Write("<Div><Table>");
            writer.Write("<tr><td><img src=\"CaptchaImage.aspx?guid="+ _captcha.UniqueID + "\"></tr></td>");
            writer.Write("<tr><td><input name=\"" + this.UniqueID + "\" type=text></tr></td>");
            writer.Write("</Table></Div>");
        }

        protected override void OnInit(EventArgs e)
        {
            Page.RegisterRequiresControlState(this);
            base.OnInit(e);
        }

        protected override void OnPreRender(EventArgs e)
        {
            if (this.Visible)
            {
                GenerateCaptcha();
            }
            base.OnPreRender(e);
        }

        protected override void LoadControlState(object savedState)
        {
            if (savedState != null)
            {
                _previousGUID = savedState.ToString();
            }
        }

        protected override object SaveControlState()
        {
            return _captcha.UniqueID;
        }

        #endregion

        #region Captcha Members

        private void GenerateCaptcha()
        {
            _captcha.DrawHeight = this.DrawHeight;
            _captcha.DrawWidth = this.DrawWidth;
            _captcha.NumberOfChars = this.NumberOfChars;

            HttpRuntime.Cache.Add(_captcha.UniqueID, _captcha, null, DateTime.Now.AddSeconds(60),
                   TimeSpan.Zero, System.Web.Caching.CacheItemPriority.NotRemovable, null);
        }

        private CaptchaImage GetCaptchaFromCache(string guid)
        {
            return (CaptchaImage)HttpRuntime.Cache.Get(guid);
        }

        private void RemoveCaptchaFromCache(string guid)
        {
            HttpRuntime.Cache.Remove(guid);
        }

        private void ValidateCaptcha(string data)
        {
            CaptchaImage captcha = GetCaptchaFromCache(_previousGUID);
            _isValidated = (captcha.CaptchaCode == data.ToUpper());
            if (_isValidated)
            {
                this.ErrorMessage = "Invalid code entered";
            }

            RemoveCaptchaFromCache(_previousGUID);
        }

        #endregion

        #region IPostBackDataHandler Members

        public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
        {
            ValidateCaptcha(postCollection[this.UniqueID].ToString());
            return false;
        }

        public void RaisePostDataChangedEvent()
        {
           
        }

        #endregion

        #region IValidator Members

        public string ErrorMessage
        {
            get;
            set;
        }

        public bool IsValid
        {
            get
            {
                return _isValidated;
            }
            set
            {
            }
        }

        public void Validate()
        {
        }

        #endregion
    }
}

CaptchaImage.cs

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System;
using System.Web;

namespace CaptchaControl
{
     class CaptchaImage
    {
        #region Public Properties

        /// <summary>
        /// Draw width of the image
        /// </summary>
        public int DrawWidth
        {
            get
            {
                return _drawWidth;
            }
            set
            {
                _drawWidth = value;
            }
        }
       
        /// <summary>
        /// Draw height of image
        /// </summary>
        public int DrawHeight
        {
            get
            {
                return _drawHeight;
            }
            set
            {
                _drawHeight = value;
            }
        }

        /// <summary>
        /// Number of the characters to be shown
        /// </summary>
        public int NumberOfChars
        {
            get
            {
                return _numberOfChars;
            }
            set
            {
                _numberOfChars = value;
            }
        }

        /// <summary>
        /// Unique Id for this captcha control
        /// </summary>
        public string UniqueID
        {
            get
            {
                return _uniqueID;
            }
            set
            {
                _uniqueID = value;
            }
        }

        /// <summary>
        /// Code to be printed on the image
        /// </summary>
        public string CaptchaCode
        {
            get
            {
                return _captchaCode;
            }
            set
            {
                _captchaCode = value;
            }
        }

        #endregion

        #region Public Methods

        public CaptchaImage()
        {
            string captchaID = GetUniqueID();
            _uniqueID = captchaID;
        }

        /// <summary>
        /// Gets the cached captcha.
        /// </summary>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public static CaptchaImage GetCachedCaptcha(string guid)
        {
            if (String.IsNullOrEmpty(guid))
                return null;

            return (CaptchaImage)HttpRuntime.Cache.Get(guid);
        }

        /// <summary>
        /// Generate the captcha image
        /// </summary>
        /// <returns>Captcha Image</returns>
        public Bitmap GenerateCaptcha()
        {
            return GenerateImage();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Generate the captcha output image
        /// </summary>
        /// <param name="captchaCode"></param>
        /// <returns></returns>
        private Bitmap GenerateImage()
        {
            string captchaCode = GetCaptchaCode();
            _captchaCode = captchaCode;

            Bitmap bmp = new Bitmap(_drawWidth, _drawHeight,
                PixelFormat.Format32bppArgb);

            Graphics g = Graphics.FromImage(bmp);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            Rectangle rect = new Rectangle(0, 0, _drawWidth, _drawHeight);

            HatchBrush brush = new HatchBrush(
              HatchStyle.Weave,
              Color.LightGray,
              Color.White);
            g.FillRectangle(brush, rect);

            g.DrawString(captchaCode,
                new Font("Tahoma", 28.0f, FontStyle.Bold),
                Brushes.Black, new PointF(0, 0));


            AddNoise(g);

            return bmp;
        }

        private void AddNoise(Graphics g)
        {
            Random rand = new Random();

            for (int i = 1; i < 500; i++)
            {
                int posX = rand.Next(1, _drawWidth);
                int posY = rand.Next(1, _drawHeight);
                int width = rand.Next(3);
                int height = rand.Next(3);
                g.DrawEllipse(Pens.Black, posX , posY,
                    width, height);  
            }
        }

        /// <summary>
        /// Generate a unique id for the this control
        /// </summary>
        /// <returns></returns>
        private string GetUniqueID()
        {
            return Guid.NewGuid().ToString();
        }

        private string GetCaptchaCode()
        {
            Random rand = new Random();
            string code = "";
            int charLen = _charSet.Length;

            for (int i = 0; i < _numberOfChars; i++)
            {
                int pos = rand.Next(0,charLen);
                code += _charSet.Substring(pos, 1);
            }

            return code;
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Char set for generating Captcha Code
        /// </summary>
        private const string _charSet = "ACDEFGHJKLNPQRTUVXYZ234679";

        private int _drawWidth = 200;

        private int _drawHeight = 50;

        private int _numberOfChars = 6;

        private string _uniqueID;

        private string _captchaCode;

        #endregion
    }
}