BA372 — ASP.NET Lab
HTML Preamble
This lab assumes that you master the (very) basics of HyperText Markup Language (HTML) and that you can read and
create (very) basic HTML documents. In case you do, please advance to Lab Start. In case you do not,
take a few minutes to work your way through this preamble and make sure that you
have a basic idea of HTML before progressing to the actual lab.
HTML is a so-called 'markup' language. This means that text is marked-up with tags containing instructions on
how the text must be rendered (shown) by an HTML rendering software such as running inside a web browser. For instance, to have a web browser show the word 'foo' in
bold (foo), you surround it with a 'start bold' and 'end bold' tag like so:
<b>foo</b>
If you embed these tags between a 'begin html' and an 'end html' tag like so:
<html>
<b>foo</b>
</html>
then stick this text in a file named foo.html and pick this file
up with your web browser (Control-o will pop up a file dialog with which you can
select your HTML file), you can see how the web browser renders this HTML.
!!! IF YOU HAVE NEVER DONE THIS, PLEASE TRY THIS OUT NOW !!!
Similarly, to make the word appear in both bold and italics (foo), you surround it with both
'start bold' and 'end bold' and 'start italics' and 'end italics' tags like so:
<i><b>foo</b></i>
Note that you should not(!!) violate the nesting order of the tags. For instance,
<i><b>foo</i></b>
is incorrect. (It is true that most HTML rendering engines are sufficiently smart to
detect this type of error and correct for it, but you should try hard not to make the error in the first place. Especially
when we start working in XML (another markup language discussed and practiced later in the course), this type of error can come back to bite you hard.
HTML offers lots of rendering options. For instance, to make a bulleted (unordered) list of the words foo, goo and zoo, each of them in bold italics:
<ul>
<li><i><b>foo</b></i></li>
<li><i><b>goo</b></i></li>
<li><i><b>zoo</b></i></li>
</ul>
which renders as follows:
Or, if you want a numbered (ordered) list:
<ol>
<li><i><b>foo</b></i></li>
<li><i><b>goo</b></i></li>
<li><i><b>zoo</b></i></li>
</ol>
which renders as follows:
- foo
- goo
- zoo
If you want a 3 x 3 table with the numbers 1-9 in the cells, try this:
<table border="2" cellpadding="2" cellspacing="2">
<tr>
<td width=20 align="center">1</td>
<td width=20 align="center">2</td>
<td width=20 align="center">3</td>
</tr>
<tr>
<td width=20 align="center">4</td>
<td width=20 align="center">5</td>
<td width=20 align="center">6</td>
</tr>
<tr>
<td width=20 align="center">7</td>
<td width=20 align="center">8</td>
<td width=20 align="center">9</td>
</tr>
</table>
Which will show as:
Finally, with HTML5 and JavaScript we can draw:
<canvas id="foo" width="100" height="100">
Oops... no HTML 5 canvas support.
</canvas>
<script>
var ex = document.getElementById('foo');
var context = ex.getContext('2d');
context.fillStyle = 'red';
context.fillRect(25, 25, 75, 75);
</script>
Which displays as:
If you are unfamiliar with this HTML markup, you might want to experiment a little with it.
A good place to do this interactively is
w3schools' interactive HTML renderer.
Web browsers contain HTML rendering software which reads the HTML tags and their content in the data retrieved from the internet and
render it accordingly. For example, to see the HTML of this page, view its HTML source code (right click —> View Page Source)
Lab Start
This lab contains exercises that familiarize you with ASP.NET and
its deployment and development with Visual Studio. ASP.NET (Active Server Pages)
is a Microsoft technology for developing and
deploying dynamic web sites; i.e.,
web sites of which the content is generated only when the page is requested by a user or program.
A word of warning. The concepts and
materials you will encounter in this lab are quite 'involved,' meaning
that there is a whole world of technology and programming concepts
behind them. Many of these concepts we have or will soon have seen and explored; e.g., C#, HTTP, HTML, OOP, etc. However, in this ASP.NET
world, they all are fused into a cohesive whole. When you work
this lab, work it carefully and slowly!! Make sure that in your mind
it is clear how things work. Do not!! just go through the movements of
cutting and pasting code.
Web stack animated and explained (video)
(video transcript)

Please note the basic web architecture displayed above:
- Web Browser makes an HTTP request to an HTTP (Web) Server.
- The Web Server requests an Application Server / program to generate the requested web content.
- The Web App under control of the web server or Application Server may have to connect to a Database Server for database interactivity.
- The Web App delivers the dynamically generated content back to the Web Server.
- The Web Server delivers the content back to the Browser (over HTTP).
Visual Studio built-in web server:
One of the issues that makes web-based
programming a bit trickier than non-web-based programming, is that in
order to run a web-based program, you need a web server (see diagram above) through which
to request and run the web app which generates the HTML to be rendered on your browser. In many cases, your company's production web server will not
be available for this type of development runs —after all, we do not
want the production
and development side
of the house to be intermixed— so traditionally you would have to install a
web server on your development machine or copy files over to a shared 'sandbox'
area on the file system accessible through the web server to do web development. Especially in lab situations such as
ours, this can be a real hassle and hence, it is very(!) convenient that
the Visual Studio IDE has its own, built-in web
server that is used to run .NET web-based programs during development.
The server is automatically started when running or debugging an
ASP.NET page and is nicely integrated into the debugging environment.
- "Hello, world..." ASP.NET style: hello.aspx
- In Visual Studio, start a new ASP.NET Web
Application (New Project—>ASP.NET Web
Application). Make sure you set the language to C#.
- Select the Web Forms template.
- Double-click on the Default.aspx component
in the Solution Explorer. The skeleton web page in the editor is set
to Markup mode (View —> Markup).
- Switch between Markup,
Code view and
Designer view a few times. Notice how in
Designer view the page shows how it would look in a web browser.
- Also note that in Code view, you are actually looking
at the code of the accompanying Default.aspx.cs
C# program.
- Switch the view back to Markup mode.
- Replace the default code with the following:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<Script runat="server">
void Page_Load(Object Sender, EventArgs E)
{
HelloWorld.Text = "Hello, world...";
}
</Script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>Hello World... ASP.NET example</title></head>
<body>
<asp:Literal id="HelloWorld" runat="server" />
</body>
</html>
- Build and run the code.
- Because of the COB's network security, it is possible that your program resulted in an HTTP 401 error.
If so, close your project and start a new project on a local drive; e.g., C:\temp or the Desktop.
- Notice how the web page is displayed in your web browser(!!!). Visual Studio
invokes your web browser and your web browser makes the HTTP request for the web page to
the web server built into VS.Net (this is quite a nice chain of events).
- Notice how in the URL line of your browser, the page is requested
from the web server that Visual Studio started for you. This web server is accessible on port XXXX on your local machine (localhost).
- In more detail:
- Visual Studio started a web server (HTTP server in the diagram above) and instructed it to listen for HTTP requests on port XXXX.
- Visual Studio started your web browser (HTTP client lane in the diagram above) and pointed it to page Default(.aspx) on the server at localhost at port XXXX.
- Your browser then made the request for page Default(.aspx) on localhost at port XXXX.
- Since the web server (started by Visual Studio) is listening on port XXXX on localhost, it receives the request to serve the file Default(.aspx).
- Since Default(.aspx) is the program for which we wrote the Markup, that is the HTML content that the server generates and hands back to the browser.
- The browser takes the HTML content and renders it on the screen (compare the content of what the browser puts up (right-click > View page source) with
the Markup content of the ASP.NET code we wrote.
- Look at the page source in your browser (Right-click—>View page source) and notice how the HTML tag <body>
has been filled with the Hello, world... string.
- !!! Please try to understand what is happening here. Your web browser was called by VS.NET. The browser then made an HTTP request to
your built-in web server running on your local machine and listening for HTTP requests coming in on port XXXX (localhost:XXXX).
The server served up the ASP.NET page that we wrote in Visual Studio. When serving the page, the server ran the
compiled ASP.NET code which resulted in some HTML code. This HTML code was served (returned) to your browser and your browser
simply rendered that HTML code !!!
!!! Please, make sure you have a good grasp about this
process because it is central and crucial to virtually ALL web-based programming. Ask about it in class or go visit your instructor
to have this explained to you !!!
- Now look again at the (Markup) code:
- Notice how in the code the HTML <body>
contains only a single line:
<asp:Literal
id="HelloWorld" runat="server" />
- This code tells the web server (remember, this is a Microsoft
technology and you cannot serve an ASP page like this from a
nonMicrosoft server such as Apache), that at this location in the HTML file; i.e., inside the
<body></body> section, a literal
string (Literal)
called HelloWorld
must be rendered.
- Now, as the compiler builds (compiles) this web page, it runs
into the <Script>...</Script>
section of the code (make sure you see this section!).
- At the top of the page is a so-called directive (<%@ Page
Language="C#" %>) that specifies that the default script language for code on this page is C#.
- Hence, the server checks and parses the code inside the <Script>...</Script>
tags accordingly.
- Inside, it finds the C# code for the method Page_Load().
Notice how it is normal C# code except for one thing:
- The code refers to a class/object called HelloWorld
and sets its Text
attribute.
HelloWorld.Text
= "Hello, world..."
- However, this HelloWorld
class/object is not declared anywhere in the script. Instead, it refers to the
asp:Literal
declared in the <body>
section of the page:
<asp:Literal
id="HelloWorld" runat="server" />
- The Page_Load()
method is automatically AND ALWAYS!! called when the page gets loaded by the
server. Hence, as the web page runs on the server, the asp:Literal
HelloWorld's
Text
attribute is set to "Hello, world...",
which in its turn replaces the <asp:Literal>
of the HTML <body>
tag.
- So, in the page source of the HTML page displayed on your
browser, you only see the Hello, world...
text.
- Make sure you thoroughly
understand this mechanism as it is the basis of the remainder of this lab and a lot of ASP.NET technology.
- Some modifications: 10 instead of one 'Hello, world's:'
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<Script runat="server">
void Page_Load(Object Sender, EventArgs E)
{
string myString = "";
for (int i = 0; i < 10; i++)
myString = myString + "<li>Hello, world...</li>";
HelloWorld.Text = myString;
}
</Script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>Example</title></head>
<body>
<ol>
<asp:Literal id="HelloWorld" runat="server" />
</ol>
</body>
</html>
- Notice a few things:
- The Page_Load()
method has been modified to create a single, longer string, that consists of ten <li> Hello,
world...</li> strings concatenated together into one (Right-click—>View page source). (The <li></li> tag indicates an HTML list item.
The <li></li> items themselves are embedded in an ordered (numbered) list (<ol></ol>).
- As we showed in the HTML preamble of this lab, it is the browser's job to interpret these HTML tags and show (render) them as a
numbered list in the browser.
I.e., your C# program does NOT write the numbers in the list. It merely writes HTML code which says that an ordered list is coming, followed by
one or more list items. The numbering is done by the browser as it interprets the HTML.
- This string of HTML tags and their content is then used to set HelloWorld.Text.
- We can include any C# code in our <Script>
that we want.
- Similarly, we can set multiple literals; same behavior, different approach:
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<Script runat="server">
void Page_Load(Object Sender, EventArgs E)
{
string myString = "<li> Hello, world...</li>";
HelloWorld1.Text = myString;
HelloWorld2.Text = myString;
HelloWorld3.Text = myString;
HelloWorld4.Text = myString;
HelloWorld5.Text = myString;
}
</Script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>Example</title></head>
<body>
<ol>
<asp:Literal id="HelloWorld1" runat="server" />
<asp:Literal id="HelloWorld2" runat="server" />
<asp:Literal id="HelloWorld3" runat="server" />
<asp:Literal id="HelloWorld4" runat="server" />
<asp:Literal id="HelloWorld5" runat="server" />
</ol>
</body>
</html>
- Clearly, with this little mechanism alone, we could generate a
great variety of web pages. For instance, our Page_Load()
method could connect to a database, make some SQL queries and post the results
to our HTML web page.
- Another example; let us see if we can take a peek at the file
system ('z:' drive) of the server (remember, the 'server' is the built-in one that runs on your local
machine).
<%@ Page Language="C#" %>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<Script runat="server">
void Page_Load(Object Sender, EventArgs E)
{
string[] files = System.IO.Directory.GetFiles("z:\\", "*");
string myFiles = "";
foreach (string myFile in files)
myFiles = myFiles + myFile + "<br/>";
theFiles.Text = myFiles;
}
</Script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>Example</title></head>
<body>
<asp:Literal id="theFiles" runat="server" />
</body>
</html>
- Note the following:
- We are getting all the files (*) from the
z:
drive. (you might want to change the drive:\directory combination; e.g., c:).
- We fill up a string array files with a single call to a
System method that
returns all the files in a specific directory.
- We use the foreach()
construct to loop through the array.
- We once again build up one long string (myFiles),
which we then assign to the asp:Literal's
Text
attribute.
- Have you, here and in the previous codes, noticed the runat="server"
attributes of both the <Script>
and the <asp:Literal>?
These indicate to the compiler that those code segments must run on the
(web) server.
- So far, we have included C# code within a separate <Script>
section on the aspx page.
However, we may instead want to separate the code in the <Script>
from the aspx
page. ASP's so-called code-behind
facility allows us to do just that:
- Close the current solution and start a new ASP.NET Web Forms Application.
- In Markup view, remove the MasterPageFile="~/Site.master" entry from the top line of the
Default.aspx file.
- Replace (ONLY!!!) the
ASP/HTML code with the following:
<!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>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal id="MyLiteral" runat="server" />
</div>
</form>
</body>
</html>
- Notice that the page no longer contains a <Script>. Instead, it refers to code
which resides in a standard C# file (CodeBehind="Default.aspx.cs")
- Now, click on the little triangle to the left of Default.aspx
in the Solution Explorer and replace the code for Page_Load
in Default.aspx.cs with the following:
protected void Page_Load(System.Object Sender, System.EventArgs E)
{
//Trace.IsEnabled = true;
MyLiteral.Text = "Hello, world...";
//Trace.Write("After setting Output");
}
- Build and run the app.
- Notice how, in concept, this code is equivalent to what we
previously did using the <Script>.
Again, the Literal's Text
attribute gets set. However, in this case the code is separated out in
a 'normal' C# file and method that is compiled into the
aspx application.
- Also note how in the top line of the
Default.aspx file
the connections with the C# language and the
Default.aspx.cs
file are declared.
- One of the things that makes web programming a bit harder than
nonweb programming is the complexity of debugging a web-based program.
Whereas in a nonweb environment we can simply run our executable code
through a debugger (we have done so several times in C# so far),
with an HTTP client and server layer added into the mix, debugging a
web app on most platforms requires some juggling and some skillful OS-level manipulation.
Fortunately, the combination of
ASP.NET, Visual Studio and its built-in web server gives us pretty much
exactly what we need. For instance:
- In your Default.aspx.cs
file, set a breakpoint on the
MyLiteral.Text = "Hello, world...";
statement and
Start Debugging.
Notice how the application halts at the
breakpoint and how you can inspect, in the usual manner, the contents
of the Output
literal.
You may not be surprised at this. After all, we have used this mechanism in debugging
nonweb C# programs. However, keep in mind that the situation here is a bit different, because Visual Studio is
simultaneously running the program and keeping track of the built-in web server.
- Halt the app, switch your breakpoint off and uncomment the first Trace...
line (Trace.IsEnabled
= true) in the code; build and run.
- Notice how your browser now lists a complete set of information
on your running aspx app.
Among other things, it shows:
- HTTP header information (both server and client side).
- Any QUERYSTRING data.
- All server-side variables.
- Details of the HTTP request.
- Some or all of these should look familiar by now.
- Uncomment the
Trace.Write("After
setting Output"); line and build and run the program.
Notice how in the Trace Information
section of your browser's output, the Trace.Write() information
appears. Notice that it was the first Trace command executed (it is in
the Page_Load()
method so it is the first thing executed on this page. Notice,
also how many other methods are executed after Page_Load()
; e.g., LoadComplete(),
Prerender(),
Render(),
etc. This whole stack
indicates all the default methods which are automatically called when rendering an aspx web
page. Programmers can provide code for each and any of these if so
desired.
- Maintaining state:
- The asp:Literal
is a very nice 'all-purpose bag.' Since it is just a string, you can
use it to store any length and complexity of HTML code. For
instance, your code-behind program could connect to a database,
make queries and return the query results as an
asp:Literal to the browser.
- However, as discussed in our HTTP class, any sort of
interactive engagement with an HTTP server; e.g., e-commerce applications or playing games,
requires that we maintain state between different invocations of the
server. As discussed in class, however, HTTP is stateless and hence,
does not support state maintenance across subsequent requests.
- In class we discussed several ways to deal with HTTP's statelessness. One of
them was by passing state information to-and-from the browser by
'burying' it into the <input
type="hidden>
tags inside an HTML <form>
(an example of what we called 'memory-on-the-go').
- For instance, let us have the server prompt us for our name
using an HTML <form>
and once we fill out the form and pass its parameters back to the
server, it will read the data passed back to it and echo them back to us as a
welcome/greeting.
- In summary; the ASP.NET framework translates our ASP.NET code into the standard HTTP/HTML mechanism
of forms and <input> variable passing. When you never look at the page source, it's all magic, but once you
see the resulting page source and you remember our HTTP class discussion, things start to make sense (yet
another example of —as one of your colleagues put it— "killing Santa Claus").
- Finally, let us build a small application that really must
'accumulate' some memory over consecutive client-server interactions.
We will have a text box in which we enter a string and every time we come
back to the website, the new string is concatenated to the string from our previous visit. Hence, the
result of the current visit depends on the result for our previous visit; state maintenance, therefore.
- Change the Text of the
RegisterButton
into Append...
- Change the ID of the
RegisterButton
into AppendButton
- Change the ID of the
WelcomeLiteral
into AppendLiteral.
- Change the ID of the
RegisterTextbox
into AppendTextBox.
- Delete the Label.
- Replace the code for
RegisterButton_Click() with the following:
protected void AppendButton_Click(System.Object Sender, System.EventArgs e)
{
AppendLiteral.Text = ViewState["myString"] + " " + AppendTextBox.Text;
ViewState.Add("myString", ViewState["myString"] + " " + AppendTextBox.Text);
AppendTextBox.Text = "";
//Trace.IsEnabled=true;
}
- Verify that the 'Click' event for AppendButton
is set to AppendButton_Click().
- Build and run the program. Keep entering strings in the textbox
and hit the 'Append...' button. Notice how on each reply the program accumulates in
a single string the previous string plus the current string.
- How does this work? How did we build memory (state maintenance) into this process
which runs over HTTP?
- Coming in to the AppendButton_Click()
event handler, we reference ViewState["myString"].
- With a reference to ViewState[]
we can retrieve state information that was previously stored there.
This state information is stored in the HTML form's <input
id="__VIEWSTATE"> field that the server
sends out. (study the page source of the HTML page!).
- Notice how this __ViewState
data is encoded/encrypted in the form passed to us from the server and
how we cannot decode/decipher its contents. However, once this <input>
field gets passed back to the server, the server can decode it and we,
on the server side, can access that state information by referencing ViewState[].
- In other words, __ViewState is
(one of) ASP.NET's implementations of the 'memory-to-go' model. (whatever must be remembered,
stick it in a variable and pass it as a 'hidden' (receiver does
not render it on the screen) input field on an HTML form). Since it is declared an 'input'
field in the form, the client will send it back on the next HTTP request.
- With the call ViewState.Add()
we can put new state information into the myString
variable. Hence, with every call to AppendButton_Click()
we first pull out the last value stored in ViewState,
append the newly entered string to it and stick the result into AppendLiteral.Text,
after which we append the newly entered string to myString
and stick it back into ViewState.
- Notice how all ViewState
information is passed back to the browser as 'hidden' input, after which
when the browser makes its next request, it gets passed back to the
server as a variable. Since the input field
has a type="hidden"
the browser won't show it when rendering the page.
- As discussed during our HTTP class, moving state information
(memory) back and forth between client and server works fine as long as
the amount of information in ViewState
does not get too large. Once it gets large we must start thinking of
other methods to keep track of state information; e.g.,
storing it on
the server or client side.
- Replace ViewState[]
and ViewState.Add()
with Session[]
and Session.Add().
- The code seems to run the same, but by using Session
instead of ViewState the
information in myString
is kept in a combination of server memory and a
Session-id cookie
rather than through a hidden HTML <input> field.
- Run the program a few times more and observe its behavior. Can you figure out what is going on?
- Please note that your instructor is well aware of some of the complexity and not-immediately-obvious
content of this whole ASP.NET/HTTP mechanism. However, once you acquire a good grasp of HTTP
and HTML pages, and you can conceptualize HTTP's client/server model, things become a lot easier
to follow. You should also keep in mind that the models demonstrated here
are essentially identical in all HTTP-based web programming. Hence, we will see some of
this back in our LAMP lab.