Organic Search Engine Optimization (SEO) Solutions. Call now on 0879807629 or contact us via email
AKA Marketing.com Logo

Blogged thoughts, is our web blog. Expect views, opinion, rants and tirades about everything and anything 

« Home / Services / Forums »        

Subscribe to our SEO / IT related blog by entering your email address below

Blogged thoughts

| by the www.akamarketing.com team

Archive for the 'ASP.NET' Category


Repeater paging with an SqlDataSource in ASP.Net

Friday, August 17th, 2007

The ASP.Net repeater control has over the last while become one of my favourite controls due to the fact it can be highly customised because it’s a templated control. Two shortcomings with the current implementation of the repeater control however are its lack of paging and sorting capabiltites. Of these I believe paging is perhaps the more desirable feature and thus I will now provide an outline of how to implement paging with a repeater using an SqlDataSource. I’ve chosen to work with an SqlDataSource as this I imagine is the most common underlying data source used with repeaters. 

PagedDataSource class
The most popular way ASP.Net developers enable repeaters to page through large amounts of results is with the help of the PagedDataSource class. This is a class which

Encapsulates the paging-related properties of a data-bound control (such as DataGrid, GridView, DetailsView, and FormView) that allow it to perform paging and is used by control developers when providing paging support to a custom data-bound control.

Since this class can be used to provide paging support to custom data-bound controls it can of course be used by built in data-bound controls such Repeaters and DataLists to provide the same support. If you look on the MSDN page which I have linked to above you’ll notice however that the class implements the ICollection interface. This means that any underlying source you want to feed into the PagedDataSource class (which in turns feeds into the repeater itself) must also implement ICollection. The SqlDataSource class does not implement this interface and thus we must put the data into some class that does implement ICollection, in this case we are using a DataView. OK lets look the c# code behind.

  1. public partial class _Default : System.Web.UI.Page
  2. {
  3.     PlaceHolder innerPlaceHolder = new PlaceHolder();
  4.     protected void Page_Load(object sender, EventArgs e)
  5.     {
  6.         Session[“pageNumber”] = 1;
  7.         Page_with_Repeater();
  8.         int totalResults = (int)Session[“totalResults”];
  9.  
  10.         //five represents the page size - could you session/viewstate
  11.         //to avoid hardcoding but for this sample it’s fine.
  12.         float numOflinks = ((float)totalResults / 5);
  13.        
  14.         //determine how many links to create/display
  15.         if (numOflinks % 1 == 0) numOflinks = (int)numOflinks;
  16.         else if(numOflinks % 1 != 0) numOflinks = (int)numOflinks + 1;
  17.        
  18.         for (int i = 1; i < numOflinks+1; i++)
  19.         {
  20.             LinkButton PagingLink = new LinkButton();
  21.             PagingLink.ID = “pagelink” + i.ToString();
  22.             PagingLink.Text = i.ToString();
  23.             PagingLink.Visible = true;
  24.             PagingLink.CommandArgument = i.ToString(); //used to detect result page required
  25.             PagingLink.Command += new CommandEventHandler(PagingLink_Command);
  26.             innerPlaceHolder.Controls.Add(PagingLink);
  27.         }
  28.     }
  29.  
  30.     public void Page_with_Repeater()
  31.     {
  32.         //SqlDataSource does not implement ICollection and
  33.         //thus will not work with PageDataSource we therefore use
  34.         //a DataView instead which implements all required Interfaces
  35.         DataSourceSelectArguments arg = new DataSourceSelectArguments();
  36.         DataView dv = (DataView)SqlDataSource1.Select(arg);
  37.  
  38.         //Instantiate an instance of PagedDataSource
  39.         //and sets its main properties
  40.         PagedDataSource PagedResults = new PagedDataSource();
  41.         PagedResults.DataSource = dv;
  42.         PagedResults.AllowPaging = true;
  43.         PagedResults.PageSize = 5; //CHANGE THIS ABOVE TOO
  44.  
  45.         int pageIndex;
  46.         Int32.TryParse(Session[“pageNumber”].ToString(), out pageIndex);
  47.         PagedResults.CurrentPageIndex = pageIndex-1; //because this is indexed based
  48.  
  49.         //after the PagedDataSource class is in place we can then
  50.         //feed this into the repeater itself
  51.         repeater1.DataSource = PagedResults;
  52.         repeater1.DataBind(); //repeater does not bind natively
  53.  
  54.         //configure paging number - Google Style
  55.         //to do this we dynamically create X amount of links based on the total
  56.         //results and the PageSize - we can’t create these buttons here as
  57.         //events will only run if added in design time or page_init/page_load
  58.         Control OuterPanel = FindControlRecursive(repeater1, “placeLinks”);
  59.         OuterPanel.Controls.Add(innerPlaceHolder);
  60.     }
  61.  
  62.     protected void SqlDataSource1_Selected(object sender, SqlDataSourceStatusEventArgs e)
  63.     {
  64.         //variable used to create X amount of buttons
  65.         Session[“totalResults”] = e.AffectedRows;
  66.     }
  67.  
  68.     protected void PagingLink_Command(object sender, CommandEventArgs c)
  69.     {
  70.         Session[“pageNumber”] = c.CommandArgument.ToString();
  71.         Page_with_Repeater();
  72.     }
  73.  
  74.     private Control FindControlRecursive(Control root, string id) { } //removed for clarity
  75.  
  76. }

All the important paging related code is encapsulated in the Page_with_Repeater() function, it’s all commented so I won’t repeat myself here. As far as what the code does, well it displays 5 rows of data at a time from the underlying datasource (in this case SqlDataSource1) in a repeater. LinkButtons are dynamically created and then added to the repeater to display page numbers as links to allow the user to select a specific result page. Often interfaces allow the user to select a specific page (as in this example) and to use previous and next buttons for working his or her way through data, on that note a good example of using buttons for repeater paging is given on the 4guysfromrolla.com website. 

The corresponding .aspx markup for the c# code is very simple and contains a repeater (named ‘repeater1′) with an embedded panel (named ‘placeLinks’) and an SqlDataSource (named ‘SqlDataSource1′) which specifies an event hander for the ’selected’ event in order for us to create the correct amount of paging links.

Incidentally you may notice in the C# code above that I have used a custom function called FindControlRecursive to enable me to add the dynamically created placeholder (which contains all the page number linkbuttons) to the statically created panel within the repeater. This is a handy function I came across recently and which I often use in conjunction with repeater controls (and many other controls too). It accepts a root control and an id of the target control to look for. It works in a similar way to the standard FindControl method except it searches all controls (including child controls) in a control tree hierachy whereas FindControl will only search the specific control you pass it without examining any child controls.

That’s it - paging with a repeater using an SqlDataSource is implemented. As you can see it is not too difficult. If you have any questions please feel free to ask.  


Microsoft Certified Technology Specialist (MCTS)

Thursday, August 9th, 2007

Booked myself in for one of the two exams required for the MCTS - .NET Framework 2.0 Web Applications certification yesterday. The exam I’m going for is the Microsoft .NET Framework 2.0 - Web-Based Client Development exam (code 70-528). I’m booked in for mid September to do it with New Horizons Ireland at a cost of €140. New Horizons seem to be the only Dublin based exam center available.

The exam focuses on using ASP.Net 2.0 to build highly dynamic, secure and scalable web applications and questions a developers knowledge of such things as standard & custom controls, data access via ADO.Net, web parts, membership, state management, mobile web applications, management & deployment of web apps and much much more. To help me prepare I got the training kit book by Glenn Johnson and Tony Northrup covering this specific exam and reviewed two very highly rated Wrox ASP.Net books which I bought last year. Additionally the fact I’ve been doing most of this stuff in my daily 9 to 5 for a good while now means I’m feeling pretty confident. In fact I anticipate much more difficulty with the other exam required for this certification - the Microsoft .NET Framework 2.0 - Application Development Foundation exam (code 70-536).

Incidentally I’m also considering going for another certification. It’s the ISEB Foundation Certificate in Software Testing. I think everyone would agree that software testing and software development are very complementary skills. Not sure where this can be done though and if classroom training is required, ideally I would just like to get stuck into a good book for a few weeks.


Ajax example - staff directory search with PHP & C# ASP.Net

Sunday, August 5th, 2007

Ajax in a nutshell is a set of technologies which allow for partial page updates without requiring the whole page to refresh after communication with the server. Usually when a visitor is on a webpage and clicks a link or a button the whole page is reloaded (and the browser window goes white) before the user can see the updated page back, however with Ajax the user could see the specific results of the link/button click almost immediately as only the relevant section of the page is updated. What Ajax (the frontend) updates the page with is usually based on what it passes to the server (backend).

Ajax uses Asynchronous communication to allow this type of update to a page. Asynchronous communication in this context basically means that the loading of data/information (for example results from an SQL Query) for display in a specific section of the web page does not interfere with the normal loading of the web page and thus the page will not freeze or go white as is normally the case. The idea with Ajax is to give the end user a much better experience. This better experience comes from increased responsiveness/speed and usability.

Have a look at the following two pages (which open in new windows) which provide the user with the ability to lookup contact details for staff of a dummy company called HollyWood MovieStars Ltd.

Standard search interfaceAjax enabled search interface (have a sneak at the source if you want)
TIP - Search for one of the vowels first.

The first page is a standard search interface where you enter in your query, press search and watch as the whole page posts back, reloads and gives you back your search results. The second page is an Ajax enabled search interface which returns results almost immediately as soon as you start typing your query - without requiring a whole page reload. I know which one would make me the happier end user.

In this post I’ll present a step by step example of how to use Ajax to create a much more responsive and user friendly interface than is possible with the regular request and wait protocol we are all so familiar with. The interface I’m actually going to put together is the Ajax enabled one shown above. As you can see it basically allows a user to quickly look up the contact details of a member of staff by sub string searching on their name information which is stored in a database somewhere. I’m tagging this one as a staff directory search but it could just as easily be used to find details for club members, clients etc. The important thing is the underlying concepts and not what it’s actually used for. 

The actual Ajax code which communicates with the server is written in Javascript and thus the frontend of this interface will just be a standard webpage (.html extension) with a mixture of Javascript/HTML and a touch of CSS/DHTML too. For the backend - which does the actual SQL query database lookup based on what the Ajax frontend passes to it and returns results I will provide summary code in both PHP and C# ASP.Net. You could actually use the exact same PHP or C# ASP.Net code to run both a standard click and wait search interface and an Ajax enabled one (if you set the form method to GET on the standard search page) so there is definitely nothing special about the backend in this case and thus summary code and summary explainations are all that’s needed for the backend in this case.

XMLHttpRequest
Let’s begin with the object that makes everything Ajax possible. The XMLHttpRequest javascript based object is the actual mechanism that allows independent asynchronous communication between client and server. Without it Ajax would not exist. As you can see from the XMLHttpRequest Wikipedia page the object has a number of methods (actions) and properties (values) available to it. The most important methods include Open() and Send(), while the most important properties are onreadystatechange, readyState, status and ResponseText at least for this example anyhow. OK let’s see some code and then I’ll offer a line or two on the above methods and properties as we come across them. The function below is your bread and butter Ajax client to server communication code…

  1.  function getText(urlToCall, functionToCallBack, divToUpdate)
  2. {
  3.    
  4.     var XMLHttpRequestObject = false;
  5.  
  6.     //will exist in navigator, firefox & safari
  7.     if (window.XMLHttpRequest)
  8.     {
  9.           XMLHttpRequestObject = new XMLHttpRequest();
  10.     } 
  11.     //will exist in explorer
  12.     else if (window.ActiveXObject)
  13.     {
  14.          XMLHttpRequestObject = new
  15.          ActiveXObject(“Microsoft.XMLHTTP”);
  16.     }
  17.  
  18.     //if object was created successfully
  19.     if(XMLHttpRequestObject)
  20.     {
  21.             XMLHttpRequestObject.open(“GET”, urlToCall);
  22.             XMLHttpRequestObject.send(null);
  23.  
  24.             XMLHttpRequestObject.onreadystatechange = function()
  25.            {
  26.                  if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200)
  27.                 {
  28.                     functionToCallBack(XMLHttpRequestObject.responseText, divToUpdate);
  29.                     delete XMLHttpRequestObject;
  30.                     XMLHttpRequestObject = null;
  31.                 }
  32.            }
  33.     } //end if object created
  34.  
  35. } //end of function
  36.  

Lines 6 through 16 are what actually creates a new instance of a XMLHttpRequest object for use later in the function. How the Javascript creates the object depends on what the current browser is. This is required as Internet Explorer creates the underlying object differently than most other browsers.  

Line 19 simply checks if the earlier logic to create the XMLHttpRequest object was successful, and if this is the case it calls the open() method of the object. This is a very important method and is used to inform the XMLHttpRequest object of the location of the backend script (urlToCall) to call and communicate with. It also specifies the mode of communication, the most common modes of communication are POST and GET. How you pass data to the backend script depends on what option you select as the mode of communication, in this case this is set to GET - meaning we will pass data (whatever the searcher types into the search box) via query strings embedded into the url of the backend script (urlToCall) which we want to communicate with. It is important to note that no actual communication with the server has begun - open() simply specifies information about an async request which is about to happen, thus in this way the use of the word open is perhaps misleading.

Line 22 is what actually kicks things off, it does this by sending the request to the backend script as specified by the urlToCall parameter. Referring back to our XMLHttpRequest Wikipedia page we notice that the send method can take one parameter called content. This parameter is used to specify the data to send to the backend script if we set our mode of communication to POST. The backend script would then by able to access this data in a standard way such as $_POST['data'] in PHP or Request.Form["data"] in C# ASP.Net. Since we are passing data via query params (GET mode) attached to the filename specified by urlToCall we only need to pass a value of null.

Next up we see the onreadystate change property which calls an anonymous function everytime the state of the request changes. In the function both readyState and status are checked to make sure the request is a) complete and b) successful. The two magic numbers here are ‘4′ (readyState) meaning the the request is fully complete and ‘200′ (status) meaning the communication between client and server was successful.

Line 28 is just a standard Javascript function call to the function specified by functionToCallBack. The call passes in the text that was returned from the backend script via the XMLHttpRequest objects’ ResponseText property as well as the id of the div (or span/p etc.) element to update with the response. It is of course possible to handle the ResponseText right there in the anonymous function, however this is not a good idea as each Ajax application will be handling responses differently so it’s better to keep the getText function clear of any hardcoding and use specific embedded callback functions for each different page. Doing this will mean you can use the same getText function again and again in lots of different Ajax interfaces without modification.

Finally for the getText function lines 29 and 30 use good programming practice and dispose of now unneeded resources.

Incidentally the getText function I’ve used here is actually a slightly modified version of a function which is part of a very simple (but more often than not sufficient) Ajax framework which was originally included with an Ajax book I read called Ajax Bible written by a guy called by Steven Holzner. I thoroughly recommend the book to anyone wanting to get aquainted with Ajax and what it can do. As for the framework, it can be downloaded from http://www.akamarketing.com/scripts/ajaxutility.js, you will notice that getText is one of four functions available. By the way don’t be scared off by the word ‘framework’, a framework in the context of development is basically just a load of pre written code for you to use as a base, it’s nothing more and nothing less.

Displaying the response in the browser
The getText function as outlined above looked after the async client & server communication side of things and called another function on line 28 (commonly referred to as the callback function) when everything was done. The whole purpose of this callback function is to handle and display the response of the aforementioned communication. Let’s have a look at this very simple function now…

  1. //this function gets called when results are ready from the server side
  2. function callbackfunction(text, divToUpdate)
  3. {
  4.     //handle response in here, in this case we are just outputting it
  5.      document.getElementById(divToUpdate).innerHTML = text;
  6. }

I’m sure anyone used to fiddling with the DOM and/or DHTML can see what’s going on here. This code is basically instructing the browser to update the div as indicated by divToUpdate with the response outputted by the backend script and passed in via the parameter text.

Getting the ball rolling with user driven events 
You’ve seen how the callback function gets called from within the getText function, but how does the getText function get called in the first place? Good Question! The getText function gets called by tying it to some user driven event such as a button click, mouse move or keypress. You can see from the Ajax enabled search interface (the one we’re trying to make) that there isn’t a button in sight so we won’t be attaching a call to the getText function to an onClick event. Instead to enable getText to get called with each and every single keypress (and hence provide search results very quickly) in the query textbox we are using the onkeyup event. Here is the code we need.

  1. <input id=“query” onkeyup=“getText(’ajax-backend.php?query=’+document.getElementById(’query’).value+”,callbackfunction, ’searchResults’)” name=“query” type=“text” /> 

Notice that in this case the backend is PHP driven, also notice how we are embedding the search query into the backend filename. In this case the HTML element which we want to update with the server response has the id ’searchResults’. This means that a div, span, p or some other HTML element which exposes the InnerHTML property and has an id of ’searchResults’ must be present on the page or a Javascript error will occur. At this stage the client side frontend of our staff search interface is complete, you can get the full source by opening the Ajax enabled search interface page and selecting View >> Source from the toolbar. You may notice that the getText function is included in the frontend via an external JS file.

All that’s left to do now is to complete the backend code. The backend code is pretty standard issue stuff. Your basically checking for a query string param called ‘query’ and if it’s found your executing an SQL query (with the query string embedded) against a DB and simply outputting the results. The backend summary code is first given for ajax-backend.aspx (C# ASP.Net) and is then given for ajax-backend.php (PHP).

ajax-backend.aspx

  1. <!–Page Language=“C#”–>
  2. <!–Import Namespace=“System.Data.SqlClient”–>
  3. <script>
  4.     protected void Page_Load(object sender, EventArgs e)
  5.     {
  6.         //if something is in the query param do a LIKE search
  7.         //against the staff directory database and return results if any
  8.         if (Request.QueryString[“query”] != null)
  9.         {
  10.             string query = Server.HtmlEncode(Request.QueryString[“query”].Replace(“‘”,“””));
  11.             SqlConnection connection = new SqlConnection(“connection string in here”);
  12.             SqlCommand command = new SqlCommand();
  13.             SqlDataReader reader;
  14.  
  15.             command.Connection = connection;
  16.             command.CommandText = “select * from staff_directory where firstname like ‘%” + query + “%’ or…”;
  17.  
  18.             connection.Open();
  19.             reader = command.ExecuteReader();
  20.  
  21.             int count = 0;
  22.             while (reader.Read())
  23.             {
  24.                 Response.Write(
  25. <tr>
  26. <td>reader[0].ToString()….. etc. etc.”);
  27.                 count++;
  28.             }
  29.  
  30.             if (count == 0)
  31.             {
  32.                 Response.Write(“Sorry no results were found for your search”);
  33.             }
  34.         }
  35.     }
  36. </script>
  37.  
  38. <!– Stripped out all other output as frontend is handled by ajax-frontend.html –>

ajax-backend.php

  1. <!–r–>if(isset($_GET[“query”]) && $_GET[“query”] != “”)
  2. {
  3.  
  4.  $dbcon = mysql_connect(“localhost”,“username”,“password”);
  5.  
  6.  if (!$dbcon)
  7.  {
  8.    die(‘Not connected : ‘ . mysql_error());
  9.  }
  10.  
  11.  $db_selected = mysql_select_db(‘DB’, $dbcon);
  12.  if (!$db_selected)
  13.  {
  14.    die (‘Can\’t use foo : ‘ . mysql_error());
  15.  }
  16.   
  17.  //setup a query
  18.  $query = “select * from staff_directory where firstname like ‘%” . $_GET[“query”] . “%’ or lastname like ‘%” . $_GET[“query”] . “%’ or firstname + ‘ ‘ + lastname like ‘%”. $_GET[“query”] . “%’”;
  19.  
  20.  //execute the query
  21.  $get_results = mysql_query($query);
  22.  if (!$db_selected)
  23.  {
  24.    die (‘Query Error : ‘ . mysql_error());
  25.  }
  26.  
  27.  if(mysql_num_rows($get_results)>0)
  28.  {
  29.   $counter=0;
  30.   while($row = mysql_fetch_array($get_results))
  31.   {
  32.    $counter++;
  33.    echo “<strong>NAME</strong>: “ . $row[0] . ” “ . $row[1] . ” <strong>PHONE:</strong> “ . $row[2] . ” <strong>EMAIL:</strong> “ . $row[3] . ” <strong>SEX:</strong> “ . $row[4] . “”;
  34.   } 
  35.  }
  36.  else
  37.  {
  38.   echo “Sorry no results were found for your search”;
  39.  }
  40.  
  41. }
  42. ?> 

Neither the C# ASP.Net or PHP code given above is complete or production ready, both code samples do however provide you with a very good idea of what needs to go on from the backend point of view. Remember anything that you Response.Write() or echo out on the backend page will be returned to the client via the XMLHttpResponse objects’ ResponseText property.

Well that’s really it, with both the frontend and backend elements of an example Ajax interface covered you should now be able to implement something similar to suit your own needs, if not I hope I have at least provided you with a good basis for further research and remember if your stuck on anything please drop me a comment. In fact even if your not stuck please drop me a comment as I’d love to get your feedback on this post.


ASP.NET input validation overview

Sunday, July 29th, 2007

Coming from a PHP background I’m used to manually adding code to perform validation in my applications to check if this field is filled in and if the value in that field is less than that value etc. Depending on the security context I may validate on the client side (via Javascript), the server side or both. Just because I’m used to doing something though doesn’t mean I like doing it, I’d much rather be spending my time sorting out other more interesting elements of my application.

Imagine the size of the smile on my face then when I started developing with ASP.Net and discovered a whole rake of input validation controls which automatically configure client and server side validation built into the .Net framework. These controls cover a wide range of validation needs (in fact many apps can be completely validated without the developer needing to write a single line of code) and require only basic configuration.

The current incarnation of ASP.Net (2.0) includes six validation controls. These controls are RequiredFieldValidator, RangeValidator, RegularExpressionValidator, CompareValidator, CustomValidator and finally ValidationSummary. I’ll cover these in detail over the next few paragraphs, starting with RequiredFieldValidator.

The most commonly used control is the RequiredFieldValidator. It allows you to specifiy that certain HTML controls must have user input and displays an error message if input is not given. To associate a RequireFieldValidator with an input control you set the ControlToValidate property equal to the ID of the input control. The ControlToValidate property is available to all validation controls except the ValidationSummary control and is a required setting. When I discuss other validation controls later in this post I may not explicitly mention this property in relation to each control, but you know now it needs to be set. Other properties common to all controls (except ValidationSummary) and which are worth a mention include ErrorMessage, Text and EnableClientScript. Both ErrorMessage and Text allow the developer to set the text that displays when some validation fails. If ErrorMessage and Text are both set Text overrides ErrorMessage. I will cover the EnableClientScript property later in this post.

Back to the RequiredFieldValidator - The InitialValue property of the RequiredFieldValidator validation control allows you to ‘tell’ the framework what’s in the HTML control by default and thus if the user does not change this default value be it some text in a textbox or a selection in a dropdown list the HTML control will be considered as not set and thus the error message will show. The InitialValue is particularly useful when you need to validate a dropdown list as often you would have a default item such as ‘– Please Select an Option –’ in the list. If the corresponding value of this option was say ‘0′ then setting the InitialValue to ‘0′ on a RequiredFieldValidator would cause the page to fail validation if the user did not change the selection.

If you need to ensure that the value a user inputs is between some defined range then the RangeValidator control can be used. This control exposes two properties called MinimumValue and MaximumValue which allow you to set the low and high bounds for correct input data. The other significant property of this control is the Type property. The Type property sets the data type of the value to check and can be set to Currency, Date, Double, Integer & String. 

The next ASP.Net input validation control is the RegularExpressionValidator. This allows developers to check if user input matches a specific pattern or form. This validation control is often used to validate email addresses or telephone numbers. Use of this control requires you to set the ControlToValidate property (as you would with the other validation controls) and the ValidationExpression property. The ValidationExpression property accepts a regular expression as input, a regular expression (regex or regexp for short) is a special text string for describing a search pattern. Regular expressions can be quite difficult to write (and even harder to read) however they are very powerful once you get the hang of them. If you are a Visual Studio user you can use its built in Regular Expression Editor which has a couple of prebuilt regular expressions for checking things like email address format, zip code format etc. The Regular Expression Editor is available from within the ValidationExpression property field. The regular expression for matching an email address is below:

  1. \w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

More information about regular expressions can be found at http://www.regular-expressions.info/.

To continue with the CompareValidator then. This control allows you to compare the value in one input control to the value in another or it allows you to compare an input control value to a defined value. An example where you might use the first method of usage would be to compare two password input textboxes to confirm the user has typed in his or her desired password correctly (as dots or asterisks will be shown in place of the real input). To use the compareValidator in this scenario you need to set the ControlToCompare, Operator and Type properties. The ControlToCompare property needs to be set to the second control which you want to compare against the first control as specified in the ControlToValidate property. The operator setting determines what type of comparsion is done, for this you can select a couple of values such as Equal, NotEqual, LessThan etc. One particularly iteresting value for this property is DataTypeCheck which if selected allows you to simply check if input is of a particular data type such as a date or a number (int). The Type property we have seen before, it simply tells the framework to treat the input data as currency, date etc.

Hopefully your beginning to see that the above validation controls can really make a developers life a lot easier, however they don’t do everything and there will often be a need for custom validation logic to help you completely fool proof your apps. This is where the CustomValidator control comes handy. This control allows the you to write custom validation logic. An example where you might use a CustomValidator might be to check if a username is already taken on a new account form. This would require a peek in the database and thus requires the validation to be performed on the server, however CustomValidator validation functions can run on the client side too (if no server side resources are needed of course).  

The CustomValidator is (because it’s custom) a little more difficult to work with than the other validation controls. If your validation logic can only run on the server (and it’s impossible for a client side function to therefore work) you can ‘get away’ with only setting the ControlToValidate property. If however you want and can have client side custom validation you need to set the ClientValidationFunction equal to the name of the Javascript function which will handle the validation logic.

What about the ServerValidationFunction property? Well there isn’t one, to tie a CustomValidator control to a server side validation function you actually need to go through the controls ServerValidate event (in Visual Studio click the yellow lightning bolt and you’ll see it) and select your server side function. Since I finally got around to installing a wordpress plugin which allows me to display nicely formatted color coded code in my posts lets write up a server side validation function to see the format required.

  1. void CheckForDuplicateUserName(object source, ServerValidateEventArgs args)
  2. {
  3.  
  4.      //create connection,
  5.      //create SQL command - something like "select count(username) from users where username = ‘args.value.ToString()’"
  6.      //execute it and store result in an int variable called resultCount;
  7.  
  8.     if(resultCount == 1)
  9.     {
  10.           args.IsValid = false;
  11.     }
  12.     else
  13.     {
  14.          args.IsValud = true;
  15.     }
  16.  
  17. }

You might be able to figure out that args.Value holds the value of the ControlToValidate control and to send the result back to the framework you set args.IsValid to true or false. If you set args.IsValid to false it means validation has failed and the specified error message will be displayed to the user, in this case the error message could be something like ‘That username is already taken, please select another one’. Obviously the above is only template code, in production code you would server.htmlencode() args.Value to be sure no malicious user is trying to attack your app, you would probably want to escape apostrophes too, additionally you may want to throw some try and catch blocks around your DB logic. In the example the data (a username represented by args.Value) fails validation if a record is returned from the DB meaning there is already a user with that username.

Using a client side validation function with CustomValidator is very similar to using a server side function, in fact the only difference is the parameters that the functions take. The format is given below:

  1. function CheckForCorrectFormat(oSrc, args)
  2. {
  3.  
  4.           //test for correct format
  5.          if(args.value == correctformat)
  6.          {
  7.                  args.InValid = false;
  8.          }
  9.          else
  10.          {
  11.                 args.InValid = true;
  12.          }
  13.  
  14. }

The final control which I’ll talk about is the ValidationSummary control. This control is different from the five aforementioned controls in that it doesn’t actually test or validate anything, its purpose is to provide a single place where you can display all a pages validation error messages from validation controls such as RequiredFieldValidator, RegularExpressionValidator etc. Consolidating all error messages like this is quite user friendly, particularly for larger forms. The default usage of a ValidationSummary control does not require the setting of any properties, you can literally just drag it on your page and the error messages (set via the ErrorMessage property) from all other validation controls on the page will show up.

Two interesting properties of the control include ShowMessageBox and ValidationGroup. ShowMessageBox allows you to instruct the framework to show any validation error messages in a Javascript alert box. This could be useful if space is a concern on your form design. The ValidationGroup property allows you to set the ValidationSummary control to only show error messages from certain and not all validation controls on a page. You use the ValidationSummary ValidationGroup property in conjuction with the ValidationGroup property of the five regular validation controls.

It is important to note that the messages which a ValidationSummary control shows are taken from the ErrorMessage property of each individual validation control it works with, it does not work with the Text setting which sets the text to display when validation fails for a specific validation control. This means you could set the Text setting for all your regular validation controls to say a ‘*’ to signify something is required and also set the ErrorMessage property for them same controls to a string such as ‘The firstname field is required’ and have that message displayed in your ValidationSummary control.  

Most of what I wanted to cover in relation to ASP.Net validation controls has been covered but before I end I do want to mention the EnableClientScript property which is available to all validation controls. This setting can be used to instruct the framework to do client side validation via Javascript on all supported browsers and is set to True by default. If you set this value to false on any validaton control the framework will only perform server side validation for that control which means a postback is required. Turning off client side validation for one validation control and not the others can result in things being out of sync which can lead to a bad user experience so be sure to go with all client side validation, all server side validation or the default implementation of both (for all controls), do not mix and match. The combination of using both client side and server side validation means that a postback can be avoided due to the Javascript client side stuff which is a nice convenience to the user however if a bold user tries to bypass security by turning off Javascript the server side stuff will still nab him good and proper, this sort of good user experience without compromising security is what the ASP.Net Framework provides in abundance. It should be noted however that if you need to access a server side resource like a DB (as in our CustomValidator username server side logic above) well then to avoid mixing and matching (and the problems that brings) you will need to go with server side and only server side validation for all controls.

Well that’s the end of another post, the first in a while I must admit, in it you got exposure to all six of the validation controls built into the ASP.Net framework. I certainly didn’t attempt to cover every single little detail of these controls hopefully however I have given you a good grounding as to what is possible and also provided a good base for further research. If you have any questions please leave me a comment and I will do my best to help out.


ASP.NET search engine optimization

Sunday, March 11th, 2007

Has anyone noticed how clumpy and verbose the source code is of some .NET generated .aspx pages are? I mean this can’t be good food for the stomaches of the major search engines, nor can it be good for download times. There is no point is creating a feature rich .aspx website in comparatively double quick time with an advanced IDE like visual studio 2005 which runs on an equally advanced framework like .NET 2.0 when that very same IDE and framework is causing so much code blote and badly placed code (much of it probably unnecessary) that it is likely hampering your positions in the search engines and/or causing people to leave your site before it is even fully loaded.

Of course the amount of bloat created depends on what type of pages your programming but often the end produced source code can be ‘cleaned up’ regardless of what controls, interfaces etc. you are using. It’s just a matter of knowing what to look out for really. One of the main culprits are as far as I can see is ASP.NET’s ViewState mechanism.

ASP.NETs ViewState is the built in mechanism which enables controls such as textboxes, labels, datasets etc. to maintain their states (data) between postback requests for the same page. It does this by hashing the current state of the page and controls into a string and saves this into a hidden field called __VIEWSTATE. At the server, ViewState is used to recontruct the web page and its server controls. This is fine and prevents an ASP.NET developer having to manually repopulate form controls using POST values like is the case with something like PHP, however it is not without a cost. Have a look below at the value of a hidden __VIEWSTATE textfield which was produced from a .aspx page with only a menu and treeview control on it.

‘/wEPDwUJMzg4NTE1Mzc4D2QWAgIDD2QWBAIDDzwrAAkCAA8WCB4NTmV2ZXJF
eHBhbmRlZGQeC18hRGF0YUJvdW5kZx4MU2VsZWN0ZWROb2RlZB4JTGFzdEluZ
GV4AgFkCBQrAAIFAzA6MBQrAAIWCB4EVGV4dAUJQ3VzdG9tZXJzHghEYXRhUG
F0aAUQLypbcG9zaXRpb24oKT0xXR4JRGF0YUJvdW5kZx4QUG9wdWxhdGVPbkR
lbWFuZGdkZAIJDzwrAA0CAA8WAh8BZ2QMFCsABQUPMDowLDA6MSwwOjIsMDoz
FCsAAhYKHwQFBEhvbWUeB0VuYWJsZWRnHgpTZWxlY3RhYmxlZx8FBSAvKltwb
3NpdGlvbigpPTFdLypbcG9zaXRpb24oKT0xXR8GZ2QUKwACFgofBAUIUHJvZH
VjdHMfCGcfCWcfBQUgLypbcG9zaXRpb24oKT0xXS8qW3Bvc2l0aW9uKCk9Ml0
fBmcUKwAEBQswOjAsMDoxLDA6MhQrAAIWCh8EBQxTbWFsbFdpZGdldHMfCGcf
CWcfBQUwLypbcG9zaXRpb24oKT0xXS8qW3Bvc2l0aW9uKCk9Ml0vKltwb3Npd
GlvbigpPTFdHwZnZBQrAAIWCh8EBQ1NZWRpdW1XaWRnZXRzHwhnHwlnHwUFMC
8qW3Bvc2l0aW9uKCk9MV0vKltwb3NpdGlvbigpPTJdLypbcG9zaXRpb24oKT0
yXR8GZ2QUKwACFgofBAUKQmlnV2lkZ2V0cx8IZx8JZx8FBTAvKltwb3NpdGlv
bigpPTFdLypbcG9zaXRpb24oKT0yXS8qW3Bvc2l0aW9uKCk9M10fBmdkFCsAA
hYKHwQFB1N1cHBvcnQfCGcfCWcfBQUgLypbcG9zaXRpb24oKT0xXS8qW3Bvc2
l0aW9uKCk9M10fBmcUKwADBQcwOjAsMDoxFCsAAhYKHwQFCURvd25sb2Fkcx8
IZx8JZx8FBTAvKltwb3NpdGlvbigpPTFdLypbcG9zaXRpb24oKT0zXS8qW3Bv
c2l0aW9uKCk9MV0fBmdkFCsAAhYKHwQFBEZBUXMfCGcfCWcfBQUwLypbcG9za
XRpb24oKT0xXS8qW3Bvc2l0aW9uKCk9M10vKltwb3NpdGlvbigpPTJdHwZnZB
QrAAIWCh8EBQdBYm91dFVzHwhnHwlnHwUFIC8qW3Bvc2l0aW9uKCk9MV0vKlt
wb3NpdGlvbigpPTRdHwZnFCsAAwUHMDowLDA6MRQrAAIWCh8EBQdDb21wYW55
HwhnHwlnHwUFMC8qW3Bvc2l0aW9uKCk9MV0vKltwb3NpdGlvbigpPTRdLypbc
G9zaXRpb24oKT0xXR8GZ2QUKwACFgofBAUJTG9jYXRpb25zHwhnHwlnHwUFMC
8qW3Bvc2l0aW9uKCk9MV0vKltwb3NpdGlvbigpPTRdLypbcG9zaXRpb24oKT0
yXR8GZ2RkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQlU
cmVlVmlldzGl0+HS1X8B5jfomTSld5U3ULhXjg== ‘

Obviously if I was to add more controls this value would grow accordingly. ViewState is enabled for all controls by default, luckily though ASP.NET has made the EnableViewState property available for setting true or false on a control by control basis and thus you can disable it for certain controls which you might never change like a label or a readonly datatable which might be populated from an external source such as a database or an XML file. For example below is the value of the same __VIEWSTATE hidden field (from above) with EnableViewState set to false for the menu control which gets populated from an XML file when the page loads and thus its state will not change between requests/postbacks.

‘/wEPDwUJMzg4NTE1Mzc4D2QWAgIDD2QWAgIDDzwrAAkCAA8WCB4NTmV2ZXJ
FeHBhbmRlZGQeC18hRGF0YUJvdW5kZx4MU2VsZWN0ZWROb2RlZB4JTGFzdEl
uZGV4AgFkCBQrAAIFAzA6MBQrAAIWCB4EVGV4dAUJQ3VzdG9tZXJzHghEYXR
hUGF0aAUQLypbcG9zaXRpb24oKT0xXR4JRGF0YUJvdW5kZx4QUG9wdWxhdGV
PbkRlbWFuZGdkZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18
WAQUJVHJlZVZpZXcxU1/1MUWW6NZaM/KXGnbkTXRYJ3w=’

That’s quite a difference right? And because the control does not change between requests/postbacks the page works exactly as before. Disabling the ViewState for the treeview control would further reduce the contents of the __VIEWSTATE hidden field, it too is populated from an external data source and thus does not require ViewState enabled. Therefore to reduce filesize and keywords to source ratio for SEO purposes turn off viewstate for each control which will not change between multiple requests for the same .aspx page. You can find the biggest ViewState contributors by examing the ‘Control Tree’ section of the trace.axd file. You need to have first enabled tracing of course.

Additionally the usual good practice of using external .js files rather than in-source embedded code will further reduce unneeded bloat and allow your .js file to be cached which should enhance download times.

Aside from generally cleaning your code up there are some other steps of optimisation which can be taken too. Specifically in terms of search engine optimisation an interesting feature of ASP.NET 2.0 is URL mapping. This allows a defined friendly URL such as akamarketing.com/televisions.aspx to be mapped to a complex SEO unfriendly URL such as akamarketing.com/store.aspx?productid=202030&basket=303303&name=television. This means that the actual URL which is the long complex one can be accessed from the shorter SEO friendly one. The original URL will of course still work too. From a programming point of view everything is exactly the same which means all the GET query parameters in the URL are still available. From an end user and search engine perspective the URL is much more friendly and spiderable. Additionally the improved keyword density in the shorter nicer URL versus the longer complex one should facilitate ranking boosts on MSN which deems keywords in URLs to quite significant and it should certainly help on the other major search engines such as Google and Yahoo too.

URL mappings must be manually defined in the web.config file, so if your adding dynamic content including new products, categories, articles etc. to your website/database a lot you will have to manually add a new mapping entry into the web.config file for each item you wish to be accessible via an SEO friendly URL. The entries follow a standard layout though so I’m sure a script could be written which examines your database and outputs the relevant mapping XML code which you could then simply copy and paste into the web.config file, infact I may write one myself over the next week or so if I get the chance. The format itself is shown below.

URL Mappings

As you can see the individual mappings must come between opening and closing tags of the urlMappings element and this element in turn must be included within the system.web element of the configuration file.

Moving on then let’s mention page titles. Not suprisingly ASP.NET provides you with the ability to dynamically change the content of a webpages HTML title tag - you know the one at the top of the browser which Google, Yahoo and MSN love to see your keywords in. It is very important that what’s included in this tag reflects your page content specifically, having something generic just won’t do. When your content is being read from a database (ie - it’s dynamic) the title tag will need to be set dynamically at runtime based on the current content item. There are a number of ways to do this, however the most simple is to access the title property of the HTML header and update it as needed. Before you can access a pages header programatically you have to set it to run on the server side by including the runat=”server” directive in the pages opening HTML head tag. To then access the title tag it is a simple as Header.Title = “new title value”; Of course in a live website you would set Header.Title to some database derived value.

In addition to the pointers above the usual common sense SEO techniques such as good content, good structure and good navigation of course still apply just as they would for any webpage or website, so try not to get completely caught up in the ‘power’ of ASP.NET while at the same time disregarding the cornerstones of SEO as you’ll most likely find yourself stuck in a bit of pickle.

HOME | ABOUT US | CONTACT US | SITEMAP | GOOGLE SITE SEARCH | TOP
12 Lorcan Crescent, Santry, Dublin 9, Ireland +353 87 9807629