When creating a server control from scratch you must implement the IPostBackEventHandler interface if you want the control to handle postback events. If you’re extending an existing control and the control already implements this interface, then you simply need to override the IPostBackEventHandler methods to add your own postback events.
The interface requires that a single method be implemented:
public void RaisePostBackEvent(string eventArgument)
{
// raise control-specific events here
}
RaisePostBackEvent is called on the IPostBackEventHandler control that raised the postback to the server. If an argument was passed to the server during the postback, it will be passed to the eventArgument parameter of the RaisePostBackEvent() method. But how does the server know which control raised the postback and how are any arguments passed back to the page? Let’s take a step back and look at how forms are submitted in HTML/JavaScript and how ASP.NET abstracts this behavior to provide us with the postback.
Submitting a Form
There are two mechanisms by which a form can be submitted to the server: an HTML submit button element or JavaScript. In order to use an HTML submit button, you must add the following markup to your form:
<input type="submit" value="Submit Form" />
This will render a simple button element which will display the text “Submit Form.” When clicked, the button will submit the form back to the server using an HTTP POST request. To do the same in JavaScript you simply need to retrieve the form DOM element and call its submit() function:
function submitForm() {
document.forms[0].submit();
}
This will also cause the form to be submitted back to the server using an HTTP POST request.
ASP.NET Postbacks
The two methods described above are all that is required to create web applications that require any kind of interaction between client and server. ASP.NET provides many different kinds of controls which we can use to post our forms back to the server, but underneath all the layers of abstraction lie those two fundamental mechanisms.
For a page that uses any control except the Button and ImageButton (which we’ll take a look at momentarily), ASP.NET generates a simple JavaScript function and two hidden <input /> elements to handle form submissions:
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
Any time you interact with an ASP.NET control in a way the should cause a postback, this function is called. The two hidden fields, __EVENTTARGET and __EVENTARGUMENT, are used to keep track of the control which caused the postback and any data that should be associated with the control, respectively. These two fields can be access on the server in either the Page.Form or Page.Params collection. The first contains a collection of all form variables posted back to the server, and the second is a combined collection of form variables, query string variables, server variables, and cookies. The following code snippets are identical:
protected void Page_Load(object sender, EventArgs e)
{
var control = Request.Form["__EVENTTARGET"];
var args = Request.Form["__EVENTARGUMENT"];
}
protected void Page_Load(object sender, EventArgs e)
{
var control = Request.Params["__EVENTTARGET"];
var args = Request.Params["__EVENTARGUMENT"];
}
This is how the server knows which control raised the postback and can call its RaisePostBackEvent() method, passing in the __EVENTARGUMENT data to the expected parameter.
The only exceptions to this rule are the Button and ImageButton controls. These controls are rendered as HTML submit button elements and therefore do not require any JavaScript to post the form and its data back to the server. These controls can still be identified when a postback is received by the server because they will be the only Button controls represented in the form collection.
Enabling a Server Control to Cause a Postback
So now that we know how postbacks work in ASP.NET, we need to add this functionality to the control that we want to implement the IPostBackEventHandler interface. After all, if the control doesn’t actually cause a postback, then the functions we implement as a part of that interface will be useless because they will never be called. Lucky for us, adding the client script necessary to cause a postback is pretty easy.
There are really two ways you can force your control to initiate a postback to the server. The first is to simply add a client event handler which fires off the __doPostBack() function, like so:
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
var script = String.Format("__doPostBack('{0}', '');", this.ClientID);
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, script);
base.AddAttributesToRender(writer);
}
Here we’ve overridden the control’s AddAttributesToRender() method and added our own onclick client event handler to call __doPostBack(). I don’t really like this method because it feels clumsy. And remember, if you don’t have any other ASP.NET controls on your page that cause __doPostBack() to be rendered to the page, then you will see JavaScript exceptions when your control tries to call that function.
A better way to add the onclick client event handler would be to use the Page.ClientScriptManager’s GetPostBackEventReference() method:
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Onclick,
Page.ClientScript.GetPostBackEventReference(this, String.Empty));
base.AddAttributesToRender(writer);
}
Not only will this add the event handler for us, but it will also ensure the __doPostBack() function is inserted into our page for us.
Bringing it all Together
Now that we’ve taken a look at how this all works, let’s build a control so we can see these concepts in action. For this example I’m going to extend the Panel control to create a simple ClickablePanel, which will fire off a postback to the server any time a user clicks inside the panel. The class should implement the IPostBackEventHandler interface by defining a RaisePostBackEvent() method. It will also define a single Click event, and will override the Panel’s AddAttributesToRender() method as demonstrated above. Here’s what the implementation should look like:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace MyViewState.Examples.Web.Controls
{
public class ClickablePanel : Panel, IPostBackEventHandler
{
public ClickablePanel()
: base()
{ }
private EventHandler _click;
public event EventHandler Click
{
add { _click += value; }
remove { _click -= value; }
}
protected virtual void FireClickEvent()
{
if (_click != null)
_click(this, new EventArgs());
}
protected override void AddAttributesToRender(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Onclick,
Page.ClientScript.GetPostBackEventReference(this, String.Empty));
base.AddAttributesToRender(writer);
}
public void RaisePostBackEvent(string eventArgument)
{
FireClickEvent();
}
}
}
Now you can add a ClickablePanel to any ASP.NET page or user control and handle its Click event to add your own logic.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="MyViewState.Examples.Web._Default" %>
<%@ Register Assembly="MyViewState.Examples.Web" Namespace="MyViewState.Examples.Web.Controls" TagPrefix="controls" %>
<!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>Example - Implementing IPostBackEventHandler in an ASP.NET Control</title>
</head>
<body>
<form id="form1" runat="server">
<controls:ClickablePanel ID="ClickablePanel" runat="server"
BackColor="Blue"
Height="200px"
Width="400px">
</controls:ClickablePanel>
<asp:Literal ID="litMessage" runat="server" />
</form>
</body>
</html>
using System;
using MyViewState.Examples.Web.Controls;
namespace MyViewState.Examples.Web
{
public partial class _Default : System.Web.UI.Page
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
ClickablePanel.Click += new EventHandler(ClickablePanel_Click);
}
protected void ClickablePanel_Click(object sender, EventArgs e)
{
var message = String.Format("You clicked the panel at {0}.", DateTime.Now.ToLongTimeString());
litMessage.Text = message;
}
}
}
Now when we run this, we'll see the following markup when the page is rendered to the browser:
<!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>
<title>
Example - Implementing IPostBackEventHandler in an ASP.NET Control
</title>
</head>
<body>
<form name="form1" method="post" action="Default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUKMTUzMzI3OTIxNGRkj5tANgOC/iyQIg7/hT+BzVmVUQo=" />
</div>
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
</div>
<div onclick="__doPostBack('ClickablePanel','')" id="ClickablePanel"
style="background-color:Blue;height:300px;width:500px;">
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
</form>
</body>
</html>
Notice the control is rendered as a <div> element with an onclick event handler that calls __doPostBack(). And if we click on the panel, the form is posted back to the server, the Click event is raised, and the message below the panel is updated.

Wrap Up
Implementing an interface with a single method should be a pretty simple task. I went a little overboard describing how to implement the IPostBackEventHandler interface, but hopefully now you have all the why’s and how’s to take with you when building your own ASP.NET server controls. If you’re interested in taking this knowledge even further, then I recommend checking out the IPostBackDataHandler, which you must implement if your control needs to examine any data that is posted back by the client.
