HomeASP.NET ASP.NET Custom Server Controls: WordHack C...
ASP.NET Custom Server Controls: WordHack Control
This article introduces you to creating a “WordHack” control, which can hack the words you type within a browser environment and automatically redirect to a website based on the user specified hacking word.
A downloadable file for this article is available here.
The sample downloadable solution (zip) is entirely developed using Visual Studio.NET 2003 Enterprise Architect on Windows Server 2003 Standard Edition. But, I am confident that it would work with other versions of Windows (which support .NET 1.1) as well.
What is this “WordHack” all about?
This is the main question everyone would ask. Before the evolution of the mouse device, everyone liked to type through the keyboard (as it is much smoother than an ordinary typewriter). When the mouse arrived, everyone wanted to work with the mouse (as it is very easy and flexible to work with a GUI). Non-typists (who don’t know any fundamentals of typing) use the mouse, as if it is a point of survival for them. They become very furious if they can't find the mouse, or if the mouse does not work.
Then came "hot keys” (or shortcut keys). I don’t think there exists anybody in this world who does not know about the “Ctrl+C” and “Ctrl+V” key shortcuts. They are famous, even in the post-mouse era. Day by day plenty of shortcut keys are being introduced (or even added) to several applications. Finally, what about the web?
Even a web page has its own way of capturing the shortcut keys using JavaScript code. If you are working with Yahoo!Mail or Gmail, plenty of shortcuts already exist to help you do things faster. Now, why don’t we design our own custom control (in ASP.NET), which can be used to capture the keys the user is typing within a web page? Why not!
This article covers that very topic. I don’t want to introduce very sophisticated methods of capturing keystrokes at the very beginning. We shall increase the sophistication (or complexity) bit by bit within this series of articles. Initially, I start with designing a simple custom control, which captures a particular word typed by the user and automatically redirects to a particular page upon typing it. It would work regardless of any control.
So, for example, if I type “yahoo” blindly on a web page (either in a text box or even on a page without a control), it has to automatically redirect to www.yahoo.com. You may be wondering why we need this! But, you will be astonished to know that one of our clients asked us to implement the acceptance of keyboard based “logout” (regardless of any web page or any control they type) to immediately log out their intranet website. They just wanted to hack the word “logout” (when the user types it) and immediately proceed to the “log out” operation.
At the beginning, I was almost shocked when they told me their requirement. They claimed that it was a simple one! I started crying in my mind about their craziness. We somehow implemented it using JavaScript. They were delighted. Later they explained, almost reasonably, that “typing LOGOUT from keyboard” is much faster than “finding and clicking on logout.” And, of course, later they asked us to implement several other keyboard based “WordHacks.”
I request every reader to consider my apologies in explaining such a big story (without any technical content on this page). But, I hope you have already understood the concept, on which I contributed this article.
So, let us start getting into the details of the “WordHack” control.
As I wanted the “WordHack” control to be as simple as possible, I declared only three properties. Let us see them step by step.
Private ReadOnly Property IsDesignTime() Get Return (Not Me.Site Is Nothing) AndAlso (Me.Site.DesignMode) End Get End Property
It checks whether the control is at the stage of design-time or run-time. This is essential for me to determine whether the control needs to emit required JavaScript or not. During design-time, it is not necessary to emit any JavaScript! It needs to be emitted only at run-time. You also need to observe that the property is “readonly” (no changes) and it is private (can be used only within the class and not outside the class). I used it only within the “Render” method.
Public Property Word2Hack() As String Get Return viewstate("Word2Hack") & "" End Get Set(ByVal Value As String) viewstate("Word2Hack") = Value End Set End Property
The above property is used to specify the word which needs to be hacked (according to my story in the previous section, it would be simply “logout” or “yahoo” or whatever was needed). The above property needs to be assigned to a specific URL. The property that assigns the URL to the word being hacked from the browser has been defined as follows:
Public Property RedirectURL() As String Get Return viewstate("RedirectURL") & "" End Get Set(ByVal Value As String) viewstate("RedirectURL") = Value End Set End Property
It does not directly render, because there exists no separate HTML tag for that. But, indirectly it does render with some sample JavaScript. In my previous examples, I used to define “RenderBeginTag”, “Render”, “RenderEndTag” and several other methods of rendering. In this scenario, as the control would never be displayed on the web page (at runtime), there exists no use for certain methods.
Finally, I came up overriding only two methods from the base class “webcontrol”. They are as follows:
AddAttributesToRender
Render
Even though it is not essential to use the “AddAttributesToRender” method in this case, I just used it to separate the registration of JavaScript code from the “Render” method (of course even “Render” is also not necessary, just used for clarity). Their definitions would be something like the following:
Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter) MyBase.AddAttributesToRender(writer) 'emit javascript only at run-time If Not IsDesignTime Then 'mouse events If Not Page.IsStartupScriptRegistered("WordHack") Then Page.RegisterStartupScript("WordHack", getJS4WordHack()) End If End If
End Sub
Within the above method, I am trying to call the “MyBase.AddAttributesToRender(Writer)” statement to add any design-time attributes to my control. It is not essential for this control in this scenario, but it is a must when we design interactive controls (as explained in my previous articles of the same series).
And you can even observe that I am using the “IsDesignTime” method here. I would like to emit JavaScript code out, if and only if, it is not design time in Visual Studio.NET. I think you can understand the rest. It just involves emitting JavaScript contained in “getJS4WordHack” (which we will see in later sections). Coming to the “Render” method, it is defined as follows:
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) AddAttributesToRender(writer) End Sub
The above method gets executed immediately when the control has to render itself. The only statement I used is the “AddAttributesToRender” statement. This statement calls the above method which actually renders (sends out) only the JavaScript. Not even a single HTML tag gets emitted out of this control (apart from JavaScript) to the client.
Until now, we have seen only the ASP.NET custom control code, but didn’t go through the JavaScript code at all. Now we shall go through the method “getJS4WordHack”.
If Me.Word2Hack.Trim = "" Then Return "" End If
Dim js As String js = "<SCRIPT LANGUAGE=""JavaScript"">"
First of all (from the above code), I am checking whether there exists any “Word2Hack” which has been provided or not. If it is not provided, I simply skip the JavaScript (because there exists nothing to really hack). Once the “Word2Hack” property is assigned to a word (something like “logout”), the JavaScript gets emitted. The above JavaScript mainly captures any key press using the “onkeypress” event of the “document” object. Once any key gets pressed, it executes the “getKey” function which actually checks to see whether the successive key we pressed matches up with “Word2Hack” or not. If so, we immediately redirect it to the value available in the property “RedirectURL”.
That is a special type of class which gets executed when the control is about to be rendered only at design time. It is defined something like the following:
Public Class WordHackDesigner Inherits System.Web.UI.Design.ControlDesigner
Public Overrides Function GetDesignTimeHtml() As String Return "WordHack works only at runtime" End Function End Class
The method “GetDesignTimeHtml” gets executed when our “WordHack” control is dragged from the toolbox onto the web page at design time. As the control does nothing here, and it does not have any properties, we simply return a message.
This class (“WordHackDesigner”) gets linked to our control with the “<Designer>” attribute at class level. The class declaration of our “WordHack” control would be something like the following:
<Designer(GetType(WordHackDesigner)), DefaultProperty("Text"), ToolboxData("< {0}:WordHack runat=server></{0}:WordHack>")> Public Class WordHack Inherits System.Web.UI.WebControls.WebControl
That finishes the matter. Please make sure that all of the ASP.NET controls (in this series) have been tested only with Internet explorer 6.0. I request that you make the necessary modifications to suit your needs of cross browser compatibility. I leave it to the developers to further enhance the same control. The areas of improving the same control would include better eventing, better JavaScript, cross browser support, and so forth. Good luck.
Any comments, suggestions, bugs, errors, feedback etc. are highly appreciated at jag_chat@yahoo.com.