Friday, July 24, 2009

A Better Mousetrap Textbox

The System.Web.UI.WebControls.Textbox server control is the workhorse of the .Net web application world. It reliably collects user input and dutifully passes it along to its destination.

Through the power of skins, CSS, and markup, it is possible to take this humble control and dress it up, but doing so usually takes development cycles away from perceptibly more important functional requirements of a project. Wouldn't it be nice to have a more visually appealing Textbox control that allowed you to simply drag-and-drop it from the Toolbox on to your form? What if it could also have built-in validators and support for context-sensitive popup help, and all with little or no programming?

I developed Uniinet.Net.Web.UI with the following requirements in mind:

  • Visually appealing and elegantly simple.
  • 100% CSS driven.
  • Easy to use and deploy across multiple projects. This ruled out the use of UserControls and required a custom server control solution.
  • Consistent appearance and behavior across major browsers including: IE, Firefox (Win/Mac), Opera (Win/Mac), Safari (Win/Mac), and Chrome.
  • Built-in context-sensitive popup help.
  • Support "FancyBox" and "RadControls" (available separately) for popup help.
  • Buit-in RequiredField and RegularExpression validators.

Uniinet.Net.Web.UI supports the following common server controls:

  • Uniinet.Net.Web.UI.Textbox
  • Uniinet.Net.Web.UI.TextArea (multi-line Textbox)
  • Uniinet.Net.Web.UI.Dropdown
  • Uniinet.Net.Web.UI.SubmitLocker

Let's take a look at the controls in action, and then I will show you how to use them in your own project. Below is a screenshot of a demo page which illustrates use of the Uniinet.Net.Web.UI server controls. You may click the image or caption below it to see the live demo. Be sure to click the page Submit button so that you can see the built-in validators at work. To see the popup help feature, click on one of the validation error icons.


Live Demo

Now that you've seen what Uniinet.Net.Web.UI can do, let's look at how to use it.

Adding Uniinet.Net.Web.UI To Your Visual Studio Toolbox

First, download the Visual Studio 2008 demo project here: Uniinet.Net.Web.UI.Demo.zip

After you've downloaded the project, you need to extract it. Once extracted, launch Visual Studio 2008 and choose File | Open Web Site... and browse to the directory where you extracted the Uniinet.Net.Web.UI.Demo project to. Click Open to open the specified website, and now you're ready to go! Run the project, experiment with it, and refer to the sources for example usage.

To register the Uniinet.Net.Web.UI component in the Toolbox, right-click in the General area of the Toolbox and select Choose Items... from the popup menu. The Choose Toolbox Items dialog will appear.


Choose Toolbox Items dialog - Before

Click the Browse... button, select the Uniinet.Net.Web.UI.dll assembly in the Bin directory where you previously extracted the project to, and click Open.


Open dialog


Choose Toolbox Items dialog - After

Now the Uniinet.Net.Web.UI server controls will be registered in the Toolbox, allowing you to easily drag-and-drop them into your own projects.


Uniinet.Net.Web.UI added to Toolbox

Quick Start

Begin by creating a Visual Studio .Net web project and creating a new page.

Next, let's take care of a few dependencies. Uniinet.Net.Web.UI relies on the amazing FancyBox for popup help support. FancyBox requires the following stylesheet and Javascript files which can be found where you previously extracted Uniinet.Net.Web.UI.Demo.zip to:

Stylesheets:

  • CSS/Fancy.css

Javascript Files:

  • Scripts/jquery-1.2.3.pack.js
  • Scripts/jquery-1.2.3.pack.js
  • Scripts/jquery-1.2.3.pack.js
  • Scripts/jquery.fancybox-1.0.0.js
  • Scripts/jquery.metadata.js
  • Scripts/jquery.pngFix.pack.js

To link in these dependencies, simply copy-and-paste the following code section into the HEAD of your webform or masterpage (if applicable).

<!--***IMPORTANT - THIS IS REQUIRED BY Uniinet.Net.Web.UI***-->
<!--***FancyBox credited to http://www.fancybox.net***-->
<script src="Scripts/jquery-1.2.3.pack.js" type="text/javascript"></script>
<script src="Scripts/jquery.fancybox-1.0.0.js" type="text/javascript"></script>
<script src="Scripts/jquery.pngFix.pack.js" type="text/javascript"></script>
<script src="Scripts/jquery.metadata.js" type="text/javascript"></script>
<link href="CSS/Fancy.css" rel="stylesheet" type="text/css" media="screen" />
    

Now, let's put a Uniinet.Net.Web.UI control on our page. If you already registered Uniinet.Net.Web.UI in the Toolbox (see instructions above), simply drag-and-drop a Textbox control on your form. Visual Studio will automatically generate the necessary directives and stubs out a basic instance of the Uniinet.Net.Web.UI.Textbox control. Don't forget to update the script and CSS paths if they differ from those shown above.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="Uniinet.Net.Web.UI" Namespace="Uniinet.Net.Web.UI" TagPrefix="uniinet" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Test Page</title>

        <!--***IMPORTANT - THIS IS REQUIRED BY Uniinet.Net.Web.UI***-->
        <!--***FancyBox credited to http://www.fancybox.net***-->
        <script src="Scripts/jquery-1.2.3.pack.js" type="text/javascript"></script>
        <script src="Scripts/jquery.fancybox-1.0.0.js" type="text/javascript"></script>
        <script src="Scripts/jquery.pngFix.pack.js" type="text/javascript"></script>
        <script src="Scripts/jquery.metadata.js" type="text/javascript"></script>
        <link href="CSS/Fancy.css" rel="stylesheet" type="text/css" media="screen" />
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <uniinet:Textbox ID="Textbox1" RunAt="server" Label="Label1" Width="200" />
            </div>
        </form>
    </body>
</html>
    

There is one more step to complete before we run the project. The Uniinet.Net.Web.UI controls need their images and CSS files in order to render properly. The easiest way to provide this is to add a Themes folder to your application and copy the App_Themes\Default\Uniinet.Net.Web.UI folder in the Uniinet.Net.Web.UI.Demo project to your theme folder. If your theme is called "Default" like it is in Uniinet.Net.Web.UI.Demo, then copy it to "Default". Otherwise, copy it to the theme of your choosing.

Now, to wire the theme files up to your page, you need to add the Theme attribute to its @ Page directive as shown below.

<%@ Page Language="C#" AutoEventWireup="true" Theme="Default" CodeFile="Default.aspx.cs" Inherits="_Default" %>
    

That's all there is to it! Run your project and you should see a Uniinet.Net.Web.UI.Textbox control on your page as shown below:


Screenshot

To fully leverage the capabilities of Uniinet.Net.Web.UI, refer to the reference below:

Property Description Usage
InitialValue
(Textbox/TextArea/Dropdown)
Gets/sets the starting value of a Textbox/TextArea or specifies the initially selected index of a Dropdown. This property works in conjuction with the built-in RequiredField validator by allowing a text string other than "empty string" to be treated as a non-value.

If you want a Textbox or TextArea control to have a default value of "Enter a name..." and still have the built-in RequiredField validator to force the user to enter a value, then set the InitialValue property to "Enter a name...".

For Dropdown list controls, you can set the InitialValue to a particular item index, and the RequiredField validator will force the user to select a different value.

Text
(Textbox/TextArea)
Gets/sets the text value of a Textbox/TextArea control. //Set a Textbox value
myTextbox.Text = "This is some sample text.";
MaxLength
(Textbox/TextArea)
Gets/sets the maximum length value that can be handled by the Textbox/TextArea. //Set maximum allowed length to 50 characters.
myTextbox.MaxLength = 50;
Control
(Textbox/TextArea/Dropdown)

Gets the constituent System.Web.UI.WebControls.Textbox control for Uniinet.Net.Web.UI.Textbox and Uniinet.Net.Web.UI.TextArea controls.

Gets the constituent System.Web.UI.WebControls.DropDownList for Uniinet.Net.Web.UI.Dropdown.

//Get constituent Textbox
System.Web.UI.WebControls.Textbox myConstituentTextbox = myTextbox.Control;

//Set a property
myConstituentTextbox.Text = "Some text...";

//Get constituent DropDownList
System.Web.UI.WebControls.DropDownList myConstituentDropDownList = myDropdown.Control;

//Set a property
myConstituentTextbox.SelectedIndex = 1;

Height
(TextArea)
Gets/sets the control height. //Set TextArea height
myTextArea.Height = 100;
Width
(Textbox/TextArea/Dropdown)
Gets/sets the control width. //Set TextArea width
myTextArea.Width = 100;
Label
(Textbox/TextArea/Dropdown)
Gets/sets the label text. //Set the label text
myDropdown.Label = "Colors";
TabIndex
(Textbox/TextArea/Dropdown)
Gets/sets the tab order for the control. //Set the tab index
myTextArea.TabIndex = 2;
ValidatorDisplayType
(Textbox/TextArea/Dropdown)

Gets/sets the validator display type.

  • None - disable built-in validators.
  • Dynamic - use dynamic display.
  • Static - use static display.

//To enable validator, choose Dynamic or Static
myTextbox.ValidatorDisplayType = System.Web.UI.WebControls.ValidatorDisplay.Dynamic;

//To disable validator, choose None
myTextbox.ValidatorDisplayType = System.Web.UI.WebControls.ValidatorDisplay.None;

RequiredFieldValidatorErrorMessage
(Textbox/TextArea/Dropdown)
Gets/set the error message that should be displayed by the built-in required field valididator. The required field validator is disabled unless this property is set. The required field validator is disabled if this property is an empty string. //Set error text
myTextbox.RequiredFieldValidatorErrorMessage = "This is a required field.";
RegularExpressionValidatorValidationExpression
(Textbox/TextArea/Dropdown)
Gets/sets the regular expression to be used by the built-in regular expression validator. The regular expression validator is only enabled if this and the RegularExpressionValidatorError Message property are set. //Only allow 3-digits
myTextbox.RegularExpressionValidatorValidationExpression = "\d{3}";
RegularExpressionValidatorErrorMessage
(Textbox/TextArea/Dropdown)
Gets/sets the error message to be displayed by the built-in regular expression validator. The regular expression validator is only enabled if this and the RegularExpressionValidatorValidationExpression property are set. //Set error text
myTextbox.RegularExpressionValidatorErrorMessage = "Please enter a 3-digit value.";
PopupHelpID
(Textbox/TextArea/Dropdown)
Gets/sets the popup help ID which is passed in the querystring when the popup help page is loaded, which is useful for displaying context-sensitive help. //Set popup help ID myDropdown.PopupHelpID = "10";
PopupHelpPage
(Textbox/TextArea/Dropdown)
Gets/sets the relative or absolute page to display. //Set popup help page
myTextArea.PopupHelpPage = "../Help/AccountManagement/CreateAccount.aspx";
PopupHelpImage
(Textbox/TextArea/Dropdown)
Gets/sets the image to display for popup help. //Set popup help image
myTextArea.PopupHelpImage = "../Images/help.gif";
PopupHelpHeight
(Textbox/TextArea/Dropdown)
Gets/sets the height of the popup help window. //Set popup help window height
myDropdown.PopupHelpHeight = 600;
PopupHelpWidth
(Textbox/TextArea/Dropdown)
Gets/sets the width of the popup help window. //Set popup help window width
myDropdown.PopupHelpWidth = 800;
PopupHelpMode
(Textbox/TextArea/Dropdown)

Gets/sets the popup help mode.

  • None - disable popup help.
  • FancyBox - use FancyBox windows.
  • RadControls - use RadControls windows (not supported in this version).
//Use FancyBox for popup help myTextbox.PopupHelpMode = Uniinet.Net.Web.UI.PopupHelpMode.FancyBox;

I hope you have found Uniinet.Net.Web.UI useful. Please provide comments/feedback, I'll try to work in any changes/improvements in the next release.

Happy coding!

[END_OF_LINE]

Friday, July 3, 2009

Prevent Duplicate Form Submissions Using .Net Server Control

Are trigger-happy users causing you a headache because they repeatedly click the form Submit button, causing your application to create duplicate records, duplicate account registrations, or even worse, duplicate credit card transactions? Wouldn't it be nice if there were a clean and simple way to prevent these duplicate POSTs from occurring, without having to do any messy client-side javascript coding?

Enter SubmitLocker. If you can drop a .Net server control on a Web Form in Visual Studio .Net, you can use SubmitLocker ...it's as easy as that!

Let's begin by taking a look at SubmitLocker in action; doing so will give us a point of reference for the rest of this discussion. Below is a screenshot of a demo page which illustrates use of the SubmitLocker server control. You may click the image or caption below to see the live example.


Live Demo

Once the SubmitLocker demo is loaded by clicking the link above, all you need to do is click the Submit button. When you do so, you should note two things:

  1. The Submit button immediately becomes disabled.
  2. The Submit button caption briefly changes from Submit, to Please wait..., and then back to Submit.

Try as hard as you like, it will be impossible to click the Submit button more than once (as long as javascript is enabled).

By contrast, let's see what would happen if SubmitLocker were not used on this page. To do this, simply uncheck the Enable Locker checkbox - this will disable its functionality. Now, click the Submit button - after a brief delay it will disable. It is disabling because the button's Click event sets the Enabled property to false. If the button disabled without SubmitLocker, then why do we need it?

The need for SubmitLocker becomes apparent when you rapidly click the Submit button multiple times in succession. Notice that with SubmitLocker disabled, you can click it dozens of times before it becomes disabled. This is happening because it takes time for the server-side code in the Click event handler to update the client, disabling the button. During this time, several more postbacks have occurred, and undesirable consequences may result.

The SubmitLocker server control has a few other properties illustrated in the demo.

  • NotifyOnLock (Boolean) - Displays a javascript alert when lock occurs.
  • LockText (String) - The text to display as the target button's caption when lock occurs.

You may play with the settings on the demo to see how they work. Try checking the NotifyOnLock option, entering Busy as the LockText text, and then clicking Submit.

Setup Your Own Local Demo Project

The following instructions will help you set up a local Visual Studio 2008 version of the SubmitLocker demo (should work with VS 2005 as well).

First, download the Visual Studio 2008 project here: Uniinet.Net.Web.SubmitLocker.Demo.zip

After you've downloaded the project, you need to extract it. Once extracted, launch Visual Studio 2008 and choose File | Open Web Site... and browse to the directory where you extracted the SubmitLocker project to. Click Open to open the specified website, and now you're ready to go! Run the project, experiment with it, and refer to the sources for example usage.

To register the SubmitLocker component in the Toolbox, right-click in the General area of the Toolbox and select Choose Items... from the popup menu. The Choose Toolbox Items will appear.


Choose Toolbox Items dialog - Before

Click the Browse... button, select the Uniinet.Net.Web.UI.dll in the Bin directory where you previously extracted the project to, and click Open.


Open dialog


Choose Toolbox Items dialog - After

Now the SubmitLocker server control will be registered in the Toolbox, allowing you to easily drag-and-drop it into your own projects.


SubmitLocker added to Toolbox

I've used SubmitLocker on many projects and have found it quite handy. Remember, it relies on client-side scripting to work, so you should not rely on it to the exclusion of server-side measures.

Happy coding!

[END_OF_LINE]

Wednesday, July 1, 2009

C# Class Template - Coding with Style

Quality in programming is usually measured in terms of the end, not the means. That is, as long as an application, component, or services meets its functional requirements, the code is deemed "good enough". But what about best practices and coding style? Why can't code meet its expectations cosmetically, as well as functionally?

The following template provides a simple yet effective structural layout for a C# class. It contains place holders for most of the common elements of a C# class and should greatly improve the readability and maintainability of your code. And last, but not least, there will be perception of quality and craftsmanship to your code that goes beyond bits and bytes, inspiring confidence in both the developer and the developed.


Screenshot of C# Class Template

Following is an enumeration of the code sections contained in the template:

  • Class Variables
  • Constants
  • Constructors
  • Delegates
  • Destructors
  • Enumerations
  • Events
  • Fields
  • Indexers
  • Methods
  • Operators
  • Property Accessors
  • Private Structures
  • Private Classes

Use the link below to download the C# class template. If you have a comment or suggestion about code templates that you would like to share, please reply to this post.

Download: CSharpCodeTemplate.txt

Happy coding!

[END_OF_LINE]