One of the biggest differences between classic ASP and ASP.NET is the execution model. In classic ASP, pages were executed in a top-to-bottom fashion. In other words, with the exception of detours to execute functions defined in the page, classic ASP pages were procedural rather than event-driven, like Visual Basic programs.
ASP.NET changes that by bringing event-driven programming to Web development through server controls and postbacks. At runtime, the code in a Web Form, as well as in any code-behind class associated with that Web Form, is compiled into an assembly. When executed, the code in that assembly fires events that you can handle—both those exposed by the Page class and those that are fired by server controls that have been added to the page.
Some events, such as those fired by the page, are fired automatically as certain stages of page processing occur. Others, such as those associated with server controls, are actually triggered on the client (such as a user clicking a button server control) but are fired and handled on the server when the page is posted back to the server. Because the page is reloaded and the control state is restored with each postback, to the client it appears as though the page is there throughout the client’s interaction with it, and the application appears to operate much like a Visual Basic form–based application.
Each stage in the processing of a Web Forms page fires an event that allows you to perform processing of your own during that stage. While you might not have realized it, you’ve already learned how to take advantage of these event handlers in your own pages. When you double-click an empty area of a Web Form in Design view, the IDE opens the code-behind module for the Web Form and places the cursor in the Page_Load event handler, which is added to the code- behind module when the Web Form (and its associated code-behind module) is added to the project. By default, Visual Studio .NET also adds a handler for the Page_Init event to the code-behind module, but this event handler is hidden using the # Region…#End Region keywords. The following illustration shows the code contained within the Web Form Designer Generated Code region in CompoundProgrammatic.aspx.cs:
private void Page_UnLoad(object sender, System.EventArgs e // Event handling cod }
Of course, you can also handle events if you’re not using code-behind by adding the appropriate event handler to a server-side script block within the .aspx page:
<script runat="server"> public void Page_Load(object sender, System.EventArgs e // Event handling cod </script>
The preceding code assumes that the AutoEventWireup attribute of the page has been set to true. For pages created outside of Visual Studio .NET, you won’t need to set this attribute manually, since true is the default setting inherited from the <pages> configuration section in Machine.config. However, pages created in Visual Studio .NET have the AutoEventWireup attribute in their @ Page directive set to false. This means that all event handlers in these pages must be manually wired to the events that they are to handle. You’ll learn more about manually wiring events in Chapter 8.
As with events exposed by the Page class, you’ve already seen many examples of handling control events in this and other chapters. Handling the default event for a given control is as simple as double-clicking the control in Visual Studio .NET’s Design view. Visual Studio .NET then takes care of adding the appropriate event handler to the code-behind module for the page, and wiring it up using the Handles keyword. For example, if you were to double-click the DropDownList control in the Compound.ascx control in Design view, Visual Studio .NET would add the following code to Compound.aspx.cs:
You can add handlers for other events associated with a control by using similar syntax. When writing the event handler in code-behind, it doesn’t matter what you name the event-handling procedure, as long as you properly add the event handler, like Visual Studio .NET does when it adds the Page_Load handler to the InitializeComponent event handler, as in this example:
this.Load += new System.EventHandler(this.Page_Load);
Still, it’s a good idea to stick with the naming convention of ControlName_EventName, as this makes it easy to tell at a glance which control and event a given procedure is handling.
When adding event handlers in a code-behind module, an easy way to make sure that your code is correct is to use the drop-down list boxes at the top of the code editor window. Simply select the control whose event you want to handle in the left-hand drop-down list, and then select the event you want to handle from the right-hand drop-down list (events are denoted by a lightning-bolt icon). Visual Studio .NET will automatically insert the code for the event handler into your code-behind module.
Handling control events in pages that do not use code-behind is fairly straightforward. There are two steps: First, add an event handler procedure to a server-side script block in the page. Then, map the event raised by the control to the event handler using an attribute on the control tag.
For example, if you wanted to handle the Click event of a Button control named Button1, you would add the following code to the <script> block in ServerControls.aspx:
public void Button1_Click(object Sender,System.EventArgs e // Event handler cod }
And then you would add the following attribute to the Button1 server control tag:
<asp:Button id="Button1" onClick="Button1_Click" runat="server"/>
Again, you are not required to name the event handler procedure with the ControlName_EventName naming convention, but using this convention will make your code easier to read.
While using structured exception handling might be useful for catching exceptions that are expected (see Chapter 3), at times you’ll want to handle errors at the page level. This is possible through a special event handler called Page_Error. The Page_Error event is raised whenever a page encounters an unhandled exception. Within the Page_Error event handler, you can examine the exception that occurred by using the Server.GetLastError method and take appropriate action or display a friendly message to the user.