advertisement

Understanding event wire-ups in ASP.NET and Visual Studio

posted by Jeff
Discuss this article   Printer friendly

There are two approaches to making something happen in an ASP.NET page, and if you use Visual Studio .NET, you should know about both.

Every now and then I notice that there's some confusion about how events are wired up in the structure of an ASP.NET page. This confusion is in part caused by the way that Visual Studio .NET adds events and the way that most books teach wiring up events.

The Windows world

To explain the difference, let's first take a step back and look at how a Windows application handles events. The constructor for the form's class makes a call to the InitializeComponent() method, which you'll find in the code region that is collapsed and says "Windows Forms Designer generated code." There is no HTML to describe the location of controls in a Windows form, so the designer generates code for you that describes the control, how it will appear, and what happens when you interact with it. Here's an example for a button control:

this.button1 = new System.Windows.Forms.Button();
this.button1.Location = new System.Drawing.Point(8, 248);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(568, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Generate Key";
this.button1.Click += new System.EventHandler(this.button1_Click);

You'll also find that the button is declared in the class, much in the same way that we declare controls in our code behind classes in ASP.NET:

private System.Windows.Forms.Button button1;

While the properties for the button are different from those in a Web form, this is another case where the properties have to be declared in code and not in the HTML, as we're used to doing. Pay particular attention to the last line, the part where a new event handler is added to the Click event. That last line of code was generated when we double-clicked the button in the form designer and it created an event for us called button1_Click. This line "wires up" the event handler with the event of the control.

In the world of ASP.NET

Now let's look at the Web forms world. Most books on ASP.NET show you how to declare a button control and assign it an event, much like this:

<asp:Button id="RegisterButton" onclick="SendRegistration" runat="server" text="Submit" />

In this example, clicking the button will fire an event called "SendRegistration," and it will look for it either in the page itself or in the code-behind class. The method might look something like this:

public void SendRegistration(object sender, System.EventArgs e)
{
	// do something here
}

Visual Studio however, assumes that you're going to build the page (or user control) just like a Windows application, so it puts AutoEventWireup="false" in your page (or user control) directive. This means that none of the standard page events (Init, Load, PreRender, and UnLoad) will fire unless they're wired up in the generated InitializeComponent() method of the page. (Note: If you import a page into a project that doesn't have this in the directive, Visual Studio will add it for you. If you do this and nothing on the page executes, that's probably why.) If we create a new page and drag a button on to it, then view the code, you'll see something like this (this shows the designer-generated code expanded):

public class TestPage : System.Web.UI.Page
{
	protected System.Web.UI.WebControls.Button Button1;

	private void Page_Load(object sender, System.EventArgs e)
	{
		// Put user code to initialize the page here
	}

	#region Web Form Designer generated code
	override protected void OnInit(EventArgs e)
	{
		//
		// CODEGEN: This call is required by the ASP.NET Web Form Designer.
		//
		InitializeComponent();
		base.OnInit(e);
	}
	
	/// <summary>
	/// Required method for Designer support - do not modify
	/// the contents of this method with the code editor.
	/// </summary>
	private void InitializeComponent()
	{    
		this.Button1.Click += new System.EventHandler(this.Button1_Click);
		this.Load += new System.EventHandler(this.Page_Load);
	}
	#endregion

	private void Button1_Click(object sender, System.EventArgs e)
	{
	
	}
}

The first thing you'll notice is that the class inherits from Page. Nothing new there, but you may not have realized that the Page class has a method called OnInit. The designer overrides this method with its own and calls the InitializeComponent() method (also generated by the designer). That's where the similarity comes to the Windows app. While we don't need to describe all of the physical properties of the control, we do need to wire up the events.

The first line of InitializeComponent() wires up our event handler for the button, and adds it to the click event, just like the Windows form did. In this situation you wouldn't need to specify OnClick="Button1_Click" in the HTML because it's being set here in the code-behind class. The next line wires up Page_Load to the page's Load event. When the page directive in the HTML does not have AutoEventWireup="false" set, this load event happens automatically without any intervention on your part (or the part of the designer).

Who is right?

So which way is "correct?" Certainly the Visual Studio way adds a lot of code. The truth is, there is no right or wrong way, but you'll likely see spirited debate on the subject in various forums, including people asking why you can't turn off the automatic insertion of AutoEventWireup="false" into the page.

On one hand, wiring up events this way further separates the user interface from the code. That's probably one of the single greatest features of ASP.NET and it makes everything more readable. On the other hand, ASP.NET has many declarative programming features that allow you to do things right in the UI without code, including validators (and even DataSource controls in the forthcoming v2.0). That endorsement shows that Microsoft itself doesn't have a clear position on the subject.