Click here to Skip to main content
6,628,952 members and growing! (18,333 online)
Email Password   helpLost your password?
Web Development » ASP.NET » General     Intermediate

Image Verifier - Custom Control in ASP.NET

By Nataraj K

An article on how to create a custom control to render dynamic images with random text content which can be used for code verification.
C# 2.0, Windows, .NET 2.0, ASP.NET, WebForms, VS2005, Architect, Dev
Posted:17 Jun 2007
Updated:5 Nov 2007
Views:27,733
Bookmarked:47 times
Unedited contribution
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
23 votes for this article.
Popularity: 5.42 Rating: 3.98 out of 5
2 votes, 8.7%
1
1 vote, 4.3%
2
2 votes, 8.7%
3
1 vote, 4.3%
4
17 votes, 73.9%
5
Screenshot - main.jpg

Introduction

This article describes how to create a custom control in ASP.NET for implementing image verification functionality. What is this Image Verification? You might have seen this implemented in many websites like microsoft.com, google.com, yahoo.com etc during the signup process. It's simply used for verifying the user's input, by validating the code which user enters against a random code displayed as image in the form. This helps the application to identify automated submission of forms and reject such requests which could even crash any web site by inputting bulk data to site.

Background

I saw this functionality implemented in various sites and thought of implementing the same while creating a personal website. When I started implementing the functionality in my site I faced few issues. Some of them are generating random text, persisting the text so that it can be verified against the user input code during post backs, avoid storing the generated code in viewstate or urls etc. Gradually I found solutions to these issues. I will be explaining those solutions in the below sections.

Key Points

Explaining every piece of code used in the sample application is difficult through this article. Hence I will explain the following key steps involved in the development of this custom control.

1. Create a custom control capable of rendering <img> tags.
2. Generate a random text, persist it and render it as image.
3. Verify the user input against the persisted random text.

Create a custom control to render <Img> tags

First of all we need to create a custom control which can render the standard HTML <img> tags. It should also generate a dynamic url and attach it to the src attribute of the <img> tag generated.

This is done in the example by derving a class named ImageVerifier from WebControl, as shown below.

namespace NatsNet.Web.UI.Controls 
{ 
    [DefaultProperty("Text")] [ToolboxData("<{0}:ImageVerifier runat="server">")]  

    public class ImageVerifier : WebControl, IHttpHandler 
    { 
        private string m_UniqueID = string.Empty; 
        public ImageVerifier(): base(HtmlTextWriterTag.Img) { } 
        private string MyUniqueID  { ... } 
        public string Text { ... }         
        private string GetRandomText() { ... } 
        
        protected override void OnInit(EventArgs e) { ... }         
        protected override void LoadControlState(object savedState) { ... }         
        protected override object SaveControlState() { ... }         
        protected override void Render(HtmlTextWriter output) { ... } 

        public void ProcessRequest(HtmlTextContext context) { ... }         
        public bool IsReusable { ... } 
    } 
}

In addition to deriving the control from WebControl, I have implemented the IHttpHandler too in that class. This is for making the control render the image itself in addition to the normal <img> tag rendering.

The rendering of the control happens inside the Render method.

protected override void Render(HtmlTextWriter output)
{
    output.AddAttribute(HtmlTextWriterAttribute.Src, "ImageVerifier.axd?uid=" + this.MyUniqueID);
    base.Render(output);
    output.Write("<script language="'javascript'">");
    output.Write("function RefreshImageVerifier(id,srcname)");
    output.Write("{ var elm = document.getElementById(id);");
    output.Write("  var dt = new Date();");
    output.Write("  elm.src=srcname + '&ts=' + dt;");
    output.Write("  return false;");
    output.Write("}</script>");
    output.Write(" <a href='#' onclick=\"return RefreshImageVerifier('"
        + this.ClientID + "','ImageVerifier.axd?&uid="
        + this.MyUniqueID + "');\">Refresh</a>");
}

The first line in the Render method assigns the src attribute for the rendered <img> tag. It generates the url in the format "ImageVerifier.axd?uid=" + this.MyUniqueID. The control has given a property named MyUniqueID which will be a unique GUID generated for each control instance. The last line of the Render method outputs a hyperlink to refresh the image with out postback.

Generate a random text, persist it and render it as image

For rendering a dynamic text as the image of this control we will be using the same class ImageVerifier through the implementation of IHttpHandler method public void ProcessRequest(HttpContext context). This method will be called when the browser request the url specified in the src attribute of the <img> tag rendered. In order to make this happen we need to configure our ImageVerifier class as an HttpHandler for the URLs like ImageVerifier.axd in the web.config file of the consuming application.

<httpHandlers>
    <add
        verb="GET"
        path="ImageVerifier.axd"
        type="NatsNet.Web.UI.Controls.ImageVerifier, NatsNet.Web.UI.Controls"
        />
</httpHandlers>

Below is the implementation of the ProcessRequest() method.

public void ProcessRequest(HttpContext context)
{
    Bitmap bmp = new Bitmap(180, 40);
    Graphics g = Graphics.FromImage(bmp);
    string randString = GetRandomText();
    string myUID = context.Request["uid"].ToString();

    if (context.Cache[myUID] == null)
        context.Cache.Add(  myUID, 
                            randString,
                            null, 
                            Cache.NoAbsoluteExpiration,
                            TimeSpan.FromMinutes(5), 
                            System.Web.Caching.CacheItemPriority.Normal, 
                            null
                        );
    else
        context.Cache[myUID] = randString;
        
    g.FillRectangle(Brushes.WhiteSmoke,0, 0, 180, 40);    
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
    
    Random rand = new Random();    
    for (int i = 0; i < randString.Length; i++)
    {
        Font drawFont = new Font("Arial", 18,
            FontStyle.Italic | (rand.Next() % 2 == 0 ? FontStyle.Bold : FontStyle.Regular));
        g.DrawString(randString.Substring(i,1), drawFont, Brushes.Black, i * 35 + 10, rand.Next()% 12);

        Point[] pt = new Point[15];
        for (inti = 0; i < 15; i++)
        {
            pt[i] = newPoint(rand.Next() % 180, rand.Next() % 35);
            g.DrawEllipse(Pens.LightSteelBlue,pt[i].X, pt[i].Y, rand.Next() % 30 + 1, rand.Next() % 30 + 1);
        }
        
        context.Response.Clear();
        context.Response.ClearHeaders();
        context.Response.ContentType = "image/jpeg";
        bmp.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);        
        context.Response.End();
    }
}

In the ProcessRequest() method a random text is generated using the private method GetRandomText() and is persisted using the Cache object as shown above. The value of query string uid will be used as the key for persisting the random text in the Cache object.

For generating random text of a specific length we can write any custom logic. Here in the sample I have used Random class to generate random numbers and convert them to corresponding characters. The same can be implemented in different ways as you wish.

private string GetRandomText()
{
    string uniqueID = Guid.NewGuid().ToString();
    string randString = "";
    
    for (int i = 0, j = 0; i < uniqueID.Length && j < 5; i++)
    {
        char l_ch = uniqueID.ToCharArray()[i];
        if ((l_ch >= 'A' && l_ch <= 'Z') || (l_ch >= 'a' && l_ch <= 'z') || (l_ch >=  '0' && l_ch <= '9'))
        {
            randString += l_ch;
            j++;
        }
    }
    
    return randString;
}

Verify the user input against the persisted random text

Finally what we need is to validate the user input against the random text which is displayed as the image. For this I have added a Text property for our user control. This property retrieves the random text stored in the Cache and returns it. We can use this value to verify the user input.

public string Text
{
    get
    {
        return string.Format("{0}",
        HttpContext.Current.Cache[this.MyUniqueID]);
    }
}

Below code shows an example of the code to be implemented in the consuming application for verifying the user input.

protected void btnSubmit_Click(object sender, EventArgs e)
{
    if (txtImgVerifyText.Text == ImageVerifier1.Text)
    {
        // User has input the correct text so can continue

        // processing the request.

    }
    else
    {
        // Either user has input an incorrect value or the request

        // is not generated by the manual input. So do not continue

        // processing the request.

    }
}

Points of Interest

In this article I have explained how to use the concept of Image Verification to help applications in identifying automated submission of forms. The implementation of this Image Verification has used few coding concepts such as HttpHandlers, Random class, Cache object etc.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Nataraj K


Member
Nataraj works as an Associate Consultant for US Technology. He has been working in the last 8+ years in software design and development of business solutions with various Microsoft technologies.

He spends his free time with music. AR Rahman is his favorite musician.
Occupation: Web Developer
Location: India India

Other popular ASP.NET articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 18 of 18 (Total in Forum: 18) (Refresh)FirstPrevNext
Generalproblem while uploading it.. PinmemberSandeep Ramani7:17 16 Nov '09  
Generalcan i use it in my project PinmemberSandeep Ramani5:01 29 Oct '09  
GeneralI need the material on custom control Pinmemberjolly mishra20:45 27 Aug '09  
Questiondoes it work in IIS 7.0? PinmemberMudasser Hassan7:17 11 Aug '09  
Generalhow to maintain the persistance using saveviewstate and loadview state methods Pinmemberanithacute22:14 5 Apr '09  
GeneralSome suggestions for improvement Pinmemberkabwla5:15 27 Mar '09  
GeneralHow can I use it in a web application? Pinmemberamir asaraf7:00 16 Nov '08  
GeneralRe: How can I use it in a web application? Pinmemberkabwla5:12 27 Mar '09  
GeneralHi Pinmembermanu_1221:12 29 Nov '07  
GeneralGood work, a little bug PinmemberJohnjames8:21 11 Nov '07  
GeneralGood Job Pinmembermerlin9815:22 6 Nov '07  
GeneralIs it strong? PinmemberDmitry Salko11:05 5 Nov '07  
GeneralRe: Is it strong? PinmemberNataraj K13:13 11 Nov '07  
QuestionHi Pinmemberphuhoa17:21 4 Nov '07  
Hi you !

I downloaded ... this project, but I can't run. This project alert:"Error - Parser Error: Unknown server tag 'cc1:imageverifier'." . And then, I open Design the file Default.aspx by VS05, but can't open. Can you tell me, how to use this project.
this is the alert detail, which i have: "Can not switch to design view because of Error in the page. Please correct all errors labeled'can not switch': in the error list and try again"
Thanks

RICHING MINDS,CHANGING LIVE

Sign In·View Thread·PermaLink
AnswerRe: Hi PinmemberNataraj K9:30 5 Nov '07  
Questionscript question PinmemberkostasV8:13 6 Sep '07  
AnswerRe: script question PinmemberkostasV7:25 7 Sep '07  
GeneralVery good article PinmemberRoshan P Mohammed19:27 18 Jun '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 5 Nov 2007
Editor:
Copyright 2007 by Nataraj K
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project