As you learned at the end of the
last chapter, one of the great things about ASP.NET is that we can pick and
choose which of the various .NET languages we like. In this chapter, we’ll
look at some key programming principles using our two chosen languages, VB.NET
and C#. We’ll start off with a run-down of some basic programming concepts
as they relate to ASP.NET using both languages. We’ll introduce programming
fundamentals such as control and page events, variables, arrays, functions,
operators, conditionals, and loops. Next, we’ll dive into namespaces
and address the topic of classes—how they’re exposed through namespaces,
and which you’ll use most often.
The final sections of the chapter cover some of the ideas underlying
modern, effective ASP.NET design, starting with that of code-behind and the
value it provides by helping us separate code from presentation. We finish
with an examination of how object-oriented programming techniques impact the
ASP.NET developer.
Programming Basics
One of the building blocks of an ASP.NET page is the application logic:
the actual programming code that allows the page to function. To get anywhere
with this, you need to grasp the concept of events. All
ASP.NET pages will contain controls, such as text boxes, check boxes, lists,
and more, each of these controls allowing the user to interact with it in
some way. Check boxes can be checked, lists can be scrolled, items on them
selected, and so on. Now, whenever one of these actions is performed, the
control will raise an event. It is by handling these events with code that
we get our ASP.NET pages to do what we want.
For instance, say a user clicks a button on an ASP.NET page. That button
(or, strictly, the ASP.NET Button control) raises an event
(in this case it will be the Click event). When the ASP.NET
runtime registers this event, it calls any code we have written to handle
it. We would use this code to perform whatever action that button was supposed
to perform, for instance, to save form data to a file, or retrieve requested
information from a database. Events really are key to ASP.NET programming,
which is why we’ll start by taking a closer look at them. Then, there’s
the messy business of writing the actual handler code, which means we need
to check out some common programming techniques in the next sections. Specifically,
we’re going to cover the following areas:
Control events and handlers
Page events
Variables and variable declaration
Arrays
Functions
Operators
Conditionals
Loops
It wouldn’t be practical, or even necessary, to cover all aspects
of VB.NET and C# in this book, so we’re going to cover enough to get
you started, completing the projects and samples using both languages. Moreover,
I’d say that the programming concepts you’ll learn here will be
more than adequate to complete the great majority of day-to-day Web development
tasks using ASP.NET.
Control Events and Subroutines
As I just mentioned, an event (sometimes more than one) is raised, and
handler code is called, in response to a specific action on a particular control.
For instance, the code below creates a server-side button and label. Note
the use of the OnClick attribute on the Button control:
When the button is clicked, it raises the Click event,
and ASP.NET checks the OnClick attribute to find the name
of the handler subroutine for that event. Here, we tell ASP.NET to call the btn1_Click() routine.
So now we have to write this subroutine, which we would
normally place within a code declaration block inside the <head> tag, like this:
Example 3.2. ClickEvent.aspx (excerpt)
<head>
<script runat="server" language="VB">
Public Sub btn1_Click(s As Object, e As EventArgs)
lblMessage.Text = "Hello World"
End Sub
</script>
</head>
This code simply sets a message to display on the label that we also
declared with the button. So, when this page is run and users click the button,
they’ll see the message "Hello World" appear next to it.
I hope you can now start to come to grips with the idea of control events
and how they’re used to call particular subroutines. In fact, there
are many events that your controls can use, some of which are only found on
certain controls—not others. Here’s the complete set of attributes
the Button control supports for handling
events:
OnClick
As we’ve seen, the subroutine indicated by this attribute
is called for the Click event, which occurs when the user
clicks the button.
OnCommand
As with OnClick, the subroutine indicated by this
attribute is called when the button is clicked.
OnLoad
The subroutine indicated by this attribute is called when the button
is loaded for the first time—generally when the page first loads.
OnInit
When the button is initialized, any subroutine given in this attribute
will be called.
OnPreRender
We can run code just before the button is rendered, using this attribute.
OnUnload
This subroutine will run when the control is unloaded from memory—basically,
when the user goes to a different page or closes the browser entirely.
OnDisposed
This occurs when the button is released from memory.
OnDataBinding
This fires when the button is bound to a data source.
Don’t worry too much about the intricacies of all these events
and when they happen; I just want you to understand that a single control
can produce a number of different events. In the case of the Button control,
you’ll almost always be interested in the Click event,
as the others are only useful in rather obscure circumstances.
When a control raises an event, the specified subroutine (if there is
one) is executed. Let’s now take a look at the structure of a typical subroutine
that interacts with a Web control:
Public Sub mySubName(s As Object, e As EventArgs)
' Write your code here
End Sub
public void mySubName(Object s, EventArgs e) {
// Write your code here
}
Let’s break down all the components that make up a typical subroutine:
Public, public
Defines the scopeof the subroutine. There are
a few different options to choose from, the most frequently used being Public (for
a global subroutine that can be used anywhere within the entire page) and Private (for
subroutines that are available for the specific class only). If you don’t
yet understand the difference, your best bet is to stick with Public for
now.
Sub, void
Defines the chunk of code as a subroutine. A subroutine is a named block
of code that doesn’t return a result; thus, in C#, we use the void keyword,
which means exactly that. We don’t need this in VB.NET, because the Sub keyword
already implies that no value is returned.
mySubName(…)
This part gives the name we’ve chosen for the subroutine.
s As Object, Object
s
When we write a subroutine that will function as an event handler, it
must accept two parameters. The first is the control that generated the event, which is an Object.
Here, we are putting that Object in a variable named s (more
on variables later in this chapter). We can then access features and settings
of the specific control from our subroutine using the variable.
e As EventArgs, EventArgs
e
The second
parameter contains certain information specific to the event that was raised.
Note that, in many cases, you won’t need to use either of these two
parameters, so you don’t need to worry about them too much at this stage.
As this chapter progresses, you’ll see how subroutines associated
with particular events by the appropriate attributes on controls can revolutionize
the way your user interacts with your application.
Page Events
Until now, we’ve
considered only events that are raised by controls. However, there is another
type of event—the page event. The idea is the
same as for control events[3], except that here, it is the page as a whole that generates the
events. You’ve already used one of these events: the Page_Load event.
This event is fired when the page loads for the first time. Note that we don’t
need to associate handlers for page events the way we did for control events;
instead, we just place our handler code inside a subroutine with a preset
name. The following list outlines the page event subroutines that are available:
Page_Init
Called when
the page is about to be initialized with its basic settings
Page_Load
Called once
the browser request has been processed, and all of the controls in the page
have their updated values.
Page_PreRender
Called once
all objects have reacted to the browser request and any resulting events,
but before any response has been sent to the browser.
Page_UnLoad
Called when
the page is no longer needed by the server, and is ready to be discarded.
The order in which the events are listed above is also the order in
which they’re executed. In other words, the Page_Init event
is the first event raised by the page, followed by Page_Load, Page_PreRender,
and finally Page_UnLoad.
The best way to illustrate the Page_Load event is
through an example:
Example 3.4. PageEvents.aspx (excerpt)
<html>
<head>
<script runat="server" language="VB">
Sub Page_Load(s As Object, e As EventArgs)
lblMessage.Text = "Hello World"
End Sub
</script>
</head>
<body>
<form runat="server">
<asp:Label id="lblMessage" runat="server" />
</form>
</body>
</html>
You can see that the control on the page does not specify any event
handlers. There’s no need, because we’re using the special Page_Load subroutine,
which will be called when the page loads. As the page loads, it will call
the Page_Load routine, to display “Hello World”
in the Label control, as shown in Figure 3.1.
Figure 3.1. The Page_Load event is raised, the subroutine is called, and the code
within the subroutine is executed.
Variables and Variable Declaration
Variables are fundamental
to programming, and you’ve almost certainly come across the term before.
Basically, they let you give a name, or identifier,
to a piece of data; we can then use that identifier to store, modify, and
retrieve the data.
However, there are, of course, many different kinds of data, such as strings, integers (whole numbers), and floating point
numbers (fractions or decimals). Before you can use a variable in VB.NET or
C#, you must specify what type of data it can contain, using keywords such
as String, Integer, Decimal,
and so on, like this:
Dim strName As String
Dim intAge As Integer
string strName;
int intAge;
These lines declare
what type of data we want our variables to store, and are therefore known
as variable declarations. In VB.NET, we use the keyword Dim, which stands for “dimension”,
while in C#, we simply precede the variable name with the appropriate data
type.
Sometimes, we want to set an initial value for variables that we declare;
we can do this using a process known as initialization:
Dim strCarType As String = "BMW"
string strCarType = "BMW";
We can also declare and/or initialize a group of variables of the same
type all at once:
Dim strCarType As String, strCarColor = "blue", strCarModel
Table 3.1 below lists the most useful data types available
in VB.NET and C#.
Table 3.1. A List of the Commonly Used Data Types
VB.NET
C#
Description
Integer
int
Whole numbers in the range -2,147,483,648 to 2,147,483,647.
Decimal
decimal
Up to 28 decimal places. You’ll use decimal most often when dealing
with costs of items.
String
string
Any text value.
Char
char
A single character (letter, number, or symbol).
Boolean
bool
True or false.
Object
Object
In .NET, all types are ultimately a type of object, and so variables
of this type can hold just about any kind of data.
There are many more data types that you may encounter as you progress,
but this list provides an idea of the ones you’ll use most often.
So, to sum up, once you’ve declared a variable as a given type,
it can only hold data of that type. You can’t put a string into an integer
variable, for instance. However, there are frequently times when you’ll
need to convert one
data type to another. Have a look at this code:
Dim intX As Integer
Dim strY As String = "35"
intX = strY + 6
int intX;
String strY = "35";
intX = strY + 6;
Now, while you or I might think that this could make sense—after
all, the string strYdoes contain
a number, so we may well wish to add it to another number—the computer
will not be happy, and we’ll get an error. What we have to do is explicitly
convert, or cast, the string into an integer first:
Dim intX As Integer
Dim strY As String = "35"
intX = Int32.Parse(strY) + 6
Now, the computer will be happy, as we’ve told it that we want
to turn the string into an integer before it’s used as one. This same
principle holds true when mixing other types in a single expression.
Arrays
Arrays are a special
variety of variable tailored for storing related items of the same data type.
Any one item in an array can be accessed using the array’s name, followed
by that item’s position in the array (its offset).
Let’s create a sample page to show what I mean:
Example 3.6. Arrays.aspx
<html>
<head>
<script runat="server" language="VB">
Sub Page_Load()
' Declare an array
Dim drinkList(4) As String
' Place some items in it
drinkList(0) = "Water"
drinkList(1) = "Juice"
drinkList(2) = "Soda"
drinkList(3) = "Milk"
' The line below accesses an item in the array by its position
lblArrayList.Text = drinkList(1)
End Sub
</script>
</head>
<body>
<form runat="server">
<asp:Label id="lblArrayList" runat="server"/>
</form>
</body>
</html>
Example 3.7. Arrays.aspx
<html>
<head>
<script runat="server" language="C#">
void Page_Load() {
// Declare an array
String[] drinkList = new String[4];
// Place some items in it
drinkList[0] = "Water";
drinkList[1] = "Juice";
drinkList[2] = "Soda";
drinkList[3] = "Milk";
// The line below accesses an item in the array by its position
lblArrayList.Text = drinkList[1];
}
</script>
</head>
<body>
<form runat="server">
<asp:Label id="lblArrayList" runat="server"/>
</form>
</body>
</html>
There are some important points to pick up from this code. First,
notice how we declare an array. In VB.NET, it looks like a regular declaration
for a string, except that the number of items we want the array to contain
is given in brackets after the name:
Example 3.8. Arrays.aspx(excerpt)
Dim drinkList(4) As String
In C#, it’s a little different. First, we declare that drinkList is
an array by following the datatype with two empty square brackets. We must
then specify that this is an array of four items, using the new keyword:
Example 3.9. Arrays.aspx(excerpt)
String[] drinkList = new String[4];
A crucial point to realize here is that the arrays in both C# and VB.NET
are what are known as zero-basedarrays. This means that the first item actually
has position 0, the second has position 1, and so on, through to the last
item, which will have a position that’s one less than the size of the
array (3, in this case). So, we specify each item in our array like this:
Notice that C# uses square brackets for arrays, while VB.NET uses standard
parentheses. We have to remember that arrays are zero-based when we set the
label text to the second item, as shown here:
Example 3.12. Arrays.aspx (excerpt)
lblArrayList.Text = drinkList(1)
Example 3.13. Arrays.aspx(excerpt)
lblArrayList.Text = drinkList[1];
To help this sink in, you might like to try changing this code to show
the third item in the list instead of the second. Can you work out what change
you’d need to make?
That’s right—you only need to change the number given in
the brackets to match the position of the new item (don’t forget to
start at zero). In fact, it’s this ability to select one item from a
list using only its numerical location that makes arrays so useful in programming,
as we’ll see as we get further into the book.
Functions
Functionsare exactly the same as subroutines, but for one key difference:
they return a value. In VB.NET, we declare a function using the Function keyword
in place of Sub, while, in C#, we simply have to specify
the return type in place of using void. The following code
shows a simple example:
Example 3.14. Functions.aspx
<html>
<head>
<script runat="server" language="VB">
' Here's our function
Function getName() as String
Return "Zak Ruvalcaba"
End Function
' And now we'll use it in the Page_Load handler
Sub Page_Load(s As Object, e As EventArgs)
lblMessage.Text = getName()
End Sub
</script>
</head>
<body>
<form runat="server">
<asp:Label id="lblMessage" runat="server" />
</form>
</body>
</html>
Example 3.15. Functions.aspx
<html>
<head>
<script runat="server" language="C#">
// Here's our function
string getName() {
return "Zak Ruvalcaba";
}
// And now we'll use it in the Page_Load handler
void Page_Load() {
lblMessage.Text = getName();
}
</script>
</head>
<body>
<form runat="server">
<asp:Label id="lblMessage" runat="server" />
</form>
</body>
</html>
Figure 3.2. The Page_Load event is raised, the function is called,
and the code within the function is executed.
Here’s what’s happening: the line in our Page_Load subroutine
calls our function, which returns a simple string that we can then assign
to our label. I hope this illustrates what functions are about and how you
can use them. In this simple example, we’re merely returning a fixed
string (my name), but the function could just as well retrieve the name from
a database—or somewhere else. The point is that, regardless of how the
function gets its data, we use it (that is, call it) in just the same way.
When we’re
declaring our function, we must remember to specify the correct return
type. Take a look at the following code:
' Here's our function
Function addUp(x As Integer, y As Integer) As Integer
Return x + y
End Function
' And now we use it in Page_Load
Sub Page_Load(s As Object, e As EventArgs)
lblMessage.Text = addUp(5, 5).ToString()
End Sub
// Here's our function
int addUp(int x, int y) {
return x + y;
}
// And now we use it in Page_Load
void Page_Load() {
lblMessage.Text = Convert.ToString(addUp(5, 5));
}
You can easily adapt the previous example to use this new code and see
the results in your browser.
Have a look at this code, and see if you can spot what’s different
and why. The first thing you might notice is that our function now accepts parameters.
Any function or subroutine can take any number of parameters, each of any
type (there’s no need for parameter types to match the return type—that’s
just coincidental in this example).
We can then readily use the parameters inside the function or subroutine
just by using the names we gave them in the function declaration (here, we’ve
chosen x and y, but we could have chosen
different names).
The other difference between this and the function declaration we had
before is that we now declare our function with a return type of Integer or int,
rather than String, because we want it to return a whole
number.
When we now call the new function, we simply have to specify the required
number of parameters, and remember that the function will return a value with
the type we specified. In this case, that means we have to convert the integer value it returns to a string,
so we can assign it to the label.
In VB.NET, we tack .ToString() onto the end of the function call, while in C#
we use the Convert.ToString(…). Note the differences
in how these two methods are used—converting numbers to strings is a
very common task in ASP.NET, so it’s good to get a handle on it early.
Don’t be too concerned if you’re a little confused by how these
conversions work, though—the syntax will become clear once we discuss
the object oriented concepts involved later in this chapter.
Again, a complete discussion of functions could take up an entire chapter,
but I hope the brief examples here are enough to prepare you for what we’re
going to cover in future chapters. Don’t worry too much if you’re
still a bit unsure what functions and subroutines are all about right now—they’ll
become second nature very quickly.
Operators
Throwing around values with variables and functions
isn’t much use unless you can use them in some meaningful way, and to
do this we use operators. An operator is a symbol that
has a certain meaning when applied to values. Don’t worry—they’re
nowhere near as scary as they sound! In fact, in the last example, when our
function added two numbers, we were using an operator—the addition
operator, +. Most of the other available operators
are just as well known, although there are one or two that will probably be
new to you. Table 3.2 outlines the operators that you’ll
use most often.
Table 3.2. ASP.NET Operators
VB.NET
C#
Description
>
>
greater than
>=
>=
greater than or equal to
<
<
less than
<=
<=
less than or equal to
<>
!=
not equal to
=
==
equals
=
=
assigns a value to a variable
Or
||
or
And
&&
and
&
+
concatenate strings
New
New
create object or array
*
*
multiply
/
/
divide
+
+
add
-
-
subtract
The following code uses some of these operators:
If (user = "Zak" And itemsBought <> 0) Then
lblMessage.Text = "Hello Zak! Do you want to proceed to " & _
"checkout?"
End If
if (user == "Zak" && itemsBought != 0) {
lblMessage.Text = "Hello Zak! Do you want to proceed to " +
"checkout?";
}
Here, we use the equality, inequality (not equals to) and logical ‘and’
operators in an If statement to print a message only for
a given user, and only when he or she has bought something. Of particular
note is C#’s equality operator, ==,
which is used when comparing two values to see if they are equal. Don’t
use a single equals sign in C# unless you are assigning a value to a variable,
or your code will have a very different meaning than you expect!
Breaking Long Lines of Code
Since the message string in the above example was too
long to fit on one line in this book, I also used the string concatenation
operator to combine two shorter strings on separate lines to form the complete
message. In VB.NET, I also had to break one line of code into two using the
line continuation symbol (_, an underscore at the end of
the line to be continued). Since C# marks the end of each command with a semicolon
(;), I can split a single command over two lines without
having to do anything special.
I’ll use these techniques throughout this book to show long lines
of code within a limited page width. Feel free to recombine the lines in your
own code if you like—there is no actual length limit on lines of code
in VB.NET and C#.
Conditional Logic
As you develop
ASP.NET applications, there will be many instances in which you’ll need
to perform an action only if a certain condition is met, for instance, if
the user has checked a certain checkbox, selected a certain item from a DropDownList control,
or typed a certain string into a TextBox control.
We check for such things using conditionals,
the simplest of which is probably the If statement. This statement is often
used in conjunction with an Else statement, which specifies
what should happen if the condition is not met. So, for instance, we may wish
to check if the name entered in a text box is "Zak,"
redirecting to one page if it is, or else redirecting
to an error page:
If (txtUsername.Text = "Zak") Then
Response.Redirect("ZaksPage.aspx")
Else
Response.Redirect("errorPage.aspx")
End If
Often, we want to check for one of many possibilities, and perform a
particular action in each case. In that event, we can use theSwitch Case (VB.NET)
or switch (C#) construct:
Dim strName As String = txtUsername.Text
Select Case strName
Case "Zak"
Response.Redirect("ZaksPage.aspx")
Case "Mark"
Response.Redirect("MarksPage.aspx")
Case "Fred"
Response.Redirect("FredsPage.aspx")
Case Else
Response.Redirect("errorPage.aspx")
End Select
string strName = txtUsername.Text;
switch (strName) {
case "Zak":
Response.Redirect("ZaksPage.aspx");
break;
case "Mark":
Response.Redirect("MarksPage.aspx");
break;
case "Fred":
Response.Redirect("FredsPage.aspx");
break;
default:
Response.Redirect("errorPage.aspx");
break;
}
Loops
As you’ve just seen, an If statement causes
a code block to execute once if the value of its test expression is true.
Loops, on the other hand, cause a code block to execute repeatedly for as
long as the test expression remains true. There are two basic kinds of loop:
While loops, also called Do loops,
which sounds like something Betty Boop might say!
For loops, including For Next and For
Each
A While loop is the simplest form of loop; it makes
a block of code repeat for as long as a particular condition is true. Here’s
an example:
Dim Counter As Integer = 0
Do While Counter <= 10
' Convert out Integer to a String
lblMessage.Text = Counter.ToString()
' Below we use the += operator to increase our variable by 1
Counter += 1
Loop
int counter = 0;
while (counter <= 10) {
// Below we use a sneaky way to convert our int to a string
lblMessage.Text = counter + "";
// C# has the operator ++ to increase a variable by 1
counter++;
}
You can try out this code—enter it inside a Page_Load subroutine
of one of the pages you’ve already created. The page illustrating Page_Load at
the start of this chapter would be ideal. Make sure you remove any other code
in the subroutine, and that there is an ASP.NET Label control
in the HTML of the page with the ID lblMessage. When you
open the page, the label will be set to show the number 0, then 1, then 2,
all the way to 10. Of course, since all this happens in Page_Load (i.e.
before any output is sent to the browser), you’ll only see the last
value assigned, 10.
This demonstrates that the loop repeats until the condition is no longer
met. Try changing the code so that the counter variable is initialized to
20 instead of 10. When you open the page now, you won’t see anything on
screen, because the loop condition was never met.
There is another form of the While loop, called a Do
While loop,
which checks if the condition has been met at the end of
the code block, rather than at the beginning:
Dim Counter As Integer = 0
Do
' Convert our Integer to a String
lblMessage.Text = Counter.toString()
' Below we use the += operator to increase our variable by 1
Counter += 1
Loop While Counter <= 10
int counter = 0;
do {
// Below we use a sneaky way to convert our int to a string
lblMessage.Text = counter + "";
// C# has the operator ++ to increase a variable by 1
counter++;
} while (counter <= 10);
If you run this code, you’ll see it provides the exact same output
we saw when we tested the condition before the code block. However, we can
see the crucial difference if we again change it so the counter variable is
initialized to 20. In this case, we will, in fact, see 20 on screen, because
the loop code is executed once before the condition is even checked! There
are some instances when this is just what we want, so being able to place
the condition at the end of the loop can be very handy.
A Forloop
is similar to a While loop, but is typically used when
the number of times we need it to execute is known beforehand. The following
example displays the count of items within a DropDownList control
called ddlProducts:
Dim i As Integer
For i = 1 To ddlProducts.Items.Count
lblMessage.Text = i.toString()
Next
int i;
for (i = 1; i <= ddlProducts.Items.Count; i++) {
lblMessage.Text = Convert.ToString(i);
}
In VB.NET, the loop syntax specifies the starting and ending values
for our counter variable in the For statement itself. In
C#, we assign a starting value (i = 1), a condition to
be tested each time through the loop, just like a While loop
(i <= ddlProducts.Items.Count), and how the counter
variable should be incremented after each loop (i++).
While this allows for some powerful variations on the theme in C#, it can
be confusing at first. In VB.NET, the syntax is considerably simpler, but
can be a bit limiting in exceptional cases.
The other type of For loop is For Each, which loops
through every item within a collection. The following example loops through
an array called arrayName:
For Each item In arrayName
lblMessage.Text = item
Next
foreach (string item in arrayName) {
lblMessage.Text = item;
}
You may also come across instances in which you need to exit a loop
prematurely. In this case, you would use Exit (VB.NET)
or break (C#) to terminate the loop:
Dim i As Integer
For i = 0 To 10
If (i = 5) Then
Response.Write("Oh no! Not the number 5!!")
Exit For
End If
Next
int i;
for (i = 0; i <= 10; i++) {
if (i == 5) {
Response.Write("Oh no! Not the number 5!!");
break;
}
}
In this case, as soon as our For loop hits 5, it
displays a warning message, using the Response.Write() method
that will be familiar to those with past ASP experience, and exits the loop
so that no further passes through the loop will be made.
Although we have only scratched the surface, VB.NET and C# provide a
great deal of power and flexibility to the Web developer, and time spent learning
the basics now will more than pay off in the future.
Understanding Namespaces
BecauseASP.NET is part of the .NET Framework, we have access to all the
goodies that are built into it in the form of the .NET Framework
Class Library. This library represents a huge resource of tools
and features in the form of classes, all organized
in a hierarchy of namespaces. When we want to use certain
features that .NET provides, we have only to find the namespace that contains
that functionality, and import that namespace into
our ASP.NET page. Once we’ve done that, we can make use of the .NET
classes in that namespace to achieve our own ends.
For instance, if we wanted to access a database from a page, we would
import the namespace that contains classes for this purpose, which happens
to be the System.Data.OleDb namespace. The dots (.)
here indicate different levels of the hierarchy I mentioned—in other
words, the System.Data.OleDb namespace is grouped within the System.Data namespace,
which in turn is contained in the System namespace.
To import a particular namespace into an ASP.NET page, we use the Import directive. Consider the following
excerpt from an ASP.NET page; it imports the System.Data.OleDb namespace,
which contains classes called OleDbConnection, OleDbCommand,
and OleDbDataReader. Importing the namespace lets us
use these classes in a subroutine to display records from an Access database:
<%@ Import Namespace="System.Data.OleDb" %>
<html>
<head>
<script runat="server" language="VB">
Sub ReadDatabase(s As Object, e As EventArgs)
Dim objConn As New OleDbConnection( _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Database\books.mdb")
Dim objCmd As New OleDbCommand("SELECT * FROM BookList", _
objConn)
Dim drBooks As OleDbDataReader
objConn.Open()
drBooks = objCmd.ExecuteReader()
While drBooks.Read()
Response.Write("<li>")
Response.Write(drBooks("Title"))
End While
objConn.Close()
End Sub
</script>
</head>
Don’t worry too much about the code right now (we cover this in
detail in Chapter 6, Database Design and Development). Suffice it to say that, as we’ve
imported that namespace, we have access to all the classes that it contains,
and we can use them to get information from an Access database for display
on our page.
Specifically, the classes from System.Data.OleDb that are used in the above code are:
OleDbConnection
Used for connecting to the database
OleDbCommand
Used for creating a statement of contents to read from the database.
OleDbConnection
Used for connecting to the database
OleDbCommand
Used for creating a statement of contents to read from the database
OleDbDataReader
Used for actually reading contents from database
Object Oriented Programming Concepts
VB.NET and C# are great programming languages because they offer a structured way
of programming. By structured, I mean that code is separated into modules,
where each module defines classes that can be imported and used in other modules.
Both languages are relatively simple to get started with, yet offer features
sophisticated enough for complex, large-scale enterprise applications.
The languages’ ability to support more complex applications—their
scalability—stems from the fact that both are object oriented
programming (OOP) languages. But ask a seasoned developer what
OOP really is, and they’ll start throwing out buzzwords
and catch phrases that are sure to confuse you—terms like polymorphism, inheritance,
and encapsulation. In this section, I aim to explain
the fundamentals of OOP and how good OOP style can help you develop better,
more versatile Web applications down the road. This section will provide a
basic OOP foundation angled towards the Web developer. In particular, we’ll
cover the following concepts:
Objects
Properties
Methods
Classes
Scope
Events
Inheritance
Objects
In OOP, one thinks of programming problems in terms of objects, properties,
and methods. The best way to get a handle on these terms is to consider a
real world object and show how it might be represented in an OOP program.
Many books use the example of a car to introduce OOP. I’ll try to avoid
that analogy and use something friendlier: my dog, an Australian Shepherd
named Rayne.
Rayne is your average great, big, friendly, loving, playful mutt. You
might describe him in terms of his physical properties: he’s gray, white,
brown, and black, stands roughly one and a half feet high, and is about three
feet long. You might also describe some methods to make him do things: he
sits when he hears the command "Sit", lies down when he hears the command
"Lie down", and comes when his name is called.
So, if we were to represent Rayne in an OOP program, we’d probably
start by creating a class called Dog. A class describes
how certain types of objects look from a programming point of view. When we
define a class, we must define the following two things:
Properties
Properties hold specific information relevant to that class of object. You
can think of properties as characteristics of the objects that they represent.
Our Dog class might have properties such as Color, Height,
and Length.
Methods
Methods are actions that objects of the class can
be told to perform. Methods are subroutines (if they don’t return a
value) or functions (if they do) that are specific to a given class. So the Dog class
could have methods such as sit(), and lie_down().
Once we’ve defined a class, we can write code that creates objects of
that class, using the class a little like a template. This means that objects
of a particular class expose (or make available) the methods and properties
defined by that class. So, we might create an instance of
our Dog class called Rayne, set its properties accordingly,
and use the methods defined by the class to interact with Rayne, as shown
in Figure 3.3.
Figure 3.3. The methods defined by the class interact with the object.
This is just a simple example to help you visualize what OOP is all
about. In the next few sections, we’ll cover properties and methods
in greater detail, talk about classes and class instances, scope, events,
and even inheritance.
Properties
As we’ve seen, properties are characteristics
shared by all objects of a particular class. In the case of our example, the
following properties might be used to describe any given dog:
Color
Height
Length
In the same way, the more useful ASP.NET Button class
exposes properties including:
Width
Height
ID
Text
ForeColor
BackColor
Unfortunately for me, if I get sick of Rayne’s color, I can’t
change it. ASP.NET objects, on the other hand, let us change their properties
very easily in the same way that we set variables. For instance, we’ve
already used properties when setting text for the Label control,
which is actually an object of class Label in the namespace System.Web.UI.WebControls:
lblMyText.Text = "Hello World"
lblMyText.Text = "Hello World";
In this example, we’re using a Label control
called lblMyText. Remember, ASP.NET is all about controls,
and, as it’s built on OOP, all control types are represented as classes.
In fact, as you’ll learn in Chapter 4, Web Forms and Web Controls, all interaction
with ASP.NET pages is handled via controls. When we place a control on a page,
we give it a name through its id attribute, and this ID
then serves as the name of the control. Rayne is an object. His name, or ID,
is Rayne. Rayne has a height of eighteen inches. The same holds true for the Label control.
The Label control’s name or ID in the previous
example is lblMyText. Next, we use the dot operator (.) to access the property Text that
the object exposes and set it to the string "Hello World."
Methods
With our dog example, we can make a particular dog do things by calling
commands. If I want Rayne to sit, I tell him to sit. If I want Rayne to lie
down, I tell him to lie down. In object oriented terms, I tell him what I
want him to do by calling a predefined command or method,
and a resulting action is performed. In VB.NET or C#, we would write this
as rayne.Sit(), or rayne.LieDown().
As Web developers, we frequently call methods when a given event occurs.
For instance, the example earlier in this chapter that took information from
an Access database created an object called objConn to
represent the connection to the database. We then opened the connection by
calling the Open() method on that object as follows:
Dim objConn As As New OleDbConnection(
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:\Database\books.mdb")
…
objConn.Open()
We say that the Open() method is exposed by
the connection object, and that we’re calling the Open() method
on the OleDbConnection object stored in objConn.
We don’t need to know what dark secrets the method uses to do its magic;
all we need to know is its name and what we use it for.
Classes
You can think of a class as a template for building as many objects
as you like of a particular type. When you create an instance of a class,
you are creating an object of that class, and the new object has all the characteristics
and behaviors (properties and methods) defined by the class.
In our dog example, Rayne was an instance of the Dog class
as shown in Figure 3.4.
Figure 3.4. A class serves as the blueprint for an object.
We see that Rayne is an object of class Dog.
In our code, we could create a new instance of the Dog class,
call it rayne, and use all the properties and methods exposed
by the object.
In OOP, when we create new instances of a class, we say we’re instantiating that class. For instance
(no pun intended!), if we need to programmatically create a new instance of
the Button control class, we could write the following
code:
Dim myButton As New Button()
Button myButton = new Button();
As you can see, we’ve essentially created a new object called myButton from
the Button class. We can then access the properties
and methods that the Button exposes through our new
instance:
myButton.Text = "Click Me!"
myButton.Text = "Click Me!";
Scope
You should now have a concept of programming objects as entities
that exist in a program and are manipulated through the methods and properties
they expose. However, in some cases, we want to create methods to use inside
our class, which are not available when that class is used in code. Let’s
return to the Dog class to illustrate.
Imagine we’re writing the Sit() method
inside this class, and we realize that before the dog can sit, it has to shuffle
its back paws forward a little (Just bear with me on this one…)! We
could create a method called ShufflePaws(), then
call that method from inside the Sit() method. However,
we don’t want code in an ASP.NET page or in some other class to call
this method—it’d just be silly. We can prevent this by controlling
the scope of that method.
The two types of scope available in VB.NET and C# that you should know
about are:
Public
Defining a property or method of a class as public allows that property
or method to be called from outside the class itself. In other words, if an
instance of this class is created inside another object (remember, too, that
ASP.NET pages themselves are objects), public methods and properties are freely
available to the code that created it. This is the default scope in VB.NET
and C# classes.
Private
If a property or method of a class is private, it cannot be used from
outside the class itself. If an instance of this class is created inside an
object of a different class, the creating object has no access to private
methods or properties of the created object.
Events
We’ve covered events fairly
well already. To sum up, events occur when a control object sends a message
in response to some change that has happened to it. Generally, these changes
occur as the result of user interaction with the control in the browser. For
instance, when a button is clicked, a Click event is raised,
and we can handle that event to perform some action. The object that triggers the
event is referred to as the event sender, while the
object that receives the event is referred to as the event receiver.
You’ll learn more about these terms in Chapter 4, Web Forms and Web Controls.
Understanding Inheritance
The term inheritancerefers to the ability
for one class to use properties and methods exposed by another class.
In our dog example, we first created a class called Dog,
then created instances of that class to represent individual dogs such as
Rayne. However, dogs are types of animals, and many characteristics of dogs
are shared by all (or most) animals. For instance, Rayne has four legs, two
ears, one nose, two eyes, etc. It might be better, then, for us to create
a base class called Animal. When we then define the Dog class,
it would inherit from the Animal class,
and all public properties and methods of Animal would
be available to instances of the Dog class.
Similarly, we could
create a new class based on the Dog class. In programming
circles, this is called deriving a subclass from Dog.
For instance, we might create a class for Australian Shepherd and one for
my other dog Amigo, called Chihuahua, both of which would inherit the
properties and methods of the Dog base class, and define
new ones specific to each breed.
Don’t worry too much if this is still a little unclear. The best
way to appreciate inheritance is to see it used in a real program. The most
obvious use of inheritance in ASP.NET comes with the technique of code-behind.
Separating Code From Content With Code-Behind
Mostcompanies that
employ development teams usually split projects into two groups, visual design
and functional development, because software engineers are usually poor designers,
and designers are often poor engineers. Until now, our ASP.NET pages have
contained code render blocks that place VB.NET or C# code directly
within the ASP.NET page. The problem with this approach is that there is no
separation between the presentational elements of the page and the application
logic. Traditional ASP was infamous for creating “spaghetti” code,
which was scattered and intertwined throughout the presentation elements.
This made it very tricky to manage the code between development teams, as
you’ll know if you’ve ever tried to pick apart someone else’s
ASP code. In response to these problems, ASP.NET introduces a new way of developing
pages that allows code developers to work separately from the presentational
designers who lay out individual pages.
This new method, called code-behind, keeps all
of your presentational elements (controls) inside the .aspx file,
but moves all your code to a separate class in a .vb or .cs code-behind
file. Consider the following ASP.NET page, which displays a simple button
and label:
<html>
<head>
<title>Sample Page using VB.NET</title>
<script runat="server" language="VB">
Sub Click(s As Object, e As EventArgs)
lblMessage.Text = "Hello World"
End Sub
</script>
</head>
<body>
<form runat="server">
<asp:Button id="btnSubmit" Text="Click Me" runat="server"
OnClick="Click" />
<br /><br /><asp:Label id="lblMessage" runat="server" />
</form>
</body>
</html>
Let’s see how this example could be separated into the following
two distinct files:
sample.aspx
layout, presentation, and static content
sample.vb, sample.cs
code-behind files containing a custom page class
First, we take all the code and place it in the code-behind file (sample.vb or sample.cs).
This file is a pure code file, and contains no HTML or other markup tags.
What it does contain is a class definition. Nevertheless,
we can still access presentation elements from this file, using their IDs,
such as lblMessage:
Example 3.16. sample.vb
' First off we import some useful namespaces
Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
' All code-behind classes generally inherit from Page
Public Class Sample
Inherits Page
' Declare the presentation elements on the ASPX page
Protected WithEvents lblMessage As Label
Protected WithEvents btnSubmit As Button
' Here's the Click handler just as it appeared before
Sub Click(s As Object, e As EventArgs)
lblMessage.Text = "Hello World"
End Sub
End Class
Example 3.17. sample.cs
// First off we import some useful namespaces
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
// All code-behind classes generally inherit from Page
public class Sample : Page
{
// Declare the presentation elements on the ASPX page
protected Label lblMessage;
protected Button btnSubmit;
// Here's the Click handler just as it appeared before
public void Click(Object s, EventArgs e) {
lblMessage.Text = "Hello World";
}
}
Without code, the main ASP.NET page becomes much simpler:
As you can see, the only line
that’s different between the .aspx pages is the Page directive:
Example 3.20. sample.aspx (excerpt)
<%@ Page Inherits="Sample" Src="Sample.vb" %>
Example 3.21. sample.aspx (excerpt)
<%@ Page Inherits="Sample" Src="Sample.cs" %>
The only real change between the VB.NET and C# versions of the page
is the source filename extension. In both cases, the page inherits from the
class Sample.
The code-behind file is written differently from what you’re used
to seeing so far. While we no longer need <script> tags,
we find a class definition in its place. Looking at the VB.NET example, we
start with three lines that import namespaces to be used in the code:
Example 3.22. sample.aspx (excerpt)
Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
The next lines create a new class, named Sample.
Because our code-behind page contains code for an ASP.NET page, our class
inherits from the Page class:
Example 3.23. sample.aspx (excerpt)
Public Class Sample
Inherits Page
This is the practical application of inheritance that I mentioned above.
Instead of using the built-in Page class, the code-behind
method has you derive a subclass of Page for each page
in your site. Next, we have to declare the controls that we want to use from the .aspx page—if we forget this
step, we won’t be able to access them from our code:
Example 3.24. sample.aspx (excerpt)
Protected WithEvents lblMessage As Label
Protected WithEvents btnSubmit As Button
Finally, we create the Click subroutine just as before,
and terminate the class:
Example 3.25. sample.aspx (excerpt)
Sub Click(s As Object, e As EventArgs)
lblMessage.Text = "Hello World"
End Sub
End Class
As I hope you can see, code-behind files are reasonably easy to work
with, and they can make managing and using our pages much more straightforward.
On a typical project, I tend to use code-behind files quite frequently, but
for simplicity’s sake, we’ll stick with code declaration blocks
for at least the next few chapters.
Summary
Phew! That’s quite a few concepts to understand over the course
of a single chapter. Don’t worry—with a little practice, these
concepts will become second nature. I hope you leave this chapter with a basic
understanding of programming concepts as they relate to the Web developer.
The next chapter will begin to put all the concepts that we’ve covered
so far into practice, beginning by covering HTML Controls, Web Forms, and
Web Controls, before launching into our first hands-on project.
[3] Strictly speaking, a page is simply
another type of control, and so page events are actually
control events. When you’re first coming to grips with ASP.NET, however,
it can help to think of them differently, especially since you don’t
usually use OnEventName attributes
to assign subroutines to handle them.