Getting Started with ASP.NET (Part 3): Postbacks and Debugging
In the previous two articles, we got an application up and running to display "Hello World" to the world (or at least to our local machine), and then added some C# code behind the scenes to give it some dynamic behavior. At this point, you should be starting to see how much power the developer has using ASP.NET and how quickly it will allow you to create web applications. However, I haven't given you quite enough information for you to work effectively on your own yet.
In this article, we'll look at some advanced use of events. Did you notice that in Part 2, I showed you how to create event handling methods for the default (most commonly used) event associated with a control, but never how to do so for other events? We'll get to that this time. In addition, we'll learn about postbacks (communication with the server that lets us handle events) and debugging with Visual Studio to understand what is happening within our application.
How will we learn this? I'm glad you asked. You're going to learn about these things the way I learned about them: trial by fire. Well, not really, I am going to purposefully lead you into a few problematic situations. Hopefully, this will get you thinking about why we ran into the problem and how to solve the problem. More importantly, it'll teach you to expect it and deal with it when you're creating your own applications. We're going to create a mock Employee Management application, similar to something your Human Resources department might use. Of course, we're going to limit it to some very small functionality: listing employees.
Create a new Web Application project in Visual Studio. If you don't remember how to do this, refer to Getting Started with ASP.NET Part 1. From here on out, you are free to use Source, Design, or Split mode in your IDE, but there will be certain times when one or the other is required. You should probably get used to moving between them, or using Split mode. In the Default.aspx page, drop in a DropDownList and a BulletedList. We'll use the BulletedList to list our employees out, and the DropDownList to filter them. We won't change any of the default properties in our ASPX page, so the markup should look similar to this (yes, I added some labels):
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="PostbacksAndDebugging._Default" %>
< !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></title>
</head>
<body>
<form id="form1" runat="server">
<div>
Filter:
<asp:DropDownList ID="DropDownList1" runat="server">
</asp>
<br />
Employees:<asp:BulletedList ID="BulletedList1" runat="server">
</asp>
</div>
</form>
</body>
</html>
Switch to the C# code in Default.aspx.cs. As we did in the previous article, add some ListItems to the DropDownList's Items collection. In this case, add "Male", "Female", and "Both" to specify the filters that we'll use for our employee list. The goal here is to make it so that when the user makes a selection from this list, we will display only the employees that match those criteria. Since we've already taken discussed the page's Load event, I'll just skip right to showing you what my Page_Load() method looks like:
protected void Page_Load(object sender, EventArgs e)
{
DropDownList1.Items.Add("Male");
DropDownList1.Items.Add("Female");
DropDownList1.Items.Add("Both");
}
This straightforeward code will set up our DropDownList. If we ran the application at this point, we'd see that the list displays our options, but our application is not yet what we set out to create. Create two strings arrays in the page's class to hold the strings that represent employees of different genders. In a "real" application, I'd probably use a List of strings, or some other generic collection. Of course, if this were production code, we'd be using a database instead of simulated data. Let's keep things simple, though. Add some names (strings) to each array, as below.
public partial class _Default : System.Web.UI.Page
{
//Hardcoded data to simulate an employee database
string[] males = {"Robert","Johnathon","William"};
string[] females = {"Linda","Mary","Sarah","Barbara"};
Here's the interesting part. Switch back to Default.aspx and click on DropDownList1 while in Design mode. Take a close look at the Property Editor. Find the "Events" button, represented by a lightning bolt, and click on it.
Visual Studio will now show you the events that are associated with this control. We don't have to worry about most of them now, but do notice that it has a Load event, just like a page. In fact, although these events live in the Control class, the Page class inherits from Control, so pages are controls. Mind blowing, huh? For now, focus on the SelectedIndexChanged event. Since Visual Studio's description of the event is nearly useless, let me tell you that it occurs whenever a different item is selected from the drop down box. Double click in the box next to SelectedIndexChanged to automatically generate a method in the code-behind to handle this event.
In this method, we'll populate the BulletedList to match the filter selected in the DropDownList. Make sense? The code I've written to do this is listed below. It should read fairly easily if you're familiar with C#, but let me walk you through it. The first line of the method clears out any items that are already in the list. We must remember to do this because the event may occur more than once. That is, we must keep in mind the current state of the control which may already have some ListItems. Next, I check to see what value is selected in the DropDownList. Note that I originally wrote code that checked against each possible value ("Male", "Female", and "Both"), but it turns out that the "Both" option shares code with the other two, so I have simplified the conditionals. Based on that value, we loop through the appropriate string array(s) and create ListItems in the BulletedList for each employee. You can copy the code I've written into your code-behind by clicking on the "Copy" button in the top right of the code block.
using System;
namespace PostbacksAndDebugging
{
public partial class _Default : System.Web.UI.Page
{
//Hardcoded data to simulate an employee database
string[] males = {"Robert","Johnathon","William"};
string[] females = {"Linda","Mary","Sarah","Barbara"};
protected void Page_Load(object sender, EventArgs e)
{
//Add filters to the DropDownList
DropDownList1.Items.Add("Male");
DropDownList1.Items.Add("Female");
DropDownList1.Items.Add("Both");
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
//Clear any previous values in the employee list
BulletedList1.Items.Clear();
//List male employees if applicable
if(DropDownList1.SelectedValue!="Female")
foreach(string employee in males)
BulletedList1.Items.Add(employee);
//List female employees if applicable
if (DropDownList1.SelectedValue != "Male")
foreach (string employee in females)
BulletedList1.Items.Add(employee);
}
}
}
So, our code is written and our application should work just fine, right? Let's run it (I shouldn't have to tell you by now, but press CTRL+F5).
Our DropDownList is populated correctly, but nothing appears to happen when we select an item from it. Hmm... I knew this wasn't going to work. This is because we have not triggered a postback with our DropDownList. A postback is when the entire page (by default) is sent back to the server, along with information about whatever event is taking place. Then, the server will make changes and send back HTML, much like when the page is initially loaded. Okay, I played a little trick on you here. DropDownLists don't cause postbacks by default because they are more commonly used simple as form choices, whose values are accessed during other events (like a button click).
However, we can enable postbacks on this control very easily. There is a boolean property of DropDownLists named AutoPostBack, which defaults to false. If we simply set it to true, the control will start causing postbacks and our event handler will run just as we expected. Set this to true using the property editor or the ASPX source.
Now, run the application again and you will see that it is functioning just as we expected.
Well, mostly. The first thing you'll notice is that nothing is shown in the employee list initially, even though "Male" is selected. This is behaving as we programmed it, believe it or not. The event we used was SelectedIndexChanged, so our method is only executed when the user makes a change to the DropDownList. To keep things simply, we're not going to fix that little "bug." You may or may not have noticed the other issue this application has. If not, try to make a second change to the DropDownList. You'll notice that each time our event handler occurs. What's up with that?
We're going to find out, using debugging. Visual Studio possess some powerful debugging tools. I won't get into all of them here - there will be another article that touches on the advanced features, like the Immediate Window. For now, know that debugging allows us to stop our code at each line, before it executes, so we can see what is going on in the application's memory. Why did this if-statement come out true? What numbers are being returned by that new method? Hell, why does our DropDownList have so many extra items? The debugger has your answer.
Switch to Default.aspx.cs. Click the margin next to the Page_Load() method header to place a breakpoint.

A breakpoint is a point in the applications execution that will be intercepted by the debugger. Now, any time the Page_Load() method is called, control will be given to the debugger. Since you control the debugger, this means you are in control of the execution, line by line, and you can find out what's going on. Run the application and see what happens. Whereas we were pressing CTRL+F5 before to Start without debugging, now press F5 to Start with debugging.
Internet Explorer appears, but before any HTML is rendered and sent to the browser, Visual Studio pops back up. The yellow arrow in the left margin shows the current point in the application's execution. None of the lines in the method have been executed yet. Since the page is still loading and we know that the DropDownList populates correctly initially, we expect that each of them will execute correctly. The debugging toolbar will help you control execution.
If the debug toolbar is not displayed in your IDE, enable it by clicking "Debug" on the View -> Toolbars menu, like this:
For now, press the play button (or F5) to return control to the application. Internet Explorer appears and the page is shown. Cause the event to occur by selecting a different item in the DropDownList.
Control will return to the debugger because the Page_Load() method is begin called again. Ah! This will shed some light on our problem. Press the Step Over button (F10) and watch what happens. The calls to DropDownList1.Items.Add() are repeated, even though DropDownList1.Items already contains data. Press F10 a few more times and you will see that the DropDownList1_SelectedIndexChanged() method is then called, as expected.
So, it makes sense that when Page_Load() is called a second (and third, and fourth...) time, the values are added to the DropDownList again, giving us those extra items in the list. But why is Page_Load() being called? The answer is not immediately obvious: the ASP.NET page lifecycle takes place everytime a page is generated, and a page is being generated anew during a postback. In other words, the page is not changing, it is being generated again, and therefore Page_Load() is called.
The fix for this is a simple one. Stop debugging by pressing Shift+F5. In the source code, add a check to the page's IsPostBack property before adding items to the DropDownList, like so:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Add filters to the DropDownList
DropDownList1.Items.Add("Male");
DropDownList1.Items.Add("Female");
DropDownList1.Items.Add("Both");
}
}
There you go! Another run of the application will show that we have fixed this bug, thanks to the debugger showing us what was being executed.
The debugger is a powerful tool. We'll look at advanced debugging, combined with something called tracing in the future to better understand what's going on under the hood of our application. The lesson we learned about postbacks and the Page_Load() method is a useful one. Anytime we expact that postbacks will be occuring on our page, we must take care not to put any initialization code in Page_Load() that would not also be appropriate for a postback, unless we wrap it in the conditional shown above. We have also learned to write event handlers for any event that may be occuring for any control. This is a fundamental skill, because these events are the only points where we can inject our C# code to programmatically control the application. Furthermore, while the standard ASP.NET controls have few events, many third party controls have a very extensive list.
This concludes our three-part series on Getting Started with ASP.NET. I hope that it helps a few of you on your road to rapid application development using the powerful tools provided by ASP.NET, and I'm looking forward to any feedback you have.
Previous article: << Getting Started with ASP.NET Part 2: Code-behind and Events








Subscribe to this category