The Basics of Creating Server Controls
page 5 of 7
by Justin Lovell
Feedback
Average Rating: 
Views (Total / Last 10 Days): 57026/ 161

Post Back - Raising Events

Most of the built-in ASP.NET controls can post back to the server to create some changes. Lets take a button for an example - you can listen to the Click event and you will be notified when the button has been clicked by the user. But the event and code resides on the server - so how does ASP.NET execute the code/listeners if HTTP is stateless? The answer is simple - with the aid of JavaScript. If you had to view the source of this very page, you will see a JavaScript function like this:

function __doPostBack(eventTarget, eventArgument) {
   var theform;
   if (window.navigator.appName.toLowerCase().indexOf("microsoft") > -1) {
      theform = document.Form1;
   }
   else {
      theform = document.forms["Form1"];
   }
   theform.__EVENTTARGET.value = eventTarget.split("$").join(":");
   theform.__EVENTARGUMENT.value = eventArgument;
   theform.submit();
}

It tells the server side form (which should be found on every ASP.NET page) to send a POST data request back to the server. But in the process, it assigns two hidden fields with some values:

<INPUT type=hidden name="__EVENTTARGET">
<INPUT type="hidden" name="__EVENTARGUMENT">

Those values contain the server control's identification that ASP.NET has to find to raise the event and a parameter to pass to the server control. The identification is guarantees to be unique - that identification contains the hierarchy location of where the server control is located on the ASP.NET page... or should be. If the server control does not exist, no event is raised on the server control. This may occur if you add controls dynamically to the control collection. Once the server control is located (must be by the end of the Load event of the page), the parameter is passed to the server control. If that server control contains multiple events, that parameter will inform the server control which event to fire.

All server controls that wants to raise events must do three things first (at least):

1. Create an event field

// [C#]
public event EventHander Click;
' [VB.NET]
Event Click As EventHander

2. Create methods to relate to the event field.

It is convenient to name it "OnEventName". Please read the Guidelines page to see all the guidelines.

// [C#]
protected void OnClick(EventArgs e) {
if (Click != null)
Click(e);
}
' [VB.NET]
Protected Sub OnClick(e As EventArgs)
   RaiseEvent Click(Me, e)
End Sub

3. Implement the IPostBackEventHandler interface.

You will also implement its only member to get that parameter that is passed for post back.

// [C#]
public class MyControl : Control, IPostBackEventHandler {
   public void RaisePostBackEvent(string eventArgument) {
      OnClick(EventArgs.Empty);
   }
}
' [VB.NET]
Public Class MyControl
   Inherits Control
   Implements IPostBackEventHandler
  
   Public Sub RaisePostBackEvent(eventArgument As String) _
Implements IPostBackEventHandler.RaisePostBackEvent
      OnClick(EventArgs.Empty)
   End Sub
End Class


Now, ASP.NET is very convenient about creating the JavaScript to call/use that JavaScript function that I discussed briefly about earlier on this page. Here is the two methods that can be utilized to get that client callee statement (used mainly during Rendering):

For demonstration purposes, we will create a control that will render a HTML <a> tag and will post back to the server. We are going to pretend that the Hyperlink control does not exist nor does the LinkButton control; but we know that the Label control does exist (so we can have those styling stuff built-in to Label control). I will put all the control's source down first before explaining what each part does.

// [C#]
public class MyOwnLinkButton : Label, IPostBackEventHandler {
private string clientPostBackScript;
   public event EventHandler Click;
   protected virtual void OnClick(EventArgs e) {
      if (Click != null)
         Click(this, e);
   }
   protected override HtmlTextWriterTag TagKey {
get { return HtmlTextWriterTag.A; }
}
   protected override void OnPreRender(EventArgs e) {
clientPostBackScript = Page.GetPostBackClientHyperlink(this,
String.Empty);
base.OnPreRender(e);
}
   protected override void AddAttributesToRender(HtmlTextWriter writer) {
    writer.AddAttribute(HtmlTextWriterAttribute.Href, clientPostBackScript);
    base.AddAttributesToRender(writer);
   }
   public virtual void RaisePostBackEvent(string eventArgument) {
OnClick(EventArgs.Empty);
}
}
' [VB.NET]
Public Class MyOwnLinkButton
   Inherits Label
   Implements IPostBackEventHandler
   Private clientPostBackScript As String
   Public Event Click As EventHandler
  
   Protected Overridable Sub OnClick(e As EventArgs)
      RaiseEvent Click(Me, e)

   End Sub
  
   Protected Overrides ReadOnly Property TagKey() As HtmlTextWriterTag
      Get
         Return HtmlTextWriterTag.A
      End Get
   End Property
   
   Protected Overrides Sub OnPreRender(e As EventArgs)
      clientPostBackScript = Page.GetPostBackClientHyperlink(Me, [String].Empty)
      MyBase.OnPreRender(e)
   End Sub
  
   Protected Overrides Sub AddAttributesToRender(writer As HtmlTextWriter)
      writer.AddAttribute(HtmlTextWriterAttribute.Href, clientPostBackScript)
      MyBase.AddAttributesToRender(writer)
   End Sub
  
   Public Overridable Sub RaisePostBackEvent(eventArgument As String) _
      Implements IPostBackEventHandler.RaisePostBackEvent
      OnClick(EventArgs.Empty)
   End Sub
End Class

I created my event called “Click”. I then associated a protected, virtual (overridable) method that is associated with the “Click” event, called “OnClick” method. I then implemented the interface, IPostBackEventHandler and its only member, the RaisePostBackEvent method. I made the RaisePostBackEvent method virtual (overridable) to make way for control developers the ability to add further post back functionality if they decide to extend our control. Since that the RaisePostBackEvent method will be called if our control does the post back and since we only have one event, we pass execution flow over to the method associated with the only event called “OnClick”.

In the C# code, the “OnClick” method will then check if the event has any delegates attached to its associated event. The “Click” event will be null, if no delegates are attached. If the event has delegates attached, then the “Click” event is then called as if it was a method. The parameters that are parsed in this calling is defined in the delegate's declaration. I will cover the basics at a latter article in the series.

In the VB.NET code, there is only one way to raise the event and that has to be with the RaiseEvent statement. This statement checks if any delegated methods are attached to the even, and if any are found, the delegated methods will be called.

I also overrode the OnPreRender method so I can do two specific tasks with one line of code (with the GetPostBackClientHyperlink method). These are the tasks that this one-liner does.

  • ASP.NET checks if the post back script block exists in the page. If not, it will register the script block (the script block that is shown at the top of this page).
  • To get the client side script to invoke the script block that was just registered to the page.

You cannot do the above operation completely during the Render event in the life cycle because ASP.NET cannot insert the script blocks as described in the first thing that the one-liner does. We simply save the client side invocation to a private variable and render it out to the client as a Href attribute.

The rest of the code is for the purpose of rendering. The TagKey property determines the enclosing tags of the control. From the Label control, this would default to be a <span> tag. I just changed the enclosing tag to an anchor (the formal word; in other words, a hyper link). The rest of the rendering is automatically done by the Label control itself (and the WebControl class).


View Entire Article

User Comments

Title: How do I put this control on a page?   
Name: G Shields
Date: 2010-07-21 11:53:01 PM
Comment:
Okay, so I have the inherited custom control class. How do I put it in my page?
Title: Need a translator   
Name: Rob
Date: 2009-05-18 2:24:18 PM
Comment:
Overall I found this article helpful, in some places though the English is so bad that it is practically illegible. As a result, I may have missed some of the finer points.
Title: Simply The Great   
Name: Dot Net Lover
Date: 2008-12-18 10:26:30 PM
Comment:
An Excellent Article.
Thanx for writing.
10 out of 10.
Title: Spell check please   
Name: bszom
Date: 2007-05-23 4:33:57 AM
Comment:
Lame-man's terms? Please, this article would be 3x as good had it been spell-checked.
Title: BRILLIANT explanations and structure!   
Name: Magnus B
Date: 2007-01-26 11:56:21 AM
Comment:
Thank you for gathering what I need to know in such a professional and independent page. Just the way I would ;)
Title: Good work   
Name: Narendra S. Jakhotia
Date: 2006-11-07 4:50:52 AM
Comment:
this topic Cleared most of my concepts on creating controls. I need help from U . I want to combine properties of Image button and Label please tell me how can I do it?
If possible please help me out.naren_pict@yahoo.co.in
Title: Excellent Example   
Name: Jayesh Chudasama
Date: 2006-09-01 2:22:23 AM
Comment:
Great Example!! It outlines all basic needs to understand to create server control.
Title: The Basics of Creating Server Controls   
Name: Jan Waiz
Date: 2005-08-04 11:53:17 AM
Comment:
Perfect!
Title: your history on classic ASP   
Name: JP
Date: 2005-08-03 3:42:12 AM
Comment:
You history on Classic ASP is not quite right. Classic ASP supported use of functions and subroutines which allowed code to be placed anywhere in your page. It also supported use of code classes and window script components (WSC). WSC files are components in XML format which did not have to be registered on the server.

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-12-11 8:40:32 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search