ASP.NET provides some very handy magic to map the .NET event model to the web. Normally, we're perfectly happy to let it handle all the details for us. There are those cases, though, where we need to pop the hood and get our hands dirty. I'll outline how ASP.NET events work behind the scenes, then show the two different ways we can work with them outside of the normal event handling patterns.
How ASP.NET Events Work
When you create a control on a page with an event, ASP.NET adds a javascript event handler to the HTML element for that control. The javascript takes a form similar to this:
__doPostBack(control, arguments);
The “control” parameter is the client ID of the control invoking the event. The “arguments” parameter defines the event. It usually just contains the name of the event, e.g. “click” or “selectionChanged”, though sometimes it carries additional contextual data.
When __doPostBack() is called, it sets two hidden form fields: __EVENTTARGET is set to the “control” parameter and __EVENTARGS is set to the “arguments” parameter. It then POSTs the containing <form> (which is why all ASP.NET pages must have a single <form> with runat=”server” on them).
Once the ASP.NET page receives the POST from with the form data, it begins the normal page lifecycle. After it’s loaded, it inspects the __EVENTTARGET value to figure out which control to pass the __EVENTARGS to.
Any control capable of responding to postback events must implement the IPostBackEventHandler interface. The interface contains a method, LoadPostData(eventArgument), which the page will call, passing __EVENTARGS as the eventArgument. From there, the control parses the event argument and performs further processing, which usually consists of firing the associated .NET events.
Generating and Handling ASP.NET Events Without Using .NET Events
It’s possible for you to create and respond to ASP.NET events without using .NET events and handlers. You can generate the events from anywhere, but handling them in such a manner requires that you create a class derived from Control that implements IPostBackEventHandler:
public class MyControl : Control, IPostBackEventHandler
{
public void RaisePostBackEvent(string eventArgument)
{
}
}
Since eventArgument is a string, you can pass whatever arbitrary value you wish. The typical format in ASP.NET is “eventName:extraData”, but there’s no requirement that you follow that format. You can then act on that value in any matter you wish, including firing your own .NET events.
Note that if your class inherits from WebControl (including UserControl), you won’t be able to handle events in this fashion, as WebControl implements IPostBackEventHandler.LoadPostData() as a private method.
To generate an event, you simply need to call __doPostBack() in javascript, passing in a control’s client ID and the appropriate event arguments. ASP.NET also provides a method to generate javascript postback and callback code on the server side: Page.ClientScript.GetPostBackEventReference() and Page.ClientScript.GetCallbackEventReference() respectively. Placing the return value from these methods in the onclick event of an HTML control will allow you to fire your own arbitrary ASP.NET events.
Detecting ASP.NET Outside of the Event Handler
Sometimes you may need to determine what event is being processed outside the event handler, such as in the PageLoad method. Since __doPostBack() creates an event simply by setting form fields, you can determe what control and event by inspecting Request.Form["__EVENTTARGET"] and Request.Form["__EVENTARGS"] respectively.
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(IsPostBack
&& Request.Form["__EVENTTARGET"] == myControl.ClientID
&& Request.Form["__EVENTARGS"].StartsWith("click"))
{
// We know we’re going to end up processing the click event on myControl.
}
}
Please note that this method of detecting events goes contrary to the ASP.NET event handling model and can lead to difficulties in understanding and debugging your code. It’s usually best to find a solution that works within the existing framework when handling events.