August 25, 2011

RangeValidator is a validation control provided by asp.net. This control can be used to validate a range of string, date, integer and double values. In this post, I will show how to use the RangeValidator to validate a range of date using today’s date as the maximum value.

The following is the RangeValidator markup.

RangeValidator markup
  1. <asp:TextBox ID="T1" runat="server"></asp:TextBox>
  2. <asp:RangeValidator ID="RV1" runat="server" ControlToValidate="T1" Type="Date" MinimumValue="01/01/2000" ErrorMessage="*"></asp:RangeValidator>
  3. <asp:Button ID="Button1" runat="server" Text="Button" />

The TextBox control is added where the users will enter the value. The Button control is added to test validation. The RangeValidator is added – its ControlToValidate property is set to TextBox’s id, data type is set to Date, the minimum value is set to an arbitrary date. The maximum value is set in the Page_Load event as shown below.

Page_Load event
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.     RV1.MaximumValue = DateTime.Today.ToShortDateString();
  4. }

The maximum value expects a value of type string, so the string format of today’s date is passed as the MaximumValue.

July 28, 2011

Transform object to xml using linq

Using Linq, it’s easily possible to query various types of data like sql database, xml, objects like DataTable, ArrayList. It’s also possible to transform data into other formats like xml using linq. In this article, I will demonstrate how to query an System.Collections.ArrayList collection and then to save the data in xml format.

At first, I will create an ArrayList object and add Person objects to it. The code to do is below.

Adding objects to ArrayList
  1. ArrayList list = new ArrayList();
  2. list.Add(new Person { FirstName = "Scooby", LastName = "Doo", DateOfBirth= new DateTime(2000, 12, 31), Height=160 });
  3. list.Add(new Person { FirstName = "Bugs", LastName = "Bunny", DateOfBirth = new DateTime(1999, 2, 7), Height = 170 });
  4. list.Add(new Person { FirstName = "Peter", LastName = "Pan", DateOfBirth = new DateTime(2001, 10, 31), Height = 150 });

The Person class has 4 public properties of different data types – string, DateTime and int as shown below.

Person class
  1. using System;
  2. namespace WebApplication1.CSClass
  3. {
  4.     public class Person
  5.     {
  6.         public string FirstName { get; set; }
  7.         public string LastName { get; set; }
  8.         public DateTime DateOfBirth { get; set; }
  9.         public int Height { get; set; }
  10.  
  11.         public override string ToString()
  12.         {
  13.             return FirstName + " " + LastName;
  14.         }
  15.     }
  16. }

Person objects are added to the ArrayList list which can be queried using linq as shown in my previous post on query ArrayList using Linq. While querying the list, System.Xml.Linq.XElement objects can be created which can be saved as xml using System.Xml.Linq.XDocument’s Save() method. The code to show this is below.

Transform ArrayList to xml
  1. private void TransformToXml()
  2. {
  3.     ArrayList list = new ArrayList();
  4.     list.Add(new Person { FirstName = "Scooby", LastName = "Doo", DateOfBirth= new DateTime(2000, 12, 31), Height=160 });
  5.     list.Add(new Person { FirstName = "Bugs", LastName = "Bunny", DateOfBirth = new DateTime(1999, 2, 7), Height = 170 });
  6.     list.Add(new Person { FirstName = "Peter", LastName = "Pan", DateOfBirth = new DateTime(2001, 10, 31), Height = 150 });
  7.  
  8.     var q = from Person p in list
  9.             orderby p.FirstName
  10.             orderby p.LastName
  11.             select p;
  12.  
  13.     var query = new XElement("Persons", from Person p in list
  14.                                 select new
  15.                                 XElement("Person",
  16.                                 new XElement("FirstName", p.FirstName),
  17.                                 new XElement("LastName", p.LastName),
  18.                                 new XElement("DateOfBirth", p.DateOfBirth),
  19.                                 new XElement("Height", p.Height)
  20.                                 )
  21.                                 );
  22.  
  23.     XDocument doc = new XDocument(query);
  24.     doc.Save(Server.MapPath("transform.xml"));
  25.  
  26.     var query2 = new XElement("Persons", from Person p in list
  27.                                 select new
  28.                                 XElement("Person",
  29.                                 new XAttribute("FirstName", p.FirstName),
  30.                                 new XAttribute("LastName", p.LastName),
  31.                                 new XAttribute("DateOfBirth", p.DateOfBirth),
  32.                                 new XAttribute("Height", p.Height)
  33.                                 )
  34.                                 );
  35.  
  36.     XDocument doc2 = new XDocument(query2);
  37.     doc2.Save(Server.MapPath("transform2.xml"));
  38. }

As can be seen, the ArrayList object is queried for Person objects. This is not really needed for the code to work but is an example on how objects can be queried from ArrayList.

Using another query, “query”, XElement objects are created. The names of the XElement – that is, the names of the xml elements are arbitrary and the value of the elements are obtained from the Person object. The XElement objects are then added to XDocument object and saved as xml using XDocument.Save() method. The resultant xml looks like below.

Xml from Linq to ArrayList
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Persons>
  3.   <Person>
  4.     <FirstName>Scooby</FirstName>
  5.     <LastName>Doo</LastName>
  6.     <DateOfBirth>2000-12-31T00:00:00</DateOfBirth>
  7.     <Height>160</Height>
  8.   </Person>
  9.   <Person>
  10.     <FirstName>Bugs</FirstName>
  11.     <LastName>Bunny</LastName>
  12.     <DateOfBirth>1999-02-07T00:00:00</DateOfBirth>
  13.     <Height>170</Height>
  14.   </Person>
  15.   <Person>
  16.     <FirstName>Peter</FirstName>
  17.     <LastName>Pan</LastName>
  18.     <DateOfBirth>2001-10-31T00:00:00</DateOfBirth>
  19.     <Height>150</Height>
  20.   </Person>
  21. </Persons>

One thing to note is that the xml declaration is automatically added. DateTime field – DateOfBirth is automatically converted to its string representation.

The xml produced previously contains elements only. The Linq query could be easily updated to change the data to be the attributes of xml elements. This is shown in another query – “query2”. System.Xml.Linq.XAttribute objects are created similarly instead of XElement objects and added to XElement object which is then added to XDocument object and saved as xml. The resultant xml file looks like below.

Xml from Linq to ArrayList
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Persons>
  3.   <Person FirstName="Scooby" LastName="Doo" DateOfBirth="2000-12-31T00:00:00" Height="160" />
  4.   <Person FirstName="Bugs" LastName="Bunny" DateOfBirth="1999-02-07T00:00:00" Height="170" />
  5.   <Person FirstName="Peter" LastName="Pan" DateOfBirth="2001-10-31T00:00:00" Height="150" />
  6. </Persons>

The data looks similar to the previous xml except that they are now attributes of “Person” element instead of child elements.

June 27, 2011

Create XML using Linq to XML

Xml stands for eXtensible Markup Language that is designed to store and transfer data. An example xml file is below.

Sample Xml file
  1. <?xml version="1.0" encoding="utf-8" standalone="no"?>
  2. <!--demo on how to create xml file-->
  3. <root>
  4.   <Country id="1" name="Australia" capital="Canberra">
  5.     <state>New South Wales</state>
  6.     <state>Victoria</state>
  7.   </Country>
  8.   <Country id="2" name="India" capital="New Delhi">
  9.     <state>Maharashtra</state>
  10.     <state>Rajasthan</state>
  11.   </Country>
  12.   <Country id="2" name="Bangladesh" capital="Dhaka"><![CDATA[Bangladesh doesn't have any states.]]></Country>
  13. </root>

Xml file starts the xml declaration as in the first line. It supports comments similar to html comments as shown in line 2. It can have elements, can have attributes and can contain CData that is data that can be considered as plain text. Line 4 shows an example of element and attributes – Country is an element and id, name and capital are attributes. The value 1, Australia, etc are the values of the attributes.

In .NET, Linq to Xml makes it easy to create and parse xml documents. It’s easy to create xml, add declarations, add elements, attributes and also add data appropriately. The necessary classes are within the System.Xml.Linq namespace. Linq to Xml has XDocument class with xml documents can be created and loaded. XComment class can be used to add comments. XElement can be used to create elements and XAttribute classes can be used to add attributes to elements. XCData class can be used to add data in cdata format. An example on how to create xml using Linq to Xml is below.

Create xml using Linq
  1. private void CreateXml()
  2. {
  3.     XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "no"));
  4.  
  5.     XComment comment = new XComment("demo on how to create xml file");
  6.     doc.Add(comment);
  7.  
  8.     XElement el = new XElement("root");
  9.     XElement p1 = new XElement("Country", new object[] { new XAttribute("id", "1"), new XAttribute("name", "Australia"), new XAttribute("capital", "Canberra") });
  10.  
  11.     XElement p1city1 = new XElement("state", "New South Wales");
  12.     XElement p1city2 = new XElement("state", "Victoria");
  13.  
  14.     p1.Add(p1city1);
  15.     p1.Add(p1city2);
  16.  
  17.     XElement p2 = new XElement("Country", new object[] { new XAttribute("id", "2"), new XAttribute("name", "India"), new XAttribute("capital", "New Delhi") });
  18.  
  19.     XElement p2city1 = new XElement("state", "Maharashtra");
  20.     XElement p2city2 = new XElement("state", "Rajasthan");
  21.  
  22.     p2.Add(p2city1);
  23.     p2.Add(p2city2);
  24.  
  25.     XElement p3 = new XElement("Country", new object[] { new XAttribute("id", "3"), new XAttribute("name", "Bangladesh"), new XAttribute("capital", "Dhaka") });
  26.  
  27.     p3.Add(new XCData("Bangladesh doesn't have any states."));
  28.  
  29.     el.Add(p1);
  30.     el.Add(p2);
  31.     el.Add(p3);
  32.     doc.Add(el);
  33.  
  34.     doc.Save(Server.MapPath("country.xml"));            
  35. }

As can be seen, once the XElement, XComment, XAttribute objects are created, they got to be added to parent object. Once the necessary data has been added, the xml file can be saved using XDocument’s Save method as in line 34 above.

June 16, 2011

Query DataTable using Linq

In this example, I will show how to use Linq to query DataTable. A DataTable is a table of data stored in memory. Since Linq can query data of IEnumerable type, the data rows are declared as as IEnumerable so that Linq can query the data.

I have already setup the web application and have added a page. I will now define the schema of the DataTable and then create it. The code for creating the DataTable is below.

Create DataTable
  1. private DataTable GetDataTable()
  2. {
  3.     DataTable dt = new DataTable();
  4.  
  5.     //add columns
  6.     dt.Columns.Add("ID", typeof (Int32));
  7.     dt.Columns.Add("Name", typeof(string));
  8.     dt.Columns.Add("DateOfBirth", typeof(DateTime));
  9.  
  10.     //add rows of data
  11.     dt.Rows.Add(new object[] { 1, "Bugs Bunny", DateTime.Now});
  12.     dt.Rows.Add(new object[] { 2, "Daffy Duck", DateTime.Now });
  13.     dt.Rows.Add(new object[] { 3, "Scooby Doo", DateTime.Now });
  14.     return dt;        
  15. }

As can be seen, columns of type int, string and DateTime are added to the DataTable. Then, rows of data are added. This DataTable is later used for querying using Linq.

As mentioned earlier, to query DataTable using Linq, it has to be of type System.Collections.Generic.IEnumerable . To do this, DataTable’s AsEnumerable method can be used. This method converts the standard DataTable to a DataTable of IEnumerable type. The method for converting and querying the DataTable is below.

Query DataTable
  1. private void QueryDataTable(DataTable dt)
  2. {
  3.     var q = from DataRow row in dt.AsEnumerable()
  4.             select row;
  5.     
  6.     int col = dt.Columns.Count;//no of columns
  7.  
  8.     foreach (DataRow row in q)
  9.     {
  10.         for (int i = 0; i < col; i++)
  11.         {
  12.             L1.Text += row[i].ToString() + "&nbsp;";
  13.         }
  14.         L1.Text += "<br/>";
  15.     }
  16. }

At first, I have converted the DataTable to of type IEnumerable and have selected all the rows. Then, I have queried each of the DataRow and retrieved the values for each of the columns. L1 is a Literal control that has been declared on the aspx page.

Please note that, I have simply added the values returned in string variables, ideally, a System.Text.StringBuilder object should be used to achieve this.

The above methods can then be called from Page_Load or other methods as shown below.

Page_Load event
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.     QueryDataTable(GetDataTable());
  4. }

June 5, 2011

Access anchor link from code-behind

Html anchor links are a way to navigate within a page. The anchor can be considered as a bookmark within a page, which when clicked takes the user to that section of a page. An anchor to a certain section of a page can be set in the following way.

  1. <a name=”anchor”></a><div>content</div>

The name attribute of the “a” element determines the anchor / bookmark to the page. The anchor can be accessed by setting the link like below.

  1. <a href=”#anchor”>Anchor</a>

However, the anchor link is a client side thing and cannot be accessed from server-side. In this post, I am going to show how the anchor link can be accessed from server-side using hidden field and javascript. The following is the code for the aspx page.

aspx page
  1. <body>
  2.     <form id="form1" runat="server">
  3.     <div>
  4.     <a name="anchor"></a>
  5.     <div>Some content <a href="#anchor" onclick="SetUrl('anchor')">click here</a></div>
  6.     <asp:HiddenField ID="HF1" runat="server" />
  7.     <asp:Button ID="B1" runat="server" Text="Check Anchor" OnClick="GetAnchor" />
  8.     <asp:Literal ID="L1" runat="server"></asp:Literal>
  9.     </div>
  10.     <script type="text/javascript">
  11.         SetUrl("");
  12.     </script>
  13.     </form>
  14. </body>

The page is simple, contains a HiddenField, Button and Literal control to display the anchor, if any. At the bottom of the page, before the closing form tag is a javascript method, SetUrl(“”) that sets the anchor in the hidden field. The code for javascript method is below.

JavaScript code
  1. <script type="text/javascript">
  2.     function SetUrl(val) {
  3.         if (val == "" && location.href.indexOf("#") > -1) {
  4.             document.getElementById('<%= HF1.ClientID %>').value = location.href; //set value of HiddenField
  5.         }
  6.         else if (val == "" && location.href.indexOf("#") == -1) {
  7.             document.getElementById('<%= HF1.ClientID %>').value = "";
  8.         }
  9.         else {
  10.             document.getElementById('<%= HF1.ClientID %>').value = val;
  11.         }
  12.         alert(val);
  13.     }    
  14. </script>

The javascript method, checks if there is a value for the anchor when the link is clicked. If not and if it does not contain the “#” character in the url, it does not set the value of the anchor in the HiddenField. Otherwise, it either sets the value when clicked or sets the url if it contains “#” character.

Once the HiddenField value is set, the value can be accessed from the server side. In this example, when the button is clicked, the value is obtained and set as the Text property of the Literal control. Here is the code for Button click event.

Button click event
  1.     protected void GetAnchor(object sender, EventArgs e)
  2.     {
  3.         string anchor = HF1.Value;//get url from hidden field
  4.         if (anchor.Contains("#"))//check if it an anchor
  5.         {
  6.             string[] list = anchor.Split(new char[] { '#' });
  7.             L1.Text = "anchor name is :" + list[1];
  8.         }
  9.         else if (anchor != "")
  10.             L1.Text = anchor;
  11.         else
  12.             L1.Text = string.Empty;
  13.     }
  14. }

The code finds the value of the HiddenField and displays it in the Literal control.

May 31, 2011

How to query an ArrayList with LINQ

In this example, I will show how to query an ArrayList using Linq. Since ArrayList are non-generic IEnumerable collections, the type of variable in the collection must be explicitly declared in the linq query.

I already have a web application setup, so, I will just add a class called Person. This is a very simple class containing only 2 properties – FirstName and LastName. The code for the class is below.

Person Class
  1. namespace WebApplication1.CSClass
  2. {
  3.     public class Person
  4.     {
  5.         public string FirstName { get; set; }
  6.         public string LastName { get; set; }
  7.  
  8.         public override string ToString()
  9.         {
  10.             return FirstName + " " + LastName;
  11.         }
  12.     }
  13. }

I will then add a web form where I will add an ArrayList, add Person objects to the collection and then query the collection using Linq. The code for this is below.

Query ArrayList with LINQ
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. using System.Collections;
  8. using WebApplication1.CSClass;
  9.  
  10. namespace WebApplication1
  11. {
  12.     public partial class LinqText : System.Web.UI.Page
  13.     {
  14.         protected void Page_Load(object sender, EventArgs e)
  15.         {
  16.             GetList();
  17.         }
  18.  
  19.         private void GetList()
  20.         {
  21.             ArrayList list = new ArrayList();
  22.             list.Add(new Person { FirstName = "Scooby", LastName="Doo" });
  23.             list.Add(new Person { FirstName = "Bugs", LastName = "Bunny" });
  24.             list.Add(new Person { FirstName = "Peter", LastName = "Pan" });
  25.  
  26.             var q = from Person p in list
  27.                     orderby p .FirstName
  28.                     orderby p.LastName
  29.                     select p;
  30.  
  31.             string br = "<br/>";
  32.             foreach (Person p in q)
  33.             {
  34.                 L1.Text += p.ToString() + br;
  35.             }
  36.  
  37.         }
  38.     }
  39. }

Note that, in the linq query, the object type is specified. The query will not work unless it is specified.

May 6, 2011

Device Filtering In Asp.Net

Asp.Net allows customization of properties of web server controls depending on the browser that is rendering the control. Well, this can be done by using javascript and css as well, by detecting the browser using javascript and then applying the correct css styles. Asp.Net makes it very easy to do without creating javascript or css.

The attributes of the controls need to contain the browser name to allow device filtering. For example, to customize the ForeColor property in Internet Explorer, the attribute need to be renamed to ie:ForeColor. For Mozilla, it will be Mozilla:ForeColor and for Pocket Internet Explorer, it’s PIE:ForeColor.

The following is sample code showing the attributes in a Label and TextBox control.

Sampele code
  1. <asp:Label ID="L1" runat="server" ie:Text="Internet explorer" Mozilla:Text="mozilla" ie:BackColor="Red" Mozilla:BackColor="Green" ie:ForeColor="White"></asp:Label>
  2. <asp:TextBox ID="T3" runat="server" ie:Text="IE" Mozilla:Text="mozilla" ie:BackColor="Gray" Mozilla:BackColor="Black" ForeColor="White"></asp:TextBox>

As can be seen, even the Text property can be customized. That is, the text on the controls would be different depending on the browser.

One important to note is that these properties can also be set declaratively meaning the properties cannot be accessed and / or modified from code behind.

March 22, 2011

In the previous articles, I showed how to create the captcha control. In this post, I will write about the handler that generates the image based on the dynamic random text generated by the GetRandomText method of the CaptchaControl usercontrol.

To generate the image, the handler needs to send its output as an image type. To get random text, it needs to access the value from the Session. The handler uses the System.Drawing.Bitmap class to create the image. The width of the image is dynamically based on the number of characters of the random text. The handler uses the background image path property to set the background image and uses the font colour, font size and font family to write the text on the image. The RotateTransform method of the System.Drawing.Graphics class is used to slightly rotate the text on the image.  the yPos method is used to randomly position the characters. The output image is then send through the stream.

The code for the class is below and can also be downloaded from CodePlex at http://captchadotnet.codeplex.com/ .

CaptchaHandler
  1. using System;
  2. using System.Web;
  3. using System.Drawing;
  4.  
  5. namespace CaptchaApp
  6. {
  7.     /// <summary>
  8.     /// Summary description for CaptchaHandler
  9.     /// </summary>
  10.     public class CaptchaHandler : IHttpHandler, System.Web.SessionState.IReadOnlySessionState
  11.     {
  12.  
  13.         private Captcha cc;
  14.  
  15.         public void ProcessRequest(HttpContext context)
  16.         {
  17.             context.Response.ContentType = "image/jpeg";
  18.  
  19.             if (context.Session != null)
  20.             {
  21.                 if (context.Session["CaptchaClass"] != null)
  22.                 {
  23.                     cc = (Captcha)context.Session["CaptchaClass"];
  24.                 }
  25.                 else
  26.                 {
  27.                     cc = new Captcha();
  28.                 }
  29.             }           
  30.  
  31.             string text = string.Empty;
  32.             if(context.Session["captcha"] !=null)
  33.                 text = (string)context.Session["captcha"];
  34.  
  35.             int imageWidth = Convert.ToInt32(((cc.FontSize + 8) * text.Length));
  36.             int imageHeight = Convert.ToInt32(cc.FontSize * 2.5);
  37.  
  38.  
  39.             Bitmap bmp = new Bitmap(imageWidth, imageHeight);
  40.             var Grph = Graphics.FromImage(bmp);
  41.             Grph.FillRectangle(new SolidBrush(Color.Lavender), 0, 0, bmp.Width, bmp.Height);
  42.  
  43.             var grp = Graphics.FromImage(bmp);
  44.             Image background = Image.FromFile(HttpContext.Current.Server.MapPath(cc.BackgroundImagePath));
  45.             grp.DrawImage(background, new Rectangle(0, 0, bmp.Width, bmp.Height));
  46.  
  47.  
  48.             Grph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
  49.             Grph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  50.             int xPos = 10;
  51.  
  52.             Font f = cc.GetFont();
  53.  
  54.             char[] textArray = text.ToCharArray();
  55.             int yPosition = 0;
  56.             Random r = new Random();
  57.  
  58.             for (int i = 0; i < textArray.Length; i++)
  59.             {
  60.                 if (i % 2 == 0)
  61.                     Grph.RotateTransform(5);
  62.                 else
  63.                     Grph.RotateTransform(-5);
  64.  
  65.                 yPosition = (int)(r.NextDouble() * 10);
  66.  
  67.                 Grph.DrawString(textArray[i].ToString(), f, new SolidBrush(Color.FromName(cc.TextColor)), xPos, yPosition);
  68.                 xPos += 20;
  69.  
  70.             }
  71.             
  72.             bmp.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
  73.  
  74.         }
  75.  
  76.         public bool IsReusable
  77.         {
  78.             get
  79.             {
  80.                 return false;
  81.             }
  82.         }
  83.  
  84.  
  85.         private int yPos()
  86.         {
  87.             Random r = new Random();
  88.             return (int)(r.NextDouble() * 10);
  89.         }                
  90.     }
  91. }

The handler also implements the System.Web.SessionState.IReadOnlySessionState interface beside the IHttpHandler. This is necessary so that the handler can access the Session of the current context.

Creating a Captcha Control – Part 4

In one of the previous posts – Creating a Captcha Control – Part 2 – I was talking about Captcha class that contains some of the properties of the control like text colour, font size, font family and background image path. The class basically defines the setter and the getter for few of the properties. The code for the class is below.

Captcha Class
  1. using System;
  2.  
  3. namespace CaptchaApp
  4. {
  5.     public class Captcha
  6.     {
  7.  
  8.  
  9.         public string FontFamily
  10.         {
  11.             get { return fontFamily; }
  12.             set
  13.             {
  14.                 if (value != string.Empty && value != null)
  15.                     this.fontFamily = value;
  16.                 else
  17.                     this.fontFamily = "Arial";
  18.             }
  19.         }
  20.  
  21.         public double FontSize
  22.         {
  23.             get { return fontSize; }
  24.             set
  25.             {
  26.                 try
  27.                 {
  28.                     if (value <= 10 || value >= 24)
  29.                         this.fontSize = 16;
  30.                     else
  31.                         this.fontSize = value;
  32.                 }
  33.                 catch (Exception ex)
  34.                 {
  35.                     this.fontSize = 16;
  36.                 }
  37.             }
  38.         }
  39.  
  40.         public string TextColor
  41.         {
  42.             get { return textColor; }
  43.             set
  44.             {
  45.                 if (value == string.Empty || value == null)
  46.                     this.textColor = "Black";
  47.                 else
  48.                     this.textColor = value;
  49.             }
  50.         }
  51.  
  52.         public string BackgroundImagePath
  53.         {
  54.             get { return backgroundImagePath; }
  55.             set
  56.             {
  57.                 this.backgroundImagePath = value;
  58.             }
  59.         }
  60.  
  61.         public System.Drawing.Font GetFont()
  62.         {
  63.             return new System.Drawing.Font(FontFamily, (float)FontSize);
  64.         }
  65.  
  66.  
  67.         private double fontSize;
  68.         private string fontFamily;
  69.         private string backgroundImagePath;
  70.         private string textColor;
  71.     }
  72.  
  73.  
  74. }

The full code for the control can be downloaded from CodePlex at http://captchadotnet.codeplex.com/

March 16, 2011

Creating a Captcha Control – Part 3

Adding Audio

In my previous 2 articles – Creating a Captcha Control – Part 1 and Creating a Captcha Control – Part 2 – I have created the user control for the captcha control. The control also allows functionality to play audio to read the text on the captcha.

To achieve the audio feature, I have used a COM library – Microsoft Speech Object Library. To add the COM library, I added a reference to Microsoft Speech Object Library (%Windir%\System32\Speech\Common\Sapi.dll). To add a reference, right-click on the Reference folder, click Add Reference, click COM tab and add the library.

captcha-add-reference

Once the reference is added, the SpeechLib namespace is imported as shown below.

Adding reference to SpeechLib
  1. using SpeechLib;

Then, the Speak method in SpVoice class is used to play the audio as per below.

ReadCaptcha method
  1. protected void ReadCaptcha(object sender, EventArgs e)
  2. {
  3.     SpVoice voice = new SpVoice();
  4.  
  5.     char[] text = ((string)ViewState["captcha"]).ToCharArray();
  6.     
  7.  
  8.     for (int i = 0; i < text.Length; i++)
  9.     {
  10.         voice.Speak(text[i].ToString(), SpeechVoiceSpeakFlags.SVSFDefault);
  11.     }
  12. }

As can be seen, I am reading out each of the text and not all the text at once. The reason is, SpVoice class will try to read it as a word instead of individual characters otherwise.

In the following article, I will show how to create and use the handler to generate the image. The whole code for the captcha control can be downloaded from CodePlex at http://captchadotnet.codeplex.com/

In my last article – Creating a Captcha Control – Part 1, I discussed on the front end of the user control that creates the captcha. In this article, I will discuss on the code-behind of the control – that is, what properties are set and how and what methods are used.

The following code shows the properties that are used.

User Control - Properties
  1. #region field initialisation
  2.  
  3. public Captcha cc;
  4. private int captchaLength;
  5. private double fontSize;
  6. private string fontFamily;
  7. private string backgroundImagePath;
  8. private string textColor;
  9. private string successMessage;
  10. private string errorMessage;
  11. private string characterSet;
  12.  
  13. #endregion

Then, the setters and getters for these properties are created as per below.

User Control - Setter / Getter
  1. #region GetterSetter
  2. public string TestButtonText
  3. {
  4.     get { return B1.Text; }
  5.     set { B1.Text = value; }
  6. }
  7.  
  8. public string SpeakButtonText
  9. {
  10.     get { return BSpeak.Text; }
  11.     set { BSpeak.Text = value; }
  12. }
  13.  
  14. public string ReLoadButtonText
  15. {
  16.     get { return B2.Text; }
  17.     set { B2.Text = value; }
  18. }
  19.  
  20. public string SuccessMessage
  21. {
  22.     get { return successMessage; }
  23.     set { successMessage = value; }
  24. }
  25.  
  26. public string ErrorMessage
  27. {
  28.     get { return errorMessage; }
  29.     set { errorMessage = value; }
  30. }
  31.  
  32. public int CaptchaLength
  33. {
  34.     get { return captchaLength; }
  35.     set
  36.     {
  37.         try
  38.         {
  39.             int k = Convert.ToInt32(value);
  40.             if (k < 5 || k > 10)
  41.                 captchaLength = 6;
  42.             else
  43.                 captchaLength = k;
  44.         }
  45.         catch (Exception ex)
  46.         {
  47.             captchaLength = 6;
  48.         }
  49.     }
  50. }
  51.  
  52. public string FontFamily
  53. {
  54.     get { return fontFamily; }
  55.     set
  56.     {
  57.         if (value != string.Empty && value != null)
  58.             fontFamily = value;
  59.         else
  60.             fontFamily = "Arial";
  61.     }
  62. }
  63.  
  64. public double FontSize
  65. {
  66.     get { return fontSize; }
  67.     set
  68.     {
  69.         try
  70.         {
  71.             fontSize = Convert.ToInt32(value);
  72.             if (fontSize <= 10 && fontSize >= 24)
  73.                 fontSize = 16;
  74.         }
  75.         catch (Exception ex)
  76.         {
  77.             fontSize = 16;
  78.         }
  79.     }
  80. }
  81.  
  82. public string BackgroundImagePath
  83. {
  84.     get { return backgroundImagePath; }
  85.     set
  86.     {
  87.         if (System.IO.File.Exists(Server.MapPath(value)))
  88.             backgroundImagePath = value;
  89.         else
  90.             backgroundImagePath = System.Configuration.ConfigurationManager.AppSettings["defaultImagePath"];
  91.     }
  92. }
  93.  
  94. public string TextColor
  95. {
  96.     get { return textColor; }
  97.     set
  98.     {
  99.         if (value == string.Empty || value == null)
  100.             textColor = "Black";
  101.         else
  102.             textColor = value;
  103.     }
  104. }
  105.  
  106. public string CharacterSet
  107. {
  108.     get { return characterSet; }
  109.     set
  110.     {
  111.         if (value == "" || value == null)
  112.             characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
  113.         else
  114.             characterSet = value;
  115.     }
  116. }
  117.  
  118. #endregion

The setters and getters are quite straight forward. The captcha length property defaults to 6 in case the value entered is not a number and if the value is less than 6 or greater than 10.

The default font family is set to Arial.

The default font size is set to 16. If fonts are too small – less than 10px – or too large – greater than 24px – the font is automatically set to 16.

The default colour is set to black.

The default character set consists of all letters in uppercase and number from 1 to 9. I have not included lower case letters and 0 as these are sometimes confusing.

The default background image is set within the web.config file. Note that the background image is expected to be within the solution and would require “~” notation to work properly.

Now, in the Page_Load event shown below, I am setting the default values and loading the captcha.

Page_Load event
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3.  
  4.     B1.Text = TestButtonText;
  5.     B2.Text = ReLoadButtonText;
  6.     BSpeak.Text = SpeakButtonText;
  7.     
  8.     SetValues();
  9.  
  10.     cc = GetCaptchaClass();
  11.  
  12.     if (!IsPostBack)
  13.     {
  14.         LoadCaptcha();
  15.     }
  16. }

As can be seen, the Button’s text are set a SetValues method is called which sets values for other properties and the method – LoadCaptcha is called if it is not a postback. Another class Captcha is set to method GetCaptchaClass which initiates a Captcha object. I will talk about the Captcha object in a little while.

The SetValues method is below.

SetValues method
  1. private void SetValues()
  2. {
  3.     if (CharacterSet == null)
  4.         CharacterSet = "";
  5.     if(CaptchaLength == 0)
  6.         CaptchaLength = 6;
  7.  
  8.     if(BackgroundImagePath == null)
  9.         BackgroundImagePath = "";
  10.     
  11.     if(FontFamily == null)
  12.         FontFamily = "";            
  13.     
  14.     if(FontSize == 0)
  15.         FontSize = 0.0;
  16.  
  17.     if(TextColor == null)
  18.         TextColor = "";
  19. }

The LoadCaptcha method is interesting – it creates random text and adds it ViewState and Session, adds the Captcha object to Session and sets the path of the Image control to CaptchaHandler.ashx handler. The code for this method is below.

LoadCaptcha method
  1. private void LoadCaptcha()
  2. {
  3.     string text = GetRandomText();
  4.     
  5.     ViewState.Add("captcha", text);
  6.     Session.Add("CaptchaClass", cc);//add captcha object to Session
  7.     Session.Add("captcha", text);//add captcha text to session
  8.     Im1.ImageUrl = "CaptchaHandler.ashx";
  9. }

The random text for the captcha is generated by GetRandomText method which basically creates random text based on the CharacterSet property. The code for this method is below.

GetRandomText method
  1. private string GetRandomText()
  2. {
  3.     char[] letters = CharacterSet.ToCharArray();
  4.     string text = string.Empty;
  5.     Random r = new Random();
  6.     int num = -1;
  7.  
  8.     for (int i = 0; i < this.CaptchaLength; i++)
  9.     {
  10.         num = (int)(r.NextDouble() * (letters.Length - 1));
  11.         text += letters[num].ToString();
  12.     }
  13.     return text;
  14. }

The Captcha class basically properties for the captcha text. The GetCaptchaClass method initiates the Captcha class and set its properties. The code for this method is below.

GetCaptchaClass method
  1. private Captcha GetCaptchaClass()
  2. {
  3.     if (Session["CaptchaClass"] != null)
  4.         cc = (Captcha)Session["CaptchaClass"];
  5.     else
  6.         cc = new Captcha();
  7.  
  8.     cc.FontSize = this.FontSize;
  9.     cc.FontFamily = this.FontFamily;
  10.     cc.BackgroundImagePath = this.BackgroundImagePath;
  11.     cc.TextColor = this.TextColor;
  12.     return cc;
  13. }

That’s pretty much all the methods for the user control. When the Reload Button is clicked the LoadAnother method is run that simply calls the LoadCaptcha method as per below.

LoadAnother method
  1. protected void LoadAnother(object sender, EventArgs e)
  2. {
  3.     LoadCaptcha();
  4. }

When the Test button is clicked, the ValidateCaptcha method is run that compares the text entered with the text in the ViewState. The code is below.

ValidateCaptcha method
  1. protected void ValidateCaptcha(object sender, EventArgs e)
  2. {
  3.     string text = T1.Text;
  4.     if (text == (string)ViewState["captcha"])
  5.         LStatus.Text = SuccessMessage;
  6.     else
  7.         LStatus.Text = ErrorMessage;
  8. }

In my next article, I will explain how the reading out the captcha text works. The captcha control is also available for download from CodePlex at http://captchadotnet.codeplex.com/

Reference: Shahed Kazi at AspNetify.com