You are on page 1of 360

Introduction - ASP.

NET - Beta2

Introduction
ASP.Net provides the most powerful environment for development of sophisticated, real-life
business applications. It was only natural for us to get sucked into the vortex of the exciting
opportunity that this language provides, to satiate our technical appetite. This book presents a
realistic tableau of the vast repertoire of features of the ASP.Net language. We have scythed
through the maze of technological jargon to present to you, in a simple yet comprehensive
manner, all the salient features of the language.

The book commences with the assumption that you are a programming tyro, with no previous
knowledge of ASP.Net or C#. It however, expects you to have a working knowledge of the Hyper
Text Markup Language (HTML). The book covers the length and breadth of the ASP.Net
framework. Since the C# language has been used for programming, the fundamentals of this
language have also been covered.

The book begins with the basics of the ASP.Net and C#. Thereafter, it moves on to the built-in
controls of ASP.Net. Next, it demonstrates how you can build your own custom controls. The
text then veers on to the concepts of the built-in C# classes, and shows you how to build your
own custom classes. It also covers the myriad aspects of handling databases, advanced
concepts of controls, mysteries of Cookies, CGI Progamming and state management,Web
Services and finally a Class Browser Application. It finally winds up with a peek into the
security issues of designing an Internet application using ASP.Net. Thus, you’ll be able to
appreciate, that a vast array of technical concepts of ASP.Net have been covered by this book.

This book is teeming with examples and explanations that discuss each concept threadbare.
The various disparate concepts have been woven together to create a beautiful tapestry of the
ASP.Net language. It has always been our modus operandi to break up large programs into
smaller fragments, comprehend each fragment thoroughly and subsequently, synthesize all the
fragments together to retrieve the original program. The same strategy has been employed in
this book also. Each concept has been substantiated with examples so that you can see how
each concept is implemented in real-life applications.

In our books, we have presented examples that emulate a concept supplied in the
documentation, or some idea we found on the Internet. However, some of the concepts
introduced are purely ours, and thus original. As far as we are concerned, you are free to use
our accepted wisdom, as long as someone somewhere in the world benefits from it.

We are sanguine that this book will go a long way in providing ample food for thought, to sate
the technological hunger of your minds. We implore you to put in sedulous effort in mastering
this language, by reading all the material provided to you in this book with sincerity, and also
by trying out all the examples that have been presented. We are confident that on doing so, you
will be able to scale dizzying heights in the world of Internet programming.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/intro.htm (1 of 3)2/13/2007 4:53:25 PM


Introduction - ASP.NET - Beta2

Requirements
The software requirements to successfully run all the programs in this book are

• Operating System - Windows 2000


• Microsoft IIS ver 5.0
• SQLServer 2000 (Evaluation Edition)
• Internet Explorer 5.5
• .Net Framework SDK Beta 2 (111 MB)

Internet Explorer 5.5 can be downloaded off the Microsoft site

• http://www.microsoft.com/windows/ie/download/ie55sp1.htm

Net Framework SDK Beta 2 can be downloaded off the Microsoft site

• http://download.microsoft.com/download/VisualStudioNET/Trial/2.0/W982KMeXP/
EN-US/setup.exe

Alternatively, you can visit the download section at Microsoft ( http://msdn.microsoft.com/


downloads/default.asp ) and download the .Net framework SDK Beta 2 under the Software
Development Kit option.

SQLServer 200
While installing the evaluation edition of SQLServer 2000, we have chosen the default selected
settings. The only modification made is in the Authentication Dialog Box.

You see two options

• Windows Authentication mode

• Mixed mode (Windows Authentication and SQL Server Mode)

The default option selected is Windows Authentication mode. We have instead selected Mixed
mode (Windows Authentication and SQL Server Mode). Once this option is selected, the
password text boxes for the ‘sa’ user gets activated. As we would prefer using a blank password
in our programs, we select Blank Password. On selecting this option, the text boxes get disabled
again.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/intro.htm (2 of 3)2/13/2007 4:53:25 PM


Introduction - ASP.NET - Beta2

Acknowledgements
We wish to thank a number of people who gave us their support, new ideas and inspiration
while writing this book.

First and foremost, thanks to Manish Jain, BPB Publications for publishing the book.

To my co-authors, Sonal and Neha who have put in a lot of hard work to complete the work
assigned to them.

To Tanuja Sodhi, an ex-Naval Officer from the first batch of lady officers and an MBA from
Jamnalal Bajaj, for editing the book. She is presently freelancing as a creative writer.

To Altaf Hemani and Kishore Rohra, for designing the cover.

Thanks to Manish Purohit for putting in all the time he had to verify the code with the
explanation, testing all the applications in the book and updated them to work under the
Release version of the product.

To Pradeep Mukhi and Shivanand Shetty, who have always been there, as a source of
inspiration and encouragement.

My Mother, Shana Aunty and a long list of friends need a mention here for their patience and
cooperation on this book while it was being written.

Vijay Mukhi

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/intro.htm (3 of 3)2/13/2007 4:53:25 PM


Getting Started - ASP.NET - Beta2

-1-

Getting Started
This book strikes up with the basics of ASP.Net or ASP+. We shall get started with the
assumption that you are a total novice as far as ASP.Net is concerned. We will go to the extent,
that even the full form of the acronym ASP sounds queer to you. We also presume that you are
unable to comprehend any programming language. Therefore, we will commence with the
absolute fundamentals. We do however take for granted, that you possess the basic knowledge
of the Hyper Text Markup Language (HTML).

So, now that we have divulged all our assumptions, let us get focused on writing code, and
applications that achieve useful results. It is our sincere aspiration that the knowledge
imparted by this book, goes a long way in furthering your career in the Information Technology
field.

Let us start by creating a simple HTML file named a.html, using any text editor, and storing it
in a subdirectory called wwwroot i.e. c:\inetpub\wwwroot.

a.html
<b> hi </b>
bye

We then start Internet Explorer (IE) to check-out the output. You can use Netscape or any other
browser of your choice, since, it will not affect the output in any way. In the Internet Explorer
Address bar, enter the following: c:\inetpub\wwwroot\a.html

The abovementioned line will beckon IE or the web browser to pick up a file called a.html from
the wwwroot subdirectory and display its contents in the browser window. Thus, the resultant
output is as follows:

Output
hi bye

Any text enclosed within a less than sign (<) and a greater than sign (>) is called an HTML tag.
As the character 'b' is enclosed within < and >, we call 'b' a tag. The 'b' tag indicates to the
browser that everything following this tag is to be displayed in bold, until the browser
encounters the same tag; however, it should be preceded by a / symbol. A tag preceded with a
slash signifies the end of the tag. These tags are found in pairs. Thus, 'hi' is displayed in bold,
whereas, 'bye' is displayed as normal text.

Thereafter, in IE, we rewrite the address as:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (1 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

http://localhost/a.html

The output, to our pleasant surprise, remains unchanged.

(To be able to see the output as shown above, make sure you are running the IIS Web Server
from Microsoft. In case you have not installed ASP.Net, please refer to the Installation section of
the Introduction chapter in this book for details.)

The only difference between the current output and the one displayed earlier is that:

• In the earlier case, the HTML file was obtained from a specified directory on our hard
disk.
• In this case, the HTML file has been obtained from the IIS Web Server.
How did this sudden variation occur?
Every machine on the Internet is recognized by a name. Thus, the Microsoft server on the
Internet is called Microsoft, while our server is called vijaymukhi. In the same vein, as all
human beings on the planet earth are called humans, every machine on the internet is
recognized by the common nomenclature of 'localhost'. Hence, your machine and my machine,
both share this common name. The World Wide Web or WWW is also technically described as
http. Therefore, while executing http://localhost/a.html, IE requests the Web Server running
on the local machine, to send back a file called a.html. Had we replaced the name localhost
with Microsoft, the browser would have requested the web server running on the Microsoft
machine, for the same file, a.html.

The pertinent question that crops up is "Where does the file a.html reside?"
To answer this question, we need to understand, that every Web Server has a default sub-
directory or root directory through which it serves the requested files. The root directory could
also be termed as the home directory. In the case of IIS, it hunts for the file in the subdirectory
wwwroot of the directory inetpub on the default drive, which in this case is the c drive. Thus,
the path along which it searches for the file is: c:\inetpub\wwwroot. IIS loads the file from disk
and transfers the contents to IE for display. This file, when handed on to the Web Browser, can
be viewed by clicking on the menu option View - Source. Regardless of the address that we type,
the same HTML file is displayed in Notepad.

Now, we shall add one more tag to our HTML file.

a.html
<b> hi </b>
<$ hi $>
bye

First, we supply the location of the file in IE, i.e. c:\inetpub\wwwroot\a.html. The output
displayed by the browser is as shown below.

Output
hi <$ hi $> bye

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (2 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

The output clearly indicates that the $ tag is alien to the browser. The HTML documentation
lucidly lists all the possible valid tags of the HTML specification. So, we can safely conclude that
if a browser does not support a tag, it simply ignores it and treats it akin to simple text. View-
Source menuoption displays our hand-written html file.

In the next round, we give the address or the URL as http://localhost/a.html. The address of a
file on Internet is also known as a URL or Uniform Resource Locator. The output that is
displayed in the browser window is as follows:

Output
hi <$ hi $> bye

View-Source
<b> hi </b>
<$ hi $>
bye

Each time IIS stumbles upon a tag that it does not recognize, it simply sends the tag across to
the browser. Thus, the $ tag too is sent to the browser. The file present on the server's hard
disk is similar to the one that finally reaches the Web Browser.

In the context of the above explanation, we hope that you are truly able to appreciate the
difference between the following:

• Asking a Web Browser to read a file from the disk.


• Requesting for the same file from the Web Server.

Let us now rename the same file as a.aspx. Here, we have merely changed the file extension and
asked IE to fetch the file from the local hard disk. On providing the file location on the address
bar, IE displays a dialog box that requests us to choose a program that shall open this file. We
choose IE itself from the list of programs displayed.
The output we receive now is as shown below
Output
<b> hi </b>
<$ hi $>
bye

Since the file extension is not html anymore, the browser refuses to parse the tags contained in
the file and displays it as is.

In the next instance, we ask the Web Server to pick up a.aspx, using the URL. On doing so, IIS
seems to go into a slumber or appears to be preoccupied elsewhere. As a result, it takes a very
long time to yield the output. It finally displays the following:

Output
hi <$ hi $> bye

View-Source
<b> hi </b>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (3 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

<$ hi $>
bye

Thus, it may be observed that the Web Server behaves differently in this situation. It interprets
a file with an aspx extension, as a special file and therefore, takes longer to process it than
before. As before, it also sends the $ tag along with the other tags.

We shall now make a small change in the a.aspx file by replacing the $ sign with a % sign

a.aspx
<b> hi </b>
<% hi %>
bye

When IE displays the file from the local hard disk, the output remains unchanged.

Output
<b> hi </b>
<% hi %>
bye
A tag is a tag is a tag. IE does not understand the tag <$ or the tag <%. So, it ignores both of
them.

In numerous instances, when you enter the same URL, i.e. http://localhost/a.aspx, IE may
not request the Web Server to send the file again. It may simply display the same contents as it
did earlier. This happens because, technically, IE fetches the file from its cache. Thus, you
should invariably click on the refresh button to make a new request to the Web Server. We shall
not remind you about this salient feature hereon.

On requesting IIS to fetch the file a.aspx, all hell seems to break loose. To our utter shock and
dismay, we get the following error page:
Output
Server Error in '/' Application.
--------------------------------------------------------------------------
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request.
Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: BC30451: The name 'hi' is not declared.
Source Error:
Line 1: <b> hi </b>
Line 2: <% hi %>
Line 3: bye
Source File: c:\inetpub\wwwroot\a.aspx Line: 2

Your sagging spirits are bound to receive a fillip on knowing that we did not commit a blunder
in the above code. The only faux pas committed was that, one of the tags had been prefixed and
suffixed by the symbol %, and it did not have a corresponding closing tag. The error message
conveys to us that the name 'hi' is not declared. What does declare mean? In cricket, it means
that one team decided not complete its innings. But in the world of programming, it has a very

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (4 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

different connotation.

So what really went wrong?


After a significant amount of brainstorming, we deciphered that the Web Server understands
and reads the text placed between the <% and %> symbols. These tags have a special
significance for IIS and hence, we need to be extremely careful about the statements that are
inserted within them. Further, on viewing the HTML source code, it was confirmed that the Web
Server was greatly annoyed by this syntax. It conveyed its irritation by generating a large HTML
file. All this ruckus was created for the lone word 'hi'. But IE does not seem to care.

Now, we shall carry out one more change in our aspx file.

a.aspx
<b> hi </b>
<% Response.Write("hell") %>
bye

The local file with the complete path gives the following output in the browser window:

Output : c:\inetpub\wwwroot\a.aspx
<b> hi </b>
<% Response.Write("hell") %>
bye

As before, IE ignores all the tags as it does not recognize the aspx extension. Henceforth, we will
not request the Web Browser to fetch an aspx file from the hard disk.

When IE requests the Web Server for the same file, the output generated is as follows:

Output : http://localhost/a.aspx
hi hell bye

View-Source
<b> hi </b>
hell
bye

Finally, we have arrived at an error free program ! No error has been generated !! This goes on
to prove that IIS gets involved when the tags are enclosed within the symbols <% and %>.
However, it does not take any notice of the tags that are enclosed within the symbols <$ and $>.
Thus, the symbol % indicates that the tag has a special significance as far as IIS is concerned.

The text Response.Write, with the word "hell" enclosed within double inverted commas, is
converted into HTML 'hell' and sent over. Using the View-Source menuoption, observe carefully
that the syntax Response.Write is not sent over. This concept of the Web Server being able to
understand a % tag and specific syntaxes like Response.Write, forms the very core of ASP+ or
Active Server Pages Plus.

The fundamental concept of ASP.Net is that, it merges the programming language code with

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (5 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

HTML. You can place unlimited code between the <% and %> symbols which finally is executed
by IIS, and the output is merged with the rest of the static HTML text.

Thus, ASP.Net is capable of creating dynamic web pages. If this had not been possible, the
Internet would not have been such a "moving experience". All that the web server would have
done then would be, serve static HTML pages, thus giving us a very limited range of experiences
available on the Internet.

On the other hand, if the web server is well equipped to create dynamic HTML pages that do not
originally exist on the server's hard disk, the variety of content that can be generated is
boundless. This dynamism is extensively exploited in different garbs, by developers of web sites
to build business applications.

In order to learn how to program ASP.Net, we have to ascertain what IIS understands. It
understands text such as Response.Write.

Response.Write is called a function. A function is represented by a word that is followed by a


pair of round brackets. IIS understands innumerable such functions. It is these functions that
make the ASP.Net programming astoundingly powerful. Functions are like black boxes that are
designed to accomplish specific tasks. As a programmer, you have to understand their
functionality and syntax. You should know what a function accomplishes, and how it operates.

The function Response.Write accepts a word enclosed within double inverted commas.
Technically, a word that is passed to this function is called a parameter. In a.aspx, the
parameter passed to the Response.Write function is merged by the server with the HTML file.

In the ultimate analysis, an ASP.Net program is a concoction of static HTML text and code. The
Web Server IIS, converts the code written within the tags <% %> into text, and thereafter, sends
it over to the Web Browser. As the Web Browser can only accept and understand HTML files, it
simply displays this file, ignoring the tags that it cannot comprehend. Thus, an aspx file
undergoes dramatic transformation before it reaches the Web Browser. Consequently, a file on
the server's hard disk is very different from the file that finally reaches the Web Browser.

ASP.Net is the single largest concept being used extensively to build Internet Enabled
Applications. In order to appreciate the concepts more deeply, you need to study the source file
using the View-Source menuoption. You can also execute the examples on the web server and
ascertain for yourself, that the results produced are identical.

a.aspx
<b> hi </b>
<% Response.Write("hell ") %>
<% Response.Write("no") %>
bye

Output : http://localhost/a.aspx
hi hell no bye

You are at liberty to insert unlimited ASP.Net tags. All the extra spaces preceding or following
the text within the tag are removed while displaying the output. The View-Source menuoption

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (6 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

will make it unambiguously apparent that IIS sends the spaces over, but it is the Web Browser
that filters them out and refuses to display them.

View-Source
<b> hi </b>
hell no
bye
a.aspx
<b> hi </b>
<% response.Write("hell") %>
bye

The letter r of the function Response is in lower case in the above program. However, IIS simply
turns a blind eye to it and displays the same output as before. Thus, it can be concluded that
IIS is not case sensitive.

We then initiate one more change in the program, we spell Write with an additional s.

a.aspx
<b> hi </b>
<% Response.Writes("hell") %>
bye

Output
Compiler Error Message: BC30456: The name 'Writes' is not a member of 'System.Web.HttpResponse'

Alas! An error message has been flashed. IIS can recognize only predefined functions, thus it
informs us that it is not aware of a function called Writes.

It is because of the cryptic error messages generated by the programming languages, that
people like us are in business. It is our job to decipher them for you. The two words, 'member'
and 'function' are identical in meaning.

All these are rules and it is these rules that constitute a programming language. Within the ASP.
Net tags, IIS works on the default assumption that we are following the rules of a language
called VBScript. Our only grouse with VBScript is that it is a language of considerable vintage.
Hence, we would rather use a language like C# which Microsoft has recently released, which is
on the cutting edge of technology. So, we decided to write all our code in C#. In order to
facilitate this, all that we need to do is, direct IIS to follow the rules of C#. This instruction is
given using a directive.

a.aspx
<%@ language="C#" %>
<b> hi </b>
<% Response.Write("hell") %>
bye

Output
Compiler Error Message: CS1002: ; expected

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (7 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

Line 4: bye

We started our ASP.Net page with a % symbol as usual, but now we shall follow it up with a @
symbol. A directive in ASP.Net is indicated with the @ sign following the % sign. In a directive,
we simply specify the language that we want to use.

The word language is called an attribute and we have initialized it to C#, the language that we
want to use in the ASP.Net tags, henceforth.

Note that the name of the programming language is enclosed within double quotes. Most
programmers of ASP.Net code however, may not use the double quotes since they are optional.

We have not yet removed the shrouds of mystery behind the error that has been generated.
Every language has its own set of rules. In C#, every statement has to be terminated by a semi
colon symbol i.e. ;. The absence of the semicolon at the end of the function statement, caused
the error. It is pertinent for you to ask, as to why was the semi colon symbol selected ? Since,
the C programming language used a ; symbol to mark the end of every statement, and
thereafter, C++ and Java also adopted the same syntax, C# also chose to follow suit.

a.aspx
<%@ language=C# %>
<b> hi </b>
<% Response.Write("hell"); %>
bye

Output
hi hell bye
On inserting the semicolon, the error vanishes. Thus to conclude, a statement in VB takes an
enter to mark the end of every statement, but in C#, it is mandatory to use a ; .

Let us now see as to what happens when we change the R of Response to lower case. If you
recall, VB ignored it completely since it is case insensitive.

a.aspx
<%@ language=C# %>
<b> hi </b>
<% response.Write("hell"); %>
bye

Output
Compiler Error Message: CS0246: The type or namespace name 'response' could not be found (are you
missing a using directive or an assembly reference?)

On changing the letter R to r, C# creates havoc, since the language is case sensitive. Thus, in
C#, a lower case and an upper case R are two different characters. In this sense, C# is more
restrictive than VB. The differences between them are not extensive, but they are sufficient to
make you cling on to one of these programming languages.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (8 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

<%@ language=C# %>


<b> hi </b>
<% Response.Write("<u>hell</u>"); %>
bye

Output
hi hell bye

Whatever parameter we pass to the Response.Write function gets sent over to the browser
unchanged. IIS does not read this parameter at all. It simply makes it a part of the text file that
it has to send over. The word 'hell' is underlined because of the u tag.

a.aspx
<%@ language=C# %>
<b> hi </b>
<% Response.Write("<img src=win2000.gif>"); %>
bye

We now see the Windows 2000 logo displayed between the words 'hi' and 'bye'. IIS sends an
html file containing an image tag over to the Web Browser. The attribute src with img denotes
the name of the picture to be displayed.

When the browser sees the img tag, it reverts to the Web Server to obtain the image file. In this
case, the specified file is win2000.gif, located in the wwwroot sub-directory. The Web Server
sends this graphic file over and the Web Browser displays it.

The Web Server cannot send a mixture of a text file as well as graphic files at the same time. It
can send only one of them at a time. The View-Source file menuoption can be used to view the
textfile .

a.aspx
<%@ language=C# %>
<b> hi </b>
<% Response.Write(vijay); %>
bye

Output
Compiler Error Message: CS0103: The name 'vijay' does not exist in the class or namespace 'ASP.a_aspx'
Line 3: <% Response.Write(vijay); %>

Initially, we shall display two lines of the error message, but once you get acquainted with the
error screen, we will display the error message only. The first line contains the actual error
message and the second line, depicted in red, indicates the position where according to C#,
feels that the error has occurred. This is only an approximation which may not be correct. The
word vijay, without quotes, is passed as a parameter to the Response.Write function. Since, C#
is not familiar with my name, it displays an error.

This really hurts my ego, because I thought I was known world over. 'Arrogance thy name is

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (9 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

Vijay Mukhi !' you may say. So, how do we make the word vijay significant to C# ?

a.aspx
<%@ language=C# %>
<b> hi </b>
<%
String vijay;
vijay = "good";
Response.Write(vijay);
%>
bye

Output
hi good bye

Reason to Rejoice! No errors have been generated by the above program. Further, vijay has been
replaced by the word 'good'. Are these two words linked in any way ?

Programmers will call vijay a variable. A variable is a word that can hold a value. We have
created a variable called vijay, and in the next line, we have assigned it the value 'good'. Thus,
from now on, wherever C# comes across vijay, it will replace it with the word 'good'. One
mystery has been solved. Now, let us take the next one by its horns!

What is the word String doing in front of the variable vijay? This word is called a data type. It
apprizes us of the nature of the content that the variable vijay shall store. Since, we want to
store letters of the alphabet or words in vijay, we precede it with the String data type.

Whenever a variable is created, C# must be informed about the nature of data or the contents
of the variable. C# recognizes a large number of data types.

One more question that may crop up in your mind to vex you is, "Why is vijay called a variable?"

a.aspx
<%@ language=C# %>
<b> hi </b>
<%
String vijay;
vijay = "hell";
Response.Write(vijay);
vijay = "no";
Response.Write(vijay);
%>
bye

Output
hi hellno bye

A variable is a word whose value can vary. The variable vijay first stored the value hell and then
'hi'. Thus, a variable can hold one value at one point in time, and a different value at another
point in time. Every program that you pen down, will revolve around variables.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (10 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

a.aspx
<%@ language=C# %>
<b> hi </b>
<%
String vijay;
vijay = "hell";
Response.Write(vijay + "<br>");
vijay = "no";
Response.Write(vijay);
%>

Output
hi hell
no

In the above program, we want to write the words hell and no, on two separate lines. To do so,
we firstly add a + sign to join the two strings. The first string is our variable vijay, and the
second string is an HTML tag br that results in a line break. The + sign does not attempt to add
the two strings as is done in arithmetic, but concatenates them to form a single string. As a
result, the final HTML file sent to the browser, is as follows:

View-Source
<b> hi </b>
hell<br>no

With this limited knowledge, we shall proceed to unravel the workings of a Search Engine.

Search Engines are programs that accept a word from you, and as soon as you click on a
specified button, it generates a page with a list of sites containing the specified word.

Let us first fortify our knowledge of HTML by learning some more of its basics.

a.aspx
<%@ language=C# %>
<input type= text >

The HTML tag input along with the attribute text, enables us to input characters just as we do
in a textbox. This widget is used to accept data from the user.

a.aspx
<%@ language=C# %>
<input type= text value=vijay> <br>
<input type= submit value=Click >

We have added another input tag with the attribute 'submit'. This generates a button on the
screen. This button has the word Click as its label, because the value attribute is assigned the
word Click. The attribute value for the textbox is vijay. Thus, vijay is displayed in the textbox
when the page is loaded.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (11 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

When we click on the button, nothing happens. Had we clicked on a similar button in a Search
Engine, it would have displayed a page with the results of the search. Let us achieve the same
functionality here also.

a.aspx
<%@ language=C# %>
<form action=a1.aspx>
<input type= text value=vijay name=aa> <br>
<input type= submit value=Click >
</form>

a1.aspx
<%@ language=C# %>
Hi in a1.aspx

A new HTML tag called form, makes its debut in our aspx file. This tag has an attribute called
action, which has been assigned the value a1.aspx. Similarly, the textbox has been given an
attribute called name that has been initialized to aa.

In the textbox, we input vijay1 and click on the submit button. This act awakens IE, which
searches for a tag called form, within the HTML file. The tag form also has an attribute called
action, with the value a1.aspx. IE takes this value and creates a new URL as http://localhost/
a1.apx. Since, only the filename is specified in the action attribute without any machine name,
it defaults to the machine containing the file a.aspx.

With a URL in the action attribute followed by the file name will have the form tag as follows:

<form action=http://localhost/a1.aspx>

Once the address is framed, IE looks for all the controls in the HTML file which have the name
attribute. We have a textbox called aa with a value of vijay1. On acquiring a name, IE adds a ?
symbol and follows it up with the name=value pair. In our case, after ?, the text given is
aa=vijay1. Thus, the IE address bar now reads as follows:

http://localhost/a1.aspx?aa=vijay1

The browser window has the following contents:

Hi in a1.aspx

The addition of the ? symbol, followed by the name=value pair, followed by the above course of
action, is called CGI or the Common Gateway Interface. What if we had two textboxes?

a.aspx
<%@ language=C# %>
<form action=a1.aspx>
<input type= text value=vijay name=aa> <br>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (12 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

<input type= text value=mukhi name=bb> <br>


<input type= submit value=Click >
</form>

We have added one more textbox and named it bb. On clicking the submit button, the following
URL is shown in the address bar:

http://localhost/a1.aspx?aa=vijay&bb=mukhi

IE uses the ampersand sign (&) as a delimiter between values of the textboxes. The web browser
connects back to the Web Server requesting it for a1.aspx, and then transfers all the extra data
that it has gathered. It is now the server's onus to hand over this data to the relevant file and
send the output to the browser.

To do so, a1.aspx has to accept and process the data keyed in by the user. The next program in
the series does just that. We will use the files a.aspx and a1.aspx throughout this chapter. Only
when we make any change to these files, will we display their new contents. In the following
program, the file a.aspx remains the same, whereas, a1.aspx has some new code inserted in it.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];
Response.Write(a);
%>

Output
Hi in a1.aspx vijay
As before, we click on the button labeled Click. This generates the ouput 'Hi in a1.aspx vijay',
signifying that the aspx file has retrieved the value given to aa and displayed it along with the
text.

Lets look at the additional code added in the file a1.aspx. We first create a variable called ‘a' of
type String. Then, we call a function Request.QueryString with one parameter, viz. aa, which is
the name of the textbox. The parameter aa is enclosed within square brackets [] instead of
round brackets ( ). These syntactical nuances have to be committed to memory, whenever we
learn a new language. This function returns the value of the textbox aa, i.e. vijay, which is
finally stored in a. Thereafter, the value is displayed using the Write function. A string enclosed
in double inverted commas can instead be replaced with a variable of type String.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];
Response.Write(a + "<br>");

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (13 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

a = Request.QueryString["bb"];
Response.Write(a);
%>

Output
Hi in a1.aspx vijay
mukhi

Just as we displayed one parameter value, we can also display another one. The same concept
is relevant, except that the values supplied as parameters get altered. The variable a, first
stores the word vijay, and subsequently, it stores the value mukhi. Thus, its value fluctuates.

Let us now write a program that has a superior level of built-in intelligence. It will display
different values depending upon the name of the user. So, here we go!

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];
if ( a == "vijay")
Response.Write("<h1> Welcome " + a + "</h1>");
if ( a == "sonal")
Response.Write("<h2> You are not Welcome " + a + "</h2>");
%>

If we input the word sonal in the first textbox and click on the submit button, we get the
following output:

Output
Hi in a1.aspx
You are not Welcome sonal

Now, if we input the word vijay, we get the following output:

Output
Hi in a1.aspx
Welcome vijay

Thereafter, if we input the word vijay1, the output obtained is as follows:

Output
Hi in a1.aspx

Thus, we get a different output depending upon the data entered in the textbox. This is only an
elementary demonstration of code that generates dynamic pages.

One way of introducing dynamism is by using the 'if' statement. The 'if' statement inserts a lot

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (14 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

of intelligence into our code. The 'if' statement checks whether the value of the variable a is
equal to vijay or not. If the answer is yes, it executes the next line. If the answer is no, then the
next line is ignored. Thus, we now have the ability to conditionally execute some code,
depending upon the value of a variable.

Variables now seem to have come of age and have begun to prove their usefulness. The 'if'
statement assists in making intelligent decisions. When the parameter aa holds the value of
vijay, the first if statement is true, but the second one is false. Similarly, when the parameter aa
has the value sonal , the first 'if' statement is false, whereas, the second one is true. In the last
case, where the value is neither vijay nor sonal, none of the 'if' statements evaluate to true.
Hence, no code within the % signs is executed.

We hope the use of the double 'equal to' , == to check for equality, did not slip your attention. It
does not alter the value of a variable. It evaluates either to true or to false. A single 'equal to'
symbol =, is used for assigning values.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];
if ( a == "vijay")
Response.Write("<h1> Welcome " + a + "</h1>");
Response.Write("Not in the range of a if <br>");
if ( a == "sonal")
Response.Write("<h2> You are not Welcome " + a + "</h2>");
%>

Output
Hi in a1.aspx Not in the range of a if
You are not Welcome sonal

In the above program, when we typed in the word sonal in the textbox, surprisingly the Write
function containing the text 'Not in the range of a if ', also got called. If you had been mindful
and observant just a few paragraphs earlier, you would be able to remember us having stated
very clearly that, the 'if' statement operates only on the immediately succeeding line. Thus, the
second Write function does not come under the influence of the first 'if' statement. The default
number of the lines under the influence of the 'if' statement, is only one.

What if we desire to have the next 10 lines controlled by the 'if' statement ? The next program
has the answer to that.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (15 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

if ( a == "vijay")
{
Response.Write("<h1> Welcome " + a + "</h1>");
Response.Write("Not in the range of a if <br>");
}
if ( a == "sonal")
Response.Write("<h2> You are not Welcome " + a + "</h2>");
%>

Output
Hi in a1.aspx
You are not Welcome sonal

The only way to execute or bypass a block of statements with the 'if' statement is, by placing
them within curly braces. Code written in curly braces is treated as one lengthy statement.
Thus, if there are more than one statement to be executed by the 'if' statement, the code
should be placed in curly braces.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
String a;
a = Request.QueryString["aa"];
if ( a == "vijay")
Response.Write("<h1> Welcome " + a + "</h1>");
else
Response.Write("<h2> You are not Welcome " + a + "</h2>");
%>
Output
Hi in a1.aspx
You are not Welcome sonal1

The data entered in the textbox is sonal1. In a1.aspx, C# stores this value in the variable a and
then checks the value against vijay, using the 'if' statement. As the content of the variable a is
not vijay, the 'if' statement becomes false. Hence, the 'else' statement is executed. The 'else'
statement can only be used as part of the 'if' statement. When the 'if'' statement is false, the
code associated with the 'else' statement is executed. Conversely, when the 'if' statement is true,
the code associated with the 'else' statement is ignored. Therefore, under any eventuality, either
the 'if' or the 'else' gets called, in other words, only one of them is executed.

We now run the program a1.aspx directly, using http://localhost/a1.aspx.

a1.aspx
<%@ language=C# %>
Hi in a1.aspx
<%
int i;
i = 10;
Response.Write(i);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (16 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

%>

Output
Hi in a1.aspx 10

We have made a few changes to our above program. We first created a variable i of type int and
not of type String, as given earlier. String and int are called classes; and i, which is a variable of
these types, is called an object. An object is technically an instance of a class. The idea behind
introducing these remarkable words is to enable you to overawe people with your profound
knowledge of programming.

The variable i can now store numbers, since its data type is an int, i.e. an integer. It is
initialized to a number, 10. Then we used the same old Response.Write function to display this
number.
ASP.Net gives us a large number of free objects such as Response and Request. Before the book
winds up, we shall certainly explain all the free objects. The object Response has innumerable
functions, and Write is just one of them. We use a dot(.) to separate the object name from the
function name. The use of the dot forms one of the rules of the C# programming language. Onto
the next program.

a1.aspx
<%@ language=C# %>
<%
int i;
i = 10;
Response.Write(i + " ");
i = 20;
Response.Write(i + " ");
i = i + 10;
Response.Write(i + " ");
i = i + 1;
Response.Write(i + " ");
i++;
Response.Write(i + " ");
%>

Output
10 20 30 31 32

Let us understand variables from a different perspective. We first created an int i and gave it a
value of 10. We then displayed it using the Write function. We also added a space within double
quotes at the end of the display to space them out. The familiar + sign is used to concatenate a
blank space with the value of i. The + sign is not used literally to add numbers, but to join a
number and a string. The value of the variable i is then modified to 20. Thereafter, we display
this value in the manner described earlier.

Now, we come across a strange line containing the text i = i + 10. An expression with an 'equal
to' sign must always be evaluated from right to left. The variable i in the expression i + 10 gets
replaced by the number 20 and the final expression evaluates to 20+10, summing up to the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (17 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

final value of 30. Once C# finishes evaluating the right hand side of the 'equal to' sign, it simply
assigns this new value to the variable on the left hand side. Hence, the variable i now receives
the new value of 30. If you find this confusing, you can run through the explanation once again.

The next line simply increments the value of i by 1. Hence, its new value is now 31.

The facility of incrementing the value of a variable by 1, is required very often in programming.
Therefore, C# has provided a short form. The expression i++ increases the value of the variable i
by 1. You can even use the expression i=i+1 interchangeably.

a1.aspx
<%@ language=C# %>
<%
Response.Write( 6 >9 );
Response.Write(" ");
Response.Write( 16 > 9 );
Response.Write(" ");
Response.Write( 6 < 2 );
Response.Write(" ");
Response.Write( 6 < 6 );
Response.Write(" ");
Response.Write( 6 <= 6 );
Response.Write(" ");
Response.Write( 6 == 6 );
Response.Write(" ");
Response.Write( 6 == 7 );
Response.Write(" ");
Response.Write( 6 != 7 );
Response.Write(" ");
Response.Write( 6 != 6 );
%>

Output
False True False False True True False True False

The above program has thrown a volley of questions.

The first Write function displays the answer to the question "Is 6 > 9?". Since the number 6 is
not greater than the number 9, the answer is either False or No. The plus sign +, the minus
sign -, and the greater than > sign are all called operators.

The next question is 'Is 16 > 9?', and the answer obviously is Yes or True. Anything that results
in True or False is called a condition. Thus, the expression 16 > 9 is called a condition. Next, we
have another condition 6 < 2, which evaluates to false. Following this is the condition 6 < 6
which is also false, since the number 6 is equal to the number 6 and not less than 6.

We are permitted to use a combination of operators. Thus, the condition 6 <= 6 evaluates to
True. The == operator that had been used earlier to compare strings, can be used to compare
numbers too. The number 6 is equal to 6, but not equal to 7.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (18 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

The last operator is != , which is the 'Not Equal To' operator. It is reverse of the == operator.

a1.aspx
<%@ language=C# %>
<%
int i = 7;
if ( i > 5)
Response.Write("true");
else
Response.Write("false");
%>

Output
True

An 'if' statement either evaluates to a True or to a False. Therefore, conditions can be placed
within an 'if' statement. As the condition in the 'if' statement i > 7 is True, True is displayed in
the browser.

a1.aspx
<%@ language=C# %>
<%
int i = 7;
if ( i )
Response.Write("true");
else
Response.Write("false");
%>

Output
Compiler Error Message: CS0029: Cannot implicitly convert type 'int' to 'bool'
Line 4: if ( i )

The C# language is a stickler for rules. It expects specific data types at certain places. If this
rule is violated, an error is generated, as seen above. In the 'if' statement, C# expects a logical
value of True or False and not a numerical value. Unlike many other languages, the C#
language is considerably ruthless when it stumbles upon any such mistakes. However, we
prefer the C# way of checking the source code rigidly and thoroughly.

a1.aspx
<%@ language=C# %>
<%
bool b;
b = true;
if ( b )
Response.Write("true ");
b = false;
if ( b )
Response.Write("false");
b = 6 > 1;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (19 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

if ( b )
Response.Write("false");
%>

Output
true false

We had mentioned earlier that there are numerous classes available in ASP.Net. So far, we have
seen only two of them, i.e. int and String. In this program, we have introduced one more class
called bool. The variable b is of type bool, so it can only store either a value of True or False.
The C# programming language recognizes the words true and false, and hence, they are termed
as reserved words. The variable b is initialized to True. Since the 'if' statement requires a logical
value or a value of type bool, the expression if (b) evaluates to the expression if(true). Hence, no
error is generated. Then, as the next value of b is false, the 'if' statement evaluates to false.
Therefore, the Write function is not executed.

All the logical operators <, >, ==, !- etc. return a bool value. Hence, they can be used with ease
within the 'if' statement.

a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1; i<=5;i++)
Response.Write(i + " " );
%>

Output
12345

Very often, we like to do certain things repeatedly in life, such as having a cup of coffee 10
times in a day. The computer programs too use the same analogy to repeat certain
instructions. Just as the 'if' statement assisted us in making our programs more intelligent and
decisive, the 'for' statement facilitates repetition of specific code.

A 'for' statement incorporates two semicolons. The explanation of the 'for' statement is as
follows:

• The instruction up to the first semicolon is executed only once. So, the variable i is
assigned the value of 1 only once.

• Then, the condition i<= 5 is checked. If this condition results in True, which is what the
present situation is because the value of the variable i is 1, C# proceeds to execute the next
line. The Response.Write function replaces the value of i with 1, thereby, displaying the
value of 1 in the window.

• After executing the instruction following the 'for' statement, the statement after the
second semicolon is executed. The statement i++ increments the value of i to 2. This value of
i is again checked with the condition i <= 5. Since 2 is less than 5, the Write function prints

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (20 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

2 and proceeds to execute the statement i++. The value of i now becomes 3 and the same
loop repeats itself again.

• When the value of i becomes 6, the condition fails and the loop is terminated. We have
executed the Write function 5 times without writing the function 5 times.

a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1; i<=5;i++)
Response.Write(i + " " );
Response.Write(i + "..." );
%>

Output
1 2 3 4 5 6...

The above program proves that the 'for' statement, like the 'if' statement, acts only on the
immediately succeeding line, by default. Also, when the last Write function gets called after the
'for' loop finishes execution, the value of i is displayed as 6 with two trailing dots. This output
confirms our explanation of the for loop laid down earlier.

a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1; i<=3;i++) {
Response.Write(i + " " );
Response.Write(i + "..." );
}
%>

Output
1 1...2 2...3 3...
If we want the 'for' loop to have control over multiple statements, we have to use curly braces { }
to enclose the following code, just as we had done in the 'if' statement. On doing so, both the
Write functions get called thrice.

a1.aspx
<%@ language=C# %>
<%
int i;
i = 1;
while ( i<=3)
{
Response.Write(i + " " );
i++;
}
%>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (21 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

Output
123

There are a million ways of achieving the same result in a programming language. Our blood
pressure is bound to mount upwards if we have to keep learning new ways of arriving at the
same outcome. All the same, it is not irrelevant to mention here that the 'while' statement
performs the same job as the 'for' statement.

The variable i is initialized to the value of 1, prior to entering the 'while' statement. The 'while'
statement evaluates a condition. If the condition is true, it enters the loop, however. if the
condition is false, it terminates the loop. In this case, since i is less than 3, the function Write
displays 1. Thereafter, the statement i++ increments the value of i by 1. The condition is
checked again to determine if the value of i is less than 3. When the value of i becomes 4, the
condition becomes false and the loop terminates.

Thus, the 'for' and 'while' loops achieve the same functionality. They differ only in the syntax.
You are at liberty to select any of the constructs that you fancy. If you have difficulty in taking a
decision, tossing a coin may be the best option. If it is heads, you may use a 'for' loop, and if it
turns out to be tails, you may use a 'while' loop.
a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1 ; i <= 3; i++)
Response.Write("<font size = " + i + " > hi </font>");
%>

Output
hi hi hi

Let us now explore the convenience that a loop provides to help us write code, which otherwise
would have been difficult to write. The font tag in HTML takes an attribute called size. This tag
determines the size of the font for the text to be displayed. Using the 'for' loop, we are assigning
different values to the variable i in such a way that we get three different font tags, each of
which has different values for the size attribute. The View-Source output endorses our
statement.

View Source
<font size = 1 > hi </font>
<font size = 2 > hi </font>
<font size = 3 > hi </font>

a1.aspx
<%@ language=C# %>
<% int i = 10; %>
<%= i %>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (22 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

10

There are a number of shortcuts in ASP.Net. One of them being, the expression <%= which is
an equivalent of the function Response.Write. Only the parameter supplied to the Response.
Write function is used with %=. It is mandatory to insert a space after the 'equal to' sign.

The code using the <%= expression is very compact and precise, and it does not require a
semicolon at the end of the statement. Let us incorporate this directive in the next example.

a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1; i<=3 ; i++)
{
%>
<font size= <%= i %> > hi </font>
<% } %>

The output of the above program is similar to that of a previous program. The only variation is
in the style and approach. If you observe very carefully, the file contains ASP.Net tags, as well
as HTML tags. Unlike the earlier case, where the code contained only ASP.Net tags, the source
code in this case, uses ASP.Net and HTML. Thus, the font tag is written in HTML with the
exception of the attribute size.

Since, a different value is required each time, variable i is enclosed within % tags. Moreover, in
a 'for' statement, only the first line following the 'for' statement is acted upon by the 'for' loop,
unless we enclose multiple lines using curly braces. Here, the variable i, the 'for' loop and the
curly braces are also enclosed within the ASP.Net tags. Thus, we are able to dynamically
generate different HTML tags. Finally, all the code is translated into an HTML file for the
convenience of the Web Browser.

All the HTML tags in an aspx file are converted into one gigantic C# program, wherein, the
static HTML tags are converted into parameters to the Response.Write function. Someday, we
shall disclose to you the source of the above information. The final transition is from one large
C# program to one large HTML file.

a1.aspx
<%@ language=C# %>
<%
int i;
for ( i = 1; i<=3 ; i++)
{
%>
<h<%= i %> > hi </h<%= i %> >
<% } %>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (23 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

Output
hi
hi
hi

The word 'hi' is displayed in three different sizes because, the heading tag (h) changes with each
iteration of the 'for' statement. This program is very similar to the font program seen earlier.
The View-Source menuoption will clear all the cobwebs in your mind, in this regard.

View-Source
<h1 > hi </h1 >
<h2 > hi </h2 >
<h3 > hi </h3 >

When the 'for' loop iterates, the h tag changes from h1 to h2 and then to h3. The same logic is
applied for the closing tag also.

a1.aspx
<%@ language=C# %>
bye
<%
if ( false)
%>
hi

Output
bye

Since, the 'if' condition has a false value, 'hi' is not displayed in the browser window. Thus, we
can safely assume that the C# code acts upon HTML statements.

Let us look at it this way: Since all the code is finally amalgamated into one large C# program,
the 'if' statement does not act on the HTML text 'hi', but on the function Response.Write("hi").

a1.aspx
<%@ language=C# %>
<%
abc();
%>

Output
Compiler Error Message: CS0103: The name 'abc' does not exist in the class or namespace 'ASP.a1_aspx'
Line 3: abc();

Here, we are calling a function called abc by writing its name, following it by a pair of round
brackets, and then ending it with a semicolon. The compiler reports an error as there is no
function called abc. This error is pretty obvious. The function call to a non-existent function
was done on purpose to educate you on the error messages thrown up by the compiler.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (24 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

The next series of programs will focus on writing functions and making function calls.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
void abc()
{
Response.Write("abc");
}
</script>
<%
abc();
%>

Output
abc

A function in an aspx file is created within an HTML tag called script. This tag uses two
attributes:

• The first one called language, is used to denote the language used in the code that
follows.
• The second one, called runat, is used to indicate the location where the execution of the
code should take place.

In our file, we have stated that the language to be used in the function is C#, and it is the
server that should execute the code, not the browser.

To create a function in C#, we simply write the name of the function followed by (). Then, within
the pair of curly braces, we are free to write as much code as our heart desires. As of now, we
have included a simple call to the Write function. The word void will be explained shortly, as we
believe in explaining 'one concept at a time'.

Thus, a function is created following one set of rules and executed following another set of
rules.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
void abc()
{
Response.Write("abc ");
}
void pqr()
{
Response.Write("pqr ");
abc();
}
</script>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (25 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

<%
abc();
pqr();
abc();
%>

Output
abc pqr abc abc

We are at liberty to create as many functions as we like. In the above program, we have created
two functions, abc and pqr. First, a call is made to function abc which simply prints abc. Then,
the function pqr is called, which prints the word pqr and calls the function abc. Hence, the
word abc is displayed again.

There is no difference between calling functions like Write, written by the programmers at
Microsoft, and calling functions like abc written by us. The call to the function abc by the
function pqr again proves that we can call the function abc as many times as we like.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
void abc()
{
Response.Write("abc ");
}
</script>
<%
abc("hi");
%>

Output
Compiler Error Message: CS1501: No overload for method 'abc' takes '1' arguments
Line 9: abc("hi");

Remember a cardinal rule in programming: "Write one line of code at a time and check for
errors". The only way to be proficient in programming is by reading and deciphering error
messages, no matter how cryptic they may be. Here, we are passing a string parameter while
calling the function abc, but the function does not accept any parameters. Hence, the error is
generated.

C# is very meticulous in matching the type and number of parameters that are actually passed
to a function with the parameters that it expects. Since the function in the above example does
not except any parameters, we've made a cardinal mistake by passing it one.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
void abc( String i, String j)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (26 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

Response.Write(i + " " + j);


}
</script>
<%
String s = "bye";
abc("hi",s);
%>

Output
hi bye

This time, we have got it right. We are calling the function abc with two parameters 'hi' and 's'.
The variable s is of type string and is initialized to the string 'bye'. So, in a sense, we are calling
abc and passing it two strings as parameters, within the open and close brackets. In the script,
abc is created with two variables i and j, both of which are type String or class String. These
variables receive the values 'hi' and 'bye' from the function abc, respectively. These values are
thereafter displayed using the Write function.

While executing the code at the server's end, C# pauses for a moment before assigning the
value to j. This is because, 's' has to first be converted to 'bye', and then sent over as a
parameter value to j. Thus, if we use variables, C# takes an extra step and replaces the variable
with the value. The advantage of using variables is that, when we change its value, something
altogether different happens.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
void abc( String i, String j)
{
Response.Write(i + " " + j);
}
</script>
<%
String s = "bye";
abc("hi",10);
%>

Output
Compiler Error Message: CS1502: The best overloaded method match for 'ASP.a1_aspx.abc(string,
string)' has some invalid arguments
Line 10: abc("hi",10);

We may fall asleep at the wheel, but the C# compiler keeps a constant vigil. It constantly
scrutinizes our code, hunting for errors. In the earlier example, C# expected the second
parameter to the function, to be a string; whereas, we have passed a number. The error
message could have been more lucid, but no one heeds our advise.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (27 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

int abc( int i, int j)


{
}
</script>
<%
abc(20,10);
%>

Output
Compiler Error Message: CS0161: 'ASP.a1_aspx.abc(int, int)': not all code paths return a value

And yet another crime has been committed. Carrying out a slight modification to our earlier
function abc, we changed the word void to int, and the compiler generated an error. It is time to
tackle the words void and int that precede a function name.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>
int abc( int i, int j)
{
return i + j;
Response.Write("hi");
}
</script>
<%
int k;
k = abc(20,10);
Response.Write(k);
%>

Output
30

The function abc adds two numbers that are passed to it as parameters and returns the result.
In this case, the numbers 20 and 10 are stored in variables, or parameters i and j in the
function abc. To return a value, the keyword return is used with the number. The function abc
returns the sum of 20+10 i.e. 30.

The function call abc(20,10) is now replaced by the return value, and this return value is
assigned to the variable k. Thus, when the word int precedes a function name, it signifies that
an integer value will be returned. Had we written String instead, the function would have to
return a String, instead of an int. No code following the return statement gets called. Hence, the
word 'hi' is not displayed. Thus, program execution of a function halts when it encounters a
return statement.

a1.aspx
<%@ language=C# %>
<script langauage="C#" runat=server>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (28 of 29)2/13/2007 4:54:25 PM


Getting Started - ASP.NET - Beta2

void abc( int i, int j)


{
return i + j;
}
</script>
<%
abc(20,10);
%>

Output
Compiler Error Message: CS0127: Since 'ASP.a1_aspx.abc(int, int)' returns void, a return keyword must
not be followed by an object expression

The word void signifies that the function does not return any value. Since we tried to return a
value, in spite of the fact that the return type of the function is void, an error was generated.
Whenever a function does not return any value, we have to declare the return type to be void.
But, if we do specify a return type, then we must ensure that the value returned by the function
is of this type.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap1.htm (29 of 29)2/13/2007 4:54:25 PM


Server Controls - ASP.NET - Beta2

-2-

Server Controls
In this chapter, we will use the controls freely available with IIS to build a real life application in
ASP+. Once you get familiar with the workings of these controls, we will then show you how you
can build a similar control yourself. So get hooked on to your computer and start on.

The file a.aspx, sent by the server, will display a textbox and a button in the browser window.

a.aspx
<%@ language=C# %>
<form action="a1.aspx" >
<asp:textbox id="aa" runat="server"/>
<asp:button text="Click a.aspx" runat="server" />
</form>

a1.aspx
<%@ language=C# %>
<form action="a1.aspx" >
Name: <asp:textbox id="aa" runat="server"/>
<asp:button text="Click a1.aspx" runat="server"/>
</form>

You may be tempted to ask as to what is so unique about a textbox and a button.

To begin with, we have not used any HTML tags to generate these two controls. A special tag
asp:textbox has been implemented, using two attributes called id and runat. In a similar
manner, a tag called asp:button, having the attributes text and runat, has been employed for
the button. This ASP.Net directive asks the server to generate the HTML tags for the
corresponding user interface widgets, at the server end with the specified attributes. The View-
Source menuoption displays the following in respect of a.aspx:

View-Source
<form action="a1.aspx" >
<input name="aa" type="text" id="aa" />
<input type="submit" name="ctrl2" value="Click a.aspx" />
</form>

When these special ASP.Net tags are converted into input tags in the HTML file, the attribute
runat is discarded. Further, the button is not assigned any name in the aspx file, due to the
missing id attribute. Therefore, the server names it ctrl2. The View-Source confirms that the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (1 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

aspx file now resembles an HTML file.

After the text vijay12 is entered in the textbox and the submit button is clicked, the IE requests
for the file a1.aspx and the address bar changes to:

http://localhost/a1.aspx?aa=vijay12&ctrl2=Click+a.aspx

But to our astonishment, the textbox is blank despite the fact that we entered the word vijay12
in it. All the details that were entered in the earlier browser windows too are nowhere to be
seen. The View-Source displays the same contents as before.

View-Source
<form action="a1.aspx" >
Name: <input name="aa" type="text" id="aa" />
<input type="submit" name="ctrl2" value="Click a1.aspx" />
</form>

When we click on the button after writing 'no', the address bar changes to- http://localhost/a1.
aspx?aa=no&ctrl2=Click+a1.aspx
but the output displayed by View-Source remains the same.

View-Source
<form action="a1.aspx" >
Name: <input name="aa" type="text" id="aa" />
<input type="submit" name="ctrl2" value="Click a1.aspx" />
</form>

This erratic behavior is the outcome of initializing the action form with the name a1.aspx, which
is also the name of the file in which it is contained. The server discards any data that is typed
in. Hence, the fields are initialized to default blank values.

Take a situation where we have a large form with numerous fields. You may enter all the data
correctly, barring one, where you may have committed some error. In consonance with the
behavior illustrated above, all the fields will be returned empty. They will have to be retyped,
thereby compelling us to be cautious in future while entering data. This is the penalty that we
get, for being inattentive while entering data.

A better way out would be to redisplay the form with all the fields that have correct entries in
one colour, and the field having the incorrect entry in a different colour. This would obviate the
need to re-enter a large amount of data.

Let us see how the server can be solicited to retain information that has been typed in.

a.aspx
<%@ language=C# %>
<form action=”a.aspx” runat="server">
<asp:textbox id="aa" runat="server"/>
<asp:button text="Click a.aspx" runat="server" />
</form>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (2 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

The only modification made by us in the source code has been, the addition of the attribute
runat to the form tag in the file a.aspx. Also, the action attribute is initialized to the same file.
After the addition of this attribute, the View-Source now displays a file that is vastly at variance
from the earlier one.

View-Source
<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDwxNDgwNTg2MzM2Ozs+" />

<input name="aa" type="text" id="aa" />


<input type="submit" name="ctrl1" value="Click a.aspx" />
</form>

A field called __VIEWSTATE has been created, which is of the type hidden. A hidden field does
not show up in the browser window, but its value is sent across to the server. We shall explain
this concept with a simple HTML example.

a.html
<form action=a1.html>
<input type=hidden value=hell name=aa>
<input type=submit value=click>
</form>

We have a hidden field aa whose value is 'hell'. While displaying this file, only the submit
button labeled 'click' is displayed. The hidden field remains invisible in the browser window.
However, when the submit button is clicked, the URL that is generated, shows this field as well
as its value, as: http://localhost/a1.html?aa=hell

In a.aspx, the value of the hidden field is a long and cryptic number. The form is assigned a
name and an id, both initialized to ctrl0. The method attribute is given a value of post. We shall
explain this concept later. By default, the method attribute has a value of 'get'. In the textbox,
we enter 'vijay13' and then click on the button. The page is refreshed and the URL bar shows
http://localhost/a.aspx
As the method is 'post', the parameters are not displayed in the URL, as was done earlier. 'Post'
does not send the parameter values along with the URL, whereas, the 'get' method does so. In
the case of 'post', they are transferred as a separate packet with data. As far as the ASP.Net
page is concerned, the task of fetching the parameter values remains the same.
With the new contents in the HTML file, the data that is entered most recently, is recovered.
Thus, the textbox shows 'vijay13'.

Let us now look 'behind the scenes' to figure out why this happens.

View-Source
<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDwxNDgwNTg2MzM2Ozs+" />

<input name="aa" type="text" value="vijay13" id="aa" />


<input type="submit" name="ctrl1" value="Click a.aspx" />

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (3 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</form>

This time, the textbox's value field displays the word 'vijay13'. This could have been possible
only if the Web Server remembered what was transferred. Hence, in the return round trip from
the server to the browser, it adds the value attribute to the textbox and assigns the new value
to it. Thus, runat asks the server to retain the values assigned to the attributes.

If you change 'vijay13' to 'vijay14' in the textbox and click on the button again, 'vijay14' will be
displayed in the textbox. Thus, new values are restored.

We now change the name of the textbox from aa to aaa in a.aspx. On executing the whole
program again, the textbox of a.aspx is displayed as empty. This occurs because the names are
different, and thus, they refer to different textboxes.

Restore the name of aa again and load a.aspx in the address bar. As the textbox names now
match, the earlier value of vijay14 is displayed again. The name and the id value of the form too
can be changed without disturbing the above process.

To improve your grasp of the above proceedings, open another copy of the browser and load a.
aspx. You will then notice that the two copies maintain distinct values. This implies that the
web server is informed about the newly opened browser too.

This book will delve deeper into these concepts. So, continue reading if you wish to satiate your
curiosity any further.

a.aspx
<%@ language=C# %>
<form action=a1.aspx>
<select name=item>
<option> Wood </option>
<option> Copper </option>
<option> Iron </option>
</select>
<input type= submit value=Click >
</form>

View Source
<form action=a1.aspx>
<select name=item>
<option> Wood </option>
<option> Copper </option>
<option> Iron </option>
</select>
<input type= submit value=Click >
</form>

To create a listbox, the HTML tag 'Select' is used. 'Select' requires 'option' as a sub-tag, where
the values within the listbox are placed. We have the prerogative to pick out any of the items
from the listbox, but when we click on the submit button, the name of the listbox is intialized to

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (4 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

the value that has been selected. Thus, item will be initialized to the value Copper, when
Copper is selected. This feature is a slight deviation for HTML novices or for those with a frail
memory, where HTML is concerned. There is no change in the aspx file other than the aspx
directive with language as C#. Select the item as Copper and the url changes to

http://localhost/a1.aspx?item=Copper

a.aspx
<%@ language=C# %>
<form action="a.aspx" runat="server">
<asp:dropdownlist id="aa" runat=server>
<asp:listitem>wood</asp:listitem>
<asp:listitem>copper</asp:listitem>
<asp:listitem>steel</asp:listitem>
</asp:dropdownlist>
<asp:button text="Click a.aspx" runat="server" />
</form>

For the sake of completeness, we have shown how you can display a combo box using the tags
asp:dropdownlist and asp:listitem, instead of the 'select the option' tag. It is more advisable to
use these tags instead of the above displayed standard HTML tags.

We will gradually proceed to build a real life application in ASP+. Has it ever ceased to astonish
you, as to how a different advertisement appears each time you visit the same website. The
application given below clarifies this mystery.

a.aspx
<%@ language=C# %>
<form action="a.aspx" runat="server">
<asp:adrotator AdvertisementFile="a.xml" runat="server"/>
<asp:button text="Click" runat="server"/>
</form>

a.xml
<Advertisements>
<Ad>
<ImageUrl>/quickstart/aspplus/images/banner2.gif</ImageUrl>
</Ad>
<Ad>
<ImageUrl>/quickstart/aspplus/images/banner3.gif</ImageUrl>
</Ad>
</Advertisements >

Each time we click on the Click button, we come across a different advertisement of banner.
How does this happen? To unravel this mystery, we first look at the HTML source that is
generated by the server for the file a.aspx.

View-Source
<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDw3MTQ1NDk0MTs7Pg==" />

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (5 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<a target="_top"><img src="/quickstart/aspplus/images/banner3.gif" border="0" /></a>


<input type="submit" name="ctrl2" value="Click" />
</form>

The anchor ( a ) and the image ( img ) tags are the newly inserted tags corresponding to asp:
adrotator. The attribute AdvertisementFile="a.xml" directs the web server to a file, a.xml, which
contains a series of img files that the web server is required to serve. a.xml must be in the same
directory as a.aspx i.e c:\inetpub\wwwroot. The runat attribute retains the information for the
web server.

An XML file is simply an HTML file. We start with a root or a starting tag called Advertisements.
Within this, is located a tag called Ad, which contains another tag called ImageUrl. ImageUrl
contains the images that are to be served in rotation. These images are present in the images
subdirectory i.e. quickstart/aspplus/images, which is created while installing ASP+ and its
samples.

a.aspx
<%@ language=C# %>
<form action="a.aspx" method="post" runat="server">
<script language="C#" runat=server>
void abc(Object a, EventArgs e)
{
Response.Write("hell");
}
</script>
<asp:textbox id="aaa" runat="server"/>
<asp:button type=submit text="Click" OnClick="abc" runat="server"/>
</form>

We have created a function abc that accepts two parameters; the first one is 'a' which looks like
a class Object, and the second one is 'e' which looks like EventArgs. The asp:button tag is used
with an additional attribute called OnClick, which is initialized to the abc function. This
function is called, when the button is clicked.
The two controls viz. textbox and button, are visible when a.aspx is displayed in the browser
window. View-Source displays the following:

View-Source
<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="YTB6MTk4ODc0NjcyX19feA==f2f03fae" />
<input name="aaa" type="text" id="aaa" />
<input type="submit" name="ctrl4" value="Click" type="submit" />
</form>

The OnClick attribute is not visible in the contents displayed by View-Source. Further, the
function abc simply vanishes without a trace ! Where did they actually vanish? If you observe
carefully, in the input tag for the button, the attribute type is displayed twice.

We now write vijay in the textbox and click on the button. The browser window displays 'hell',

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (6 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

followed by the textbox that contains 'vijay', and then the View-Source displays the following:

View-Source
hell<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="YTB6MTk4ODc0NjcyX19feA==f2f03fae" />
<input name="aaa" type="text" value="vijay" id="aaa" />
<input type="submit" name="ctrl4" value="Click" type="submit" />
</form>

This proves the fact that when the button was clicked, the web server was asked to execute a.
aspx. The button 'Click' has a function abc associated with it that displays 'hell'. So, IIS
executes this function and then generates an HTML file with the output of the function abc.
Furthermore, it remembers that the data entered in the textbox was 'vijay'. Hence, the value
with the textbox is initialized to this value.
a.aspx
<%@ language=C# %>
<form action="a.aspx" method="post" runat="server">
<script language="C#" runat=server>
int i = 0;
void abc(Object a, EventArgs e)
{
i++;
Response.Write("hell " + i.ToString());
}
</script>
<asp:textbox id="aaa" runat="server"/>
<asp:button type=submit text="Click" OnClick="abc" runat="server"/>
</form>

The browser window shows the same controls as before. Before the button is clicked, the
variable i is initialized to 0, and thereafter, the web server executes the function abc. Within the
function abc, i is increased by one and then its value is displayed.

An int class has a function called ToString that converts a number into a String. The + sign
concatenates two strings. Thus, in the first instance, we see 'hell 1', and the View-Source shows
the following:

View-Source
hell 1<form name="ctrl0" method="post" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="YTB6MTk4ODc0NjcyX19feA==f2f03fae" />
<input name="aaa" type="text" value="vijay" id="aaa" />
<input type="submit" name="ctrl4" value="Click" type="submit" />
</form>

Each time we click on the button, the entire aspx file gets executed from the very beginning.
Therefore, the value of the variable i gets initialized to zero everytime. This results in the text
'hell 1' being displayed each time. The variable i does not retain its previous values, because
everything starts afresh whenever the button is clicked.
a.aspx
<%@ language=C# %>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (7 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<form action="a.aspx" method="post" runat="server">


<script language="C#" runat=server>
void abc(Object a, EventArgs e)
{
cc.Text = aa.Text + " " + bb.SelectedItem;
}
</script>
<asp:textbox id="aa" runat="server"/>
<asp:dropdownlist id="bb" runat=server>
<asp:listitem>Wood</asp:listitem>
<asp:listitem>Copper</asp:listitem>
<asp:listitem>iron</asp:listitem>
</asp:dropdownlist>
<asp:button type=submit text="Click" OnClick="abc" runat="server"/>
<asp:label id="cc" runat="server"/>
</form>

In the above example, we have introduced one more tag called asp:label, having the id of cc.
This label, for the moment, does not get displayed on the screen. Its behaviour is similar to that
of hidden types. We then enter the text 'vijay' in the textbox named aa, and select the option
named Wood from the listbox called bb.

The Web Server first executes the function abc. Every textbox has a property called Text,which
returns the text entered by the user. Thus, aa.Text will return 'vijay'. Setting aa.Text to 'Mukhi'
will change 'vijay' to 'Mukhi'. Also, a listbox has a property called SelectedItem that returns the
item selected. Thus, bb.SelectedItem returns the value 'Wood'.

It is our intent to display these details using the label control. Similar to the textbox, every label
has a member or a property called Text. We initialize this property to the contents of the textbox
and listbox. Hence, 'vijay Wood' is displayed in the browser window.

a.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{
aa.Text = "Time is : " + DateTime.Now;
}
</script>
<asp:label id="aa" font-size="24" font-bold="true" runat=server/>

Output
Time is : 2001-03-22T19:08:46

View Source
<span id="aa" style="font-size:24px;font-weight:bold;">Time is : 2001-03-22T19:08:46</span>

In this program we have a tag called asp:label with an id of aa. No text is initially assigned to
the label. Therefore, the text attribute is not specified. Instead, two new attributes are given, viz.
the font-size and font-bold with the values of 24 and True, respectively.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (8 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

As before, we did not expect our HTML file to display any labels, since no text value is assigned.
But to our utter disbelief, we can see the current date and time displayed in bold, on our
screen.

We shall now reveal a secret to you: The Web Server is programmed to call the function
Page_Load in the beginning, whenever it is present in an aspx file. In this function, we change
the Text property of the label aa to "Time is : " and to the value returned by DateTime.Now.

DateTime has a variable called 'Now' that returns the current date and time on our server.
Hence, the contents in View-Source display the date and time in the specified font format, using
the HTML span tag.

The essential point to be remembered is that the server is oblivious to C# code. Whenever the
function Page_Load is present, it is executed prior to generating the page.

a.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{
aa.Text = "vijay";
bb.NavigateUrl = "a1.aspx?cc=" + aa.Text;
}
</script>
<asp:hyperlink id="bb" font-size=24 runat=server>
Hi <asp:label id="aa" runat=server/> Click here
</asp:hyperlink>

We now have an asp hyperlink tag that is equivalent of the <a href=> </a> tag in HTML. It is
given an id of bb. The file also contains a label called aa.

In the Page_Load function, the label is changed to vijay and the NavigateUrl property of the
hyperlink bb is changed to a1.aspx?cc=vijay. Thus, the first screen merely displays 'Hi vijay
Click here'. When you click on the anchor, a1.aspx is called with cc initialized to vijay.

a1.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void Page_Load(Object s,EventArgs e)
{
aa.Text = Request.Params["cc"];
}
</script>
Hi <asp:label id="aa" runat=server/>!

In the file a1.aspx, Page_Load is the first function to be called by the server. The function
Request.Params is similar to Request.QueryString. It accepts the name of the parameter cc
which is enclosed within square brackets, and returns its value, i.e. vijay. Consequently, the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (9 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

browser window displays the text 'Hi vijay'!

You are granted with great flexibility in performing a lot of activities using the Page_Load
function.

a.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void abc(Object Src, EventArgs E)
{
if (aa.Text != "")
{
Response.Redirect("a1.aspx?bb=" + aa.Text);
}
else
{
cc.Text = "Enter your name in the textbox!";
}

}
</script>
<form runat=server>
Name: <asp:textbox id="aa" runat=server/>
<asp:button text="Enter" Onclick="abc" runat=server/>
<p>
<asp:label id="cc" forecolor="red" font-bold="true" runat=server/>
</form>

a1.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void Page_Load(Object s,EventArgs e)
{
aa.Text = Request.Params["bb"];
}
</script>
Hi <asp:label id="aa" runat=server/>!

The above example performs many more error checks than its predecessor. Here, there is a
textbox called aa and a simple button that has a label named 'Enter'. The Onclick attribute of
this button points to the function abc. The label is named cc and displayed in red colour. It has
no text associated with it.

Without entering any data in the textbox, you can click on the button to call the function. This
function scrutinises the contents of the textbox attribute for a value. If the textbox contains
some text, in other words, if it is not blank, the function Response.Redirect creates a new URL
called a1.aspx, followed with the ? and abc=vijay and then travels to it. We are assuming that
the text entered is vijay. If the textbox contents are blank, the text attribute of the label is
displayed with a warning message in red.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (10 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

The html code is totally unaware about the 'behind the scene' tasks carried out by the server.
Hence, the View-Source displays a simple html file. Thus, error checks can be automated using
the programming language. The above program also demonstrates that parameters can be
passed to an aspx file.

a.aspx
<%@ language=C# %>
<script language="C#" runat="server">
void abc(Object Src, EventArgs E)
{
String a = System.Web.HttpUtility.UrlEncode(aa.Text, System.Text.Encoding.UTF8);
cc.Text = a;
}
</script>
<form runat=server>
Name: <asp:textbox id="aa" runat=server/>
<asp:button text="Enter" Onclick="abc" runat=server/>
<p>
<asp:label id="cc" forecolor="red" font-bold="true" runat=server/>
</form>

Output
vijay+mukhi+%2b

In the textbox, we have keyed in the text 'vijay mukhi +'. Thereafter, if we click on the button,
the abc function calls another function UrlEncode, which accepts two parameters. The first
parameter is the text written in the textbox aa.Text and the second parameter is System.Text.
Encoding.UTF8, which is the encoding style used on the Internet.

A URL is used to signify a computer address. It cannot contain characters such as a space, the
plus sign etc. Therefore, all these special characters are converted into a form that is acceptable
in a URL. To achieve this, C# has functions like UrlEncode, that converts a space into a + sign,
and all other reserved characters into their ASCII equivalents in hex . In addition to this, it
prefixes them with the % sign. This conversion is termed as URL encoding. Its reverse is termed
as URL decoding. If the data received from the Internet is encoded, then it has to be decoded
before it can be used in our programs.

Validation Controls
a.aspx
<%@ language=C# %>
<form action="a.aspx" runat="server">
<asp:RequiredFieldValidator ControlToValidate="aaa" errormessage="Please Write something"
runat=server />
<asp:textbox id="aaa" runat="server"/>
<asp:button type=submit text="Click" runat="server"/>
</form>

In the browser, a textbox and a button are displayed. When we click on the button, the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (11 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

following error message is displayed 'Please Write something'. Here, we have created a simple
error check. We offered the user a textbox where we expected him to enter some data. If, for any
reason, he refuses to do so, we can prevent him from proceeding further.

To validate data, we use a new ASP.Net tag called asp:RequiredFieldValidator with the attribute
ControlToValidate initialized to the control id. In our case, the control to be checked is the
textbox, hence, aaa is given. The attribute errormessage of this new tag is provided with text of
the error message that we desire to display on the occurrence of an error.

In order to implement error checks, this is all that is required to be done by us. On
implementing this error check, we receive an error message if the textbox is left blank. If you
select the View-Source menuoption, you will be surprised to see a large number of lines of code
written in a language called Javascript. This code is executed on your web browser.
View-Source
<form name="ctrl0" method="post" action="a.aspx" language="javascript" onsubmit="ValidatorOnSubmit();"
id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDwtNTEwNzM4MzUzOzs+" />
<script language="javascript" src="/aspnet_client/system_web/1_0_2914_16/WebUIValidation.js"></script>

<span id="ctrl1" controltovalidate="aaa" errormessage="Please Write something"


evaluationfunction="RequiredFieldValidatorEvaluateIsValid" initialvalue="" style="color:Red;visibility:
hidden;">Please Write something</span>

<input name="aaa" type="text" value="kk" id="aaa" />


<input type="submit" name="ctrl2" value="Click" onclick="if (typeof(Page_ClientValidate) == 'function')
Page_ClientValidate(); " language="javascript" type="submit" />
<script language="javascript">
<!--var Page_Validators = new Array(document.all["ctrl1"]);// -->
</script>
<script language="javascript">
<!--
var Page_ValidationActive = false;
if (typeof(clientInformation) != "undefined" && clientInformation.appName.indexOf("Explorer") != -1) {
if (typeof(Page_ValidationVer) == "undefined")
alert("Unable to find script library '/aspnet_client/system_web/1_0_2914_16/WebUIValidation.js'. Try
placing this file manually, or reinstall by running 'aspnet_regiis -c'.");
else if (Page_ValidationVer != "121")
alert("This page uses an incorrect version of WebUIValidation.js. The page expects version 121. The
script library is " + Page_ValidationVer + ".");
else
ValidatorOnLoad();
}
function ValidatorOnSubmit() {
if (Page_ValidationActive) {
ValidatorCommonOnSubmit();
}
}
// -->
</script>
</form>
A massive program has been generated by the server. If you go to the script sub-directory
mentioned in the src attribute, aspnet_client/system_web/1_0_2914_16, you will find a file

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (12 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

called WebUIValidation.js that contains almost 455 lines of code.

The salient concept to be grasped here is that, the server is not called upon for conducting error
checks, as this process takes too long. Instead, code that can be executed by the client is
generated. Further, this code is generated in Javascript (invented by Netscape), which is a
language that is compatible with all browsers. You can use the Microsoft version of Javascript i.
e. Jscript, in ASP.Net, in lieu of the C# programming language.

The crucial concept that has been implemented is that, it is more sensible for the browser to
carry out validations and then send the corrected data to the server for processing. If the entire
responsibility of data validation is assigned to the server, it would have to send the data to and
fro very often, resulting in data congestion. The browser speeds up the process of data
validation and it ensures greater interaction with the user.

Whenever we click on the button, some Javascript code gets called, which executes the error
checking.

a.aspx
<%@ language=C# %>
<form action="a.aspx" runat="server">
<asp:dropdownlist id="aa" runat=server>
<asp:listitem><!--Choose--></asp:listitem>
<asp:listitem >Wood</asp:listitem>
<asp:listitem >Copper</asp:listitem>
<asp:listitem >Steel</asp:listitem>
</asp:dropdownlist>
<asp:RequiredFieldValidator ControlToValidate="aa" InitialValue="<!--Choose-->" errormessage="You
must select something" runat=server/>
<asp:button type=submit text="Click" runat="server"/>
</form>

To perform similar error checks for a listbox or any other control, we enforce the use of the
attribute InitialValue to ensure that the user selects some value from the listbox before clicking
on the button. If none of the values is selected, an error message is displayed. You should make
sure that the InitialValue contains some informative message. This is to ensure that if the user
does not select any of the options, the error message that is displayed is meaningful.

The Web Forms framework has a repertoire of validation server controls that are used to
validate input forms for errors. They also display relevant error messages which inform the user
about any inaccuracies.

There is no difference in the procedures for adding a listbox control or a validation control to a
form. So far, we have delved upon only one type of Validation. However, a large number of
validations are possible. We shall deliberate over them in the pages to come. There is no
restriction on adding multiple Validation controls to an HTML control. However, it is pertinent
to note that not all HTML controls can be validated.

a.aspx
<html>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (13 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<head>
<script language="C#" runat=server>
void abc(Object S, EventArgs e)
{
if (Page.IsValid == true)
{
aa.Text = "Page is Valid!";
}
else
{
aa.Text = "Some of the required fields are empty";
}
}
</script>
</head>
<body>
<form runat="server">
<asp:Label ID="aa" text="fill it up" runat=server />
<ASP:RadioButtonList id=bb runat=server>
<asp:ListItem>a1</asp:ListItem>
<asp:ListItem>a2</asp:ListItem>
</ASP:RadioButtonList>
<asp:RequiredFieldValidator id="r1" ControlToValidate="bb" InitialValue="" runat=server>
*
</asp:RequiredFieldValidator>
<ASP:TextBox id=cc runat=server />
<asp:RequiredFieldValidator id="r2" ControlToValidate="cc" Width="100%" runat=server>
hey
</asp:RequiredFieldValidator>
<ASP:Button id=B1 text="Validate" OnClick="abc" runat=server />
</form>
</body>
</html>

Now we have presented a more complicated validation example. The two widgets that have been
used in the form are:

• A radio button that displays two values


• A textbox.

We also have to apply a validation control to each of the controls. The first validation control
has an asterick sign ( * ). The second validation control has the word 'hey'.

The validation ensures the follows:

• When no text is entered in the textbox, the word 'hey' is displayed in front of the textbox.
When the user enters some text in the textbox, the word 'hey' disappears.
• When no option is chosen in the radio button, a red coloured asterix (*) is displayed in
front of the radio button. When the user selects an option in the radio button, the *
vanishes.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (14 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

Finally, when we fill up both the controls, the page is considered valid, since all controls on the
page now contain some value or the other.

Every ASP+ page has a free variable called Page.IsValid, that tells us if all the controls on the
page contain valid data or meet the validation rules. If all the controls satisfy the validation
rules, then and only then, the free variable Page.IsValid is assigned a value of True. Otherwise,
by default, it is assigned the value of False.

Thus, after all the controls contain valid data, when we click on the button labeled Validate,
IsValid is assigned the value True. Hence, the label displays the text 'Page is Valid'.

Code can be validated either on the server or on the client. ASP+ has no knowledge of the
browser that is being used. But, if your browser supports dynamic HTML, then the HTML page
that is generated will contain a large amount of code to be executed on the browser.

In such a situation, whenever we click on a submit button, before the data can be sent to the
server, the browser code in your HTML file gets executed first. In case of any error, the form is
not sent to the server. Therefore, the data is sent to the server only if it is free from all errors.
This concept is known as Client Side Programming. Note that it is the Web Server that
generates the client side verification code.

A URL is created when we click on the Submit button. Alternatively, the same URL can be
keyed into the address bar by the user. There is no way that a web server can differentiate
between these two actions. In both these situations, the Web Server will perform the same error
checks at its end, regardless of the fact that the client has already carried out validation of all
the fields.

a.aspx
<%@ language=C# ClientTarget=DownLevel %>
<form action="a.aspx" runat="server" method=get>
<asp:RequiredFieldValidator ControlToValidate="aaa" errormessage="Please Write something"
runat=server />
<asp:textbox id="aaa" runat="server"/>
<asp:button type=submit text="Click" runat="server"/>
</form>

View Source
<form name="ctrl0" method="get" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDwtMTQ5NzczMjY1MDs7Pg==" />

&nbsp;
<input name="aaa" type="text" id="aaa" />
<input type="submit" name="ctrl2" value="Click" onclick="if (typeof(Page_ClientValidate) == 'function')
Page_ClientValidate(); " language="javascript" type="submit" />
</form>

On changing the value of the property ClientTarget to DownLevel, the contents displayed by
View-Source menuoption do not contain the Javascript code generated by the Web Server. By

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (15 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

default, this property has a value of UpLevel, which results in a request to the browser to
perform error checking on the data entered by the user.

a.aspx
<%@ language=C# ClientTarget=DownLevel %>
<html>
<head>
<script language="C#" runat=server>
void abc(Object S, EventArgs e)
{
if (Page.IsValid == true)
{
aa.Text = "Page is Valid!";
}
else
{
aa.Text = "Some of the required fields are empty";
}
}
</script>
</head>
<body>
<form runat="server">
<asp:Label ID="aa" text="fill it up" runat=server />
<ASP:TextBox id=cc runat=server />
<asp:RequiredFieldValidator id="r2" ControlToValidate="cc" Width="100%" runat=server>
hey
</asp:RequiredFieldValidator>
<ASP:Button id=B1 text="Validate" OnClick="abc" runat=server />
</form>
</body>
</html>

This program is identical to its predecessor, but with a slight modification in that, the server
performs all the validation checks and not the client. This has been achieved by assigning the
value of Downlevel to the property ClientTarget.

Previously, the form had the filename a.aspx. However, this file name has been omitted here.
Thus, when we click on the button the first time without entering any text, the function abc is
called from the server. The function fills up the label with the message 'Some of the required
fields are empty'.

When we enter some text in the textbox, and click on the button, the server receives a True
value for Page.IsValid and thus, it changes the value of the label to 'Page is Valid!'. This
happens only when the same form is sent back to the server.

a.aspx
<%@ language=C# ClientTarget=DownLevel%>
<html>
<head>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (16 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<script language="C#" runat=server>


void abc(Object Sender, EventArgs E )
{
ss.DisplayMode = (ValidationSummaryDisplayMode) aa.SelectedIndex;
}
</script>
</head>
<body>
<form runat="server">
Select Fruit
<ASP:RadioButtonList id=rr runat=server>
<asp:ListItem>Apples</asp:ListItem>
<asp:ListItem>Oranges</asp:ListItem>
</ASP:RadioButtonList>
<asp:RequiredFieldValidator id="r1" ControlToValidate="rr" ErrorMessage="Select one fruit "
InitialValue="" runat=server>
*
</asp:RequiredFieldValidator>
Enter the quantity : <ASP:TextBox id=tt runat=server />
<asp:RequiredFieldValidator id="R2" ControlToValidate="tt" ErrorMessage="Quantity cannot be blank"
runat=server>
*
</asp:RequiredFieldValidator>
<asp:ValidationSummary ID="ss" runat="server" HeaderText="You must enter a value in the following
fields:"/>
<ASP:Button id=Button1 text="Validate" runat=server />
<br>
<p>
Select display format for error messages
<asp:DropDownList id="aa" OnSelectedIndexChanged="abc" AutoPostBack =true runat=server >
<asp:ListItem>List</asp:ListItem>
<asp:ListItem selected>Bulleted List</asp:ListItem>
<asp:ListItem>Single Paragraph</asp:ListItem>
</asp:DropDownList>
</form>
</body>
</html>

We have a similar program as before, i.e. it has two controls, viz. a textbox and a radio button,
with a validator for each of them. We have also added a new tag called <asp:
ValidationSummary that has the name ss, and some text in the attribute HeaderText.

Further, a listbox having the name aa is added which contains three items. Whenever the user
changes the selection from the listbox, the function abc gets called.

The function changes the value of the attribute DisplayMode from the ValidationSummary tag,
to one of the values stated in the listbox.
The listbox conatins a list of different formating style. The attribute SelectedIndex returns the
option that is selected from the listbox.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (17 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

Thus, each time we change the item selected from the listbox, we see the error summary
displayed in different formats. As the client target property is assigned the value of DownLevel,
all error checks take place only at the server. The AutoPostBack attribute is True. This gets
converted into a select statement in HTML, with the Onchange attribute pointing to a function
called __doPostBack.

<select name="aa" id="aa" onchange="javascript:__doPostBack('aa','')">

This function reads as follows:

function __doPostBack(eventTarget, eventArgument)


{
var theform = document.ctrl2
theform.__EVENTTARGET.value = eventTarget
theform.__EVENTARGUMENT.value = eventArgument
theform.submit()
}

The function merely calls Submit with all the form parameters. This reaches the server, which
thereafter, generates a fresh page with the new format for the validation tag. This tag displays
the list of errors only if IsValid is False.

a.aspx
<%@ Page clienttarget=downlevel %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object s, EventArgs e)
{
if (Page.IsValid)
{
aa.Text = "Result: Valid!";
}
else
{
aa.Text = "Result: Not valid!";
}
}
void pqr(Object s,EventArgs e)
{
cc.Operator = (ValidationCompareOperator) bb.SelectedIndex;
cc.Validate();
}
</script>
</head>
<body>
<form runat=server>
<asp:TextBox Selected id="t1" runat="server">
</asp:TextBox><br>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (18 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<asp:TextBox id="t2" runat="server">


</asp:TextBox>
<asp:Button runat=server Text="Validate" onclick="abc" />
<asp:ListBox id="bb" OnSelectedIndexChanged="pqr" runat="server">
<asp:ListItem Selected Value="Equal" >Equal</asp:ListItem>
<asp:ListItem Value="NotEqual" >NotEqual</asp:ListItem>
<asp:ListItem Value="GreaterThan" >GreaterThan</asp:ListItem>
<asp:ListItem Value="GreaterThanEqual" >GreaterThanEqual</asp:ListItem>
<asp:ListItem Value="LessThan" >LessThan</asp:ListItem>
<asp:ListItem Value="LessThanEqual" >LessThanEqual</asp:ListItem>
</asp:ListBox>
<asp:CompareValidator id="cc" ControlToValidate ="t1" ControlToCompare = "t2" Type="String"
runat="server"/>
<asp:Label ID="aa" runat="server"/>
</form>
</body>
</html>

There are two textboxes t1 and t2, a label aa and a button in the above program. The function
abc is called whenever we click on the button. In the listbox bb, we have a large number of
options, which have names that are similar to terms used for comparison, such as Greater
Than, GreaterThanEqual, NotEqual etc.

A new ASP.Net tag <asp:CompareValidator is introduced in the program for the first time. This
tag is given the name cc along with names of two other controls, whose values have to be
compared. The controls t1 and t2 which are to be verified, are provided to the two attributes
ControlToValidate and ControlToCompare.

Whenever the user changes the selected item from the listbox, the function pqr is called. This
function initializes cc, a property operator, to the selected listbox value. Thereafter, the function
Validate from CompareValidator control compares the values. If we choose 'Equal' in the
listbox, the comparison that shall be carried out is, t1.Text == t2.Text. If it is True, then IsValid
becomes True. Otherwise, it remains false.

Clicking on the button also results in the display of a message in the label. This message
depends upon the value of IsValid. You can iteratively change the value in the listbox, and then
click on the button to ascertain the result of the comparison.

The attribute type of the control cc is 'data type String' since, the values to be compared are of
String type. However, you can modify the type of this property, to be able to compare other data
types too.

Thus, to compare any two controls, validator control is reinforced in ASP.Net.

a.aspx
<%@ Page clienttarget=downlevel %>
<html>
<head>
<script language="C#" runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (19 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

void abc(Object s, EventArgs e)


{
cc.Validate();
if (Page.IsValid)
{
aa.Text = "Result: Valid!";
}
else
{
aa.Text = "Result: Not valid!";
}
}
</script>
</head>
<body>
<form runat=server>
Value within the range of 10-20 :
<ASP:TextBox id=t3 value=20 runat=server />
<asp:Button runat=server Text="Validate" onclick="abc" />
<asp:RangeValidator id="cc" Type="Integer" ControlToValidate="t3" MaximumValue=20
MinimumValue=10 runat="server"/>
<asp:Label ID="aa" runat="server"/>
</form>
</body>
</html>

In the above program, we have used a validator called RangeValidator that checks whether the
specified value falls within a range or not. The control that is to be validated, should be
mentioned with the validator. Hence, ControlToValidate is initialized to t3. Furthermore, the
maximum value and the minimum value of the range are to be provided. This is achieved by
assigning these values to the attributes MaximumValue and MinimumValue, respectively. If the
value contained in the control t3 does not fall within the specified range, IsValid becomes False.

When the page is loaded, the third textbox has the value 20. If we change the value in the third
textbox to 15 and click on the button, the function abc is called, where the Validate function
from the control cc, checks the value contained in the IsValid property.

Earlier, we had selected an operator from a listbox. Hence, the type was a String. In this case,
since we are dealing with numbers, we change the Type property to integer.

a.aspx
<%@ Page clienttarget=downlevel %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object s, EventArgs e)
{
cc.Validate();
if (Page.IsValid)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (20 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

aa.Text = "Result: Valid!";


}
else
{
aa.Text = "Result: Not valid!";
}
}
</script>
</head>
<body>
<form runat=server>
Enter 5 digits
<ASP:TextBox id=t3 value=20 runat=server />
<asp:Button runat=server Text="Validate" onclick="abc" />
<asp:RegularExpressionValidator id="cc" runat="server" ControlToValidate="t3" ValidationExpression="^
\d{5}$" />
</asp:RegularExpressionValidator>
<asp:Label ID="aa" runat="server"/>
</form>
</body>
</html>

The validator RegularExpressionValidator, which is introduced for the first time, is employed to
validate control values. The validator simply requires the control to be validated, followed by a
regular expression.

A Regular Expression generally appears like gibberish, since it contains special characters, but
it can prove to be extremely powerful. A whole lot of books have been written on the simplicities
and the complexities of Regular Expressions.

A regular expression is an expression that matches the data entered, with a pattern or a rule.
In the above case, we want the user to enter a zip code that consists of only 5 numbers. He has
to type in exactly 5 numbers, and they must be nothing but numbers. The regular expression
will be ^\d{5}$. A caret sign ^ matches the input from the beginning of the line, while a dollar
sign $ indicates the end. \d refers to a digit, and 5 in {} braces indicates 5 occurrences of the
specified data type, i.e. 5 digits. In simple terms, only 5 digits should be entered. Thus, '^/d{5}
$' corresponds to 'start - check 5 digits - end'.

Let us look at another Regular Expression reflected on the next line.


^[\w-]+@[\w-]+\.(com|net|org|edu|mil)$

This expression verifies whether the e-mail address has been provided in the right format or
not. The square brackets agree with any one of the many characters that it embodies. \w
permits any character to be typed in. + means one or more, and the @ is an actual literal.
Round brackets with value of ( aa | bb ) will check for either aa or bb. And as mentioned
earlier, ^ marks the beginning of the line, while $ denotes the end of the line. The above Regular
Expression will match an e-mail address exactly with the pattern specified. This is just a
preface to regular Expressions. There is a lot more to it than meets the eye at present. However,
this introduction shall suffice for the time being.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (21 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

a.aspx
<html>
<head>
<script language="C#" runat=server>
void pqr(object sender, EventArgs e)
{
aa.Text = " ";
if (Page.IsValid)
aa.Text = "Page is valid!";
}
</script>
</head>
<body>
<form runat="server">
Enter a number greater than 100<p>
<asp:Label id=aa runat="server" /><br>
<asp:TextBox id=bb value=1000runat="server" />
<asp:CustomValidator id="cc" runat="server" ControlToValidate="bb" ClientValidationFunction="abc" >
Number must be larger than 100
</asp:CustomValidator>
<p>
<asp:Button text="Validate" onclick="pqr" runat="server" />
<script language="javascript">
function abc(source, value)
{
if (value.Value > 100)
value.IsValid= true;
else
value.IsValid = false;
}
</script>
</form>
</body>
</html>

This program restricts data entry of any number less than 100. The error is checked at the
client end and not at the server end. Here, you are introduced to one more validator tag <asp:
CustomValidator, which accomplishes this task.

Conventionally, this tag is supplied with the control name to be validated, i.e. bb. This is
followed by the name of the function, i.e. abc, with the attribute ClientValidationFunction.

The function abc is called whenever we click on the button. This function accepts two
parameters, viz. source and value, where the first parameter is the control and the second one
is the value typed in that control. The code entered in this function is in Javascript, a language
that is easier to learn than C#. In Javascript, variables do not have any type and functions are
at liberty to return values of any type. If the value.IsValid is initialized to True, the value in the
control passes the validation check. If it is given a value of False, then it fails the validation
check. Thus, if the value of variable source is larger than 100, a value of True is returned. If not

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (22 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

then a value of False is returned. In the case of the function abc in Javascript, the View-Source
menuoption shows code that is similar to what we had entered in aspx.

Thus, we have clearly demonstrated how to build your own custom error checks.

a.aspx
<html>
<head>
<script language="C#" runat=server>
void pqr(object sender, EventArgs e)
{
if (Page.IsValid)
{
aa.Text = "Page is valid!";
}
else
{
aa.Text = "Page is not valid! :-(";
}
}
void abc (object source, ServerValidateEventArgs value)
{
int n = Int32.Parse(value.Value);
if (n > 100)
value.IsValid = true;
else
value.IsValid = false;
}
</script>
</head>
<body>
<form runat="server">
<asp:Label id=aa runat="server" /><br>
<asp:TextBox id=bb runat="server" />
<asp:CustomValidator id="cc" runat="server" ControlToValidate="bb" OnServerValidate="abc" >
Number must be larger than 100
</asp:CustomValidator>
<asp:Button text="Validate" onclick="pqr" runat="server" />
</form>
</body>
</html>

How do we achieve the same validation on the Server? To do so, CustomValidator takes an
additional attribute called OnServerValidate, which is initialized to the function abc. Thus, each
time we click on the button, data is retransmitted to the function abc, which is located on the
server. On being called, the function abc checks the number. Thereafter, the function pqr is
called. If the function abc returns true, IsValid in pqr becomes true.

C# code never gets executed on the client-side. It is the Web Server's responsibility to parse the
C# code and create the correct HTML file. The View-Source menuoption will substantiate this

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (23 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

fact.

Functional Controls
Buttons
a.aspx
<html>
<body>
<asp:Button id=Button1 runat="server" Text="vijay" onmouseover="this.style.backgroundColor='yellow'"
onmouseout="this.style.backgroundColor='buttonface'"/>
<asp:Button id=Button2 runat="server" Text="mukhi" onmouseover="this.style.fontWeight='bold'"
onmouseout="this.style.fontWeight='normal'"/>
</body>
</html>

Output

A simple button can perform complicated tasks. The aspx file contains two button controls,
labeled vijay and mukhi. Two different properties are associated with each of them.

The button with an id of Button1, which contains the text 'vijay', has properties called
onmouseover and mouseout. The property mouseover is called when the mouse moves over the
button. At this point, we are employing this property to change the background colour of the
button to yellow. In the same vein, the property onmouseout is called when the mouse leaves
the button. Here, we utilize this property to change the colour back to normal.

In the second button, having an id of button2 and the text 'mukhi', we take the same style
property and change the font weight to bold. The 'this' keyword is optional.

a.aspx
<html>
<object id="i" class="System.Collections.ArrayList" runat=server/>
<script language="C#" runat=server>
void Page_Load(Object sender, EventArgs e) {
i.Add("a1");
i.Add("b1");
i.Add("c1");
l.DataSource = i;
l.DataBind();
}
</script>
<body>
<asp:datalist id="l" runat=server>
<ItemTemplate>
Vijay: <%# Container.DataItem %>
</Itemtemplate>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (24 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</asp:datalist>
</body>
</html>

Output
Vijay: a1
Vijay: b1
Vijay: c1

The object tag in an aspx file is used to create an object. When we work with database controls,
we will be creating an object that is an instance of a class ArrayList. Thus, by using the object
tag with the class of System.Collections.ArrayList, we do not have to create an ArrayList object
ourselves. The system accomplishes this for us. This object is called 'i' and is available in the
Page_Load function.

The framework automatically adds the line 'i = new ArrayList'. Container.DataItem retrieves
values from a list. This concept will be explained in greater detail in the database chapter.
Thus, objects can be created, using a declarative tag based syntax.
Server-side comments
a.aspx
<%@ Page Language="C#"%>
<html>
<body>
hi
<%--
Response.Write("hee);
--%>
</body>
</html>

Output
hi

One of the few things that we programmers really detest is, writing comments.

ASP+ offers us its unique facility of inserting comments in the server. Anything that is enclosed
in <%-- tags, is ignored by the server. In the above case, we consciously avoided the double
inverted commas to close the string, just to prove that the server ignores the comments. These
comments are not sent to the browser either.

Thus, we can use these comments to prevent the server from executing some part of the code.

a.aspx
<%@ Page Language="C#"%>
<html>
<body>
<!-- #Include File="a.txt" -->
<p>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (25 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

Vijay Mukhi
<p>
<!-- #Include File="b.txt" -->
</body>
</html>

a.txt
<b>Sonal Mukhi</b>

b.txt
VMCI

Output
Sonal Mukhi
Vijay Mukhi
VMCI

We can display the contents of any text file within our aspx file, by using the reserved word
'include'. The filename that we specify, gets added to our asp file. Using this facility, common
files that can be used by other ASP files, can be merged as and when required.

CheckBoxList
a.aspx
<html>
<head>
<script language="C#" runat="server">

void abc(object Source, EventArgs e)


{
for (int i=0; i < c.Items.Count; i++)
{
if ( c.Items[ i ].Selected )
l.Text = l.Text + c.Items[i].Text + "<br>";
}
}
void pqr(Object sender, EventArgs e)
{
if (cd.Checked == true)
{
c.RepeatDirection = RepeatDirection.Horizontal;
}
else
{
c.RepeatDirection = RepeatDirection.Vertical;
}
}
</script>
</head>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (26 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<body>
<form runat=server>
<asp:CheckBoxList id=c runat="server">
<asp:ListItem>vijay</asp:ListItem>
<asp:ListItem>Sonal</asp:ListItem>
<asp:ListItem>vmci</asp:ListItem>
</asp:CheckBoxList>
<br>
<asp:CheckBox id=cd OnCheckedChanged="pqr" Text="Horizontal" AutoPostBack="true" runat="server" />
<p>
<asp:Button Text="Click" onclick="abc" runat="server"/>
<p>
<asp:Label id=l runat="server"/>
</form>
</body>
</html>

Output

We have used a control CheckBoxList with an id of 'c', with 3 items in the checkbox list. A
simple checkbox has only one option, i.e. either true or false, whereas a CheckBoxList can store
multiple checkboxes.

When we click on the button, the function abc gets called. In this function, we use Count,
which is a member of the Items collection object, to control the iteration of the loops. Items[0]
references the first checkbox, while Items[1] references the second checkbox, and so on.

Every checkbox has a Selected member, that identifies whether the checkbox has been selected
or not. If it has been selected, the Text member of the checkbox is added to the text property of
the label. Thus, when the page is loaded again, all the selected items are displayed.

When we click on a checkbox which has the id as 'cd', the function pqr gets called. Here, we are
simply changing a member called RepeatDirection of the object 'c' to Horizontal or Vertical,
depending upon the state of the checkbox.

It is again upto you to decide, whether you want to use a single checkbox or a list of checkboxes.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (27 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

ImageButtons
a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(object Source, ImageClickEventArgs e)
{
Response.Write("hell");
}
</script>
</head>
<body>
<form runat=server>
<asp:ImageButton ImageUrl="/quickstart/aspplus/images/mango.jpg" onclick="abc" runat="server"/>
</form>
</body>
</html>

Output
hell

We can display a button, which has a picture on it. Whenever we click on this picture, it
behaves like a normal button and calls function abc.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(object Source, ImageClickEventArgs e) {
Response.Write("x: " + e.X.ToString() + " y:" + e.Y.ToString());
}
</script>
</head>
<body>
<form runat=server>
<asp:ImageButton id=Button1 ImageUrl="/quickstart/aspplus/images/billg.gif" onclick="abc"
runat="server" />
</form>
</body>
</html>

Output
x: 91 y:107

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (28 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

The guys at Microsoft and Mr. Bill Gates have a fine sense of humour. They have actually given
us an example that allows us to hit/click Mr Gates with a mouse. It returns the positions at
which you made the contact. We decided to play safe. When we click on the photo, it simply
tells us the x and y co-ordinates of the position at which you clicked.

The ImageClickEventArgs has a large number of members, two of them being the x and y co-
ordinates. These positions specify in pixels, the location at which we clicked on the image. What
we do with these values, is left to our discretion.

a.aspx
<html>
<head>
<style>
.aa { border:0.6cm solid blue }
.bb { border:0.2cm solid gainsboro }
</style>
</head>
<body>
<form runat=server>
<asp:ImageButton runat="server" ImageUrl="/quickstart/aspplus/images/banana.jpg"
onmouseover="this.style.border='0.2cm solid black';" onmouseout="this.style.border='0.2cm solid
gainsboro';" />
<asp:ImageButton runat="server" ImageUrl="/quickstart/aspplus/images/banana.jpg"
onmouseover="this.className='aa'" onmouseout="this.className='bb'"/>
<asp:ImageButton runat="server" ImageUrl="/quickstart/aspplus/images/banana.jpg"
onmouseover="this.src='/quickstart/aspplus/images/mango.jpg';" onmouseout="this.src='/quickstart/
aspplus/images/banana.jpg';"
/>
</form>
</body>
</html>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (29 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

We start off by displaying three image buttons, all of which display the same picture of a
banana.

The first image displays a black border when the mouse moves over it. This is because, the
onmouseover assigns a 0.2cm solid black value to the style.border property. When we move out
of the image, the grey border reappears.

In the case of the second image, a style is created in the aspx program using the style tags. This
requires two words or styles called aa and bb. We now use these styles in the mouse events.
The use of style, forms the basis of CSS or cascading style sheets.
The third image uses the onmouseover event to change the banana to a mango. The
onmouseover event changes the src property to execute this change in the image. The
onmouseout event reverts the src property back to the banana.

Panel
a.aspx
<html>
<head>
<script language="C#" runat="server">
void pqr(object Source, EventArgs e)
{
p.Visible = false;
}
void abc(object Source, EventArgs e)
{
Response.Write("hell");
Label l = new Label();
l.Text = "Sonal ";
l.ID = "Sonalid";
p.Controls.Add(l);
p.Controls.Add(new LiteralControl("<br>Vijay Mukhi <br>"));
TextBox t = new TextBox();
t.Text = "VMCI ";
p.Controls.Add(t);
}
</script>
</head>
<body>
<form runat=server>
<asp:Panel id="p" runat="server" Height="200px" Width="300px">
Vijay Mukhi
</asp:Panel>
<asp:Button Text="Add Controls" onclick="abc" runat="server"/>
<asp:Button Text="Hide" onclick="pqr" runat="server"/>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (30 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</form>
</body>
</html>

A Panel control places different controls in one widget. We have created a panel control called
'p', and initialized its height and width properties to specific values. Two buttons named Add
Controls and Hide have also been introduced. Clicking on the Add button results in a call to the
abc function.

Within this function, we first create a Label and initialize the Text member to Sonal. The text is
given an id of Sonalid. After initializing the members with the values, the control is added to the
Panel, by using Add function.

Similarly, an instance of a LiteralControl is created and added to the Panel. The text passed on
to the constructor gets displayed in the Panel. Finally, a textbox is created.

Panel and many other controls have a property called Visible. When this property is set to false,
it hides the control. This is one of the powerful features of a panel. By changing a single
property, a large number of controls simply vanish. Hence, the look and feel of the page gets
transformed completely.

Radio Buttons
a.aspx
<html>
<script language="C#" runat="server">
void SubmitBtn_Click(Object Sender, EventArgs e)
{
if (r1.Checked)
{
Response.Write("one");
}
else if (r2.Checked)
{
Response.Write("two");
}
else if (r3.Checked)
{
Response.Write("three");
}
}
</script>
<body>
<form runat=server>
<asp:RadioButton id=r1 Text="Vijay" Checked="True" GroupName="rrr" runat="server" />
<br>
<asp:RadioButton id=r2 Text="Mukhi" GroupName="rrr" runat="server"/>
<br>
<asp:RadioButton id=r3 runat="server" Text="Sonal" GroupName="rrr" />

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (31 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<br>
<asp:button text="Submit" OnClick="SubmitBtn_Click" runat=server/>
</form>
</body>
</html>

Output

A checkbox is used whenever the answer is to be returned as either yes or no, i.e. true or false.
If a choice has to be made from amongst multiple options, a radio button is used instead.

In this program, 3 radio buttons with ids r1, r2, r3 are created with some text. The checked
property of the first radio button is set to true. These radio buttons are then grouped together
by initializing the GroupName, to a common value named rrr.

When we click on the button, the function SubmitBtn_Click is called. Using the 'if' statement,
the Checked property of each radio button, is determined and displayed using a Write
statement. This is a tedious process. In a RadioButton Group, only one radio button can be
chosen at a time.

Calendar
a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(object sender, EventArgs e) {
switch (c.SelectedDates.Count)
{
case (0):
l.Text = "No dates are currently selected";
break;
case (1):
l.Text = "The selected date is " + c.SelectedDate.ToShortDateString();
break;

case (7):
l.Text = "The selection is a week beginning " + c.SelectedDate.ToShortDateString();
break;
default:
l.Text = "The selection is a month beginning " + c.SelectedDate.ToShortDateString();
break;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (32 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

}
</script>
</head>
<body>
<form runat=server>
<asp:Calendar id=c runat="server" onselectionchanged="abc" DayNameFormat="Short"
SelectionMode="DayWeekMonth"
TodayDayStyle-Font-Bold="True" DayHeaderStyle-Font-Bold="True" OtherMonthDayStyle-
ForeColor="gray"
TitleStyle-BackColor="#3366ff" TitleStyle-ForeColor="white"
TitleStyle-Font-Bold="True" SelectedDayStyle-BackColor="#ffcc66"
SelectedDayStyle-Font-Bold="True" NextMonthText = "<img src='/quickstart/aspplus/images/
monthright.gif' border=0>"
PrevMonthText = "<img src='/quickstart/aspplus/images/monthleft.gif' border=0>" SelectorStyle-
BackColor="#99ccff"
SelectWeekText = "<img src='/quickstart/aspplus/images/selweek.gif' border=0 onmouseover=this.
style.backgroundColor='#ffcc66' onmouseout=this.style.backgroundColor='#99ccff'>"
SelectMonthText = "<img src='/quickstart/aspplus/images/selmonth.gif' border=0 onmouseover=this.
style.backgroundColor='#ffcc66' onmouseout=this.style.backgroundColor='#99ccff'>"
/>
<asp:Label id=l runat="server" />
</form>
</body>
</html>

Output

The selected date is 05/09/2001

We could write a thesis on the options of a calendar control. Some programmer must have
spent years writing this control.

Irrespective of the week or day or month that we select, the function abc gets called. In this
function, a member called c.SelectedDates.Count tells us the day or the month that was
selected. This is displayed with a relevant message on the browser screen. Further, the date
that has been selected is shown highlighted in the calendar.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (33 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

<html>
<body>
<form runat=server>
<asp:Calendar runat="server" SelectionMode="DayWeekMonth" SelectWeekText = "vijay"
SelectMonthText = "month"/>
</form>
</body>
</html>

Output

We have a simple calendar that uses the SelectionMode property as DayWeekMonth. Thus, all
the three entities viz. day, week and month are displayed and underlined. As we have initialized
the property SelectWeekText to 'vijay', each time we click on it, the entire week gets highlighted.
Similarly, when we click on the month, the entire month gets selected.

There is not a single aspect that has not been catered for in the calendar control. It is extremely
comprehensive.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(object sender, DayRenderEventArgs e)
{
CalendarDay d = ((DayRenderEventArgs)e).Day;
Response.Write(d.Date.Month.ToString() + " " + d.Date.Day.ToString());
TableCell c = e.Cell;
String h = "Vijay " + d.Date.Day.ToString() + "<br>";
c.Controls.Add(new LiteralControl(h));
}
</script>
</head>
<body>
<form runat=server>
<asp:Calendar id=Calendar1 runat="server" ondayrender="abc"/>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (34 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</form>
</body>
</html>

Each time that the calendar displays a date, it calls a function specified in the property
ondayrender. This function is passed a DayRenderEventArgs parameter named 'e'. This object
has a property called Date, and has two members called Month and Day. These two members
give the current month and day.

This function gets called for each and every date that is displayed. We simply use the Cell
property to return a TableCell object. The Add function of the Controls member is used to add
other controls to the Table Cell.

Here, we are simply adding a Literal Control with Vijay and the current Date. The Microsoft
example adds a holiday. The basic idea is that we can add anything that we like, to the cell or
the date that is displayed.

Hyperlink
a.aspx
<html>
<script language="C#" runat=server>
void Page_Load(Object sender, EventArgs e)
{
l.NavigateUrl = "/QuickStart";
}
</script>
<body>
<form runat=server>
<asp:hyperlink id=l runat="server">
Vijay Mukhi
</asp:hyperlink>
</form>
</body>
</html>

View Source
<html>
<body>
<form name="ctrl2" method="post" action="a.aspx" id="ctrl2">
<input type="hidden" name="__VIEWSTATE"
value="YTB6MTQ5MzQ0OTE2OF9hMHpfaHo1ejJ4X2Ewel9oejV6MXhfYTB6YTB6aH
pOYXZpZ2F0ZVVybF8vUXVpY2tTdGFydHhfX3hfX3h4X3h4X3hfX3g=d6300be0" />
<a id="l" href="/QuickStart">
Vijay Mukhi
</a>
</form>
</body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (35 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</html>

Output
Vijay Mukhi

A hyperlink control is similar to <a href tag in HTML. We have created a hyperlink tag called l.
In the function Page_Load, we have initialized the property NavigateUrl to /Quickstart. We
could have initialized this property in the tag itself. Since Page_Load gets called initially at the
server end, the HTML file that gets generated, has this URL specified in the <a href...> tag.

The View-Source confirms that pure HTML files are generated by the web server. At times, we
may have a dash of JavaScript. The hidden tag called ViewState is used to maintain state
between the browser and the server. The value field uniquely identifies each browser session.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
Response.Write("hell");
}
</script>
</head>
<body>
<form runat=server>
<asp:LinkButton Text="Vijay Mukhi" onclick="abc" runat="server"/>
</form>
</body>
</html>

Output
hell
Vijay Mukhi

We can have buttons of all types and sizes. The control LinkButton looks like a hyperlink, but it
is actually a button. The common adage that "if it walks like a duck, quacks like a duck, it is a
duck", does not hold water for a LinkButton. If we click on it, the function abc gets called. We
are not redirected to another URL, as we may have expected.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(object Source, EventArgs e)
{
f.PostedFile.SaveAs("c:\\" + t.Value);
Response.Write("File uploaded successfully to c:\\"+ t.Value + " on the web server");
}
</script>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (36 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

</head>
<body>
<form enctype="multipart/form-data" runat="server">
Select File to Upload:
<input id="f" type=file runat="server">
<p>
Save as filename :
<input id="t" type="text" runat="server">
<p>
<input type=button value="Upload" OnServerClick="abc" runat="server">
</form>
</body>
</html>

The input tag with the type initialized to 'file', has an id of 'f'. Since the type is file, we see a
textbox, as well as, a button labeled Browser. When we click on this button, we see a dialog box
that enables us to choose the file name.

After selecting a file, click on the button labeled Upload. This calls the function abc, where the
control 'f' calls a function SaveAs, using its property PostedFile. The function saves the file on
the web server's hard disk in the root directory. Thereafter, we simply display a simple message,
that the file has been copied in C:\. The <input type=file.. is handled locally by the browser.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(object Source, EventArgs e)
{
if (Page.IsPostBack)
{
ss.InnerHtml="value: " + h.Value ;
}
}
void abc(object Source, EventArgs e)
{
h.Value=s.Value;
}
</script>
</head>
<body>
<form runat=server>
<input id="h" type=hidden value="Vijay" runat=server>
<input id="s" type=text size=40 runat=server>
<input type=submit value="Enter" OnServerClick="abc" runat=server>
<span id=ss runat=server>sonal mukhi</span>
</form> </body>
</html>
We have an HTML control, with an id of 'h' and type as 'hidden'. Hidden types are not displayed
in the browser window. This control is given an initial value of 'Vijay'.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (37 of 38)2/13/2007 4:58:14 PM


Server Controls - ASP.NET - Beta2

We then have a textbox named as 's', followed by a button. If we click on the button, the
function abc gets called. This function simply picks up the text entered into the textbox and
assigns it to the hidden field.

The Page_Load function uses the span field 'ss' ,to display the value contained the hidden field.
As Page_Load is called first, the span field displays the previous value of the textbox. This is
because the function abc initializes the hidden control to the new value, subsequently. Thus,
we can use hidden fields to transfer data from the web browser to the web server, keeping the
user oblivious to it.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap2.htm (38 of 38)2/13/2007 4:58:14 PM


Writing our own Web Controls - ASP.NET - Beta2

-3-

Writing our own Web Controls


So far, we have been exclusively using controls provided by Microsoft. Since they are web
based, they are also termed as Web Controls. In this chapter, we will show you how to create
your own web control. Any Web Form can be modified to become a Web Control. A Web Form
that is used as a server control is termed as a user control.

a.aspx
<%@ Language="C#" %>
<%@ Register TagPrefix="vijay" TagName="sonal" Src="a1.ascx" %>
<html>
hi <br>
<vijay:sonal runat="server"/>
</body>
</html>

a1.ascx
Great ASP+ book

Output
hi
Great ASP+ book

Nothing can be simpler than creating a user control. We first need a tag or a tag prefix to
identify the control. In the previous chapter, all ASP+ controls started with the tag prefix asp:.
This tag prefix was then followed by the word button or textbox. These type of words are given
the nomenclature of tag names.

In the case of user controls, we initially need to register our control with ASP+. To achieve this,
a directive called Register is used. It is followed by the attributes TagPrefix, TagName and Src.
Register is known as a directive because it is preceded by the @ sign. TagPrefix and TagName
are initialized to vijay and sonal, respectively. So, the tag usage will now be vijay:sonal. Finally,
it is essential to provide the file name of the file that contains the source code of our control. To
accomplish this, Src is initialized to a1.ascx.

By convention, we shall always name our source code file as a1.ascx. The big boys at Microsoft
have requested the developers to standardize the file extension as ascx, but this is not
mandatory. The file a1.ascx has only a single line of text i.e. Great ASP+ book. Hence, the
output replaces the control tag vijay:sonal with this line. Life could not get any simpler !

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (1 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>


<html>
hi <br>
<form runat="server">
<vijay:mukhi id="aaa" runat="server"/>
<br>
</form>
</body>
</html>

a1.ascx
<script language="C#" runat="server">
public String Color = "blue";
</script>
The color property is <%= Color %>

Output
hi
The color property is blue

This program associates a property called Color with the control. A property can be introduced
by simply adding a public variable in the ascx file, and then displaying it using <%=. Here, the
public variable Color is initialized to blue. Hence, we catch sight of the colour blue in the
browser. This simple act of creating a public variable, which gets converted into a property, can
also be used with tags created by us. The next program illustrates this point.

a.aspx
<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>
<html>
hi <br>
<form runat="server">
<vijay:mukhi id="aaa" Color="green" runat="server"/>
<br>
</form>
</body>
</html>

Output
hi
The color property is green

The original value of the property can be overwritten in the tag. Hence, we see the value as
green and not blue.

a.aspx
<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>
<script language="C#" runat="server">
void abc(Object s, EventArgs E)
{
aaa.Color = "red";

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (2 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

}
</script>
<html>
hi <br>
<form runat="server">
<vijay:mukhi id="aaa" Color="green" runat="server"/>
<br>
<asp:button text="Change " OnClick="abc" runat=server/>
</form>
</body>
</html>

Output
hi
The color property is red

Bear in mind that there is no distinction between the properties created by us and the built-in
properties of the tag. Thus, in the function abc, we can modify the value of the property Color to
red. The new values override the default ones.

a.aspx
<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>
<script language="C#" runat="server">
void abc(Object s, EventArgs E)
{
aaa.Color = "red";
}
</script>
<html>
hi <br>
<form runat="server">
<vijay:mukhi id="aaa" Color="green" runat="server"/>
<br>
<asp:button text="Change " OnClick="abc" runat=server/>
</form>
</body>
</html>

a1.ascx
<script language="C#" runat="server">
String aa = "blue";
public String Color
{
get
{
return aa;
}
set
{
aa = value;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (3 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

}
</script>

The color property is <%= Color %>

We start with the output window displaying the following output:

Output
hi
The color property is green

And after we click on the button, the output that is now displayed, is as follows:

Output
hi
The color property is red

We have carried out numerous modifications to the file a1.ascx, but we have left the file a.aspx
untouched.

The C# programming language understands properties and uses keywords/accessors like 'get'
and 'set' to operate upon them. Since the language used in the ASP+ file is given as C#, this
feature can easily be exploited to act upon the tag properties.

In the ascx file, the local variable aa is initialized to the value blue. On the next line, the
statement commences with the word 'public' associated with the Color property and with the
return value as String.

A property can either be used on the left or the right side of an = sign. If it is on the left, then it
is being assigned a value. So, when we write Color="blue" in a tag, we are setting the value of
the property Color to blue, which is a string. ASP+ uses the set accessor to store the value into
the property. The variable aa contains the value blue. Hence, the property Color is initialized to
blue.

When a property is placed on the right side of the 'equal to' sign, it will return the value
contained in it. In the aspx file, <%= Color> is used to obtain the current value of the property
Color. Accordingly, ASP+ calls the 'get' accessor. The only statement within 'get' is 'return aa'
which will return the value stored in aa to the aspx file.

Apparently, both the techniques that used to create a property, appear identical; however,there
is a subtle difference. In the first case, we are merely changing the value of a variable, whereas,
in the second instance, we are calling functions.

A function can contain and execute innumerable lines of code. These statements can perform
error checks and ensure that the user does not infringe on the permissible values of the
property. A similar paradigm is noticeable in the highly successful Microsoft product, Visual
Basic, which extensively supports the concept of properties.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (4 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>


<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs E)
{
if (Page.IsPostBack)
{
Response.Write("true a.aspx");
aa.Text = bb.Password;
}
else
Response.Write("false a.aspx");
}
</script>
<form runat="server">
<vijay:mukhi id="bb" Password="hell" runat="server"/>
</form>
<asp:Label id="aa" runat="server"/>
</body>
</html>

a1.ascx
<script language="C#" runat="server">
public String Password
{
get
{
return Pass.Text;
}
set
{
Pass.Text = value;
}
}
</script>
<ASP:TextBox id="Pass" TextMode="Password" runat="server"/>
<ASP:Button Text="Submit" runat="server"/>

Output
false a.aspx

The file a.aspx has a custom tag called vijay:mukhi. It has an id of bb and a property called
password, which has been initialized to 'hell'.

Since the label aa has no value, Page_Load does not display any text when the page is loaded.
Since the file a.aspx has been requested for, from the server by writing the url as http://
localhost/a.aspx, (submit button is not used), the property IsPostBack is false. Hence, the
output is depicted as false.

The source code file a1.ascx has a property called password, which is declared public and

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (5 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

which returns a String. In order to initialize and retrieve values of the property, a textbox with
an id of Pass is used instead of a variable. Since the TextMode is Password, the characters that
are keyed in are not visible.

Further, a button labeled as 'submit' has been added to the ascx file to take us back to the
server. Therefore, an existing control can be used to hold a value.

A user control can accommodate multiple controls. The View-Source too does not spring up any
surprises.

View-Source
false a.aspx
<html>
<form name="ctrl1" method="post" action="a.aspx" id="ctrl1">
<input type="hidden" name="__VIEWSTATE" value="YTB6MTI3MTQyMTk4M19fX3g=d6c4c93a" />

<input name="bb:Pass" type="password" value="hell" id="bb_Pass" />


<input type="submit" name="bb:ctrl1" value="Submit" />
</form>
<span id="aa"></span>
</body>
</html>

In the ascx file, the textbox was assigned the id of Pass, and the control name in a.aspx name
was bb. Hence, in the HTML file generated by the server, it is termed as bb:Pass. This is done
merely to maintain the sanctity of names, as the same name could have been assigned to the
textbox in both the files. When we type hell in the textbox and click on the button, the output
that is displayed is as follows:

Output
True a.aspx
Hell

When we click on the submit button, the file a.aspx is called. Since the button is responsible for
calling the a.aspx file, the property IsPostBack is assigned a value of true. Hence, True is
displayed. The label in Page_Load is initialized to the password 'hell' because our textbox
contains the word 'hell'.

Had we modified this value, we would not have been in such a muddle. Instead, the label would
have displayed these values too. All this happens only on the server. An ascx file can definitely
contain code that is normally written in an aspx file.

a.aspx
<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs e)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (6 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

{
if (Page.IsPostBack)
Response.Write("true1");
else
Response.Write("false1");
}
</script>
<form runat="server">
<vijay:mukhi runat="server"/>
</form>
</body>
</html>

a1.ascx
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs e)
{
if (Page.IsPostBack)
Response.Write("true");
else
Response.Write("false");
}
void abc(Object sender, EventArgs e)
{
Response.Write(aa.SelectedItem.Value);
}
</script>
<ASP:DropDownList AutoPostBack="true" id="aa" OnSelectedIndexChanged="abc" runat="server">
<ASP:ListItem value="business">Business</ASP:ListItem>
<ASP:ListItem value="trad_cook">Traditional Cooking</ASP:ListItem>
<ASP:ListItem value="mod_cook">Modern Cooking</ASP:ListItem>
</ASP:DropDownList>

Output
false1falsetrad_cook

Along with properties, a user control can also have events associated with it. In fact, it can
contain every feature that is usually built into a tag. We can implement our own callbacks also.
The above example amply validates this feature.

We have integrated a listbox in our control and associated a function abc with it. With every
change in the item that is selected from the options in the listbox, abc shall be called.

Both files have a Page_Load function. It is relatively easy to verify which Page_Load function
gets invoked first. This can simply be accomplished by placing a Write function with each of
these functions, and verifying the output by determining the order in which they are being
executed.

The output lucidly and comprehensively demonstrates that the Page_Load, which forms the
part of the main file a.aspx, is summoned first, followed by the user controls. Moreover, as we

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (7 of 8)2/13/2007 4:54:19 PM


Writing our own Web Controls - ASP.NET - Beta2

keep changing the current selection, the abc function gets called repeatedly, resulting in the
display of the newly selected values.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap3.htm (8 of 8)2/13/2007 4:54:19 PM


Classes - ASP.NET - Beta2

-4-

Classes
In the earlier chapters, we had exploited the existing C# classes like String and int, which were
utilized to display text and values. In this chapter, we shall focus on creating our own classes.

a.aspx
<%@ Inherits="zzz" Src="b1.cs" language=C# %>

b1.cs
public class zzz
{
}

Output
Parser Error Message: 'zzz' is not a valid base class because it does not extend class 'System.Web.UI.
Page'.

So far, we have learnt about the 'language' attribute with the ASP directive, which is used to
specify the programming language that we shall be using in the file. The 'language' attribute
was initialized to C#, thereby signifying that the rules of C# will be applicable on the code
inserted with the aspx tags.

We now introduce two more attributes in addition to the 'language' directive.


• inherits - This attribute requires the name of a class and hence, we have provided the
name zzz.
• src - This attribute is initialized to b1.cs, which is a program file that contains the class.

A class is a collection of variables and methods, which have been bunched together. It can
therefore be considered as a container of things.

The file b1.cs is a C# file which contains the syntax 'public class zzz', followed by a pair of curly
braces. The keyword 'class' results in the creation of a class called zzz. The curly braces signify
the beginning and end of a class. Currently, the class that we have created does not contain
any variables or methods.

Thus, we can conclude that the integer class was created through the syntax 'class int', while
the string class was created through the use of the syntax 'class string'. There is no other
procedure available, to create a class. The rules that apply to one class are common to the rest
of the classes in C#. All the code in the C# language is contained in classes only.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (1 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

In the above program, an error is generated, since ASP+ does not expect an empty class. It
expects the class to contain variables and functions that it needs to invoke. However, they are
not currently present in the class. Since there is a paucity of time, and moreover, due to lack of
perseverance that is vital for writing all this code ourselves, we shall borrow code from an
existing class that contains the relevant functions and variables.

To inherit or borrow from another class, we have to make one small amendment to the source
code in the file b1.cs.

b1.cs
public class zzz : System.Web.UI.Page
{
}

There exists a free class called System.Web.UI.Page that has been written by the programmers
at Microsoft. This class has all the functions that ASP+ requires. To inherit or borrow from an
existing class, we are required to place a colon : after the name of the class (as in zzz), and then
specify the class that we want to inherit from, i.e. System.Web.UI.Page. You may have noticed
that, for the Page class, the name System.Web.UI.Page is an extended one. We shall look into
the reasons for the same, a little later.

Technically, we can say that the class zzz derives from class Page. This implies that all the
methods and variables of class Page are now available to class zzz also. In a sense, it is akin to
writing all the methods and variables in the zzz class, by ourselves. When we derive from the
class Page, whatever is contained in the class, also exists in the derived class zzz, making it a
rich class.

The word 'public', which precedes the class name, is an access modifier. Access modifiers are
used to restrict access to a class, since it may not be desirable to allow everyone to access the
class. The access modifier 'public' facilitates anyone and everyone to access the class. On
making these changes to the source code, no errors are generated when we run our program.

a.aspx
<%@ Inherits="zzz" Src="b1.cs" language=C# %>
<form action="a.aspx" runat="server">
<asp:button type=submit text="Click" OnClick="abc" runat="server"/>
</form>

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object a, System.EventArgs e)
{
Response.Write("hi");
}
}

After every click on the button, you will see the word 'hi' displayed. Let us now understand how
the button works. Each time we click on a button, the function abc is called, since it is

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (2 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

associated with the attribute OnClick.


You will not notice words such as, 'script' in the aspx file because the function code is not
present in a.aspx. It is located in the class zzz, which is present within the src file named b1.cs.
As you must have noticed, this function resides within the class zzz.

The 'inherits' attribute makes the code, which is present in the class zzz of the file b1.cs,
accessible to the aspx file. Now, the function abc does not generate any error, since it meets its
match and displays 'hi' in the browser window.

This is fascinating because it demonstrates that all the code within a C# file, can now be used
with ASP+. So, let us now expand our horizons about the basics of C# programming. We shall
leave a.aspx untouched for a long while, and modify the file b1.cs progressively, to explain
certain issues related to the C# programming language.

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object o, System.EventArgs e)
{
yyy a;
}
}

Output
Compiler Error Message: CS0246: The type or namespace name 'yyy' could not be found (are you
missing a using directive or an assembly reference?)

In b1.cs, we are trying to create an object 'a', that is an instance of a class yyy. But, the output
displays an error, stating that C# is unaware of the class yyy.

The occurrence of this error is understandable, because C# may be well informed about, and
familiar with classes such as Page and a vast number of built-in classes, but it definitely is not
familiar with a user-defined class called yyy.

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object o, System.EventArgs e)
{
yyy a;
}
}
public class yyy
{
}

You may be able to recall what we had mentioned a little while ago, that, the only way to create
a class is by using the keyword 'class', followed by the class name. It cannot get simpler than
this. Thus, no more errors are generated.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (3 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object o, System.EventArgs e)
{
yyy a;
a.pqr();
}
}
public class yyy
{
public void pqr()
{
Response.Write("hell");
}
}

Output
Compiler Error Message: CS0165: Use of unassigned local variable 'a'

It is not a child's play to learn a programming language, especially when it also entails
deciphering cryptic errors. What does the error message 'unassigned local variable' signify? If
you may recall, in chapter 2, we had created a variable i of type int, and called the ToString
function off it. In a similar manner, we have now created a variable a of type yyy and have
called the function pqr off it. So, why is it that an error is generated now, while it was not
generated in the earlier instance?

The answer lies in the manner in which C# works internally. It divides all the classes it
recognizes, into two types, i.e. value types and reference types. Classes like int, bool and string,
which are called basic classes, are of value type, and all the other classes are of reference type.

A value type variable is created when we declare it. This means that i comes into existence and
occupies memory space when we declare it, using the syntax 'int i'. No extra code has to be
added after that, to create this.

In the case of a reference type variable, C# is first informed about the data type of the variable
that we want to create, and also the variable name that we would use to reference it. This
happens when we use the statement yyy a. In the next round, the keyword 'new' or a function
has to be used to formerly bring the variable into existence, and then it is to be assigned a
memory location, to enable it to reference members of the specified data type.

Note, that unless the second step is executed, the members in the class remain inaccessible to
the object.

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object o, System.EventArgs e)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (4 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

{
yyy a;
a = new yyy();
a.pqr();
}
}
public class yyy
{
public void pqr(){
}
}
No errors are visible any longer. It is because we have used the keyword 'new' to create an
object 'a', which looks like yyy. In technical jargon, 'a' is now an instance of class yyy. Thus, the
only way to create an object is, by using the keyword 'new', followed by the name of the class.
Thereafter, we have to use a pair of opening and closing curly braces to encompass the actual
code of the class.

The instance 'a' now stores the return value of 'new', which is a memory location. Henceforth, it
can be used to refer to all the members in the class.

b1.cs
public class zzz : System.Web.UI.Page
{
public void abc(System.Object o, System.EventArgs e)
{
xxx a;
a = new xxx();
a.pqr();
}
}
public class yyy
{
public void pqr()
{
}
}
public class xxx : yyy
{
}

In this program, we have gone a step further. The instance 'a' looks like xxx instead of yyy, and
the function pqr is called from class xxx. The class xxx is derived from class yyy, following the
simple rule of placing a colon first, followed by the name of the class yyy. Thus, the class xxx
inherits all members of class yyy. For the moment, the class yyy has only one function called
pqr, which the class xxx 'inherits'. Therefore, even though the class xxx does not contain the
function pqr, the object 'a' of type xxx can call it, which is because the class xxx inherits the
same from the class yyy.

We need to explore the C# programming language in greater depth to be able to fully


understand what ASP.NET does with the C# code written in a .cs file. In order to steer clear of

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (5 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

clutter, we have created a sub directory called aaa in the root where we have written the
following program in a file called b1.cs.

c:\>md aaa
c:\aaa>edit b1.cs

b1.cs
public class zzz
{
}

This program is very similar to the ones we have written earlier. The code written in a .cs file
must be converted into an executable program, as the web server and the web browser are not
involved here. To create an executable file, we use the command csc along with the file name. In
simple terms, the command csc can be called a program which creates an executable, but in
the context of the C# programming language, it is identified as the C# compiler. Thus, the
command is as follows: C:\aaa>csc b1.cs

Output
Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]
Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
error CS5001: Program 'b1.exe' does not have an entry point defined

The compiler reports an error, since there is no 'entry point' defined in the exe file. What is an
entry point? Whenever a C# program begins execution, it starts execution from a base function.
This base function is called an entry point function.

Here, we are getting into the details of the C# programming language, because all the code
written in ASP+ is first converted into C# code and then executed.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
}
}

Output
hi

Akin to the pqr function in yyy, we have introduced a function called Main within zzz in the file
b1.cs. This function calls another function named System.Console.WriteLine. System.Console.
WriteLine comprises of a parameter, which is a string called 'hi'. The compiler now successfully
generates 'b1.exe' in the same subdirectory, without displaying any error messages. If you run
this program at the command prompt, using the command 'c:\aaa>b1', the output displayed
will be the word 'hi'. This proves that Main is the base function or the entry point in any C#
program.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (6 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

You may have noticed that the System.Console.WriteLine function in a.cs program, behaves like
the Response.Write function of ASP+.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
abc();
}
public void abc()
{
System.Console.WriteLine("abc");
}
}

Output
b1.cs(6,1): error CS0120: An object reference is required for the nonstatic field, method, or property
'zzz.abc()'

Despite having reiterated this concept on numerous occasions, we shall go over it once again,
that 'Only an object i.e. an instance of a class, is allowed access to the members of that class'.
Thus, in the above program, we are not allowed to call the function abc, since we have still not
created an instance of the class zzz.

However, there is an exception to this rule, which we shall introduce in the next program.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
abc();
}
public static void abc()
{
System.Console.WriteLine("abc");
}
}

Output
hi
abc

We have added the keyword 'static' to the function abc. The keyword 'static' allows access to
functions or variable, even though, an instance of the class wherein it is contained, has not
been created. Hence, no error is generated. First the word 'hi' is displayed on the screen, which

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (7 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

is followed by the word 'abc'.

We shall employ one more program to demonstrate the functionality of the keyword 'static'.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
yyy.abc();
yyy a;
a = new yyy();
a.pqr();
}
}
public class yyy
{
public static void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}

Output
hi
abc
pqr

In the class yyy, we have two functions:

• The function abc, which has the static keyword.


• The function pqr, which is non-static.

To summon a static function, we simply use the name of the class, followed by the function
name i.e. yyy.abc. Since the function abc is static, there is no need to create an object that is an
instance of the class yyy. In short, a static function is associated with a class and not with an
object.

In the case of the function pqr, the rules get transformed completely. Since pqr is a non-static
function, we have to first create an object 'a' that is an instance of class yyy, and then use the
object to call the function pqr. The syntax is as follows: a.pqr().

b1.cs
public class zzz

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (8 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

{
public static void Main()
{
System.Console.WriteLine("hi");
yyy.abc();
yyy a;
a = new yyy();
a.pqr();
}
}
namespace aaa
{
public class yyy
{
public static void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}
}

Output
Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914]
Copyright (C) Microsoft Corp 2000-2001. All rights reserved.
b1.cs(6,1): error CS0246: The type or namespace name 'yyy' could not be found (are you missing a
using directive or an assembly reference?)
b1.cs(7,1): error CS0246: The type or namespace name 'yyy' could not be found (are you missing a
using directive or an assembly reference?)
b1.cs(8,1): error CS0103: The name 'a' does not exist in the class or namespace 'zzz'
b1.cs(9,1): error CS0246: The type or namespace name 'a' could not be found (are you missing a using
directive or an assembly reference?)
On adding the words 'namespace aaa' to the program, we obtain four errors. Why does this
happen? The answer reveals itself in the next program.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
aaa.yyy.abc();
aaa.yyy a;
a = new aaa.yyy();
a.pqr();
}
}
namespace aaa

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (9 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

{
public class yyy
{
public static void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}
}

Output
hi
abc
pqr

The errors have disappeared. This could only be achieved by preceding the class name, i.e. yyy
in Main, with the namespace aaa, and then using the dot as the delimiter. Here, aaa is called a
namespace.

The concept of a namespace is very simple.


Let us presume that in the .NET world, there are a million functions. A programmer will go
bonkers trying to recollect the names of all these functions, along with the names of their
respective classes. It surely makes more sense to tidy them up by organizing them in a
systematic and logical fashion?

All printing functions can be placed in one category, while all functions that write to a file can
be placed in another category. Instead of christening this type of classification as 'categories',
the C# programming language makes use of the term 'namespace'. To use a class belonging to a
particular namespace, we have to use the format 'namespace.class'.

As our class yyy belongs to the aaa namespace, the full name of the class becomes aaa.yyy, and
not merely yyy.

b1.cs
public class zzz {
public static void Main(){
System.Console.WriteLine("hi");
aaa.bbb.yyy.abc();
aaa.bbb.yyy a;
a = new aaa.bbb.yyy();
a.pqr();
}
}
namespace aaa{
namespace bbb{
public class yyy

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (10 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

{
public static void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}
}
}
Output
hi
abc
pqr

We can nest namespaces to as many levels as desired. Here, we have a primary namespace
called aaa containing a secondary namespace called bbb. The full name of our class yyy
therefore becomes aaa.bbb.yyy, and the static function abc can be called using aaa.bbb.yyy.
abc.

Whenever we read an entity in C#, we read it backwards, i.e. from right to left. We have the
name of the function at the right most end. This is preceded by the name of the class, and the
class name is preceded by the name of the namespace.

In the past, whenever we had derived from System.Web.UI.Page, Page was the name of the class
and System.Web.UI was the name of the namespace.

Similarly, in the case of Response.Write, Response is the name of a class, while Write is a static
function contained in it. In the past, we had deliberately tried to shield you from these
complicated and perplexing concepts. This was for the simple reason that, we believe in
divulging such intricate concepts only when the time is right for them to be appreciated.

b1.cs
using aaa.bbb;
public class zzz
{
public static void Main()
{
System.Console.WriteLine("hi");
yyy.abc();
yyy a;
a = new yyy();
a.pqr();
}
}
namespace aaa
{
namespace bbb

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (11 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

{
public class yyy
{
public static void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}
}
}

Output
hi
abc
pqr

It shall prove to be incredibly cumbersome if we have to write aaa.bbb.yyy, every time we want
to refer to the class yyy. In order to overcome this difficulty, C# offers to us a short cut in the
form of a keyword called 'using'.

The keyword 'using' is followed by the namespace and terminated by a semicolon. Every time a
class name appears in Main, C# replaces it with its long name, by placing the namespace in
front of it. In case of any mismatch, the error message 'namespace.class not found' is
generated. The keyword 'using' is similar to shorthand. It gives you the freedom to write the
name of a class without actually mentioning the namespace. At the same time, the keyword
'using' can occur as many times as you want it to, in your program.

Constructors
b1.cs
public class zzz
{
public static void Main()
{
yyy a;
System.Console.WriteLine("hi");
a = new yyy();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy");
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (12 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

Output
hi
yyy

Here, we have performed something that is unusual and anomalous, that is to say, we have
assigned the same name to the function as to the class, i.e. yyy. Whenever a function has the
same name as that of the class, it is treated like a special function. It is called a constructor. A
constructor is automatically called, whenever an instance of the class is created.

So, the code that is to be executed when an object is created, is normally placed in the
constructor. You are free to place any code in the constructor.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
System.Console.WriteLine("hi");
a = new yyy();
}
}
public class yyy
{
public void yyy()
{
System.Console.WriteLine("yyy");
}
}

Output
b1.cs(12,13): error CS0542: 'yyy': member names cannot be the same as their enclosing type

The syntax 'new yyy ()' creates an instance of the class yyy. This implies that, it internally
allocates memory for the methods and the variables of the class yyy. The constructor is called,
as the last action in this sequence.

At the time when the constructor is being executed, the object has not been created. Thus,
constructors cannot return any values, because there is no object available to accept these
values. The void data type signifies that there is no return value. However, in the case of
constructors, there is no possibility of any value being repeated. The C# compiler assumes that
yyy is a normal function because of the return type. Since a normal function cannot possess
the same name as the name of the class, the above error message is generated.

An object is created only after the constructor finishes executing its code successfully.

b1.cs
public class zzz
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (13 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

public static void Main()


{
yyy a;
System.Console.WriteLine("hi");
a = new yyy();
a.yyy();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy");
}
}

Output
b1.cs(8,1): error CS0117: 'yyy' does not contain a definition for 'yyy'

A constructor is a function with only two restrictions:

• The first is that it cannot return any values, as explained above.


• The second is that we cannot call a constructor explicitly. It gets called automatically,
only during the creation of an instance of a class.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy();
a.abc();
a.abc("hi");
a.abc(10);
}
}
public class yyy
{
public void abc()
{
System.Console.WriteLine("abc");
}
public void abc(string s)
{
System.Console.WriteLine("abc " + s);
}
public void abc(int i)
{
System.Console.WriteLine("abc "+ i);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (14 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

}
}

Output
abc
abc hi
abc 10

In C#, we are allowed to create different functions having the same name, as long as they
accept different number and types of parameters. We may be acquainted with a function only
by its name, but C# identifies a function by using its name, as well as, through the number of
its parameters along with their data types.

We have created three separate functions in our program using the same function i.e. abc.
However, since the parameter types are different in each case, C# flags them as separate
functions.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy("hi");
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy");
}
}

Output
b1.cs(6,5): error CS1501: No overload for method 'yyy' takes '1' arguments
A constructor is basically a function. So, all the rules of a function also apply to a constructor.
Thus, in the case of yyy, we need a function/constructor that accepts a string as a parameter.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy("hi");
}
}
public class yyy
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (15 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

public yyy()
{
System.Console.WriteLine("yyy");
}
public yyy(string s)
{
System.Console.WriteLine("yyy " + s);
}
}

Output
yyy hi

To eliminate the above error, we have introduced one more constructor that takes a single
string type parameter. The constructor that has more than one parameter is ignored, and the
one with a single parameter is called. Thus, when we create an object using 'new', only the
constructors that pre-exist in the class are called. If a constructor with a specific number of
parameters, does not exist, we cannot use 'new' to create an object with those many number of
parameters, because it will generate an error.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy();
}
}
public class yyy
{
public yyy(string s)
{
System.Console.WriteLine("yyy " + s);
}
}

Output
b1.cs(6,5): error CS1501: No overload for method 'yyy' takes '0' arguments

Life consists of unexpected twists and turns, which adds, in no small measure, to its
excitement. Earlier, when we had not used constructors in our code, C# allowed us to use the
keyword 'new' with abandon. However unexpectedly, when constructors were introduced, it
raised several objections.

The rationale behind this is, when we have a class without any constructors, by default, the
compiler introduces a constructor that has no parameters, as in public yyy() { }. This is provided
to us for free. Thus, when we have no constructors in a class, we are provided with one that has
no parameters.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (16 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

But, if we explicitly introduce even a single constructor, the free constructor brought in by the
compiler, is retracted. In class yyy, since we have a constructor with one parameter, the free
constructor that has no parameters, is not added. Hence, the above error is generated.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy ");
}
public yyy(string s)
{
System.Console.WriteLine("yyy " + s);
}
}

Output
yyy

The only way of getting rid of the error message is by introducing a constructor that has no
parameters in the class yyy.

b1.cs
public class zzz {
public static void Main()
{
System.Console.WriteLine("main");
yyy a;
System.Console.WriteLine("main 1");
a = new yyy();
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy ");
}
static yyy()
{
System.Console.WriteLine("yyy static");

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (17 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

}
}
Output
main
main 1
yyy static
yyy

Static constructors are always called before the non-static or instance constructors. Moreover,
they get called before any member of a class can be accessed.

b1.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("main");
yyy.abc();
yyy a;
System.Console.WriteLine("main 1");
}
}
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy ");
}
static yyy()
{
System.Console.WriteLine("yyy static");
}
public static void abc()
{
System.Console.WriteLine("abc");
}
}

Output
main
yyy static
abc
main 1
The above program demonstrates that the static constructor is called before the static function
abc. As we are not creating an object that is an instance of class yyy, the non-static constructor
of class yyy is never called.

Interfaces
b1.cs

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (18 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

public class zzz


{
public static void Main()
{
}
}
public interface yyy
{
}

An interface is similar to a class. It is a reserved word in the C# programming language. Since it


has been used correctly from a syntactical point of view, no errors are generated.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
}
}
public interface yyy
{
}

We are also permitted to declare an object that looks like an interface, yyy. No errors are
generated at all. A question that vexes us, is- 'Are interfaces and classes similar?' Do not lose
sleep over this, since they are as similar to each other, as a fish is to a fowl.

b1.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy();
}
}
public interface yyy
{
}

Output
b1.cs(6,5): error CS0144: Cannot create an instance of the abstract class or interface 'yyy'

The first difference between an interface and a class is that, an interface cannot be instantiated
by using the keyword 'new'. We can use 'new' only to instantiate a class and not an interface.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (19 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

b1.cs
public class zzz : yyy
{
public static void Main()
{
zzz a;
a = new zzz();
}
}
public interface yyy
{
void abc();
}

Output
b1.cs(1,14): error CS0535: 'zzz' does not implement interface member 'yyy.abc()'

An interface can only consist of function prototypes, i.e. the function name with its parameters.
Hence, yyy is an interface that contains only one function called abc, that takes no parameters
and returns a void. You may have noticed that we have not used the open and close curly
braces to enclose the function code. Instead, we have terminated the function with a semicolon.
Class zzz is derived from the interface yyy in the usual manner, i.e. by using a colon sign. We
get an error message because the code of the function abc, is not present anywhere in the class.

When one class derives from another class, it inherits all the functions of the base class. But
when a class derives from an interface, i.e. when it implements an interface, the code for the
functions in the interface, has to be explicitly specified in the class.

b1.cs
public class zzz : yyy
{
public static void Main()
{
zzz a;
a = new zzz();
a.abc();
}
public void abc()
{
System.Console.WriteLine("abc");
}
}
public interface yyy
{
void abc();
}

Output
abc

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (20 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

The error message has vanished, since we have implemented all the functions in the interface
yyy. If the interface yyy has 10 functions or definitions or prototypes, we have to add the code
for all these functions in the class zzz.

b1.cs
public class zzz : yyy,xxx
{
public static void Main()
{
zzz a;
a = new zzz();
}
public void abc()
{
System.Console.WriteLine("abc");
}
public void pqr()
{
System.Console.WriteLine("pqr");
}
}
public interface yyy
{
void abc();
}
public interface xxx
{
void pqr();
}

We are allowed to derive from as many interfaces as we like. This is not the case with classes.

In the above program, we are deriving from two interfaces, viz. yyy and xxx at the same time. All
that is required to be done is, to ensure that we have added the code for functions abc and pqr,
in the class zzz.

b1.cs
public class zzz : yyy,xxx
{
public static void Main()
{
}
}
public class yyy
{
}
public class xxx
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (21 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

Output
b1.cs(1,24): error CS0527: 'xxx' : type in interface list is not an interface

As we have stated earlier, we are not allowed to derive from two classes. In C#, multiple
inheritance from classes is strictly prohibited.

a.aspx
<%@ language=C# %>
hi
<%
Respone.Write("hi");
error
%>

We have created a simple aspx called a.aspx, and created an error in the C# code. The reason
behind doing this is that, we intend to discover the code that is generated by ASP+.

When we clicked on the last link called + Show Complete Compilation Source, we got the
following output:

Output
Line 1: //--------------------------------------------------------------
Line 2: // <autogenerated>
Line 3: // This code was generated by a tool.
Line 4: // Runtime Version: 1.0.2914.16
Line 5: //
Line 6: // Changes to this file may cause incorrect behavior and will be lost if
Line 7: // the code is regenerated.
Line 8: // </autogenerated>
Line 9: //--------------------------------------------------------------

Line 10:
Line 11: namespace ASP {
Line 12: using System;
Line 13: using System.Collections;
Line 14: using System.Collections.Specialized;
Line 15: using System.Configuration;
Line 16: using System.Text;
Line 17: using System.Text.RegularExpressions;
Line 18: using System.Web;
Line 19: using System.Web.Caching;
Line 20: using System.Web.SessionState;
Line 21: using System.Web.Security;
Line 22: using System.Web.UI;
Line 23: using System.Web.UI.WebControls;
Line 24: using System.Web.UI.HtmlControls;
Line 25:
Line 26:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (22 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

Line 27: public class a_aspx : System.Web.UI.Page, System.Web.SessionState.


IRequiresSessionState {
Line 28:
Line 29: private static System.Web.UI.AutomaticHandlerMethodInfos __autoHandlers;
Line 30:
Line 31: private static bool __intialized = false;
Line 32:
Line 33: private static System.Collections.ArrayList __fileDependencies;
Line 34:
Line 35: public a_aspx() {
Line 36: System.Collections.ArrayList dependencies;
Line 37: if ((ASP.a_aspx.__intialized == false)) {
Line 38: dependencies = new System.Collections.ArrayList();
Line 39: dependencies.Add("C:\\Inetpub\\wwwroot\\a.aspx");
Line 40: ASP.a_aspx.__fileDependencies = dependencies;
Line 41: ASP.a_aspx.__intialized = true;
Line 42: }
Line 43: }
Line 44:
Line 45: protected override System.Web.UI.AutomaticHandlerMethodInfos AutoHandlers {
Line 46: get {
Line 47: return ASP.a_aspx.__autoHandlers;
Line 48: }
Line 49: set {
Line 50: ASP.a_aspx.__autoHandlers = value;
Line 51: }
Line 52: }
Line 53:
Line 54: protected System.Web.HttpApplication ApplicationInstance {
Line 55: get {
Line 56: return ((System.Web.HttpApplication)(this.Context.ApplicationInstance));
Line 57: }
Line 58: }
Line 59:
Line 60: public override string TemplateSourceDirectory {
Line 61: get {
Line 62: return "/";
Line 63: }
Line 64: }
Line 65:
Line 66: public override void InstantiateIn(System.Web.UI.Control control) {
Line 67: this.__BuildControlTree(control);
Line 68: }
Line 69:
Line 70: private void __BuildControlTree(System.Web.UI.Control __ctrl) {
Line 71: __ctrl.SetRenderMethodDelegate(new System.Web.UI.RenderMethod(this.
__Render__control1));
Line 72: }
Line 73:
Line 74: private void __Render__control1(System.Web.UI.HtmlTextWriter __output, System.
Web.UI.Control parameterContainer) {

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (23 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

Line 75: __output.Write("\r\nhi\r\n");


Line 76:
Line 77: #line 3 "C:\Inetpub\wwwroot\a.aspx"
Line 78:
Line 79: Respone.Write("hi");
Line 80: error
Line 81:
Line 82:
Line 83: #line default
Line 84: }
Line 85:
Line 86: protected override void FrameworkInitialize() {
Line 87: this.FileDependencies = ASP.a_aspx.__fileDependencies;
Line 88: }
Line 89:
Line 90: public override int GetTypeHashCode() {
Line 91: return 2141278421;
Line 92: }
Line 93: }
Line 94: }
Line 95:

The output displayed above is the C# code generated by ASP+ in respect of our aspx file. Let us
try and decipher this output with the limited knowledge of C# that we have acquired so far.

We begin with a series of 'using' statements that are followed by the names of the namespaces.
These 'using' statements ensure that we do not have to write the namespace names anymore.
The C# file generated by ASP+ has a class name called a_aspx, since 'a' is the name of our aspx
file. This class is derived from System.Web.UI.Page, which means that, all the code in the Page
class is now available to a_aspx. The class also implements an interface called
IRequiresSessionState, which we shall touch upon, a little later.

The class consists of a static constructor a_aspx, which has no parameters. Amongst the other
functions present in the file, the most important function is __Render__control1. We will ignore
all the above code for the moment, and focus only on this function.

This function always gets called by ASP+. All code other than the aspx code, i.e. the code in
HTML or Javascript etc., get added to this function. This function therefore, happens to be the
most crucial one. It accepts two parameters:
• The first parameter is output, which is an instance of the class HtmlTextWriter in the
System.Web.UI namespace. Write is a function in the class HtmlTextWriter. Hence, it can be
invoked by calling output.Write.

• The second parameter to __Render__control1 is parameterContainer. It is an instance of


the class Control in the System.Web.UI namespace. This parameter represents a control.
The HTML text 'hi' is converted into a parameter and passed to the function Write .

The C# functions get copied word for word, just as we had entered them. Hasn't ASP+ become
more comprehensible now? We have learnt a lot about ASP+ by making errors, and then

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (24 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

analyzing the code that was generated. We recommend the same for you.

Writing Components
One question that continues to bother us is "How does C# compile the ASP generated code?" To
understand this, we go back to our subdirectory aaa and create two files called a.cs and b.cs.

a.cs
public class zzz
{
public static void Main()
{
yyy a;
a = new yyy();
a.abc();
}
}

Output
Microsoft (R) Visual C# Compiler Version 7.00.9254 [CLR version v1.0.2914] Copyright (C) Microsoft
Corp 2000-2001. All rights reserved.

a.cs(5,1): error CS0246: The type or namespace name 'yyy' could not be found (are you missing a using
directive or an assembly reference?)
a.cs(6,1): error CS0103: The name 'a' does not exist in the class or namespace 'zzz'
a.cs(7,1): error CS0246: The type or namespace name 'a' could not be found (are you missing a using
directive or an assembly reference?)

An error is generated, since C# cannot locate the class yyy anywhere. So far, all our classes
were stored in a single file called a.cs. In this program, the class yyy is present in the file b.cs.

b.cs
public class yyy
{
public void abc()
{
System.Console.WriteLine("abc");
}
}

Using the csc command, not only can we create an executable file such as a.exe, but also a dll.
The acronym dll stands for Dynamic Link Library. Code that needs to be shared under
Windows, comes packaged in a dll. To create a dll, we use the same csc command, but with
different options. We use the following command

c:\aaa>csc /t:library /out:b.dll b.cs

The /t:library option instructs the compiler to create a library or a dll. By default, the compiler
creates an exe file. Further, the /out: option allows us to assign a name to the file. Had we not

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (25 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

assigned any name, the default name would have been b.dll, since the source file is named b.
cs. Now that we have created our dll file, we simply need to inform our csc compiler to look into
this file, for the code of our desired classes. Now, all that we do is, run csc as follows:

c:\aaa>csc /r:b.dll a.cs

The /r option asks the compiler to look into b.dll for the code of those classes, that are not
contained in the file a.cs. The above program will produce a file called a.exe which, when
executed, will call the function abc from the class yyy. This concept is quite simple and clear-
cut, don't you agree ?

Let us now run the following aspx file:

a.aspx
<%@ language=C# %>
<%
error
%>

We get an error message. When we click on + Show Detailed Compiler Output:, we see the
following command:

C:\WINNT\system32> "c:\winnt\microsoft.net\framework\v1.0.2914\csc.exe" /t:library /utf8output /


R:"c:\winnt\assembly\gac\system\1.0.2411.0__b77a5c561934e089\system.dll"
/R:"c:\winnt\assembly\gac\system.xml\1.0.2411.0__b77a5c561934e089\system.xml.dll"
/R:"c:\winnt\assembly\gac\system.drawing\1.0.2411.0__b03f5f7f11d50a3a\system.drawing.dll" /
R:"c:\winnt\assembly\gac\system.data\1.0.2411.0__b77a5c561934e089\system.data.dll" /R:"c:
\winnt\assembly\gac\system.web.services\1.0.2411.0__b03f5f7f11d50a3a\system.web.services.dll" /
R:"c:\winnt\microsoft.net\framework\v1.0.2914\mscorlib.dll" /R:"c:\winnt\assembly\gac\system.
web\1.0.2411.0__b03f5f7f11d50a3a\system.web.dll" /out:"C:\WINNT\Microsoft.NET\Framework
\v1.0.2914\Temporary ASP.NET Files\root\fa7064c6\2014c0f1\jhbdrf-n.dll" /debug- /optimize+ "C:
\WINNT\Microsoft.NET\Framework\v1.0.2914\Temporary ASP.NET Files\root\fa7064c6\2014c0f1
\jhbdrf-n.0.cs"

This appears quite complicated, but it is very simple to follow.

ASP+, by default, runs in the subdirectory of WINNT\system32. So, the C# compiler csc is
invoked from this directory. Now, since csc is not located in the system32 subdirectory, the
absolute path is given for the command i.e.

"c:\winnt\microsoft.net\framework\v1.0.2914\csc.exe"
You will also notice a large number of /R options, that direct the compiler to look into all the
specified dlls for code of classes. In case we require code from a dll that is not listed above, then
we are surely out of luck.

Thereafter, the C# compiler is instructed to create a library and not an exe file. This output file
is given a dll name by using the /out: option, and it is stored in a particular directory

/out:"C:\WINNT\Microsoft.NET\Framework\v1.0.2914\Temporary ASP.NET Files\root\fa7064c6\2014c0f1


\ehcuumxx.dll"

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (26 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

The name assigned to the C# program is ehcuumxx.0.cs. We can physically verify these files by
going to the specified subdirectories.

This goes on to prove that all the HTML text and the C# code that we write in an aspx file, are
finally packed into a dll. When the aspx file called 'a', is loaded for the very first time, it
consumes a considerable amount of time. This is because, ASP+ has to first write out the C#
program, and then compile it to generate a dll. Finally, the code is executed, which results in
the display of the output in the browser window. All this happens only once, and thus, it takes
a very long time. But subsequently, when the same file is requested off the server, the HTML file
is generated in a much speedier manner, since the dll has already been created.

a.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs E)
{
int i = 10;
short j = 2;
j = i;
}
</script>
</body>
</html>

Output
Compiler Error Message: CS0029: Cannot implicitly convert type 'int' to 'short'
Line 7: j = i;

We have created two variables of two different data types, namely, i as an int and j as a short.
We are not allowed to equate two different data types with each other. Thus, we get an error
'cannot covert to … line 7 j=i '. C# does not support the concept of equating different data types.

a.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs E)
{
int i = 10;
short j = 2;
j = (short)i;
}
</script>
</body>
</html>

The same program now shows no error, which is because we made sure that both sides of the
'equal to' sign are of the same data type. This is incorporated by means of using the round

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (27 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

brackets, and then by mentioning the data type to which we want the other side converted. This
does not change the value of i, since it is only for a short time, that we change its data type,
from an int to a short. Now, since both sides of the 'equal to' sign have a short data type, we do
no get any error. The above pair of () brackets, with the data type mentioned within it, is called
a cast operator.

The next program employs user controls, as by now, we are fairly familiar with the concept of
'new'.

a.aspx
<%@ Register TagPrefix="vijay" TagName="mukhi" Src="a1.ascx" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs E)
{
Page.Controls.Add(new HtmlGenericControl("hr"));
UserControl c1 = (UserControl) LoadControl("a1.ascx");
((a1_ascx)c1).Category = "business";
Page.Controls.Add(c1);
}
</script>
</body>
</html>

a1.ascx
<script language="C#" runat="server">
public String aa;
public String Category
{
get
{
return aa;
}
set
{
aa = value;
}
}
</script>
<span >Sonal: <%=aa%></span>

Output
Sonal: business

Let us look at a.aspx. In the Page_Load function, we first create an HTML tag 'hr', by using
'new'. This control is then added to the list of controls, using the Add function in Page.Controls.
In this manner, we can dynamically add any control or tag we like, to a page. The a1.ascx file
that contains the control, is then loaded, using the LoadControl function. The result of this
function is a control that is stored in an object called c1.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (28 of 29)2/13/2007 4:54:24 PM


Classes - ASP.NET - Beta2

The control has a property called Category, which is initialized to business. We need to cast it to
a1_ascx, since we need to convert c1, which looks like class UserControl, into an a1_ascx class.

Due to the Register attribute on the control file named a1.ascx, ASP+ creates a class a1_ascx that
represents our control. Hence, we need to use a cast operator, because the object c1 does not
contain any property called Category. We use the Add function again to add c1 to the page.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap4.htm (29 of 29)2/13/2007 4:54:24 PM


Database Controls - ASP.NET - Beta2

-5-

Database Controls
This chapter, which is based on databases, will probe into the rudiments of handling data from
a database program, i.e. Microsoft's SQLServer. To ensure that the programs work as per our
explanation, this database server must be installed along with the samples that are provided
along with the .NET package. The details have been given in the installation section in the
Introduction chapter, with the aim of assisting you in installing this product and the samples.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat=server>
void abc(Object s, EventArgs e)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co = new SqlDataAdapter("select * from Titles ", c);
DataSet d = new DataSet();
int i = co.Fill(d, "zzz");
Response.Write(i.ToString());
l.DataSource = d.Tables["zzz"].DefaultView;
l.DataBind();
}
</script>
<body>
<form action="a.aspx" runat="server">
<asp:button type=submit text="Fetch" OnClick="abc" runat="server"/>
<ASP:DataGrid id="l" runat="server"/>
</form>
</body>
</html>

When the file a.aspx is loaded on, by providing the URL http://localhost/a.aspx, the browser
displays a blank screen with only one button labeled Fetch. If you now click on the button, the
same window shall get filled up with data, in a well-formatted tabular manner.

Are you astonished? Well, the best way to comprehend the output is, by analyzing the source
file. In order to do so, we clicked on View-Source and found that the program that we had run
on the server, and the HTML file generated, are as dissimilar as fish and fowl.

The asp:button of type 'submit', generates a submit button which calls the function abc on the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (1 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

server, whenever we click on it. This function first creates an object c, which is an instance of
the class SqlConnection. All database handling classes either belong to the System.Data
namespace or to the System.Data.SqlClient namespace.

The directive <%@ Import Namespace= is the ASP+ equivalent of the C# keyword 'using'. Since
we believe in the adage that 'brevity is the soul of wit', wemake use of this directive and
initialize it to the System.Data.SqlClient and System.Data namespaces. We can include as
many Import directives in the file as we want.

To create an object of type SqlConnection, the constructor with one parameter is called. This
parameter is a string where we initialize some words as follows:

• server to localhost
• uid to sa
• pwd to nothing
• database to pubs.

The class uses these values internally. The server provides relevant details about the machine
on which the SQLServer database is running to SqlConnection. The relevance of these values is
explained below:

Here, we have used localhost, which refers to the local machine and not to a machine on the
network.

A database cannot be accessed unless we identify ourselves. In order to do so, we have to


provide it with a user id and a password. So, the word uid is used, which refers to the user id,
and the word pwd is used to refer to the password. SQLServer has only one pre-built user in
the system called sa, which does not require a password. Hence, in this case, uid is initialized
to sa and pwd is not assigned any value.

Finally, in general terms, a database is made up of tables where all data is stored. In our
program, we will be constantly working with only one database called pubs. c now refers to this
connection made to the pubs database, on the local disk. Observe carefully that semi-colons
separate the name-value pairs in the string.

The next task in the sequence is to fetch data from the database. To accomplish this, we need
to be well informed and conversant with a language that can handle a database, and also fetch
the desired data. This language is called SQL or Structured Query Language. SQL is a universal
language that works on all database servers and is not a trademark of any database vendor.
Thus, Microsoft, Oracle or any other database vendor, do not possess the ownership rights of
SQL.

In the SQL language, a Select statement fetches data from a database. As mentioned earlier,
data is stored in a table within rows and columns. A row of the table is called a record and the
columns are identified as fields. Further, every table has a name, and the fields in it signify the
type of data that is stored within them.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (2 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

The pubs database contains a table called titles. Writing an SQL command as 'Select * from
titles', will fetch us all the data from the titles table. This is because the * signifies all the fields
and records of a table.

As we want to display all the records from this table in the browser window, we have to use this
SQL select statement in ASP+. Prior to that, we need to create one more class that understands
SQL commands. This class is called SqlDataAdapter, which belongs to one of the namespaces
imported in the file.

We call the constructor of SqlDataAdapter class with two parameters; the SQL statement within
double quotes i.e. "select * from Titles"; and the connection object i.e. 'c'. This links up the SQL
command with the database connection.

So far, we have created two objects, the first of which contains the connection details and
second holds the SQL command. As we need to accommodate the data that we retrieve from the
table somewhere, we need one more object that is of type DataSet. This object deals with data
that comprises of multiple rows and columns.

Now, we shall get down to real work. We need to fill up the DataSet object with data. To do so,
the SqlDataAdapter class provides us with a function called Fill, which accepts two parameters.
The first parameter is a DataSet object 'd', and the second one is any string, zzz, which
identifies the table. This function returns an int, which informs us about the number of rows
added to the DataSet object. As there are 18 rows in the titles tables, Fill stores 18 in the
variable i. As before, we can use Response.Write function to display the value stored in the
variable i. But, since this function requires a string, the ToString function from the int class is
called to display this value in the string format.

In the aspx file, besides the asp button, we have introduced a new tag called <asp:DataGrid,
having an id of l. This tag is capable of displaying data in a grid form.

In the function abc, we are initializing the DataSource property of l, i.e. a DataGrid to the data
that it should display. The DataSet object 'd' has a member called 'Tables', which is assigned
the value of zzz. If you recheck the program, you will find that the string zzz was provided to
identify the DataSet. The DefaultView member of 'Tables', returns a view of the data. It is this
series of statements that connects our DataGrid to our DataSet.

If we halt at this stage, no output will be displayed. To display data on the screen, a function
called DataBind from the DataGrid class, has to be invoked. This function populates the
DataGrid with data.

The DataBind function internally performs numerous tasks. The programmers who wrote the
code for this function obviously possessed an extremely high IQ, since, it is no mean task to
write a function that is endowed with such a high level of complexity. This function firstly
ascertains the number of rows and columns in the result set. Accordingly, it creates an HTML
table with the specified number of rows and columns. Thereafter, it retrieves the values from
the result set and fills the table with all the data. Effortlessly, we can now view the data from a
table in the database, simply by using one function.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (3 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

In our opinion, the DataGrid control is extremely significant. So, we shall spend a little more
time in understanding this control in greater detail, before shifting our focus to SQLServer.
Since it is not our intention to confuse you any further, we shall populate the Data Grid with
static data. We shall enter the data ourselves, rather than obtaining it from a database.

This DataGrid server control not only displays data in a tabular form, but also consents to
perform certain basic operations on it, such as select, sort, page, edit, etc.

By default, the number of fields displayed in the control, are equal to the number of columns
found in the data source. The field names appear at the top and all the values, irrespective of
their data type, are rendered as text labels in a default format.
a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataTable d = new DataTable();
DataColumn c = new DataColumn("Integer", typeof(Int32));
DataColumnCollection c1 = d.Columns;
c1.Add(c);
d.Columns.Add(new DataColumn("Vijay", typeof(string)));
d.Columns.Add(new DataColumn("Sonal", typeof(bool)));
DataRow dr;
dr = d.NewRow();
dr[0] = 1;
dr[1] = "vijay1";
dr[2] = true;
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;
dr[1] = "vijay2";
dr[2] = false;
d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" BorderColor="red" BorderWidth="1" GridLines="Both"
CellPadding="3" CellSpacing="4" Font-Name="Verdana" Font-Size="8pt" HeaderStyle-
BackColor="#aaaadd" />
</form>
</body>
</html>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (4 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

As usual, the function Page_Load is called automatically. Here, we first create an object d,
which is an instance of the class DataTable. Since every table has columns, a separate object c
of type DataColumn class, is created to represent a column. The constructor of the DataColumn
class takes two parameters:

• The first is the column name i.e. Integer, enclosed within double quotes.
• The second is the data type of the column.

The class int is internally known as Int32. The word 'typeof' is a C# keyword, which returns an
object of class Type. The syntax typeof(Int32) places an object of class Type representing the
Int32 datatype, as the second parameter to the contructor.

An extremely large number of columns can be displayed in the DataGrid. Therefore, we need
some mechanism to keep track of all these columns. This is where the Columns property which
is available in the class DataTable, comes handy. This property returns an instance to the
DataColumnCollection Object, which is stored in object c1. The Add function is called off the
object c1, to store the column c.

Similarly, we can add two or more columns to our Data Table. The column named Vijay will
contain data of type string, whereas, the column Sonal can only hold the data of type bool.
However this time, we sidestep the DataColumnCollection statement and write these steps in
one single statement. You can choose whichever method you are most comfortable with.

Once the columns have been added, we have to introduce the rows containing data for each of
the column. To achieve this, we now create an object dr, which is an instance of the class
DataRow, to represent a row of data. This object is then added to the DataGrid. The NewRow
function creates a blank row. So, before adding it, we have to populate the three columns with
some data.

The first column is represented by the variable dr[0], the second by the variable dr[1], and the
third by the variable dr[2]. The square brackets are part of the syntax. Thereafter, we initialize
the first column to an int value of 1, the second column to a string value of 'Vijay' and the third
column to a bool value of True. Once the values are assigned to every column, the row is added
to the table by calling the Add function in the Rows class of the DataTable.

We repeat the same procedure to add the second row. The DataTable object now consists of
three columns and two rows.

We need one more object, which is a DataView object. The constructor of this object is provided
with a DataTable object called 'd'. The DataSource property within DataGrid, accepts a
DataView object and indirectly maps it to the DataTable object. Finally, DataBind is called to

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (5 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

display the data within the table.

The DataGrid control has many more attributes, such as, foreground color, background color,
spacing between columns, grid lines between columns, and so on. These options are endless.
You could spend a month enhancing the look and feel of the DataGrid, however, we would
advise you against spending your quality time in this manner, at this stage.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataTable d = new DataTable();
DataColumn c = new DataColumn("Integer", typeof(Int32));
DataColumnCollection c1 = d.Columns;
c1.Add(c);
d.Columns.Add(new DataColumn("bad", typeof(double)));
DataRow dr;
dr = d.NewRow();
dr[0] = 11;
dr[1] = 1.234567;
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;
dr[1] = 4.3;
d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" BorderColor="black" BorderWidth="1" GridLines="Both"
CellPadding="3" CellSpacing="0"
AutoGenerateColumns="false">
<Columns>
<asp:BoundColumn HeaderText="Price" DataField="bad" DataFormatString="{0:c}" ItemStyle-
HorizontalAlign="right" />
<asp:BoundColumn HeaderText="vijay" DataField="Integer" />
</Columns>
</asp:DataGrid>
</form>
</body>
</html>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (6 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Most of the code in the function Page_Load remains the same, except that we have removed one
column completely and renamed the other column. This is to make the program smaller in size.
The data type of the second column is 'double'. Hence, we can store values having decimal
points in this column.

The <asp:DataGrid tag is given the same id of l, alongwith the other attributes of BorderColor,
BorderWidth, and Autogeneratedcolumns. If you observe carefully, you will realise that the
DataGrid tag does not end on the same line. The forward slash is now missing. Instead, we
have closed the tag after a couple of lines, just as we did in the case of an HTML tag, using </
asp:DataGrid>.

All statements inserted within the opening and the closing tag relate to the same object. One of
the elements of the DataGrid object is 'property'. It is given the name Columns, which is a
reserved word with a special meaning, and it ends after two lines.

Within the property tag, we have another control called <asp:BoundColumn, that represents the
actual columns displayed. The new values given here, override the Column properties created in
the function abc. The value given to HeaderText gets displayed as the column header, and
DataField represents the column name that is to be changed. The column called 'bad' has two
additional properties:

• The first is DataFormatString, where we want the currency field displayed, with two
decimal places.
• The second is ItemStyle-HorizontalAlign, which aligns the data to the right.

The control called BoundColumn influences the manner in which columns are displayed.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
dr = d.NewRow();
dr[0] = 11;
dr[1] = "String 1";
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (7 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

dr[1] = "String 2";


d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" GridLines="Both" AutoGenerateColumns="false">
<Columns>
<asp:HyperLinkColumn HeaderText="Text of Header" DataNavigateUrlField ="c1"
DataNavigateUrlFormatString ="a1.aspx?mukhi={0}"
DataTextField ="c2" Target="_new" />
</Columns>
</asp:DataGrid>
</form>
</body>
</html>

a1.aspx
<html>
<head>
<script language="C#" runat="server">
string s;
void Page_Load(Object sender, EventArgs e)
{
s=Request.QueryString["mukhi"];
}
</script>
</head>
<body>
You selected <%= s %>
</body>
</html>

Output

Output : when String 1 is selected


http://127.0.0.1/a1.aspx?mukhi=11
You selected 11

Output : when String 2 is selected


http://127.0.0.1/a1.aspx?mukhi=2
You selected 2

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (8 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

In the function Page_Load, we have two columns c1 and c2, consisting of data types Int32 and
string, respectively. Most of the code is similar to the earlier program, except for a few changes
in the variable names and values.

We now introduce a new tag called <asp:HyperLinkColumn within the property tag. The
attribute HeaderText is used to display the column heading. The most important attribute with
the HyperLinkColumn control is DataTextField, which is assigned a column name. The text in
this column becomes a hyperlink. DataTextField is initialized to the value of c2. Hence, String 1
and String 2 are displayed as hyperlinks on the table.

When we click on any of the hyperlinks, a URL is required for navigation. We can decide on the
format of this url by initializing the attribute DataNavigateUrlFormatString to a value. In this
case, we have provided the value a1.aspx?'mukhi'={0}.

ASP+ automatically adds http://localhost/ to the value and replaces {0} with the value of
column c1. Thus, {0} is replaced by the contents of column c1, depending on the string that is
selected. In case of String 1, the URL becomes http://localhost/a1.aspx?'mukhi'=11. Since
Target is initialized to _new, it will open a new browser window to display the contents of the file.

The program a1.aspx displays the value of the parameter mukhi. This value is retrieved by
using Request.QueryString with the parameter name, and then it is stored in a string called 's'.
The value is then displayed on the screen using <%=.

Thus, we can use the tag HyperLinkColumn to convert values in a column of a DataGrid, into a
hyperlink. Although we can use as many of such Column types as we like, however presently,
as we are still learning the concept, we have restricted ourselves to only one Column type.
Hence, we are not using BoundColumn in the same example. However, nothing stops you from
doing so.

By clicking on the hyperlink in the file a1.aspx, we could use the value of 'mukhi' to load
another series of records from a database. We can add more code to the file a1.aspx if we so
desire.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
dr = d.NewRow();
dr[0] = 11;
dr[1] = "String 1";
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (9 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

dr[1] = "String 2";


d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" GridLines="Both" AutoGenerateColumns="true">
<Columns>
<asp:BoundColumn HeaderText="Vijay" DataField="c1" />
<asp:BoundColumn HeaderText="mukhi" DataField="c2"/>
</Columns>
</asp:DataGrid>
</form>
</body>
</html>

Output

Instead of two columns, we are now presented with four columns, because the property called
AutoGenerateColumns is initialized to True. This modifies our DataGrid completely. We first see
our Bound Columns 'Vijay' and 'mukhi', and then the columns that we have created in our
DataTable, c1 and c2.

If the attributeAutoGenerateColumns is assigned the value of False, as was the case in the
earlier programs, the columns originally placed in the DataTable get overridden by the new ones.

Session Variables
a.aspx
<html>
<script language="C#" runat="server">
int i;
void Page_Load(Object sender, EventArgs e)
{
i = (int)Session["mukhi"];
}
</script>
<body>
<form runat=server>
<%= i %>
</form>
</body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (10 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</html>

Output
Server Error in '/' Application.
-------------------------------------------------------------------------
Value null was found where an instance of an object was required.

When the file is loaded in the browser, we get an application error. Let us understand the cause
for this.

We have used a free object called Session with the [] brackets, to reference a word called
'mukhi'.The return value of this Statement is stored in the variable i. Since it has generated a
null reference error, it confirms that the word 'mukhi' does not exist in the Session object. It
can safely be assumed that there is nothing wrong with our syntax.

a.aspx
<html>
<script language="C#" runat="server">
int i;
void Page_Load(Object sender, EventArgs e)
{
if ( Session["mukhi"] == null)
{
Response.Write("one<br>");
i = 1;
Session["mukhi"] = 20;
}
else
{
Response.Write("two<br>");
i = (int) Session["mukhi"] ;
}
}
</script>
<body>
<form runat=server>
<%= i %>
</form>
</body>
</html>

Output
one
1

Let us try to understand this program step by step. We request you to run this program in the
manner that we want you to, otherwise, our explanations may appear incomprehensible to you.
When we run the aspx file in our browser, we get the output as displayed above.

The function Page_Load gets called, each time the page is sent to the browser. The earlier

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (11 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

program failed because the value returned by Session["mukhi"], was null. Continuing on these
lines, in the current program, the 'if' statement results in True, since Session["mukhi"] returns
null. The Write function therefore displays one. Thereafter, the variable i is given a new value of
1, and Session["mukhi"] is initialized to 20.

Session['mukhi'] is initialized like any other variable, to a value. Since it is not a variable, this
statement creates a word or a variable called 'mukhi', and links it with the running copy of your
browser.
<%= i %> within the form tags, displays the value of i as 1.

When you click on the Refresh Button in your browser, it will restart the procedure of
requesting for the current file a.aspx from the server. Since the page is to be sent over, the
function Page_Load is called once again. It is all the same, but this time, the 'if' condition with
Session["mukhi"], fails. Since we have assigned it a value of 20, the session with 'mukhi' in
square brackets, fetches the value of the variable 'mukhi'. Therefore, it is not null in this case.
Hence, the output is as follows:

Output
two
20

Since the 'else' block of 'if' statement is called, the value two is displayed, and the value of i is
displayed as 20, since 'mukhi' was assigned this value earlier.

To summarize, Session["mukhi"'] creates a variable called 'mukhi' in the first round, if it doesn't
already exist. By default, the value assigned to it is null, and hence, we have to initialize it to
some value. In future, 'mukhi'- the session variable can be used like any normal variable.

What is so special about creating variables? Have we not created enough of them?

It is important to realise that the session variables are special. To prove this, start a fresh copy
of the browser. To your utter surprise, you will see One and 1 displayed on the screen again.
When you click on the Refresh button, you will see Two and 20.

This implies that ASP+ keeps track of the browser copies you are working with while accessing
the same file. Each copy of the browser has a different value for 'mukhi'. Thus, 'mukhi' is a
variable, but with a dash of lime. Every time we start a new copy of the browser, we get a new
copy of this variable too. As a new browser starts a new session, all variables like 'mukhi' that
are associated with a session, get reinitialized to their initial values.

This functionality is akin to ASP+, having a million eyes to monitor your activities, with every
new copy of the browser. How it undertakes supervision of this magnitude, is yet another story!

Given below is another program designed to make the concept of sessions, more
comprehensible for you.

a.aspx
<html>
<script language="C#" runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (12 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

int i;
void Page_Load(Object sender, EventArgs e)
{
if ( Session["mukhi"] == null)
{
i = 0;
Session["mukhi"] = (int)i;
}
else
{
i = (int) Session["mukhi"] ;
i = i + 1;
Session["mukhi"] = i;
}
}
</script>
<body>
<form runat=server>
<%= i %>
</form>
</body>
</html>

Output
0

When we load the above program, we get to see the number zero in the browser window. In case
you witness a value of 21, you need to start a new copy of the browser. This is because the
session variable 'mukhi' already exists with the current copy of the browser.

Each time we click on the Refresh button, the number displayed is incremented by one. Once
again, if you start a new copy of the browser, the value displayed will again be zero. Now, click
on the Refresh Button a couple of times in the second copy, and then revert back to the first
copy of the browser. Here, the browser still displays the old value. Refresh will increment this
value, only by one. This confirms that there are two independent copies of 'mukhi', with their
respective values associated with a particular copy of the browser.

The concept of sessions demonstrates the standalone behavior of data variables, depending
upon the instance of a browser.

A Shopping Cart Example


We now apply this concept of sessions to create a shopping cart, one of the most widely used
applications on the Internet.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (13 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<script language="C#" runat="server">


DataTable Cart;
DataView cv;
void Page_Load(Object sender, EventArgs e)
{
if (Session["zzz"] == null)
{
Cart = new DataTable();
Cart.Columns.Add(new DataColumn("Item", typeof(string)));
Cart.Columns.Add(new DataColumn("Price", typeof(string)));
Session["zzz"] = Cart;
}
else
{
Cart = (DataTable)Session["zzz"];
}
cv = new DataView(Cart);
sc.DataSource = cv;
sc.DataBind();
if (!IsPostBack)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(string)));
d.Columns.Add(new DataColumn("c2", typeof(double)));
DataRow dr;
dr = d.NewRow();
dr[0] = "Product 1";
dr[1] = 11.3;
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = "Product 2";
dr[1] = 10.6;
d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource= dv;
l.DataBind();
}
}
void abc(Object sender, DataGridCommandEventArgs e)
{
DataRow dr = Cart.NewRow();
TableCell it = e.Item.Cells[2];
TableCell pr = e.Item.Cells[3];
string item = it.Text;
string price = pr.Text;
Response.Write(item + " " + price);
if (((LinkButton)e.CommandSource).CommandName == "AddToCart")
{
dr[0] = item;
dr[1] = price;
Cart.Rows.Add(dr);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (14 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

}
else
{
cv.RowFilter = "item='"+item+"'";
if (cv.Count > 0)
{
cv.Delete(0);
}
cv.RowFilter = "";
}
sc.DataBind();
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" AutoGenerateColumns="false" OnItemCommand="abc">
<columns>
<asp:ButtonColumn HeaderText="Add to cart" Text="Add" CommandName="AddToCart" />
<asp:ButtonColumn HeaderText="Remove from cart" Text="Remove"
CommandName="RemoveFromCart" />
<asp:BoundColumn HeaderText="Item" DataField="c1"/>
<asp:BoundColumn HeaderText="Price" DataField="c2" />
</Columns>
</asp:DataGrid>
<ASP:DataGrid id="sc" runat="server"/>
</form>
</body>
</html>

Output
Product 2 10.6

We have a DataGrid with an id of l, and a property called OnItemCommand which is set to the
function abc.

As before, we have the columns attribute followed by a tag <asp:ButtonColumn, that is repeated
twice. It has three attributes:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (15 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

• The HeaderText attribute signifies the column header that should be displayed.
Therefore, the first column in the DataGrid control shows 'Add to Cart', and the second one
exhibits 'Remove from cart'.

• Now that we are done with the column heading, we concentrate on the data within the
column. The second attribute Text in the Button property decides the text that is to be
displayed. This value is repeated for all the rows of the table. Thus, the first column shows
Add and the second shows Remove. Every time we click on the text Add or Remove, the
function name stated in the attribute OnItemCommand, gets executed. Thus, function abc
is called.

• Shouldn't there be a way to figure out as to which Button Command was clicked? The
third attribute in the Button property i.e. CommandName, does exactly this. It assigns a
name to a button, which we can refer to in our code later, to figure out which button was
chosen.

Now, we proceed to the next two lines. We use the familiar BoundColumn tag, which we had
come across in one of the earlier programs. This tag is used to add values contained in two
columns c1 and c2 of the table, to the DataGrid control. The HeaderText displays the column
headings as Item and Price, thus, resulting in a total of four columns.

A point to be noted here is that, within the properties tag, any tag that ends with the word
Column, ends up being a column in the DataGrid.

Another DataGrid Control having the id of sc, is added to the page. You are free to add as many
DataGrid controls as you like. The reason for adding this control shall be explained in a short
while.

As usual, the server calls the Page_Load function. The first line in this function checks for the
existence of the zzz session variable. Since it is null, an object called Cart, of type DataTable, is
created. Two columns are added to this table with the labels of Item and Price, to hold string
values. Following this, Session["zzz"] = Cart; initializes the zzz session variable to Cart.

A session is required at this point, because the user will be adding and eliminating items from
his shopping cart. A record of the items currently present in the shopping cart, has to be
maintained.

Since the first DataGrid control with the id of l, has a fixed number of records and cannot be
changed, the second DataGrid having the id of sc, is utilized to hold the items added or
removed by the user. The number of records contained in it, keep varying constantly.

It is imperative to maintain this state information from one copy of the browser to another.
Therefore, we had initially created a DataTable object with the two Columns of Item and Price,
and stored it in the cart object. No data is added to or deleted from this DataTable, unless the
user clicks on the Add or Remove Text. Further, this DataTable has to be created only once, at
the very beginning, so that a blank DataTable is displayed when the user loads this file for the
first time.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (16 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Output

When the user clicks on the Refresh button, or the page is again requested from the server, the
'else' block is called, which initializes the cart object to the values contained in zzz.

Irrespective of the statements being called, an object called cv, which is an instance of the class
DataView, is created every time. The constructor of this class is called with the Cart object. The
DataSource member of the second DataGrid control named sc, is assigned to cv, thereby
associating the data within cv with the DataGrid Control. Since there are no records in the
shopping cart currently, DataGrid does not display any records.

Before we explore about filling up data in the second DataGrid control, in greater detail, we
need to populate the first one with some data. Two columns, c1 and c2 with two records, are
added to the DataTable object called 'd'. As this data is to be inserted only once, we can place it
either in the 'if' block when the session variable holds a null value, or when IsPostBack returns
a value of False.

We prefer to employ the second method because the original Microsoft sample uses it. You are
at a liberty to choose whichever method suits you. This is how the first DataGrid is supplied
with data. Keep in mind that this is a one-time activity. The GridControl displays these values
on the browser screen.

Each time we click on the Add or Remove text, the function abc gets called. The second
parameter to this function i.e. DataGridCommandEventArgs e, is of importance here.

Since the text Add and Remove are repeated for every row, we first need to identify the row that
the user has clicked on.

A DataGrid is made up of a number of rows and columns, and we want to identify the specific
column when the row is known to us. DataGridCommandEventArgs has a member called Item,
which represents a row. Thus, using e.Item, we can identify the row that the user has clicked
on. This row has four columns. The first two are ButtonColumns and the next two are
BoundColumns. We are interested in the values contained in the last two columns. As the
column numbering start from zero, the Cells[0] member in Items, represents the first column.
In the same manner, Cells[2] denotes the third Column which contains the name of the
product, and Cells[3] represents the fourth column, which contains the price of the product.

The Cells member in Item, returns a TableCell object that represents the data. Every TableCell
object has a member called Text, which returns the column value in the string format. Using
Response.Write function, we can display these column values in the browser.

The values are not returned directly, since they can belong to any data type. The parameter e
also has a member called CommandSource. The return value is cast to a LinkButton, as we

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (17 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

want to access a member called CommandName within it. CommandName contains either
AddToCart or RemoveFromCart, depending upon the button that the user clicked on. This value
is acquired from the CommandName attribute of the ButtonControls. Thus, we can find out the
button that was clicked.

If the user clicks on Add, the newly created row with members dr[0] and dr[1], is assigned the
values held in item and price. Thereafter, the Add function is used to add the row to the Cart
object of DataTable.

In case the user clicks on Remove, the RowFilter member of cv, which is the DataView class, is
used to filter out or remove all records from the DataGrid that do not meet the specified
condition.

RowFilter takes a value in the form of 'fieldname = value'. Hence, we have assigned it to
'item='Product 1' to ensure that DataGrid checks records, matching this condition only. Once
the records are filtered out, the Count member in DataView is used to count the number of
records present. If the value is zero, then it signifies that there are no records matching the
condition. Hence, no changes are required to be made to the DataView.

If Count has a value greater than 0, the first record in the filtered set is deleted, using the
Delete function in cv. Once the records have been modified, the filter is reset to null, resulting
in its removal. DataBind thereafter redisplays all the records in the shopping cart after omitting
the record that was deleted.

A filter does not physically remove any records. It merely hides them for the moment. DataBind
is used to redisplay the rows, excluding the hidden ones. It is important to remember that all
this happens on the server. If it is hard for you to believe us, you can ascertain this for yourself,
by viewing the file received by the browser, by clicking on View-Source.

Templates
a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
DataTable Cart;
DataView cv;
void Page_Load(Object sender, EventArgs e)
{
if (Session["zzz"] == null)
{
Cart = new DataTable();
Cart.Columns.Add(new DataColumn("Item", typeof(string)));
Cart.Columns.Add(new DataColumn("Price", typeof(string)));
Session["zzz"] = Cart;
}
else
{
Cart = (DataTable)Session["zzz"];

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (18 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

}
cv = new DataView(Cart);
sc.DataSource = cv;
sc.DataBind();
if (!IsPostBack)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(string)));
d.Columns.Add(new DataColumn("c2", typeof(double)));
DataRow dr;
dr = d.NewRow();
dr[0] = "Product 1";
dr[1] = 11.3;
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = "Product 2";
dr[1] = 10.6;
d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource= dv;
l.DataBind();
}
}
void abc(Object sender, DataGridCommandEventArgs e)
{
DataRow dr = Cart.NewRow();
TableCell it = e.Item.Cells[1];
TableCell pr = e.Item.Cells[2];
string item = it.Text;
string price = pr.Text;
Response.Write(item + " " + price);
if (((LinkButton)e.CommandSource).CommandName == "AddToCart")
{
dr[0] = item;
dr[1] = price;
Cart.Rows.Add(dr);
}
else
{
cv.RowFilter = "item='"+item+"'";
if (cv.Count > 0)
{
cv.Delete(0);
}
cv.RowFilter = "";
}
sc.DataBind();
}
</script>
<body>
<form runat=server>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (19 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<asp:DataGrid id="l" runat="server" BorderColor="black" BorderWidth="1" GridLines="Both"


CellPadding="3" CellSpacing="0" Font-Name="Verdana" Font-Size="8pt" HeaderStyle-
BackColor="#aaaadd" AutoGenerateColumns="false" OnItemCommand="abc">
<columns>
<asp:TemplateColumn HeaderText="Add/Remove">
<ItemTemplate>
<asp:LinkButton ID=AddButton Text="Add" CommandName="AddToCart" ForeColor="blue"
runat="server" />
<asp:LinkButton ID=RemoveButton Text="Remove" CommandName="RemoveFromCart" ForeColor="blue"
runat="server" />
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn HeaderText="Item" DataField="c1"/>
<asp:BoundColumn HeaderText="Price" DataField="c2" />
</columns>
</asp:DataGrid>
<ASP:DataGrid id="sc" runat="server"/>
</form>
</body>
</html>

Output

This program is very large in size, however, nothing much has really changed since the earlier
program. We have the first DataGrid containing a large number of attributes, to make it appear
fancy. This is akin to the process of pleasing our companion of the opposite sex, who likes to
look great, and fancies everything in the world that can enhance her good looks further.

We have introduced a new tag called <asp:TemplateColumn, in place of ButtonColumn. As this


is the first column in the properties, we will see the HeaderText displayed as Add/Remove, in
the first column of the text. A template column has a name, and it contains other tags such as
LinkButton. The LinkButton has an ID and some text, that is to be displayed in the column.
The colour attribute is used for setting the colour of the font. The CommandName, as we have
already seen, is used to reveal the Button that had been clicked. Thus, we can add a number of
entities into one column, in order to have greater flexibility in deciding the column contents.

Thus, instead of having Add and Remove as two separate columns, we have combined them in a
single column, but with different Command Names. Most of the code is not altered. The Cells
parameter is reduced by one, as we have one column less. Thus, templates give us more
flexibility in designing our DataGrid.

a.aspx
<%@ Import Namespace="System.Data" %>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (20 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<html>
<script language="C#" runat="server">
DataTable Cart;
DataView cv;
void Page_Load(Object sender, EventArgs e)
{
if (Session["zzz"] == null)
{
int nn;
Cart = new DataTable();
Cart.Columns.Add(new DataColumn("Qty", typeof(string)));
Cart.Columns.Add(new DataColumn("Item", typeof(string)));
Session["zzz"] = Cart;
for (int i=1; i<5; i++)
{
DataRow dr = Cart.NewRow();
nn=(i%2)+1;
dr[0] = nn.ToString();
dr[1] = "Item " + i.ToString();
Cart.Rows.Add(dr);
}
}
else
{
Cart = (DataTable)Session["zzz"];
}
cv = new DataView(Cart);
if (!IsPostBack)
{
bbb();
}
}
public void Edit(Object sender, DataGridCommandEventArgs e)
{
l. EditItemIndex = (int) e.Item.ItemIndex;
bbb();
}
public void Cancel(Object sender, DataGridCommandEventArgs e)
{
l.EditItemIndex = -1;
bbb();
}
public void Update(Object sender, DataGridCommandEventArgs e)
{
string item = e.Item.Cells[1].Text;
string qty = ((TextBox)e.Item.Cells[2].Controls[0]).Text;
cv.RowFilter = "Item='"+item+"'";
if (cv.Count > 0)
{
cv.Delete(0);
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (21 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

cv.RowFilter = "";
DataRow dr = Cart.NewRow();
dr[0] = qty;
dr[1] = item;
Cart.Rows.Add(dr);
l.EditItemIndex = -1;
bbb();
}
public void bbb()
{
l.DataSource = cv;
l.DataBind();
}
</script>
<form runat="server">
<asp:DataGrid id="l" runat="server" BorderColor="black" BorderWidth="1" CellPadding="3" Font-
Name="Verdana" Font-Size="8pt" HeaderStyle-BackColor="#aaaadd" OnEditCommand="Edit"
OnCancelCommand="Cancel" OnUpdateCommand ="Update" AutoGenerateColumns="false">
<Columns>
<asp:EditCommandColumn EditText="Edit1" CancelText="Cancel1" UpdateText="Update1" ItemStyle-
Wrap="false" HeaderText="Edit Command Column" HeaderStyle-Wrap="false"/>
<asp:BoundColumn HeaderText="Item" ReadOnly="true" DataField="Item"/>
<asp:BoundColumn HeaderText="Quantity" DataField="Qty"/>
</columns>
</asp:DataGrid>
</form>
</body>
</html>

The above program allows us to edit data that is present in a DataGrid. As usual, we have our
DataGrid with an id of l, having a number of attributes. We have added three more attributes in
addition to the regular ones, which we shall elucidate while discussing the program.

In the property tag, we have a newly introduced tag called <asp:EditCommandColumn. As this
is placed first in sequence in the column definition, it is displayed as the first column of our
DataGrid. The HeaderText is displayed at the top of the column as the column header, and the
other attributes of EditText, UpdateText and CancelText have been assigned string values. By
default, the value 'Edit1' assigned to EditText, is displayed on the screen.

The other two columns are inserted using BoundColumns. We will explain the attributes given
to them, in a short while.

As the Page_Load function is the first function to be called, the DataGrid Control gets populated
with values. There are four rows and three columns. The EditCommandColumn gets repeated
for every new row that is inserted into the grid.

The Item field has values displayed in a chronological order, whereas, the Quantity field has
values that depend on the result of dividing the remainder value by 2 + 1.

Numbers cannot be inserted into the columns, because the columns are defined to contain

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (22 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

string values. Thus, the ToString function is used to convert the integer values into strings. The
modus operandi of using a 'for' loop to populate fields with values, has been borrowed from the
Microsoft samples.

The output in browser window is shown below.

Output

If you click on Edit1 in any of the rows, the text will get replaced with Update1 and Cancel1.
These values were assigned to UpdateText and CancelText attributes in the
EditCommandControl. Further, instead of static text being displayed, the value assigned to
quantity in the current row, is displayed in an editable textbox.

Output

The above output is displayed, since the function Edit, gets called when we click on Edit1. This
is so because the attribute OnEditCommand is initialized to Edit in the DataGrid Control. This
function has only one line

l. EditItemIndex = (int) e.Item.ItemIndex;


It, thereafter, calls a function named bbb.

Response.Write can be used to display the value of e.Item.ItemIndex. This value displays the
record number of the rows that we clicked upon. So, as the numbering starts from 0, Item 1
will have a record number of 0, Item 2 will have the ItemIndex of 1, and so on.

The task assigned to the Edit function is to set the value of the EditItemIndex member of the
DataGrid to the record number. Hence, it is initialized to the current record number. This
allows editing of the fields in the current row. The Quantity field is the only field that is
currently editable, since the readonly property of the item field, has been set to True.
Thereafter, the function bbb is called, which associates DataSource with the DataGrid Control
and calls DataBind. As we have to use this segment of code repeatedly at various places in the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (23 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

program, we have placed it in a separate function.

Any changes made to the Quantity field, are preserved when we click on Update1. Update1 is
connected with the function Update, using the attribute OnUpdateCommand. We intend
retrieving the values that the user enters, and to add them to the DataGrid.
Thus, e.item.Cell[1].Text retrieves the text available in column 2, which is the Item column.
Further, e.item.Cell[2].Text does the same for column 3, which is the Quantity Column.

Hence, assuming that you clicked on Update for Item 1, e.item.Cell[1].Text will contain Item 1.
But, to retrieve values from the Quantity field, we will have to use one more level of indirection.
This is because the value is contained in an edit box. So, we use Controls[0] for the control in
this column. Thereafter, the Text member in the control, is used to return the text contained in
it.

Thereafter, we use the same process as described earlier. That is:

• filter the record that matches the item, i.e. item="Item 1"
• delete the old record
• add a new record at the end, with the new values contained in the Item and Quantity
fields. Since these values remain the same, the resultant effect would be that the record
would be moved to the end.

We set the value of EditItemIndex to -1 to avoid the values being displayed in the edit textbox.
Any value other than -1, will force ASP+ to display an editbox for the value 'long' with the record
number, thereby, allowing the text to be edited.

When the user clicks on Cancel, the Cancel function is called. It means that the changes
incorporated by the user, are to be cancelled and not to be displayed in the DataGrid. So, we
simply set EditItemIndex to -1, to undo any editing that has been carried out.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
dr = d.NewRow();
dr[0] = 11;
dr[1] = "String 1";
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;
dr[1] = "String 2";
d.Rows.Add(dr);
DataView dv = new DataView(d);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (24 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

l.DataSource = dv;
l.DataBind();
}
void abc(Object sender, EventArgs e)
{
l.Columns[1].Visible = !l.Columns[1].Visible;
l1.Text = "Column 1's visible property is " + l.Columns[1].Visible.ToString();
}
</script>
<body>

<form runat=server>
<ASP:DataGrid id="l" runat="server" GridLines="Both" AutoGenerateColumns="false">
<columns>
<asp:BoundColumn HeaderText="vijay" DataField="c1" />
<asp:BoundColumn HeaderText="mukhi" DataField="c2"/>
</columns>
</asp:DataGrid>
<asp:Button Text="Change" OnClick="abc" runat="server" />
<asp:Label id="l1" runat="server" />
</form>
</body>
</html>

Output

In the above example, we are altering the visibility of a column. Just like before, we have two
BoundColumns, c1 and c2 in a DataGrid l, having the column headings of 'vijay' and 'mukhi'.
Further, a label l1 and a button with the label of 'Change', are added to the page. Irrespective of
whether column 1 is visible or not, the label l1 displays a text message. The button calls the
function abc whenever the user clicks on it.

In the function abc, we access the columns in the DataGridControl, by using the member
Columns and stating the column number in [] brackets. As the numbering within square
brackets start from 0, Columns[1] refers to the second column, which has the title of 'mukhi'.

Every column object has a member called Visible, which is set to True or False, depending upon
whether we want that column to be visible or not. The ! sign changes false to true and true to
false. Initially, the Visible member of Column 1 will be True, hence, the right hand side of the
'equal to' sign returns True. The ! operator which precedes it now, makes it False. This value is
then reassigned to the Visible member, as a result of which, the column now disappears from
the screen. The text in the label also gets updated.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (25 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Output

Column 1's visible property is False

If we click on the button again, the value of Visible property gets toggled. Thus, we have
complete control over the visibility of columns in a DataGrid.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
string s ;
void Page_Load(Object sender, EventArgs e)
{
bbb();
}
void abc(Object sender, DataGridSortCommandEventArgs e)
{
s = (string)e.SortExpression;
bbb();
}
void bbb()
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
dr = d.NewRow();
dr[0] = 1;
dr[1] = "String 3";
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 2;
dr[1] = "String 2";
d.Rows.Add(dr);
dr = d.NewRow();
dr[0] = 3;
dr[1] = "String 1";
d.Rows.Add(dr);
DataView dv = new DataView(d);
dv.Sort = s;
l.DataSource = dv;
l.DataBind();
}
</script>
<body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (26 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<form runat=server>
<ASP:DataGrid id="l" runat="server" AllowSorting="true" OnSortCommand="abc" />
</form>
</body>
</html>

Output

The above example shows us how we can sort a particular column in a DataGrid. The DataGrid
control with the id of l, has an attribute called AllowSorting set to True. Also, when the user
clicks on the column, the function abc is called. Instead of positioning all the code in
Page_Load, we have placed it in a function called bbb. Page_Load calls this function.

In bbb, a DataTable consisting of two columns and three rows, is created. A DataView instance
'dv' is created with the Data Table 'd' as a parameter to its constructor. Once the object is
created, we use a member of this object called Sort, and initialize it to the value stored in the
string s. At the moment, there is no value in the string s. Hence, Sort is assigned a value of
null.

Since the process of sorting is executed on columns, the column names get underlined, i.e. they
become hyperlinks when they are displayed. When we click on the column c2, the function abc
will get called. The parameter 'e' of type DataGridSortCommandEventArgs has a member called
SortExpression, which contains the name of the column that we click on. We store this value in
a variable called 's', and then call the function bbb.

Before redisplaying the data, the Sort member of DataView is again initialized to 's', which now
holds the column name, whose data is to be sorted. Thus, the data within this column is shown
in a sorted order in our DataGrid.

Table Cells
a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (27 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

for (int j=0; j<3; j++)


{
TableRow r = new TableRow();
for (int i=0; i< 2; i++)
{
TableCell c = new TableCell();
c.Controls.Add(new LiteralControl("row no " + j.ToString() + ", coll no " + i.ToString()));
r.Cells.Add(c);
}
t.Rows.Add(r);
}
}
</script>
</head>
<body>
<form runat=server>
<asp:Table id="t" CellPadding=5 CellSpacing=0 BorderColor="black" BorderWidth="1" Gridlines="Both"
runat="server"/>
</form>
</body>
</html>

Output

The above program demonstrates how tables can be populated with data in ASP+. We use <asp:
Table control, with an id of 't', to which rows and columns are to be added. The spacing
between the cells in the table, and the other display features of tables are given by initializing
the attributes supported by this control.

Page_Load function contains a 'for' loop that will be executed thrice. Within this loop construct,
a new object 'r' which looks like TableRow, is created. Every row is made up of columns or
cells. A cell is created using an independent class called TableCell. Here, since we require two
cells per row, we have incorporated one more for the loop, which repeats twice within the loop.
This loop first creates a TableCell called 'c'. Then, using the Add function of the TableCell
member Controls, the cell is assigned a string value or a literal. The Add function in the Cell
member of r called TableRow, adds this cell to the row. This is done twice, as we want two cells
per row. Once the row is ready, it is added to the table, using the Add function of the Row
member in the Table. Since the loop has a count of 3, 3 rows are added to the Table. Thus,
finally we obtain 3 rows containing 2 columns each, with a literal for each of the columns.

This is one more way to add data to a table.

Paging

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (28 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs e)
{
if (c.Checked)
l.PagerStyle.Mode=PagerMode.NumericPages;
else
l.PagerStyle.Mode=PagerMode.NextPrev;
bbb();
}
void abc(Object sender, DataGridPageChangedEventArgs e)
{
Response.Write("hi");
l.CurrentPageIndex = e.NewPageIndex;
bbb();
}
void bbb()
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
for (int i = 0; i < 200; i++)
{
dr = d.NewRow();
dr[0] = i;
dr[1] = "Item " + i.ToString();
d.Rows.Add(dr);
}
DataView dv = new DataView(d);
l.DataSource = dv;

l.DataBind();
l1.Text = "CurrentPageIndex is " + l.CurrentPageIndex + "PageCount is " + l.PageCount;
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" AllowPaging="True" PageSize="10" PagerStyle-Mode="NumericPages"
PagerStyle-HorizontalAlign="Right" PagerStyle-NextPageText="Next1" PagerStyle-PrevPageText="Prev1"
OnPageIndexChanged="abc"
/>
<p>
<asp:Checkbox id="c" runat="server" Text="Show numeric page navigation buttons"
AutoPostBack="true" />
<p>
<asp:Label id="l1" runat="server" /><br>
</form>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (29 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</body>
</html>

Output

The DataGrid control contains a new set of attributes, two of them being:

• AllowPaging, which is set to True.


• PageSize, which is assigned a value of 10. This controls the number of records that are
displayed on one page.

The function bbb called by Page_Load, has a 'for' loop to facilitate addition of 200 records into
our DataGrid. Then, the text in the label l1 is changed to display the value of two DataGrid
members, namely, the CurrentPageIndex and the PageCount. The PageCount member contains
the total number of pages. As the PageSize is 10, (i.e. 10 records are to be displayed on one
page), the total number of pages for 200 records becomes 20. Also, since paging has been
allowed, the values given to the attributes of PagerStyle-NextPageText and PagerStyle-
PrevPageText, reflect Next1 and Prev1 as hyperlinks in the table.

A check box is displayed below the table and it is currently unselected. Whenever we click on
the checkbox, function Page_Load gets called, since the AutoPostBack variable is set to True.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (30 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

The 'if' condition in Page_Load, checks whether the checkbox has been checked or not. This is
verified by the value stored in the boolean member Checked.

• If it is checked, then we set a member of the DataGrid, PagerStyle.Mode to a value of


PagerMode.NumericPages
• If it is not checked, it is set to a value of PagerMode.NextPrev.

This property decides as to which of the two pager styles is to be used. Since the checkbox is
initially unchecked, the default style is PagerMode.NextPrev, where we see two hyperlinks
named Next1 and Prev1, which help us to navigate page by page. The second style uses page
numbers to scroll through the pages. Since we have 20 pages, the numbers 1 to 10 are
displayed along with dots ....

As we keep clicking, the CurrentyPageIndex that started at zero, either increases by one or
decreases by one, depending upon the link that we click on.

The function abc has no significant role to play, since it calls the function bbb once again, to
display the new set of data. The object e that looks like DataGridPageChangedEventArgs has a
member NewPageIndex that internally keeps a record of the data it has currently displayed, and
the set of data that is to be displayed next. Hence the value contained in CurrentPageIndex
changes as it is initialised to NewPageIndex.

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs e)
{
bbb();
}
void pqr(Object sender, DataGridPageChangedEventArgs e)
{
l.CurrentPageIndex = e.NewPageIndex;
bbb();
}
void abc(Object s, EventArgs e)
{
String arg = ((LinkButton)s).CommandArgument;
if ( arg == "next")
{
if (l.CurrentPageIndex < (l.PageCount - 1))
l.CurrentPageIndex ++;
}
else if ( arg == "prev")
{
if (l.CurrentPageIndex > 0)
l.CurrentPageIndex --;
}
else if ( arg == "last")
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (31 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

l.CurrentPageIndex = (l.PageCount - 1);


}
else
l.CurrentPageIndex = Convert.ToInt32(arg);

bbb();
}
void bbb()
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(string)));
DataRow dr;
for (int i = 0; i < 200; i++)
{
dr = d.NewRow();
dr[0] = i;
dr[1] = "Item " + i.ToString();
d.Rows.Add(dr);
}
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
l1.Text = "CurrentPageIndex is " + l.CurrentPageIndex + "PageCount is " + l.PageCount;
}
</script>
<body>
<form runat=server>
<ASP:DataGrid id="l" runat="server" AllowPaging="True" PageSize="10" OnPageIndexChanged="pqr"/>
<p>
<asp:LinkButton runat="server" Text="Previous page" CommandArgument="prev" OnClick="abc" />
<asp:LinkButton runat="server" Text="Next page" CommandArgument="next" OnClick="abc" />
<asp:LinkButton runat="server" Text="Go to Page 8" CommandArgument="7" OnClick="abc" />
<asp:LinkButton runat="server" Text="Go to the first page" CommandArgument="0" OnClick="abc" />
<asp:LinkButton runat="server" Text="Go to the last page" CommandArgument="last" OnClick="abc" />
<p>
<asp:Label id="l1" runat="server" /><br>
</form>
</body>
</html>

Output

Previous page Next page Go to Page 8 Go to the first page


Go to the last page

CurrentPageIndex is 0PageCount is 20

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (32 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

In the earlier example, the DataGridControl was totally in command, since we had used the
attributes that it contained. In this program, we would like to build our own user interface for
paging.

To do so, we have five LinkButtons with different texts for each, but we call the same function
abc. In addition to this, there is a CommandArgument attribute, which is initialized to a
different value for each of them.

Thus, when the page is loaded with the values, the Text is displayed as hyper links.

Notice that the DataGrid Control shows the less than (<) and greater than (>) symbols, which
too can be imlemented to facilitate movement between pages.

When we click on the Text defined for the LinkButton, the function abc is called. In this
function, we first need to extract the command argument. To do so, the first paramter, s of type
Object, is used. This object is cast to a LinkButton class, and the data within the
CommandArgument member is retrieved. The value is stored in a String variable called arg.

If we click on the first button labeled 'Previous page', the variable arg will hold the value of prev,
and so on. If the value of arg is prev, a check is performed on the CurrentPageIndex to ascertain
if it is greater than zero. If so, its value is reduced by 1, thus, showing the records on the
previous page.

Finally, it is the value that is stored in l.CurrentPageIndex, that displays the relevant page.
Thus, if we change the value in this member to 3, we will see page 4 (number count starts from
0). For the last page, we pick up the value in the PageCount member and reduce it by 1. Note,
that the arg is a string variable. Hence, to assign a value to CurrentPageIndex, the ToInt32
function from the Convert class has to be used.

This feature proves to be very useful, when a table contains a large number of records that are
to be displayed. So, whenever we display records from a database, it makes more sense to fetch
the relevant data in small chunks, instead of fetching them all in one stroke.

Data Manipulation
a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
SqlConnection c;
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlCommand co = new SqlCommand("Create Table a1 (name char(10),vno int)", c);
c.Open();
co.ExecuteNonQuery();
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (33 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</script>
</head>
<body>
<form runat=server>
<asp:Button OnClick="abc" text="click" runat=server/>
</form>
</body>
</html>

Structured Query Language (SQL) is commonly used to work with data in a database. The next
few programs will concentrate on adding, modifying and deleting data, using this language. We
will start by creating a very simple table.

The above program, when loaded, shows a button in the browser window. When we click on the
button, nothing apparently happens.

In the function abc, c is an SqlConnection object. All necessary parameters are provided to
establish a connection to the pubs database. Next, an SQL command has to be given to create a
table. For this, we need a Command object called co, that accepts an SQL statement to be
executed. Earlier, we used a Select statement. Here, we use a Create table statement.

In the SQL Create statement, we first specify the name of the table that is to be created. In our
case, the name is a1. Thereafter, we give the names of the fields and the datatype for the values
that are to be stored within them, in brackets. In this case, the table is structured to contain
two fields called name and vno, and their data types are specified as character and integer,
respectively. Moreover, with the char datatype, we have specified the number 10 in brackets,
which signifies the length of the field.

Once the ingredients are in place, we open a connection to the database server, by calling a
function called Open in the SqlConnection Object. The function connects to the database
residing on the server cited, and checks whether we have a valid User id and password to use
SQL Server or not. An error check is normally performed here to determine success or failure.
Since we have decided to avoid error checks for the time being, we continue on the assumption
that the connection has been established successfully.

Finally, the function ExecuteNonQuery from SqlCommand object, is executed. This function
executes the SQL Create command. The words NonQuery signify that we are dealing with a SQL
statement that does not return data, but alters the database instead.

To check whether our table has been created or not, we click on Start, Programs, Microsoft SQL
Server, Query Analyzer. Thereafter, we click on the OK button in the 'Connect to SQL Server'
dialog box. Once the connection with the computer has been established, we see a window with
a list of databases in the left windowpane. Since our table has been created in a database called
pubs, we click on the + sign in front of the database pubs, and then on the + in front of User
Tables. Here, we catch sight of a list of tables in which, a1 is displayed as the first table. The
name given to the table is dbo.a1. You will also witness the titles tables that we had used
earlier, as dbo.titles, which happens to be the last entry in the list. Click on the + of a1, and
then on Columns, to see the two columns given as name and vno.
When we click with the right mouse button on the table named a1, a menu pops up. From this

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (34 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

menu, select the option Open, to display the data in the table. Our table has no data so far.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
SqlConnection c;
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlCommand co = new SqlCommand("Insert into a1 values ('vijay' , 2)", c);
c.Open();
co.ExecuteNonQuery();
}
</script>
</head>
<body>
<form runat=server>
<asp:Button OnClick="abc" text="click" runat=server/>
</form>
</body>
</html>

The above program adds one record into the table a1. Use the program Query Analyzer to verify
the result.

In this program, we have replaced the Create Table statement with an Insert command. The
syntax of this command makes it mandatory for us to use the word 'into', followed by the name
of the table, and finally followed by the word 'values'. Thus, the statement becomes 'Insert into
a1 values'. Thereafter, the values to be inserted in the table are enclosed within brackets. As
the first field is a character field of length 10, we place its value 'vijay' within single inverted
commas. In the case of numbers, the single quotes are not required. The data values are
required to be separated by commas. The final outcome is a new record with values 'vijay' and
2, added to our table a1.

These rules have been framed by the inventors of the SQL language, and are to be strictly
adhered to, if you want to use the language.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
SqlConnection c;
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (35 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

string s = "Insert into a1 values ('" + aa.Text + "' , " + bb.Text + ")";
Response.Write(s);
SqlCommand co = new SqlCommand(s, c);
c.Open();
co.ExecuteNonQuery();
}
</script>
</head>
<body>
<form runat=server>
First Name : <asp:TextBox id=aa runat=server/> <br>
Vno: <asp:TextBox id=bb runat=server/><br>
<asp:Button OnClick="abc" text="click" runat=server/>
</form>
</body>
</html>

Output
Insert into a1 values ('mukhi' , 22)

Most of us detest static values, and seek excitement in things that are dynamic and
challenging. Programmers too prefer their code to be dynamic.

This program accepts data in two textboxes and adds them to the database. The two textboxes
have ids of aa and bb, respectively. The data entered in them is 'mukhi' and 22. When the
button is clicked, the function abc is called. This function creates a string 's' that concatenates
the Text attributes of the textboxes, and passes it on to the Insert command.

As a result, the values contained in the textboxes get placed as the data values in the Insert
command. This makes the insert statement dynamic, wherein, the data that is entered in the
text boxes, has now been added into the database. To provide evidence of this fact, we have
displayed the Insert statement that is created internally in the browser.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<head>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
SqlConnection c;
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
string s = "Update a1 set name = '" + aa.Text + "' where vno =" + bb.Text ;
Response.Write(s);
SqlCommand co = new SqlCommand(s, c);
c.Open();
co.ExecuteNonQuery();
}
</script>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (36 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</head>
<body>
<form runat=server>
First Name : <asp:TextBox id=aa runat=server/> <br>
Vno: <asp:TextBox id=bb runat=server/><br>
<asp:Button OnClick="abc" text="click" runat=server/>
</form>
</body></html>
Output
Update a1 set name = 'sonal' where vno =2

This program is almost identical to the earlier one, except for one single variation. An Update
statement has now replaced the Insert statement.

This statement requires the name of the table, followed by the name of the field that is to be
changed, and finally, the value to which the field is to be updated. If we do not use the 'where'
clause, all records in the table will get modified to the new value. Since this is not what is
actually desired, we add the where clause, which acts like a filter. Now, only those records that
meet the specified condition, get affected. So, the field vno that has a value of 2, will get
modified.

In the same way, you can try the delete statement. Delete removes records from a table. Thus,
the SQL statement 'Delete from a1 where vno = 2' will remove all records whose vno field has a
value of 2.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat=server>
void abc(Object se, EventArgs e)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
string s = "select * from authors where state = '" + aa.Value + "'";
Response.Write(s);
SqlDataAdapter co = new SqlDataAdapter(s, c);
DataSet d = new DataSet();
co.Fill(d, "zzz");
l.DataSource = d.Tables["zzz"].DefaultView;
l.DataBind();
}
</script>
<body>
<form action="a.aspx" runat="server">
<select id="aa" runat="server">
<option>CA</option>
<option>IN</option>
<option>KS</option>
<option>MD</option>
<option>MI</option>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (37 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<option>OR</option>
<option>TN</option>
<option>UT</option>
</select>
<asp:button type=submit text="Fetch" OnClick="abc" runat="server"/>
<ASP:DataGrid id="l" runat="server"/>
</form>
</body>
</html>

Output
select * from authors where state = 'IN'

Here, the earlier program has been made more dynamic. We used the HTML tag called 'select',
to fill up a listbox with the abbreviated names of the states. When we choose a state and click
on the button labeled 'Fetch', the function abc gets called. We have used the Value attribute of
the select tag, to dynamically figure out the name of the state. This is then added to the Select
statement. Thus, depending upon the state that the user selects, the records from the authors
table that match the specified state, are displayed.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat=server>
void abc(Object se, EventArgs e)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co = new SqlDataAdapter("select * from Authors where state = @zzz", c);
SqlParameter p = new SqlParameter("@zzz", SqlDbType.VarChar, 2);
co.SelectCommand.Parameters.Add(p);
co.SelectCommand.Parameters["@zzz"].Value = aa.Value;
DataSet d = new DataSet();
co.Fill(d, "zzz");
l.DataSource = d.Tables["zzz"].DefaultView;
l.DataBind();
}
</script>
<body>
<form action="a.aspx" runat="server">
<select id="aa" runat="server">
<option>CA</option>
<option>IN</option>
<option>KS</option>
<option>MD</option>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (38 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<option>MI</option>
<option>OR</option>
<option>TN</option>
<option>UT</option>
</select>
<asp:button type=submit text="Fetch" OnClick="abc" runat="server"/>
<ASP:DataGrid id="l" MaintainState="false" runat="server"/>
</form>
</body>
</html>

This program works in the same manner as the earlier program, but theoretically, it is
supposedly faster than the earlier program. Let us understand the reasoning behind it.

The select statement passed to the SqlDataAdapter has a 'where' clause that contains a name
zzz, beginning with an @ sign. Earlier, we had used the value member of the TextBox. Any word
that begins with @ is called a placeholder. So, even though the name of the state has not been
acquired at this stage, we are free to pass an incomplete Select statement to the constructor.

Since the Select is incomplete, we create an object of type SqlParameter, whose constructor
requires three parameters:

• The first parameter is the placeholder, zzz, used in the select statement.
• The second parameter is the data type of the field. In our case, since zzz is a placeholder
for the state field, and the data type of this column is VarChar, we enter the second
parameter as SqlDbType.VarChar. VarChar is another word for characters or a string.
• The third last parameter is given the value of 2, which represents the width of the
column.

We can have as many placeholders as we like, in a single select statement. The only restriction
here is that they must be registered or added, using the Add function.

The SqlDataAdapter class has a member called SelectCommand of the SqlCommand datatype.
This class has a member called Parameter of data type SqlParameters, which contains a
function called Add. Now that we have registered our placeholder zzz, we need to assign it a
value. The next line uses the [] brackets syntax to inform ASP+ about the placeholder @zzz, and
also alerts it to the fact that, it will be replaced by the value selected in the listbox named aa.

So, how does all the above, help our program run faster? It should logically slow things down.

When we submit a Select statement or for that matter, any SQL statement, a lot of activity
takes place behind the scene. SQLServer performs a variety of checks.

• The syntax of the statement is check to ascertain whether it abides by all the rules of
SQL. This consumes some time.
• Then, it checks for the table given in the statement in its database, eg. titles.
• Next, the fields mentioned in the statement are looked up, in the specified table.
• Thereafter, it checks whether the user, sa, has a right to access each of the entities.
• Once the above entities are verified and found to be satisfactory, the database server

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (39 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

then figures out as to how the select statement should be executed. This is called the
execution plan.

The intelligence of a database lies in the execution plan. Once the plan is ready, the select
statement is executed. This execution plan is independent of the parameters passed to the
'where' clause.

It is a much better idea to execute all the actions up to the execution plan, only once.
Thereafter, use it, for every SQL statement that follows, rather than repeating it for every query.
This is achieved by implementing the concept of parameters. It saves on database time, since it
does not have to execute all the above actions over and over again.

One more property called MaintanState has been added to our DataGrid Control. It has been
set to false, since it will not be beneficial for the DataGrid to store the state information
internally. When the data is populated on every request, there is no reason to send it back to
the server, or on a round trip when the form is reposted.

To maintain state, the data grid must store all its data. There is no other alternative for
achieving this. When the form is requested for, with the method as post, this data gets
transmitted to and fro. We turn it off because of the large overheads it entails, which adversely
affect the overall performance.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
{
SqlDataAdapter co = new SqlDataAdapter("select distinct State from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "States");
l1.DataSource= ds.Tables["States"].DefaultView;
l1.DataBind();
}
}
public void abc(Object sender, EventArgs E)
{
String s = "select * from Authors where state = @zzz";
SqlConnection c1 = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co1 = new SqlDataAdapter(s, c1);
co1.SelectCommand.Parameters.Add(new SqlParameter("@zzz", SqlDbType.VarChar, 2));
co1.SelectCommand.Parameters["@zzz"].Value = l1.Value;
DataSet ds = new DataSet();
co1.Fill(ds, "Authors");
l.DataSource= ds.Tables["Authors"].DefaultView;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (40 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

l.DataBind();
}
</script>
<form runat="server">
<select id="l1" DataTextField="State" runat="server"/>
<input type="submit" OnServerClick="abc" Value="Authors" runat="server"/><p>
<ASP:DataGrid id="l" runat="server" MaintainState="false"/>
</form>
</body>
</html>

Let us retrieve the same data as shown in the earlier example, but in a more efficient manner.
The Page_Load function gets called by the server every time, but as explained earlier, the 'if'
statement is executed only once.

Each time, a new SqlConnection object is created, but the state data for the listbox that uses a
DataSource, is generated only once. Fetching data all the time, is an exercise in futility, if the
final list is to remain the same. The 'distinct' clause in the select statement will not give
duplicate records for the same state in the output. Thus, the list box l1 is being filled up in the
same way, as a DataGrid.

Each time we click on the button, the function abc fills up the DataGrid as shown earlier. The
listbox data is initially statically populatedusing SQL commands. It will not produce correct
results, if the data changes very frequently in the database.

Thus, the above example indicates that if data is read from a database, actual values should be
avoided in our aspx file. Otherwise, with every new entry on state, the aspx file will have to be
changed.

It is time for us to take a short diversion from databases, to break the monotony. Instead, we
shall refocus our attention on the issue of error handling.

We create a file called a.cs and then run the C# compiler on it, using the command >csc a.cs .
We run the compiled C# code as >a

a.cs
public class zzz {
public static void Main()
{
yyy a = new yyy();
a.abc();
System.Console.WriteLine("After abc");
}
}
public class yyy
{
public void abc()
{
System.Console.WriteLine("Before throw");
throw new System.Exception();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (41 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

System.Console.WriteLine("After throw");
}
}
Output
Before throw
Unhandled Exception: System.Exception: Exception of type System.Exception was thrown.
at yyy.abc()
at zzz.Main()

So far, we have learnt that the functions may return values. However, they are not expected to
return errors. But, there may be certain situations in which the functions may end up
returning errors. Let us study a few such cases, which are demonstrated below:

Constructors can consist of a large amount of code, but they are prohibited from returning any
values. What happens if the code fails? We shall discover the answer in a moment.

Under the assumption that constructors are prohibited from returning any values, we open five
files in a program. Every time we open a file, we need to check for a variety of errors that may
occur, while a file is being opened. These errors could be of the form-
file not found,
read only file, etc.

In these circumstances, errors also known as Exceptions, are thrown by a function when an
error occurs. Hence, the function abc first displays the String given in WriteLine, and then
throws an exception.

An exception is an object that is either an instance of the class Exception or it is derived from
it. In the function abc, we have consciously thrown an exception. But in real life situations, an
exception is generated, only when an error occurs. Further, depending upon the type of error,
different types of Exceptions are thrown.

There are a couple of points to be kept in mind, while going through the above program:

• Any code that is written after a point where the exception is thrown, does not get called.
• In the case of an exception being thrown, any code that follows the function call, does
not get executed. Hence, we encounter a warning when we compile the code.
• When an Exception is thrown, a Message Box is shown at runtime.

The user would undoubtedly be scared out of his wits on seeing the Message Box pop up
infront of him. Thus, Exceptions that are thrown on the occurence of an error have to be
caught. The next program depicts how the errors can be dealt with.

a.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (42 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

try
{
a.abc();
System.Console.WriteLine("After abc");
}
catch ( System.Exception e)
{
System.Console.WriteLine("In Exception " );
}
System.Console.WriteLine("After catch");
}
}
public class yyy
{
public void abc()
{
System.Console.WriteLine("Before throw");
throw new System.Exception();
System.Console.WriteLine("After throw");
}
}

Output
Before throw
In Exception
After catch

In order to catch an Exception, all the code that is likely to be thrown in an Exception, is placed
in a 'try block'. Every 'try' is normally followed by 'catch'. So, if an exception occurs, the code
placed in the catch block, gets executed. As there is no return statement in the catch block, the
statements that follow the catch block, will also get called. We have the flexibility to decide as to
how we propose to handle the error.

Let us coalesce whatever we have learnt so far about Execptions, with ASP+.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb();
}
public void abc(Object sender, EventArgs E)
{
if (au_id.Value == "" || au_fname.Value == "" || au_lname.Value == "" || phone.Value == "")

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (43 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

{
m.InnerHtml = "ERROR: Null values not allowed for Author ID, Name or Phone";
m.Style["color"] = "red";
bbb();
return;
}
String s = "insert into Authors values (@Id, @LName, @FName, @Phone, @Address, @City, @State,
@Zip, @Contract)";
SqlCommand co = new SqlCommand(s, c);
co.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));
co.Parameters["@Id"].Value = au_id.Value;
co.Parameters.Add(new SqlParameter("@LName", SqlDbType.VarChar, 40));
co.Parameters["@LName"].Value = au_lname.Value;
co.Parameters.Add(new SqlParameter("@FName", SqlDbType.VarChar, 20));
co.Parameters["@FName"].Value = au_fname.Value;
co.Parameters.Add(new SqlParameter("@Phone", SqlDbType.Char, 12));
co.Parameters["@Phone"].Value = phone.Value;
co.Parameters.Add(new SqlParameter("@Address", SqlDbType.VarChar, 40));
co.Parameters["@Address"].Value = address.Value;
co.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20));
co.Parameters["@City"].Value = city.Value;
co.Parameters.Add(new SqlParameter("@State", SqlDbType.Char, 2));
co.Parameters["@State"].Value = state.Value;
co.Parameters.Add(new SqlParameter("@Zip", SqlDbType.Char, 5));
co.Parameters["@Zip"].Value = zip.Value;
co.Parameters.Add(new SqlParameter("@Contract", SqlDbType.VarChar,1));
co.Parameters["@Contract"].Value = contract.Value;
c.Open();
try
{
co.ExecuteNonQuery ();
m.InnerHtml = "<b>Record Added</b><br>" + s.ToString();
}
catch (SqlException e)
{
if (e.Number == 2627)
m.InnerHtml = "ERROR: A record already exists with the same primary key";
else
m.InnerHtml = "ERROR: Could not add record, please ensure the fields are correctly filled out";
m.Style["color"] = "red";
}
c.Close();
bbb();
}
public void bbb()
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (44 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

}
</script>
<body >
<form runat="server">
<ASP:DataGrid id="l" runat="server" MaintainState="false"/>
Author ID: <input type="text" id="au_id" value="000-00-0000" runat="server">
Last Name: <input type="text" id="au_lname" value="Mukhi" runat="server">
First Name: <input type="text" id="au_fname" value="Vijay" runat="server">
Phone: <input type="text" id="phone" value="022 496-4339" runat="server">
Address: <input type="text" id="address" value="B13 Everest Tardeo" runat="server">
City: <input type="text" id="city" value="Bombay" runat="server">
State:
<select id="state" runat="server">
<option>CA</option>
<option>IN</option>
<option>KS</option>
<option>MD</option>
<option>MI</option>
<option>OR</option>
<option>TN</option>
<option>UT</option>
</select>
Zip Code: <input type="text" id="zip" value="400036" runat="server">
Contract:
<select id="contract" runat="server">
<option value="0">False</option>
<option value="1">True</option>
</select>
<input type="submit" OnServerClick="abc" value="Add Author" runat="server">
<span id="m" runat="server"/>
</form>
</body>
</html>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (45 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

This program may appear very long, but when you work on real life applications, you will be
expected to write a code that looks like the above program. This program adds one record to the
authors table and also does some error checking.

In Page_Load, we create an SqlConnection object called 'c'. If required, the function bbb is
called. This function is solely responsible for displaying data from the relevant table. Hence, it is
constantly called by the other functions in the code. In the function bbb, we first create an SQL
select statement to display all the records from the authors table. Subsequently, a DataSet
object is created, which is finally added to the DataGrid. This constantly refreshes the DataGrid
Control with data from the authors table.

The function abc is called when you click on the button labeled 'Add Record'. Here, the 'if'
condtion checks for empty values in the following text fields:

• au_id
• au_fname
• au_lname
• phone number

If any one of these is null or blank, the function bbb is called to redisplay the values. The
'return' keyword ensures that the rest of the code in the function abc does not get executed.

Therefore, if any one of the above four fields is blank, no record is added. This is because the
function terminates with the return statement. The main rationale behind this mechanism is
that we do not want our database to contain a record with blank values.

The || sign introduces flexibility into the 'if' statement. Therefore, whenever any of the
conditions results in a true, i.e. if any of the fields is blank, the statements in the block are
executed. Without the || operator, we would have been compelled to repeat the above code four
times in the 'if' statement. The resultant error message is displayed in red, using the Label
control 'm'.

If we do not encounter any errors, a record gets added to our database. Firstly, a string is
created with the placeholders for the data. The method that has been applied to one parameter
in the earlier program, is applied to all the parameters. Finally, the Insert statement is
executed. The function ExecuteNonQuery is placed in a try-catch block, since an error is likely
to occur at runtime while accessing the database.

Output

insert into Authors values (@Id, @LName, @FName, @Phone, @Address, @City, @State, @Zip,
@Contract)

What is a runtime error ?

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (46 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Every database must hold atleast one field containing unique values for all the records. This is
essential to be able to uniquely identify every record in a database. This field is called a Primary
field. In the authors table, the primary field is the au_id field. If we try and add a record, where
the value of au_id is the same as one of the existing values of another record, an exception will
be thrown.

The exception that will be thrown is of type SqlException. This exception is caused by the
member Number. For e.g. if the value of Number is 2627, then it is a duplicate Primary Key
error. The relevant error message is displayed and then the connection is closed. When
SQLServer has a problem in handling the data provided to it, a runtime error is thrown.

The rest of the code is simply a series of textboxes, whose values are used to create the SQL
insert statement.

You should first add a valid record into the table and see it appear in the DataGrid instantly.
Then you should add another record, leaving some of the fields blank. You will notice that the
error appears in red. Now, add a record with a duplicate Primary key, i.e. a record where the
field au_id contains a value present in another record. This is how error checks are built into
our application.
Let us now proceed further.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb();
}
public void abc(Object sender, EventArgs E)
{
String s = "insert into Authors values (@Id, @LName, @FName, @Phone, @Address, @City, @State,
@Zip, @Contract)";
SqlCommand co = new SqlCommand(s, c);
co.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));
co.Parameters["@Id"].Value = au_id.Value;
co.Parameters.Add(new SqlParameter("@LName", SqlDbType.VarChar, 40));
co.Parameters["@LName"].Value = au_lname.Value;
co.Parameters.Add(new SqlParameter("@FName", SqlDbType.VarChar, 20));
co.Parameters["@FName"].Value = au_fname.Value;
co.Parameters.Add(new SqlParameter("@Phone", SqlDbType.Char, 12));
co.Parameters["@Phone"].Value = phone.Value;
co.Parameters.Add(new SqlParameter("@Address", SqlDbType.VarChar, 40));
co.Parameters["@Address"].Value = address.Value;
co.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20));
co.Parameters["@City"].Value = city.Value;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (47 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

co.Parameters.Add(new SqlParameter("@State", SqlDbType.Char, 2));


co.Parameters["@State"].Value = state.Value;
co.Parameters.Add(new SqlParameter("@Zip", SqlDbType.Char, 5));
co.Parameters["@Zip"].Value = zip.Value;
co.Parameters.Add(new SqlParameter("@Contract", SqlDbType.VarChar,1));
co.Parameters["@Contract"].Value = contract.Value;
c.Open();
try
{
co.ExecuteNonQuery();
m.InnerHtml = "<b>Record Added</b><br>" + s.ToString();
}
catch (SqlException e)
{
if (e.Number == 2627)
m.InnerHtml = "ERROR: A record already exists with the same primary key";
else
m.InnerHtml = "ERROR: Could not add record, please ensure the fields are correctly filled out";
m.Style["color"] = "red";
}
co.Connection.Close();
bbb();
}
public void bbb()
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
<ASP:DataGrid id="l" runat="server" MaintainState="false"/>
Author ID: <input type="text" id="au_id" value="000-00-0000" runat="server">
<asp:RequiredFieldValidator id="au_idReqVal" ControlToValidate="au_id" runat=server>
*
</asp:RequiredFieldValidator>
Last Name: <input type="text" id="au_lname" value="Mukhi" runat="server">
<asp:RequiredFieldValidator id="au_lnameReqVal" ControlToValidate="au_lname" runat=server>
*
</asp:RequiredFieldValidator>
First Name: <input type="text" id="au_fname" value="Vijay" runat="server">
<asp:RequiredFieldValidator id="au_fnameReqVal" ControlToValidate="au_fname" runat=server>
*
</asp:RequiredFieldValidator>
Phone: <input type="text" id="phone" value="022 496-4339" runat="server">
<asp:RequiredFieldValidator id="phoneReqVal" ControlToValidate="phone" runat=server>
*
</asp:RequiredFieldValidator>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (48 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Address: <input type="text" id="address" value="B13 Everest Tardeo" runat="server">


City: <input type="text" id="city" value="Bombay" runat="server">
State:
<select id="state" runat="server">
<option>CA</option>
<option>IN</option>
<option>KS</option>
<option>MD</option>
<option>MI</option>
<option>OR</option>
<option>TN</option>
<option>UT</option>
</select>
Zip Code: <input type="text" id="zip" value="400036" runat="server">
<asp:RegularExpressionValidator id="RegularExpressionValidator1"
ASPClass="RegularExpressionValidator"
ControlToValidate="zip" ValidationExpression="[0-9]{5}" runat=server>
* Zip Code must be 5 numeric digits <br>
</asp:RegularExpressionValidator>
Contract:
<select id="contract" runat="server">
<option value="0">False</option>
<option value="1">True</option>
</select>
<input type="submit" OnServerClick="abc" value="Add Author" runat="server">
<span id="m" runat="server"/>
<asp:RegularExpressionValidator id="phoneRegexVal" ControlToValidate="phone"
ValidationExpression="[0-9]{3} [0-9]{3}-[0-9]{4}" runat=server>
* Phone must be in form: XXX XXX-XXXX <br>
</asp:RegularExpressionValidator>
<asp:RegularExpressionValidator id="au_idRegexVal" ControlToValidate="au_id"
ValidationExpression="[0-9]{3}-[0-9]{2}-[0-9]{4}" Font-Name="Arial" Font-Size="11" runat=server>
* Author ID must be digits: XXX-XX-XXXX <br>
</asp:RegularExpressionValidator>
</form>
</body>
</html>

This example is enormous in size, and it includes some exceptionally sophisticated error
checks. It basically amalgamates all that we have learnt so far. All the code, up to the closing
tag of script </script>, remains unchanged.

In the function abc, we have removed the 'if' statement that carries out checks for fields which
contain a null value, or which are blank. Instead, we have used the validators that we had
learnt in one of the earlier chapters. Therefore, let us discern each error check, one at a time.

The Primary Key au_id cannot be left blank, hence, the RequiredFieldValidator is used for this
field. Since au_lname, au_fname, phone, city fields too cannot be blank, the same Validator is
used for these fields as well.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (49 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

In USA, a zip code is 5 digits long and comprises of numbers only. For this reason, we use [0-9],
which signifies that the input can be any digit from 0 to 9. The syntax {5} signifies that there
will be five digits that are to be matched in the expression.

The phone number must also comprise of numbers only. Here, we want the first three numbers
to be followed by a space, then by another two numbers, followed by a - sign, and finally with
four numbers at the end. For example- 123 45-6789.

We deliberately entered 6 digits for the zip code, so that we could force an error when we clicked
on the button. Thus, it is quite easy to validate data in ASP+.

Output

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb();
}
public void Edit(Object sender, DataGridCommandEventArgs E)
{
l.EditItemIndex = (int)E.Item.ItemIndex;
bbb();
}
public void Cancel(Object sender, DataGridCommandEventArgs E)
{
l.EditItemIndex = -1;
bbb();
}
public void Update(Object sender, DataGridCommandEventArgs E)
{
String u = "UPDATE Authors SET au_id = @Id, au_lname = @LName, au_fname = @FName, phone =
@Phone, "
+ "address = @Address, city = @City, state = @State, zip = @Zip, contract = @Contract where
au_id = @Id";
SqlCommand co = new SqlCommand(u, c);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (50 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

co.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));


co.Parameters.Add(new SqlParameter("@LName", SqlDbType.VarChar, 40));
co.Parameters.Add(new SqlParameter("@FName", SqlDbType.VarChar, 20));
co.Parameters.Add(new SqlParameter("@Phone", SqlDbType.Char, 12));
co.Parameters.Add(new SqlParameter("@Address", SqlDbType.VarChar, 40));
co.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20));
co.Parameters.Add(new SqlParameter("@State", SqlDbType.Char, 2));
co.Parameters.Add(new SqlParameter("@Zip", SqlDbType.Char, 5));
co.Parameters.Add(new SqlParameter("@Contract", SqlDbType.VarChar,1));
Response.Write(l.DataKeys[(int)E.Item.ItemIndex].ToString());
co.Parameters["@Id"].Value = l.DataKeys[(int)E.Item.ItemIndex];
co.Parameters["@LNAME"].Value = ((TextBox)E.Item.Cells[2].Controls[0]).Text;
co.Parameters["@FNAME"].Value = ((TextBox)E.Item.Cells[3].Controls[0]).Text;
co.Parameters["@PHONE"].Value = ((TextBox)E.Item.Cells[4].Controls[0]).Text;
co.Parameters["@Address"].Value = ((TextBox)E.Item.Cells[5].Controls[0]).Text;
co.Parameters["@City"].Value = ((TextBox)E.Item.Cells[6].Controls[0]).Text;
co.Parameters["@State"].Value = ((TextBox)E.Item.Cells[7].Controls[0]).Text;
co.Parameters["@Zip"].Value = ((TextBox)E.Item.Cells[8].Controls[0]).Text;
if (String.Compare(((TextBox)E.Item.Cells[9].Controls[0]).Text, "true", true)==0)
co.Parameters["@Contract"].Value = "1";
else
co.Parameters["@Contract"].Value = "0";
c.Open();
try
{
co.ExecuteNonQuery();
m.InnerHtml = "<b>Record Updated</b><br>" + u;
l.EditItemIndex = -1;
}
catch (SqlException e)
{
if (e.Number == 2627)
m.InnerHtml = "ERROR: A record already exists with the same primary key";
else
m.InnerHtml = "ERROR: Could not update record, please ensure the fields are correctly filled out";
m.Style["color"] = "red";
}
c.Close();
bbb();
}
public void bbb()
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (51 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<span id="m" runat="server"/><p>


<ASP:DataGrid id="l" runat="server" OnEditCommand="Edit" OnCancelCommand="Cancel"
OnUpdateCommand="Update" DataKeyField="au_id">
<columns>
<asp:EditCommandColumn EditText="Edit1" CancelText="Cancel1" UpdateText="Update1" ItemStyle-
Wrap="false"/>
</columns>
</ASP:DataGrid>
</form>
</body>
</html>

Output

The above example shows us the same DataGrid control, but the word Edit1 is displayed in the
first column. We had shown you one example earlier, which contained an Edit link. The same
concept is applied to the data that is retrieved from a database.

Updating data in a database is no mean task. The head honchos at Microsoft were aware about
how tricky and important a database update could be. Hence, they made sure that the
DataGrid Control had in-built support for updating a database. Some of the explanation given
below is a repetition of what we had discussed earlier.

A DataGrid supports a property called EditItemIndex. If the value of this property is 10, then
the DataGrid control lets the user edit record number 10 of the database. Thus, instead of
seeing simple text labels, the user can actually change the data in the textboxes that are
displayed. The default value of -1, prevents any record from being edited.

When the user clicks on Edit1, which is the text displayed in the first column, a function called
Edit is invoked, since the DataGrid's OnEditCommand property is set to this function name.
Similarly, the Update and Cancel functions get called when their respective labels are clicked.

When we click on Edit1, the ItemIndex member reveals the record number of that record. So,
we set the property EditItemIndex to this ItemIndex value, as we want the user to edit the
current record. When the user clicks on Cancel1, it means that any changes that have been
made, are to be undone. To execute this, we give EditItemIndex a value of -1.

Thus, Update is the most important option, since it has to update the data in the database with
the newly entered data. Hence, the function Update is called.

First, we create a string 'u' that contains the SQL Update statement. In place of field values, the
placeholders are inserted. Since the primary key is most crucial in an update operation, we
have a 'where clause' with the primary key au_id initialized to the placeholder @id. The
programmers at Microsoft have allowed us access to the primary key. Thus, they have provided

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (52 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

us a member called DataKeys in the DataGrid. This member, when supplied with the record
number, returns the primary key of that record. We are displaying this value using the Write
function. You should be aware that the primary key can be composite i.e. it can be made up of
more than one field.

We now need to initialize all the placeholders to their values. Earlier, it was easy, since we had
simple textboxes. To enable entering of a value in the 'last name' field, we use E.Item.Cells[2].
Controls[0].Text. This field could be the first field in the database, but we need an offset of 2,
since we have one extra column named Cancel1, that is to be accounted for. The rest of the
code is the same as before.

The last column shows a True or a False, but the value displayed is either 1 or 0, respectively.
So, we use an 'if' statement to check the value contained in it.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb();
}
public void Edit(Object sender, DataGridCommandEventArgs E)
{
l.EditItemIndex = (int)E.Item.ItemIndex;
bbb();
}
public void Cancel(Object sender, DataGridCommandEventArgs E)
{
l.EditItemIndex = -1;
bbb();
}
public void Update(Object sender, DataGridCommandEventArgs E)
{
String u = "UPDATE Authors SET au_id = @Id, au_lname = @LName, au_fname = @FName, phone =
@Phone, "
+ "address = @Address, city = @City, state = @State, zip = @Zip, contract = @Contract where
au_id = @Id";
SqlCommand co = new SqlCommand(u, c);
co.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));
co.Parameters.Add(new SqlParameter("@LName", SqlDbType.VarChar, 40));
co.Parameters.Add(new SqlParameter("@FName", SqlDbType.VarChar, 20));
co.Parameters.Add(new SqlParameter("@Phone", SqlDbType.Char, 12));
co.Parameters.Add(new SqlParameter("@Address", SqlDbType.VarChar, 40));
co.Parameters.Add(new SqlParameter("@City", SqlDbType.VarChar, 20));
co.Parameters.Add(new SqlParameter("@State", SqlDbType.Char, 2));

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (53 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

co.Parameters.Add(new SqlParameter("@Zip", SqlDbType.Char, 5));


co.Parameters.Add(new SqlParameter("@Contract", SqlDbType.VarChar,1));
Response.Write(l.DataKeys[(int)E.Item.ItemIndex].ToString());
co.Parameters["@Id"].Value = l.DataKeys[(int)E.Item.ItemIndex];
co.Parameters["@LNAME"].Value = ((TextBox)E.Item.Cells[2].Controls[0]).Text;
co.Parameters["@FNAME"].Value = ((TextBox)E.Item.Cells[3].Controls[0]).Text;
co.Parameters["@PHONE"].Value = ((TextBox)E.Item.Cells[4].Controls[0]).Text;
co.Parameters["@Address"].Value = ((TextBox)E.Item.Cells[5].Controls[0]).Text;
co.Parameters["@City"].Value = ((TextBox)E.Item.Cells[6].Controls[0]).Text;
co.Parameters["@State"].Value = ((TextBox)E.Item.Cells[7].Controls[0]).Text;
co.Parameters["@Zip"].Value = ((TextBox)E.Item.Cells[8].Controls[0]).Text;
if (String.Compare(((TextBox)E.Item.Cells[9].Controls[0]).Text, "true", true)==0)
co.Parameters["@Contract"].Value = "1";
else
co.Parameters["@Contract"].Value = "0";
c.Open();
try
{
co.ExecuteNonQuery();
m.InnerHtml = "<b>Record Updated</b><br>" + u;
l.EditItemIndex = -1;
}
catch (SqlException e)
{
if (e.Number == 2627)
m.InnerHtml = "ERROR: A record already exists with the same primary key";
else
m.InnerHtml = "ERROR: Could not update record, please ensure the fields are correctly filled out";
m.Style["color"] = "red";
}
c.Close();
bbb();
}
public void bbb()
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
<span id="m" runat="server"/><p>
<ASP:DataGrid id="l" runat="server" OnEditCommand="Edit" OnCancelCommand="Cancel"
OnUpdateCommand="Update" DataKeyField="au_id" AutoGenerateColumns="false">
<columns>
<asp:EditCommandColumn EditText="Edit" CancelText="Cancel" UpdateText="Update" ItemStyle-
Wrap="false"/>
<asp:BoundColumn HeaderText="au_id" SortExpression="au_id" ReadOnly="True" DataField="au_id"

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (54 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

ItemStyle-Wrap="false"/>
<asp:BoundColumn HeaderText="au_lname" SortExpression="au_lname" DataField="au_lname"/>
<asp:BoundColumn HeaderText="au_fname" SortExpression="au_fname" DataField="au_fname"/>
<asp:BoundColumn HeaderText="phone" SortExpression="phone" DataField="phone"/>
<asp:BoundColumn HeaderText="address" SortExpression="address" DataField="address"/>
<asp:BoundColumn HeaderText="city" SortExpression="city" DataField="city"/>
<asp:BoundColumn HeaderText="state" SortExpression="state" DataField="state"/>
<asp:BoundColumn HeaderText="zip" SortExpression="zip" DataField="zip"/>
<asp:BoundColumn HeaderText="contract" SortExpression="contract" DataField="contract"/>
</columns>
</ASP:DataGrid>
</form>
</body>
</html>

The program remains the same up to the closing tag script. We have repeated the program once
again, since we wanted to provide you with running programs and not just code fragments.

The problem with the earlier Edit program was that we could easily change the Author id field,
but this change never got reflected in our database. In the above program, we use
BoundColumns to introduce our own fields. Thus, all the fields are editable, except the au_id
field, since the ReadOnly attribute for this property is set to True. Further, the
AutoGenerateColumns attribute for the DataGridControl is set to False, resulting in a display of
only one set of columns, instead of two. The use of BoundColumns thus, renders us with a lot
more flexibility.

We have elucidated a similar example, earlier in the text.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb();
}
public void Delete(Object sender, DataGridCommandEventArgs E)
{
String d = "DELETE from Authors where au_id = @Id";
SqlCommand co= new SqlCommand(d, c);
co.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));
co.Parameters["@Id"].Value = l.DataKeys[(int)E.Item.ItemIndex];
c.Open();
try
{
co.ExecuteNonQuery();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (55 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

m.InnerHtml = "<b>Record Deleted</b><br>" + d;


}
catch (SqlException)
{
m.InnerHtml = "ERROR: Could not delete record";
m.Style["color"] = "red";
}
c.Close();
bbb();
}
public void bbb()
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
<span id="m" runat="server"/><p>
<ASP:DataGrid id="l" runat="server" DataKeyField="au_id" OnDeleteCommand="Delete">
<columns>
<asp:ButtonColumn Text="Delete Author1" CommandName="Delete"/>
</columns>
</ASP:DataGrid>
</form>
</body>
</html>

Output

This program simply deletes a record. Delete is the simplest of all the SQL commands. We
simply add one more column or Button to the DataGrid, and when we click on it, the delete
function gets called.

In the SQL statement, we simply replace Update with the word Delete alongwith the placeholder
containing the primary key. No other code is modified.

Sorting
a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (56 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<script language="C#" runat="server">


SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb("au_id");
}
void abc(Object Src, DataGridSortCommandEventArgs E)
{
bbb(E.SortExpression);
}
public void bbb(String s)
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
DataView Source = ds.Tables["Authors"].DefaultView;
Source.Sort = s;
l.DataSource=Source;
l.DataBind();
}
</script>
<body>
<form runat="server">
<ASP:DataGrid id="l" runat="server" OnSortCommand="abc" AllowSorting="true" />
</form>
</body>
</html>

As we have enabled sorting in the DataGrid, we see a hyperlink for all the column headers. If
we click on any of the columns, the function abc gets called. This function uses E.
SortExpression, which holds details of the column that we click on, and thereafter, it calls bbb
with the Sort field as a parameter. The member Sort is initialized to this new field, and
thereafter, the DataGrid sorts the records automatically. If we try to understand the same
concept of Sorting with a Database, it unshields this power of a DataGrid Control.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E)
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
if (!IsPostBack)
bbb("au_id");
}
void abc(Object Src, DataGridSortCommandEventArgs E)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (57 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

{
bbb(E.SortExpression);
}
public void bbb(String s)
{
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
DataSet ds = new DataSet();
co.Fill(ds, "Authors");
DataView Source = ds.Tables["Authors"].DefaultView;
Source.Sort = s;
l.DataSource=Source;
l.DataBind();
}
</script>
<body>
<form runat="server">
<ASP:DataGrid id="l" runat="server" OnSortCommand="abc" AllowSorting="true"
AutoGenerateColumns="false">
<columns>
<asp:BoundColumn HeaderText="au_id" SortExpression="au_id" DataField="au_id" ItemStyle-
Wrap="false"/>
<asp:BoundColumn HeaderText="au_lname" SortExpression="au_lname" DataField="au_lname"/>
<asp:BoundColumn HeaderText="au_fname" SortExpression="au_fname" DataField="au_fname"/>
<asp:BoundColumn HeaderText="phone" SortExpression="phone" DataField="phone"/>
<asp:BoundColumn HeaderText="address" SortExpression="address" DataField="address"/>
<asp:BoundColumn HeaderText="city" SortExpression="city" DataField="city"/>
<asp:BoundColumn HeaderText="state" SortExpression="state" DataField="state"/>
<asp:BoundColumn HeaderText="zip" SortExpression="zip" DataField="zip"/>
<asp:BoundColumn HeaderText="contract" SortExpression="contract" DataField="contract"/>
</columns>
</ASP:DataGrid>
</form>
</body>
</html>

We have introduced a slight modification to the earlier program. Since we are using
BoundColumn, our own fields can now be sorted.

We can thus decide on the number of columns that the user can sort on. We can also avoid
displaying the entire database and restrict the display of all the columns.

Stored Procedures
a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (58 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=Northwind");


SqlDataAdapter co = new SqlDataAdapter("Ten Most Expensive Products ", c);
co.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds = new DataSet();
co.Fill(ds, "Products");
l.DataSource=ds.Tables["Products"].DefaultView;
l.DataBind();
}
</script>
<body>
<ASP:DataGrid id="l" runat="server"/>
</body>
</html>

Output

The above program executes a stored procedure on the database server.

A stored procedure is code that is to be executed on the server, in one single stroke. Ad hoc
queries, like the ones we have been writing so far, are performance expensive. Using stored
procedures, introduces speed and momentum to our programs. Within a stored procedure, we
can write any SQL statement. We also have the power of a programming language at our
disposal. Today, all known databases support the concept of a stored procedure, which was not
the case a few years ago.
A connection is made to the NorthWind database, instead of pubs. This database contains a
stored procedure called 'Ten Most Expensive Products'. Instead of supplying an SQL statement
to the SqlDataAdapter constructor, we now supply the name of the stored procedure.

Thereafter, ASP+ is to be informed that the string provided is a stored procedure and not an
SQL command. To do so, we use the member CommandType and initialize it to a number
signifying a stored procedure. By default, the CommandType has a number pertaining to an
SQL statement.

Other than these modifications, the code remains the same. Given below is the code contained
in the stored procedure. At this point in time, it consists of a simple select statement, but it can
easily accommodate a large amount of code.

Ten Most Expensive Products

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (59 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

ALTER procedure "Ten Most Expensive Products" AS


SET ROWCOUNT 10
SELECT Products.ProductName AS TenMostExpensiveProducts, Products.UnitPrice
FROM Products
ORDER BY Products.UnitPrice DESC

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
public void abc(Object sender, EventArgs E)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=Northwind");
SqlDataAdapter co = new SqlDataAdapter("SalesByCategory", c);
co.SelectCommand.CommandType = CommandType.StoredProcedure;
co.SelectCommand.Parameters.Add(new SqlParameter("@CategoryName", SqlDbType.NVarChar, 15));
co.SelectCommand.Parameters["@CategoryName"].Value = sc.Value;
co.SelectCommand.Parameters.Add(new SqlParameter("@OrdYear", SqlDbType.NVarChar, 4));
co.SelectCommand.Parameters["@OrdYear"].Value = yr.Value;
DataSet ds = new DataSet();
co.Fill(ds, "Sales");
l.DataSource=ds.Tables["Sales"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
<select id="sc" runat="server">
<option>Beverages</option>
<option>Condiments</option>
<option>Confections</option>
<option>Dairy Products</option>
<option>Grains/Cereals</option>
<option>Meat/Poultry</option>
<option>Produce</option>
<option>Seafood</option>
</select>
<select id="yr" runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (60 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<option>1996</option>
<option>1997</option>
<option>1998</option>
</select>
<input type="submit" OnServerClick="abc" Value="Get Sales" runat="server"/><p>
<ASP:DataGrid id="l" runat="server" />
</form>
</body>
</html>

Output

We can pass as many parameters as we like, to a stored procedure. Along with a button labeled
'Get Sales' to retrieve data, we display two listboxes. The first one facilitates choosing of a
category, while the second one facilitates selection of the year for the sales data.

To pass parameters to the stored procedure, we create a placeholder, as explained before. The
names given to the parameters, namely, CategoryName and OrdYear, should match the names
in the stored procedure. Thereafter, the placeholders are initialized to the items selected in the
listbox.

The source code of the stored procedure reads as follows:

SalesByCategory

ALTER PROCEDURE SalesByCategory


@CategoryName nvarchar(15), @OrdYear nvarchar(4) = '1998'
AS
IF @OrdYear != '1996' AND @OrdYear != '1997' AND @OrdYear != '1998'
BEGIN
SELECT @OrdYear = '1998'
END

SELECT ProductName,

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (61 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

TotalPurchase=ROUND(SUM(CONVERT(decimal(14,2), OD.Quantity * (1-OD.Discount) * OD.


UnitPrice)), 0)
FROM [Order Details] OD, Orders O, Products P, Categories C
WHERE OD.OrderID = O.OrderID
AND OD.ProductID = P.ProductID
AND P.CategoryID = C.CategoryID
AND C.CategoryName = @CategoryName
AND SUBSTRING(CONVERT(nvarchar(22), O.OrderDate, 111), 1, 4) = @OrdYear
GROUP BY ProductName
ORDER BY ProductName

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

We supply the procedure with two parameters and store them in two variables, beginning with
the @ sign. All this is part of the SQLServer syntax for stored procedures. Then, using an 'if'
statement, we check whether the year is some predefined value or not. If it is, we give it a
default value of 1998.

In case the OrdYear parameter is sent across, the default value that it assumes, is 1998. Then,
we use a 'join' to merge the three tables. The 'Group by' clause gives a summary, and the 'sum
function' adds the parameters that have been supplied. We shall not go on exploring more
details of SQL any further.

Thus, we can see that the stored procedure is a programming language that has been merged
with SQL.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
public void abc(Object sender, EventArgs E)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=Northwind");
SqlDataAdapter co = new SqlDataAdapter("Employee Sales By Country ", c);
co.SelectCommand.CommandType = CommandType.StoredProcedure;
co.SelectCommand.Parameters.Add(new SqlParameter("@Beginning_Date", SqlDbType.DateTime));
co.SelectCommand.Parameters["@Beginning_Date"].Value = BD.SelectedDate;
co.SelectCommand.Parameters.Add(new SqlParameter("@Ending_Date", SqlDbType.DateTime));
co.SelectCommand.Parameters["@Ending_Date"].Value = ED.SelectedDate;
DataSet ds = new DataSet();
co.Fill(ds, "Sales");
l.DataSource=ds.Tables["Sales"].DefaultView;
l.DataBind();
}
</script>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (62 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<body>
<form runat="server">
<ASP:Calendar id="BD" BorderWidth="2" BorderColor="lightblue" Font-Size="8pt" TitleStyle-Font-
Size="8pt" TitleStyle-BackColor="#cceecc" DayHeaderStyle-BackColor="#ddffdd" DayHeaderStyle-Font-
Size="10pt" WeekendDayStyle-BackColor="#ffffcc" SelectedDate="7/1/1996" VisibleDate="7/1/1996"
SelectedDayStyle-BackColor="lightblue" runat="server"/>
<p>
<ASP:Calendar id="ED" runat="server"/>
<input type="submit" OnServerClick="abc" Value="Get Employee Sales" runat="server"/><p>
<p>
<ASP:DataGrid id="l" runat="server"/>
</form>
</body>
</html>

Output

This example is short, sweet and pretty. Here, we are creating a calendar by using the tag
Calendar. We have two calendar controls, having the ids of BD and ED. The first one has a
large number of options, whereas, the second has none. This is just to demonstrate the fact
that a large number of options can be set in the calendar tag.

We chose the start date in the first calendar and the end date in the second calendar. Then we

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (63 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

clicked on the button labeled 'Get Employee Sales'. The function abc is associated with this
button. This function has a stored procedure called 'Employee Sales by Country'. We provide
the SqlParameters named Beginning_Date and Ending_Date, to this stored procedure. The
Calendar control stores the selected dates in one of its member called SelectedDate. Hence, the
Parameters are initialized to these dates.
A point to be noted here is that, a date from the previous century has to be provided, or else an
exception will be thrown. The code of the stored procedure named Employee Sales By Country,
is as follows:

Employee Sales by Country

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

ALTER procedure "Employee Sales by Country"


@Beginning_Date DateTime, @Ending_Date DateTime AS
SELECT Employees.Country, Employees.LastName, Employees.FirstName, Orders.ShippedDate, Orders.
OrderID, "Order Subtotals".Subtotal AS SaleAmount
FROM Employees INNER JOIN
(Orders INNER JOIN "Order Subtotals" ON Orders.OrderID = "Order Subtotals".OrderID)
ON Employees.EmployeeID = Orders.EmployeeID
WHERE Orders.ShippedDate Between @Beginning_Date And @Ending_Date

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

Master-Detail relationship
Generally, data is not stored in one single table. It is spread over many tables. The data model
used currently cannot represent relationships in a single grid.

We would also like our display to follow the same principle i.e., it should display the master
column as a hyperlink, and when we click on the link, the details represented by the master be
displayed below.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E )
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (64 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

DataSet ds = new DataSet();


co.Fill(ds, "Authors");
l.DataSource=ds.Tables["Authors"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
<ASP:DataGrid id="l" runat="server" DataKeyField="au_id">
<columns>
<asp:HyperLinkColumn DataNavigateUrlField="au_id" DataNavigateUrlFormatString="a1.aspx?id={0}"
Text="Get Details1"/>
</columns>
</ASP:DataGrid>
</form>
</body>
</html>

This program simply displays all the fields of all the records from the authors table. To this, we
simply add a column containing the text ‘Get Details1’, using HyperLinkColumn. Whenever the
user clicks on this link of a specific record, a new URL is created with a1.aspx, followed by id=
and {0}. The {0} gets replaced with the value contained in the authors id for that record.

Let us go over to a1.aspx to understand the nitty gritties.

a1.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
SqlConnection c;
void Page_Load(Object Src, EventArgs E )
{
c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
String s = "select t.title_id, t.type, t.pub_id, t.price from titles t, titleauthor ta, authors a where ta.
au_id=@Id AND ta.title_id=t.title_id AND ta.au_id = a.au_id";
SqlDataAdapter co = new SqlDataAdapter(s, c);
co.SelectCommand.Parameters.Add(new SqlParameter("@Id", SqlDbType.VarChar, 11));
co.SelectCommand.Parameters["@Id"].Value = Request.QueryString["id"];
DataSet ds = new DataSet();
co.Fill(ds, "Titles");
l.DataSource=ds.Tables["Titles"].DefaultView;
l.DataBind();
}
</script>
<body >
<form runat="server">
Details for Author <%=Request.QueryString["id"]%>
<ASP:DataGrid id="l" runat="server"/>
</form>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (65 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</body>
</html>

In the file a1.aspx, the select statement looks up three tables. The placeholder @Id gives us the
author id. This parameter ld is initialized to the value returned by QueryString["id"]. As we have
learnt earlier, QueryString returns the value contained in the name-value pair in the URL. So,
QueryString["id"] will return the author id of the record that we have clicked on.

Output

http://127.0.0.1/a1.aspx?id=238-95-7766

Details for Author 238-95-7766

The new window displays a data grid that contains all the books that this particular author has
written. This is how a master-detail relationship can be established..

XML
XML is an abbreviation for the eXtensible Markup Language. There are many proponents of this
language who will try to convince you that XML is a very powerful language that can even
eradicate poverty from this world. That may be a bit too far-fetched, but we cannot stop people
from propagating the benefits of XML and how it can make the world a better place to live in.

The DataSet concept invented by Microsoft, delinked the data from its source. So, while
implementing DataSet, it does not make any difference whether the data is in a SQL Server
database or in XML. Thus, the concept of a DataSet is independent of the actual data source.

Let us actually read some data in XML.

a.aspx
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E) {
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("a1.xml"),FileMode.Open,FileAccess.Read);
StreamReader r = new StreamReader(fs);
ds.ReadXml(r);
fs.Close();
DataView Sv = new DataView(ds.Tables[0]);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (66 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

s.InnerHtml = Sv.Table.TableName;
l.DataSource = Sv;
l.DataBind();
}
</script>
<body>
<span runat="server" id="s"/>
<p>
<ASP:DataGrid id="l" runat="server"/>
</body>
</html>

We have a simple DataGrid l with no attributes defined. In this control, the data obtained from
the XML file is to be displayed. In the Page_Load function, a new DataSet object is created. This
is followed by a FileStream object called 'fs'.

To create an object of type FileStream, the constructor is passed three parameters:

• the name of the XML file.


• a number denoting file open.
• a number denoting file read.

The MapPath function gives the file an absolute path name. In our case, as we have installed
IIS on C:\, the first parameter eventually reads as c:\inetpub\wwwroot\a1.xml.

After FileStream, we create a StreamReader object called 'r'. This is accomplished by passing
the newly created FileStream object 'fs' as a parameter to the constructor.

Finally, the function ReadXml is called off the DataSet and passed the parameter 'r', thus
indirectly providing the XML filename. Once the records are read, the file is closed.

We then create a DataView object called 'Sv' and we pass a DataTable object to the constructor.
The span object 's' is filled up with the name of the table stored in Sv.Table.TableName. It is
obvious that the name is acquired from a1.xml. Finally, we bind 'Sv', a DataView object to the
DataGrid.
Thus, the final execution is almost identical to what was done using SQL, thereby, making it
difficult for us to decipher the source of the data.

a1.xml
<root>
<schema id="DocumentElement" targetNamespace="" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xdo="urn:schemas-microsoft-com:xml-xdo" xdo:DataSetName="DocumentElement">
<element name="Products">
<complexType>
<all>
<element name="ProductID" type="int"></element>
<element name="CategoryID" minOccurs="0" type="int"></element>
<element name="ProductName" type="string"></element>
</all>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (67 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</complexType>
</element>
</schema>
<DocumentElement>
<Products>
<ProductID>1001</ProductID>
<CategoryID>1</CategoryID>
<ProductName>Chocolate City Milk</ProductName>
</Products>
<Products>
<ProductID>3004</ProductID>
<CategoryID>3</CategoryID>
<ProductName>Fizzy Fizzing Drink</ProductName>
</Products>
</DocumentElement>
</root>

Output
Products

An XML file contains only tags. We start with a tag called 'root' and end with the tag called '/
root'. XML is very stringent about rules governing tags. Thus, we have to follow certain basic
rules when we use these tags. The tag <element> has an attribute called 'name', which is
initialized to a table name. In our case, this name is Products.

Within the tags <all> and </all>, we use the element tag again, but this time, it is used with the
names of the fields and their data types. These two values are supplied to the name and type
attributes in element. All this data describes the schema, and hence, we enclose this data in a
tag called schema.

The tag schema has an attribute called DataSetName, that specifies a tag called
DocumentElement, within which all the data is placed. The individual records are placed within
the Products tags and the individual values for the fields are enclosed within tags representing
the field names. Thus, it is possible to display data from an XML file in the DataGrid Control,
assuming that it originated from a database.

a.aspx
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("s.xml"),FileMode.Open,FileAccess.Read);
StreamReader sc = new StreamReader(fs);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (68 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

ds.ReadXmlSchema (sc);
fs.Close();
fs = new FileStream(Server.MapPath("d.xml"),FileMode.Open,FileAccess.Read);
StreamReader r = new StreamReader(fs);
ds.ReadXml(r);
fs.Close();
DataView Sv = new DataView(ds.Tables[0]);
s.InnerHtml = Sv.Table.TableName;
l.DataSource = Sv;
l.DataBind();
}
</script>
<body>
<span runat="server" id="s"/>
<p>
<ASP:DataGrid id="l" runat="server"/>
</body>
</html>

s.xml
<schema id="DocumentElement" targetNamespace="" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xdo="urn:schemas-microsoft-com:xml-xdo" xdo:DataSetName="DocumentElement">
<element name="Products">
<complexType>
<all>
<element name="ProductID" type="int"></element>
<element name="CategoryID" minOccurs="0" type="int"></element>
<element name="ProductName" type="string"></element>
</all>
</complexType>
</element>
</schema>

d.xml
<DocumentElement>
<Products>
<ProductID>3003</ProductID>
<CategoryID>3</CategoryID>
<ProductName>Kona Diet Cola</ProductName>
</Products>
<Products>
<ProductID>3004</ProductID>
<CategoryID>3</CategoryID>
<ProductName>Fizzy Fizzing Drink</ProductName>
</Products>
</DocumentElement>

Output
Products

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (69 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

The output is the same as shown with the earlier program. The only change is that, we have
separated the schema and the data into separate XML files named s.xml and d.xml,
respectively. As the schema is placed in a file s.xml, in ASP+, the ReadXmlSchema function is
utilized to read the schema. Thereafter, the entire process is repeated again to read the XML
data, using a different function named ReadXml.

You are at liberty to decide whether you want the schema and data to reside in a single file or
you want to place the the schema (or data definition) and the data in separate files. ASP+ can
handle both the situations with equal aplomb.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<head>
<script language="C#" runat="server">
public DataView dv;
public DataSet ds;
public void abc(Object sender, EventArgs evt)
{
if (IsPostBack)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co = new SqlDataAdapter("select * from Authors", c);
ds = new DataSet();
co.Fill(ds, "Table");
dv = new DataView(ds.Tables[0]);
l.DataSource=dv;
l.DataBind();
}
}
</script>
</head>
<body bgcolor="ffffcc">
<form runat="server">
<input type="submit" runat="server" OnServerClick="abc">
<% if (Page.IsPostBack) { %>
<textarea cols=80 rows=25>
<%
ds.WriteXml(Response.Output);
%>
</textarea>
<% } %>
<ASP:DataGrid id="l" runat="server"/>
</form>
</body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (70 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</html>

This program achieves the reverse of the earlier program in the sense it creates an XML file
from the data retrieved from the database.

We first associate our data grid with all the records of the authors table. We then come to the
textarea html tag, which can display a large amount of data. Next, we use a function called
WriteXml from the dataset object 'ds' that fills up the text area with the records present in the
database in an XML equivalent form.

The text area displays the actual records within tags. Thus, we can take SQL data and write out
an XML file, or read an XML file into a DataGrid.

Data Binding and DataLists


a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object s, EventArgs e)
{
DataBind();
}
string yyy
{
get
{
return "Vijay";
}
}
</script>
</head>
<body>
<form runat=server>
Name: <b><%# yyy %></b>
</form>
</body>
</html>

Output
Name: Vijay

Before we get back to reading data from a table, let us delve upon another aspect of working
with databases, namely, the Data Binding Server controls.

We have created a property called yyy with a 'get' only. Thus, we cannot modify it, since it has a
'read only' property. The text returned here is "Vijay". On loading the ASP+ program, we see
"Name: Vijay" displayed in the browser window.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (71 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

This is because, in the function Page_Load, we are simply calling the familiar function called
DataBind. This function looks at tags beginning with the symbol <%#. It is aware that the word
yyy following this symbol, is a property. Therefore, it calls the get accessor within it. That is why
the value "Vijay" is displayed. Without the DataBind function, a blank value for yyy would have
been displayed.

In functionality, it is similar to using an 'equal to' sign. Then, why is it called 'binding a
property'?

To obtain the answer, you have to continue reading on.


a.aspx
<html>
<head>
<script language="C#" runat="server">
void abc(Object s, EventArgs e)
{
DataBind();
}
</script>
</head>
<body>
<form runat=server>
<asp:TextBox id="aa" runat="server" />
<asp:button Text="Submit" OnClick="abc" runat=server/>
<p>
TextBox:
<asp:label text='<%# aa.Text %>' runat=server/>
</form>
</body>
</html>

Output

In this example, we have a textbox named 'aa' and a button. When the button is clicked, it calls
the function abc. The text within the label is the value returned by a <%#. We replace yyy with
aa.Text.

The function abc contains the DataBind function which is called when we click on the button.
As before, the tags <%# are searched and evaluated. If we enter some text in the textbox and
click on the button, the label will reflect the contents of the textbox.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object Sender, EventArgs E)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (72 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

{
ArrayList v = new ArrayList();
v.Add (12);
v.Add (113);
v.Add (23);
l.DataSource = v;
l.DataBind();
}
</script>
</head>
<body>
<form runat=server>
<asp:DataGrid id="l" runat="server" />
</form>
</body>
</html>

Output

We have learnt how to populate a DataGrid with data from a database and also from a
DataTable. In this program we use an ArrayList class to fill up the control.

An ArrayList object 'v' is created and then, using the Add function, this ArrayList object is filled
up with data. Next, the DataSource member of the DataGrid is initialized to 'v'. Thus, we see
the three values added to our ArrayList object in the DataGrid control.

An ArrayList object simply stores a series of values. It can store an infinite number of values.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{
ArrayList v = new ArrayList();
v.Add (10);
v.Add (20);
v.Add (30);
l.DataSource = v;
l.DataBind();
}
String abc(int n)
{
if ( n >= 15)
return "hi";
else

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (73 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

return "bye";
}
</script>
</head>
<body>
<form runat=server>
<asp:DataList id="l" runat="server">
<ItemTemplate>
Vijay: <%# Container.DataItem %>
Mukhi: <%# abc((int) Container.DataItem) %>
</Itemtemplate>
</asp:datalist>
</form>
</body>
</html>

Output
Vijay: 10 Mukhi: bye
Vijay: 20 Mukhi: hi
Vijay: 30 Mukhi: hi

Data Binding is an extremely powerful concept, since it enables us to bind anything that we
wish to bind.

We have an ArrayList 'v' that has three values of 10, 20 and 30. A template is created that
displays Vijay: and Mukhi :. The rest of the output is dynamic.

We have a member called Container in a template, that uses the property DataItem to retrieve
the values in the list. With Mukhi:, we go a step ahead and call the function abc, giving it the
values of the ArrayList.
If the value contained in 'n' is larger than 15, 'hi' is returned, otherwise 'bye' is returned. Thus,
the output of a function can also be bound.

The next program uses the DataList control, which is similar to a DataGrid.

a.aspx
<%@ Import namespace="System.Data" %>
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs e)
{
DataTable d = new DataTable();
d.Columns.Add(new DataColumn("c1", typeof(Int32)));
d.Columns.Add(new DataColumn("c2", typeof(bool)));
DataRow dr;
dr = d.NewRow();
dr[0] = 11;
dr[1] = true;
d.Rows.Add(dr);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (74 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

dr = d.NewRow();
dr[0] = 2;
dr[1] = false;
d.Rows.Add(dr);
DataView dv = new DataView(d);
l.DataSource = dv;
l.DataBind();
}
</script>
</head>
<body>
<form runat=server>
<asp:DataList id="l" runat="server">
<ItemTemplate>
Num: <%# DataBinder.Eval(Container.DataItem, "c1", "{0:N2}") %>
Check: <asp:CheckBox id=chk1 Checked='<%# (bool)DataBinder.Eval(Container.DataItem, "c2") %>'
runat=server/>
</Itemtemplate>
</asp:Datalist>
</form>
</body>
</html>

Output

This is another program that amply substantiates the importance of data binding. Here, we
have added a new function called DataBinder.Eval, which accepts three parameters:

• The Container containing the DataItem.


• The column name.
• The format.

Num, the first numeric field is displayed with two decimal places and Check:, the second field
accepts a logical value, as the Checked attribute of the checkbox can be either marked or
unmarked.

Note that the second call to the DataBinder.Eval function has only two parameters instead of
three, as no formatting is required here.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (75 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");


SqlDataAdapter co = new SqlDataAdapter("select * from Titles where type='" + ca.SelectedItem.Value +
"'", c);
DataSet ds = new DataSet();
co.Fill(ds, "Titles");
l.DataSource = ds.Tables["Titles"].DefaultView;
l.DataBind();
}
</script>
<body>
<form action="a.aspx" method="post" runat="server">
<asp:dropdownlist id="ca" runat=server>
<asp:listitem >psychology</asp:listitem>
<asp:listitem >business</asp:listitem>
<asp:listitem >popular_comp</asp:listitem>
</asp:dropdownlist>
<asp:button type=submit text="Lookup" OnClick="abc" runat="server"/>
<asp:datalist id="l" repeatcolumns="2" runat="server">
<Itemtemplate>
<img src='<%# DataBinder.Eval(Container.DataItem, "title_id", "/quickstart/aspplus/images/title-{0}.
gif") %>'> <br>
<%# DataBinder.Eval(Container.DataItem, "title_id", "/quickstart/aspplus/images/title-{0}.gif") %>'>
<br>
<%# DataBinder.Eval(Container.DataItem, "title") %><br>
Price: <%# DataBinder.Eval(Container.DataItem, "price", "${0}") %> <br>
</Itemtemplate>
</asp:datalist>
</form>
</center>
</body>
</html>

A dropdown listbox with an id of 'ca', displays the names of the categories. When we click on
the button 'LookUp', the function abc gets called. The code remains almost the same as before,
with the exception that 'l' now refers to a DataList and not a DataGrid. The select statement
obtains its value from the listbox.

In the form, the DataList has an attribute called repeatcolumns, which is set to 2. We have
initialized it to 2 because we want two books to be placed side by side. The template property
then allows us to decide on the columns that we want. The first column is an <img> tag. To fill
up the 'src' attribute for the image tag, we use DataBinder.Eval for the title_id field with
Container.DataItem as the first parameter. This will display the picture. The next line will
display the address of the file and finally the third line will display the title.

As the value contained in the title field is PS1372, first the image /quickstart/aspplus/images/
title-PS1372.gif' will be displayed, followed by the URL which gives the address of the file, and
finally, the title of the book. An image must be present in the subdirectory for it to be displayed.

The price is formatted with a dollar sign.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (76 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=pubs");
SqlDataAdapter co = new SqlDataAdapter("select * from Titles", c);
DataSet ds = new DataSet();
co.Fill(ds, "Titles");
l.DataSource = ds.Tables["Titles"].DefaultView;
l.DataBind();
}
</script>
<body>
<form action="a.aspx" method="post" runat="server">
<asp:button type=submit text="Lookup" OnClick="abc" runat="server"/>
<p>
<asp:datalist id="l" layout="flow" showfooter=true borderwidth=0 runat=server>
<headertemplate>
Header: Product Listing <p>
</headertemplate>
<Itemtemplate>
Item:
<%# DataBinder.Eval(Container.DataItem, "title_id") %>
<%# DataBinder.Eval(Container.DataItem, "title") %>
<%# DataBinder.Eval(Container.DataItem, "price", "${0}") %> <br>
</Itemtemplate>
<separatortemplate>
Separator: vijay mukhi <p>
</separatortemplate>
<footertemplate>
footer: End <p>
</footertemplate>
</asp:datalist>
</form>
</body>
</html>

Output
Header: Product Listing
Item: BU1032But is It User Friendly?$19.99
Separator: vijay mukhi
Item: BU1111Cooking with Computers: Surreptitious Balance Sheets$11.95
footer: End

The advantage of using a template is that we have complete flexibility in deciding the format for
displaying the data. The fact that it may be a DataGrid or a DataList, is of no consequence at
all.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (77 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

Here, we start with a headertemplate that gets displayed only once in the beginning. Hence, we
see Header: Product Listing at the very beginning. The footertemplate gets displayed only once,
but at the end. Therefore, Footer: End is displayed at the end of the page.

Thereafter, the item template gets displayed once for every record and the separator template
gets displayed between records.

Business Objects
a.aspx
<html>
<script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs E)
{
zzz c = new zzz();
string s = c.abc() ;
Response.Write(s);
}
</script>
</html>

c:\inetpub\wwwroot> md bin
c:\inetpub\wwwroot> cd bin
c:\inetpub\wwwroot\bin> edit b.cs

b.cs
public class zzz
{
public System.String abc()
{
return "hell1";
}
}

We run the C# compiler using the following command:

c:\inetpub\wwwroot\bin>csc /target:library b.cs

On loading the aspx program, the framework realizes that it cannot find a class called zzz. But,
before it generates an error, it peeps into the 'bin' subdirectory of the current directory. Since
we have run a.aspx from wwwroot, it checks for a 'bin' subdirectory that has to lie underneath
the wwwroot directory. Here, it looks into each and every dll for the class zzz. On locating the
specific dll, it executes the function abc from it.

It is important to clarify the fact that this class could have been written in COBOL for all that
we care, but it does not make any difference here. The class zzz is termed as a business object
and it can contain any valid C# code.

In Page_Load, we are creating a new instance of class zzz and storing it in the object 'c'. 's' holds

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (78 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

the return value of the function abc. Using the Write function, we display the value of 's'. Thus,
the word 'hell' is displayed because the function abc returns just this string.

While writing code, it is preferable to separate the business logic from the presentation logic.
Thus, in the above case, we have created two files:

• a.aspx, that contains code to display a user interface to the user.


• b.cs, that holds code which understands business logic or business rules.

Thus, whenever a change is required, it is incorporated in the relevant file, without modifying
the other. This is also characterized as 'encapsulating logic in business components'. Thus, we
can incorporate multiple layers in the software world.

ASP+ looks for our business objects in a well-known sub-directory called 'bin'. Hence, the
executables are placed in the 'bin' subdirectory. Thus, they do not have to be registered at all.
The bin sub-directory is checked every time, and when any change is made to the
code, it can be recompiled for future use. Thus, a new copy is automatically used, without
restarting the server.

The other advantage of a pre-decided sub-directory is that it can be assigned 'ftp rights', and
the user can then comfortably locate his files from anywhere in the world.

Under normal circumstances, while you are running an exe program, you issue a command to
delete it, but it will not get deleted since the file gets locked on the disk. However, such is not
the case here. Whenever a business object is loaded into memory, it does not get locked on the
disk. A shadow copy is loaded in memory, thereby facilitating multiple versions to run
concurrently. Thus, at the very basic or core level, a business component is nothing but a class.

a.aspx
<%@ Import Namespace="ddd" %>
<html>
<script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs E)
{
if (!IsPostBack)
{
zzz d = new zzz("server=(local)\\NetSDK;uid=sa;pwd=;database=grocertogo");
c.DataSource = d.abc();
c.DataBind();
}
}
public void abc(Object sender, EventArgs E)
{
zzz d = new zzz("server=(local)\\NetSDK;uid=sa;pwd=;database=grocertogo");
l.DataSource = d.pqr(c.SelectedItem.Value);
l.DataBind();
}
</script>
<body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (79 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

<form runat="server">
<ASP:DropDownList id="c" DataValueField="CategoryName" runat="server"/>
<input type="Submit" OnServerClick="abc" Value="Show" runat="server"/><p>
<ASP:DataList id="l" RepeatColumns="2" runat="server">
<Itemtemplate>
<ASP:ImageButton command="Select" ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ImagePath")
%>' runat="server"/>
</Itemtemplate>
</ASP:DataList>
</form>
</body>
</html>

b.cs
namespace ddd
{
using System;
using System.Data;
using System.Data.SqlClient;

public class zzz


{
String s;
public zzz(String s1)
{
s = s1;
}

public DataView abc()


{
SqlConnection c = new SqlConnection(s);
SqlDataAdapter co = new SqlDataAdapter("select distinct CategoryName from Categories", c);
DataSet ds = new DataSet();
co.Fill(ds, "yyy");
return ds.Tables["yyy"].DefaultView;
}

public DataView pqr(String ca)


{
SqlConnection c = new SqlConnection(s);
SqlDataAdapter co = new SqlDataAdapter("select ImagePath from Products p,Categories c where c.
CategoryName='" + ca + "' and p.CategoryId = c.CategoryId", c);
DataSet ds = new DataSet();
co.Fill(ds, "xxx");
return ds.Tables["xxx"].DefaultView;
}
}
}

> csc /target:library b.cs

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (80 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

This is a two-tier application. In the file a.aspx, we import the namespace ddd, since all our
business objects are placed in this namespace. Since it is optional, it may or may not be
incorporated. When Page_Load is called, since IsPostBack is false, we create a business object
called zzz, which resides in b.cs.

This file is placed in the c:\inetpub\wwwroot\bin sub-directory and has been compiled to
create a dll. We will explain the signifance of the bin directory in the next chapter.

The constructor of the zzz class saves the string parameter containing the connection string, in
an instance variable called 's'. There is a drop down listbox having an id 'c', that displays the
list of categories whose products we would like to see. We initialize the DataSource member of
the listbox from our business object zzz to the value returned by the function abc.

The function abc in b.cs creates a new SqlConnection using the string passed in the
constructor, which is now available in the instance variable 's'. We then select only one field
named, CategoryName from the Categories table, and prefix it with the word 'distinct'. As we
had mentioned earlier, in SQL Language, the word 'distinct' represents unique records.

As you may have observed in this entire chapter, we have created a DataSet and returned a
DataView object of yyy. This represents three records in our case, namely, 'Cereals', 'Milk' and
'Soda'.

When the function abc finishes execution in the aspx file, the data is bound to the control.
Since we have chosen the property DataValueField in control 'c' to be CategoryName, only the
values in the CategoryName are displayed in the listbox. It is essential for us to populate the
listbox from the database. We have made a specific mention of it here, incase you have
overlooked this fact. We can choose any category and then click on the button labeled 'Show'.

In the function abc located in the aspx file, we have created a new instance of type zzz and
passed it the same parameters as that of the constructor. The DataSource object of the DataList
l, is initialized by the function pqr in the class zzz. This function is assigned one parameter
which is the item or the category selected from the drop down listbox.

The functionality of the function pqr is the same as that of the function abc, except for the SQL
Select statement. The select statement that is a link of two tables, i.e. Products and Categories,
is given one field called ImagePath, and the filter is set to the category that is selected from the
listbox. Thus, the DataView that is returned, contains only those products that fall in the
selected category.

If you click on the button, you will see images on your screen. This is because we have
customized the template for the DataList object. A tag called ImageButton, with the property
ImageUrl containing the name of a picture file, is placed in the template. This path name is
taken from the ImagePath field, using the Eval function.

Thus, we have bifurcated our code into two:

• The database handling issues are in a business object within the file b.cs
• The presentation issues in the file a.aspx.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (81 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

We normally use business objects to perform data access. However, when this code is placed in
an external component or object, it becomes easier for others to understand our code. Thus, it
separates the User Interface issues from the Backend.

We would like to list out the two reasons for working on the samples provided by Microsoft:

• We are working with a beta copy. So, when we are experimenting with code, we cannot
be sure whether it is a mistake on our part, or a bug in the beta copy.
• Various tables and pictures are readily available to us.

Three Tier applications


a.aspx
<%@ Import Namespace="n1" %>
<html>
<script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs E)
{
if (!IsPostBack)
{
bbb b = new bbb();
c.DataSource = b.abc();
c.DataBind();
}
}
public void abc(Object sender, EventArgs E)
{
int id = 0;
if (cid.Text != "")
id = Int32.Parse(cid.Text);
bbb b = new bbb();
l.DataSource = b.pqr(c.SelectedItem.Value,id);
l.DataBind();
}
</script>
<body >
<form runat="server">
<ASP:DropDownList id="c" DataValueField="CategoryName" runat="server"/>
<ASP:TextBox id="cid" Width="35" runat="server"/>
<input type="Submit" OnServerClick="abc" Value="fetch" runat="server"/>
<ASP:DataList id="l" RepeatColumns="2" runat="server">
<Itemtemplate>
<ASP:ImageButton command="Select" ImageUrl='<%# DataBinder.Eval(Container.DataItem, "ImagePath")
%>' runat="server"/>
<%# DataBinder.Eval(Container.DataItem, "ProductName") %>
<br>
<%# DataBinder.Eval(Container.DataItem, "UnitPrice", "{0:C}").ToString() %>
<br>
</Itemtemplate>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (82 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</ASP:DataList>
</form>
</body>
</html>

b.cs
namespace n1
{
using System;
using System.Data;
using System.Data.SqlClient;
using n2;
public class bbb
{
ccc da;
public bbb()
{
da = new ccc("server=(local)\\NetSDK;uid=sa;pwd=;database=grocertogo");
}
public DataView abc()
{
return da.abc1();
}
public DataView pqr(String c, int id)
{
DataView v = da.pqr1(c);
double d = 0;
if (id <= 25 )
d = .50;
else
d = 1.50;
for (int i=0; i<v.Count; i++)
{
v[i]["UnitPrice"] = Double.Parse(v[i]["UnitPrice"].ToString()) - d;
}
return v;
}
}
}

c.cs
namespace n2
{
using System;
using System.Data;
using System.Data.SqlClient;
public class ccc
{
String s;
public ccc(String s1)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (83 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

s = s1;
}
public String ConnectionString
{
get
{
return s;
}
set
{
s = value;
}
}
public DataView abc1()
{
SqlConnection c = new SqlConnection(s);
SqlDataAdapter co = new SqlDataAdapter("select distinct CategoryName from Categories",c);
DataSet ds = new DataSet();
co.Fill(ds, "uuu");
return ds.Tables["uuu"].DefaultView;
}
public DataView pqr1(String ca)
{
SqlConnection c = new SqlConnection(s);
SqlDataAdapter co = new SqlDataAdapter("select ProductName, ImagePath, UnitPrice, c.CategoryId
from Products p, Categories c where c.CategoryName='" + ca + "' and p.CategoryId = c.CategoryId",c);
DataSet ds = new DataSet();
co.Fill(ds, "yyy");
return ds.Tables["yyy"].DefaultView;
}
}
}

This example is large in size and is spread over three files. It introduces a few more concepts.
We first compile c.cs as follows:

>csc /target:library c.cs /R:system.data.dll /R:system.dll

And then, we compile b.cs as follows:

>csc /target:library b.cs /R:system.data.dll /R:system.dll /R:c.dll

The file b.cs refers to the code present in the file c.cs. Hence, c.dll is incorporated while creating
the file b.dll. We do not observe any major difference in the output from the earlier programs.

Let us now understand how it works.


'bbb b = new bbb()' will take us to the file b.cs because, the class bbb dwells in it. Within the
constructor, we are simply creating a new object named ccc and giving it the connection string.

The object ccc is located in c.cs. The constructor of this class simply initializes the instance

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (84 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

variable 's' to the data supplied to it in the form of parameters. The database handling tasks are
performed in ccc.

The DataSource for the DropDownList 'c' is initialized by calling the function abc from the
object 'b'. The object abc in the class bbb in turn, calls the function abc1 from the class ccc.
This function then fetches unique categories from the Categories Table and returns the
DefaultView of the DataSet. Earlier, this code was in the class bbb.

The statement l.DataSource = b.pqr(c.SelectedItem.Value,id) in the function abc, will call the
function pqr in the file b.cs with two parameters, viz. the string 'c' that contains the category,
and the customer id, which is contained in an int variable called 'id'.

In this function, the DataView object 'v' is initialized to the output of pqr1 from ccc. This
function takes one parameter, viz. the category. In the file c.cs, the function pqr fills data into
the DataView, after fetching it from the two tables named Products and Category. These values
are obtained only from three fields.

Once the Data is ready, the customer number received in id is then verified to check whether it
is less than or equal to 25. Accordingly, the double variable 'd', that stands for the discount, is
assigned a value of .5 or 1.5.

The DataView object 'v' has a member called Count, which gives a count of the records present
in the object. Using the array notation v[i], we refer to the individual records and then give the
indexer["UnitPrice"] to access the field. Our intention is to reduce the price or UnitPrice by the
amount of discount offered to the customers. So, we retrieve the value in the UnitPrice field and
convert it into a string. Thereafter, we Parse it and finally subtract the discount from it.

Thus, in the above program, the class bbb contains the business logic for calculating the
discount, while the class ccc contains the data handling routines. Such type of applications are
called Three Tier Applications. The second layer or the middle layer is also called middleware.
Thus, software written for the business world comprises of database retrieval, as well as,
business logic.

Before we end this chapter, one more program that displays the data contained in the
ArrayLists.

a.aspx
<html>
<head>
<script language="C#" runat="server">
void Page_Load(Object Sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ArrayList v = new ArrayList();
v.Add(new ppp("Vijay", "Mukhi", "150 Rs"));
v.Add(new ppp("Sonal", "VMCI", "25 Dollars"));
r.DataSource = v;
r.DataBind();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (85 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

}
}
void abc(object sender, RepeaterCommandEventArgs e)
{
l.Text = e.CommandName + " " + e.CommandArgument;
}
public class ppp
{
string n;
string t;
string s;
public ppp(string n1, string t1, string s1)
{
n = n1;
t = t1;
s = s1;
}
public string name
{
get
{
return n;
}
}
public string tick
{
get
{
return t;
}
}
public string share
{
get
{
return s;
}
}
}
</script>
</head>
<body>
<form runat=server>
<asp:Repeater id=r onitemcommand="abc" runat="server">
<ItemTemplate>
<asp:Button Text="Buy" CommandName="buy" CommandArgument='<%# DataBinder.Eval(Container.
DataItem, "tick") %>' runat="server" />
<asp:Button Text="Sell" CommandName="sell" CommandArgument='<%# DataBinder.Eval(Container.
DataItem, "share") %>' runat="server" />
<asp:Label Text='<%# DataBinder.Eval(Container.DataItem, "name") %>' runat=server />
<p>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (86 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

</Itemtemplate>
</asp:Repeater>
<asp:Label id=l runat="server" />
</form>
</body>
</html>

Output

A new aspx control, by the name of Repeater, has been introduced here. It has an id of 'r' and it
calls the function abc whenever it is clicked. A Repeater Control functions like a 'for' statement
or a loop.

The controls specified within the template are repeated for each item in the DataSource
property of the repeater. To prove this, in the Page_Load function, we create an array that has
three items of type ppp. This class has three properties, i.e. name, tick and share. In the
constructor, the instance variables are initialized to the constructor parameters and then
returned in the properties. Also, the DataSource property of Repeater is initialized to the
ArrayList obejct. Thus, the repeater control will repeat the template tag twice for these two
values of Vijay and Sonal.

On loading the above file, we see two buttons having the labels of Buy and Sell. These are the
values assigned to the Text attribute. The label calls the Eval function with the DataItem as the
first parameter, and the name of a property as the second parameter. Thus, the value returned
by the property name will be displayed on the screen.

The function abc is called when we click on the button. The second parameter 'e' to the function
abc, is an instance of RepeaterCommandEventArgs. It has two useful members. One of them is
CommandName, which returns the value of a property called CommandName in the button, i.e.
Buy or Sell. The second member is CommandArgument, that contains either the property value
tick or share, depending upon the button that we click on. The values in these two members
are finally displayed in the label.

Thus, the buttons can be associated with some value from a database and we can bubble up
these values to identify the button that has been clicked on.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (87 of 88)2/13/2007 4:54:39 PM


Database Controls - ASP.NET - Beta2

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap5.htm (88 of 88)2/13/2007 4:54:39 PM


User Controls - ASP.NET - Beta2

-6-

User Controls
In this chapter, you will learn a little more about C#, so that you can incorporate it while
writing your own controls.

We will create our own controls in a slightly different manner than what was done earlier. To do
so, we create:

• a.aspx in c:\inetpub\wwwroot subdirectory.


• b.cs in c:\inetpub\wwwroot\bin subdirectory.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" Assembly="c"%>
<html>
<body>
<form method="POST" action="s.aspx" runat=server>
<ttt:zzz runat=server/>
</form>
</body>
</html>

b.cs
using System.Web.UI;
namespace nnn
{
public class zzz : Control
{
}
}

You can compile the above file named b.cs, by giving the following command:

>csc /target:library /out:c.dll b.cs /r:System.Web.dll

The compiler creates a file called c.dll in the inetpub\wwwroot\bin subdirectory.

In the above C# program, we have simply created a class zzz that is derived from the class
Control. The class Control belongs to the System.Web.UI namespace. We do not have any other
code in our program. Thus, we see a blank screen.

The file a.aspx will remain the same for the initial programs.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (1 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

b.cs
using System.Web.UI;
namespace nnn
{
public class zzz : Control
{
protected override void Render(HtmlTextWriter o)
{
o.Write("<b>hell</b>");
}
}
}

We now have added a function called Render that accepts a parameter 'o', which is an instance
of the class HtmlTextWriter, and its return type is void. The modifiers 'override' and 'protected',
shall be explained to you, in a while. Also, we now call the Write function in the class
HtmlTextWriter, and give it a string, <b>hell</b>.

When you load the aspx file, you will see 'hell' displayed in bold on your screen.

o is an instance of HtmlTextWriter. Now that we have seen some output, let us understand the
working of the program.

In the file a.aspx, we have used a directive called Register (which has been explained in one of
the earlier chapters), and created our own tag prefix called ttt. Along with these details, we have
also declared a namespace called nnn. Our custom tag starts with the prefix ttt, followed by a
colon and then the word zzz. By merely furnishing this information, we see the word 'hell'
displayed in the browser window.

While executing the aspx file, when the web server comes across a custom tag, it first looks for
the directory that is running the aspx file. On receiving the directory, it then looks into a
subdirectory to locate another subdirectory called bin. In our case, bin is located in the c:
\inetpub\wwwroot subdirectory. Thereafter, all the dlls in the bin subdirectory, are loaded into
memory.

Every dll that is loaded into memory, contains information or metadata that consists of the
classes and namespaces existing in it. The web server will check every file for the presence of a
class named zzz (ttt: is followed by zzz) within the nnn namespace (This namespace is given
with the Register directive). The file c.dll meets the match.

The Web server is programmed to call a function by the name of Render, which takes an
HtmlTextWriter object as a parameter in the acquired dll. Using this object, text is rendered to
the browser.

Thus, a user-defined tag is nothing but a class with the same name, but which derives from the
class Control. Also, every user-defined tag must contain a function called Render.

Now, let us get back to C# and understand what the word 'protected' signifies.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (2 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

z.cs
public class zzz {
public static void Main()
{
yyy a = new yyy();
a.abc();
}
}
public class yyy {
private void abc()
{
}
}

Output
z.cs(6,1): error CS0122: 'yyy.abc()' is inaccessible due to its protection level

If you compile the above code as

>csc z.cs

an error will be generated.

This is because the function abc is tagged with the modifier private. The private modifier allows
only the members of the same class to access the function. As a result, only members of the
class yyy are allowed to access the function abc. Therefore, the object 'a' of type yyy in the
class zzz, is restricted any access to private members of the class yyy.

Thus, private is called an access modifier, since it prohibits access to members of a class.
Private is the most restrictive access modifier, while public is the most tolerant. These access
modifiers do not apply to members of the same class.

z.cs
public class zzz
{
public static void Main()
{
xxx a = new xxx();
a.abc();
}
}
public class yyy
{
}
public class xxx : yyy
{
protected void abc()
{
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (3 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Output
z.cs(6,1): error CS0122: 'xxx.abc()' is inaccessible due to its protection level

The same error gets repeated again with the protected modifier as a protected member is
accessible only to a derived class object.

Had any member of class yyy tried to access the functions in class xxx, which has been derived
from the class yyy, no errors would have been generated. A protected modifier signifies that
only derived classes are allowed access its members. Thus, a protected modifier lies in the
midst of the two extremes, private and public.

z.cs
public class zzz
{
public static void Main()
{
xxx a = new xxx();
yyy b = new yyy();
xxx c = new yyy();
yyy d = new xxx();
}
}
public class yyy
{
}

public class xxx


{
}

Output
z.cs(7,9): error CS0029: Cannot implicitly convert type 'yyy' to 'xxx'
z.cs(8,9): error CS0029: Cannot implicitly convert type 'xxx' to 'yyy'

C# is extremely stern about equating different data types to each other. Thus, we cannot equate
a yyy object with an xxx object. The entities on both sides of an 'equal to' sign must have the
same data type, or else an error stating 'cannot covert to', is generated.

z.cs
public class zzz
{
public static void Main()
{
xxx a = new xxx();
yyy b = new yyy();
xxx c = new yyy();
yyy d = new xxx();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (4 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
}
public class yyy
{
}
public class xxx : yyy
{
}

Output
z.cs(7,9): error CS0029: Cannot implicitly convert type 'yyy' to 'xxx'

Now, the error vanishes because, class xxx is derived from class yyy. As a result, class xxx now
comprises of two classes, a yyy class and an xxx class. Therefore, the statement xxx c = new yyy
() does not raise any error.

As class xxx derives from class yyy, we call xxx a higher class, since it contains the lower class
yyy, and more. We can thus, have a higher class on the right hand side of the 'equal to' sign
and a lower class on the left hand side. Technically speaking, we can use a derived class on the
right hand side, and a base class on the left hand side of an 'equal to' sign.

If they are placed the other way around, that is, if the class yyy is on the right hand side and
the xxx class is on the left hand side, an error is generated. A derived class cannot be made
equal to a base class.

z.cs
public class zzz {
public static void Main()
{
yyy a = new xxx();
a.abc();
a.pqr();
}
}
public class yyy {
public virtual void abc()
{
System.Console.WriteLine("yyy abc");
}
public virtual void pqr()
{
System.Console.WriteLine("yyy pqr");
}
}
public class xxx : yyy
{
public override void abc()
{
System.Console.WriteLine("xxx abc");
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (5 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

public new void pqr()


{
System.Console.WriteLine("xxx pqr");
}
}

Output
xxx abc
yyy pqr

We have two functions in class yyy namely, abc and pqr. We have added a modifier named
'virtual' to these functions. This modifier permits the derived classes to override the functions
abc and pqr. Without the word virtual, the derived classes cannot override functions in the base
class.

The derived class has the option of overriding the functions of the base class, i.e. creating a new
function with the same names which may or may not bear any relation to the functions of the
base class.

Adding a modifier 'new' to the virtual function in the derived class, breaks all links with the
function having the same name in the base class. Thus, the base class pointer has no access to
the derived class functions.

The override modifier overrides the function of the base class. 'a' is a pointer to a yyy class and
it is initialized to the derived class xxx. Hence, when we call a.abc(), the function abc of the
derived class xxx will be called.

Thus, in the case of a virtual function, C# goes a step further and checks the run time data
type of the object, and not the compile time data type. If the function in the derived class has
an override modifier, as in the case of the function abc, the function gets called from the derived
class. In case of new, as in the case of the function pqr, it becomes a new function. And thus, it
ignores the existence of such a function in the class xxx. The only option available is to call the
function from the class yyy itself.

There is a function called Render in the class Control. If we want our function Render to be
called in class zzz, we have to use the override modifier. Otherwise, the function will be called
from the class Control instead.

z.cs
public class zzz
{
public static void Main()
{
yyy a = new xxx();
a.abc();
}
}
public class yyy
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (6 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

public virtual void abc()


{
System.Console.WriteLine("yyy abc");
}
}
public class xxx : yyy
{
protected override void abc()
{
System.Console.WriteLine("xxx abc");
}
}

Output
z.cs(18,25): error CS0507: 'xxx.abc()': cannot change access modifiers when overriding 'public'
inherited member 'yyy.abc()'

We get the above error because, when we override a function of the base class, we cannot
change it's access modifiers. Everything, including the modifiers, must be identical to what is
present in the base class. Since the function Render is marked as protected in the base class,
we have to use the same access modifier in the class zzz also.

Let us get back to Controls again.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" Assembly="c"%>
<html>
<body>
<form method="POST" action="S.aspx" runat=server>
<ttt:zzz aa="hi" bb=100 runat=server/>
</form>
</body>
</html>

b.cs
using System.Web.UI;
namespace nnn
{
public class zzz : Control
{
public string s;
public string aa
{
get
{
return s;
}
set
{
s = value;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (7 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
}
public int bb = 12;
protected override void Render(HtmlTextWriter o)
{
o.Write("hell " + bb + " " + aa);
}
}
}

Output
hell 100 hi

A property can either consist of a getset accessor or it can contain a simple instance variable.
Also, it can be used in place of a variable. In the case of a property, source code can be
executed. However, the user of the tag will never be exposed to the internal workings of a
property and its implementation in a tag.

The set accessor is called before the function Render gets executed. This enforces the situation
where all the properties have to be initialized first, and only then the Render function can be
executed.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" Assembly="c"%>
<html>
<body>
<form method="POST" action="S.aspx" runat=server>
<ttt:zzz aa-bb="hi" aa-cc=100 runat=server/>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class yyy
{
public string bb = "no";
public int cc = 200;
}
public class zzz : Control
{
yyy a = new yyy();
public yyy aa
{
get
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (8 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

return a;
}
}
protected override void Render(HtmlTextWriter o)
{
o.Write(aa.bb + " " + aa.cc);
}
}
}

Output
hi 100

We look at the .cs file first. In the class zzz, we have created an object a, that is an instance of
the class yyy. This class is created in the same namespace nnn as given along with the aspx
Register directive. aa is a property that returns a yyy object in its get accessor.
Class yyy also has two members named bb and cc, which are initialized to 'no' and 200,
respectively. Once a yyy object is created, using the dot syntax, we can access these members
individually. In an aspx file, a minus sign is used instead of a dot, to access the members.
Hence, to access the bb member in yyy, we use the statement 'aa-bb'.

The only difference here is in the choice of the separator, between the name of the property and
the name of the member, belonging to the object that the property returns.

Now, we return back to C#.

z.cs
public class zzz
{
public static void Main()
{
int [] a;
int i;
a = new int[3];
a[0] = 1;
a[2] = 8;
a[0]++;
System.Console.WriteLine(a[0]);
i = 0;
System.Console.WriteLine(a[i]);
i = 2;
System.Console.WriteLine(a[i]);
}
}

Output
2
2
8

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (9 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Whenever we want to store multiple items of the same type, we use a data type called an array.
An array stores similar items together. Here, 'a' is an array that is declared, using a pair of
square brackets [].
We now proceed to create an array of ints. To do so, the keyword 'new' is used along with the
size of the array, which in our case is 3. The array size cannot be specified at the time of
creation of the array. It must be specified along with 'new'.

To access the members of the array, we use the name of the array, followed by a pair of square
brackets which enclose the index of the specific array variable. Thus, the first variable is a[0],
the second is a[1], and so on. The counting for the array index begins with zero and not from 1.

An array variable can be easily used in place of a normal variable. The advantage in using
arrays is that it makes the code concise. For example, when we use the form a[i], i is an integer
variable holding values ranging from 0 to 2. When the value of i is 0, the name of the variable
becomes a[0]. When we change the value of i to 1, the name of the variable now becomes a[1].
Thus, by changing the value of one variable, we are able to change the name of another
variable, and thus, access a different value.

It is this feature of arrays, which makes them very useful. We are guilty of the crime of having
used arrays earlier in this book, without explaining them in detail.

z.cs
public class zzz
{
public static void Main()
{
int [] a;
int i;
a = new int[3];
for ( i = 0; i<=2; i++)
a[i] = i*2;
System.Console.WriteLine(a.Length);
for ( i = 0; i< a.Length; i++)
System.Console.Write(a[i]);
}
}

Output
3
024

Arrays are ideal in a looping construct. In the first 'for' loop, we initialize the variable a[0] to 0, a
[1] to 2 and a[2] to 4. Every array type has a member called Length, that returns the size of the
array. In our case, the array size is 3. We can use this fact to iterate through all the members of
the array.

z.cs
public class zzz

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (10 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

{
public static void Main()
{
string [] a;
a = new string[]{"hi","bye"};
foreach ( string s in a)
System.Console.WriteLine(s);
}
}

Output
hi
bye

We can create an array of any data type. Earlier, we created an array of type int. In this
program, we have created an array of type string. We are also allowed to initialize the array
members at the time of creation, by using the square brackets.

We can use the 'foreach' statement to iterate through the array. During each iteration, the
string 's' will sequentially hold the string values in the array. Thus, in the first iteration, 's' will
contain the string 'hi', and in the next iteration, it will contain the string 'bye'.

The 'foreach' construct is a more convenient way of iterating through an array, though we could
even have used a 'for' construct. You are free to choose from any of these constructs, as per
your requirement.

z.cs
public class zzz
{
public static void Main()
{
yyy a = new yyy();
a[2] = "hi";
System.Console.WriteLine(a[2]);
}
}
public class yyy
{
public string a;
public string this[int i]
{
get
{
System.Console.WriteLine("get " + i);
return a;
}
set
{
System.Console.WriteLine("set " + value + " " + i);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (11 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

a = value;
}
}
}

Output
set hi 2
get 2
hi

Although, we have not created any array in the above program, we are still using the array
syntax. We first create an object 'a' of type yyy. Then we use the syntax a[2] = "hi". When the
program reaches this statement, C# stops for a while and looks for an indexer in our program.

An indexer is a property with a special name called 'this'. Since we have created such a
property, C# calls the set accessor of this property and assigns a value of 2 to the parameter i.
As the return type of the property is a string, the hidden variable named 'value' contains the
string 'hi'. We are supposed to simulate an array within the property. Since this has not been
done, the indexer simulates an array that does not exist.

Let us get back to ASP+.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz runat=server>
vijay mukhi
</ttt:zzz>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class zzz : Control
{
protected override void Render(HtmlTextWriter o)
{
if ( HasControls() )
o.Write("True <br>");
LiteralControl l = (LiteralControl) Controls[0];
o.Write(l.Text);
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (12 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Output
True
vijay mukhi

In the aspx file, we have inserted the text 'vijay mukhi' within ttt, which is a newly created tag.
We would like to display this text in the browser.

To do so, we call a function called HasControls in the Render function, which does not take any
parameter.

Since this function is not present in our class zzz, it is taken from the Control class. The return
value of true or false depends upon the presence of controls in our web page. If the page has
controls, HasControls shows true, or else, it shows false.

The class Control has a property called Controls that returns a ControlCollection object. This
class has an indexer that returns a Control object. Thus, the use of Controls[0] will return the
first control on our page.

In our program, Controls[0] returns a LiteralControl, which is a class derived from Control.
Hence, the cast operator is required.

The Text property in this control, displays the text given within the tag.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" runat=server>
vijay mukhi
</ttt:zzz>
<asp:Button id="bye" runat=server>
</asp:Button>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class zzz : Control
{
protected override void Render(HtmlTextWriter o)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (13 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

int j = Controls.Count;
o.Write(j + "<br>");
for( int i = 0; i< j; i++)
{
if ( Controls[i] is LiteralControl )
{
LiteralControl l = (LiteralControl) Controls[i];
o.Write(l.Text + " " + l.ClientID);
}
}
}
}
}

Output
1

vijay mukhi ctrl1

The class ControlCollection has a member called Count, which contains a count of the number
of Controls that are present on our page. The value held in this member is 1, which indicates
that the Button control used outside the ttt tag, has not got added to our collection.

A 'for' loop is used to iterate through the collection. A check is performed for a LiteralControl;
thereafter, two members of this control, Text and ClientID, are displayed. The member ClientID
shows crtl1, even though it has been assigned an id of 'hi'. These controls are called child
controls.

Composite Controls
a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{
hi.aa++;
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" runat=server/>
<asp:button text="Add" OnClick="abc" runat=server/>
</form>
</body>
</html>

b.cs
using System;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (14 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz: Control, INamingContainer
{
public int aa
{
get
{
return Int32.Parse(((TextBox)Controls[1]).Text);
}
set
{
((TextBox)Controls[1]).Text = value.ToString();
}
}
protected override void CreateChildControls()
{
this.Controls.Add(new LiteralControl("Vijay Mukhi: "));
TextBox b = new TextBox();
this.Controls.Add(b);
b.Text = Controls.Count.ToString();
}
}
}

Output

Vijay Mukhi:

On loading the aspx file, we see ' 2' in the textbox and then, a button labeled Add is displayed.

In the second program, we have explained the function called Render, which is called when you
have a User Defined Control. In the same vein, if a function by the name of CreateChildControl
is present in the file, it too gets called. In this function, we can add as many controls as we
desire.

Every function in a class is given an extra parameter called 'this'. This parameter refers to an
instance of the class that the function resides in. Thus, truly speaking, the function Render is
called with two parameters and not one. The code for it is as follows:

Render ( zzz this, HtmlTextWriter o).

Therefore, this.Controls.Add or Controls.Add means the same thing. Whenever you see this
syntax, you can safely ignore it.

In the function CreateChildControls, we have added a Literal Control object, and created a

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (15 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Literal Control object on the same line. The syntax Add introduces one more control to the
Controls collection, and hence, we can proudly see 'Vijay Mukhi' displayed in the browser
window.

To add a TextBox to the controls collection, we simply create a TextBox object and use the same
Add function from the Controls class. Hence, the count 'property' shows the number 2 in the
editbox, because we have initialized the Text member to this value.

In the class zzz, we have a property called aa which is given the id of 'hi' in the aspx file. The
property can now be accessed by writing hi.aa. The syntax consists of the id name, followed by
name of the property.
Within this property, the value contained in the TextBox is incremented by one, every time. The
set accessor uses value, which is the hidden variable, to change the Text member. In the get
accessor, we simply return the value stored in the Text member. The cast operators are
mandatory.

We also assume that the TextBox is the second member of the Controls Collection and hence,
we use Controls[1] to access it. The user cannot be made aware of the fact that the controls
were created in the function CreateChildControls.

The HTML file simply shows it as HTML tags. We are thus creating new controls by combining
existing controls. Such controls are called Composite controls, and the technique used is called
class composition. The User Controls created earlier, were present in a file with the .ascx
extension which is a text file, whereas now, we have placed the control in an assembly or a dll
file.

In every other sense, composite controls are similar to User Controls and use the same ASP.
NET syntax.

Zzz is derived from the interface INamingContainer that does not contain any methods at all.
We use it merely as a tagging interface. When the class implements the above interface, every
new child control that is created, is given a unique id in ASP+. This concept is important
because we may have many instances of our control on the same page; therefore, their ids need
to be different. Zzz does not need to override the Render method, because the child controls
contain their own rendering logic or code.

You can also expose a single property that internally uses multiple properties from multiple
controls.

But before that, let us first learn all about events and delegates.

z.cs
using System;
delegate void ddd();
class zzz
{
public void abc()
{
Console.WriteLine("abc " );

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (16 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
public static void Main()
{
zzz z = new zzz();
ddd a;
a = new ddd(z.abc);
a();
}
}

Output
abc

The delegate ddd is created by specifying the return type, the parameter types, and the reserved
word delegate. Thereafter, we are allowed to declare an object 'a', which is of the delegate type
ddd.

To instantiate a delegate object, 'new' is used along with the name of the function, z.abc, which
has to be called through a delegate object named 'a'. Thus, a() will call the function abc. This is
an indirect way of calling the function abc through the delegate object.

z.cs
using System;
delegate void ddd(string s);
class zzz {
public static void abc(string s)
{
Console.WriteLine("abc " + s);
}
public static void pqr(string s)
{
Console.WriteLine("pqr " + s);
}
public static void Main()
{
ddd a, b, c, d;
a = new ddd(abc);
b = new ddd(pqr);
c = a + b;
d = c - a;
a("one");
b("two");
c("three");
d("four");
}
}

Output
abc one
pqr two

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (17 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

abc three
pqr three
pqr four

This example shows us the capabilities of a delegate. We have created two delegate objects, a
and b, and associated them with the functions abc and pqr, respectively. These functions are
called indirectly through the delegate objects.

The power of a delegate gets displayed when we combine them, as in a + b . The result of this
operation is stored in delegate c. Thus, the syntax c() calls both the functions abc and pqr. This
is the first time that the plus sign is being used to call two functions through a delegate. The
same concept could be applied to call numerous functions by using a single delegate. The
delegate 'c' represents the functions abc and pqr. Subtracting 'a' from 'c', i.e. subtracting the
function abc from the functions abc and pqr, results in the delegate 'd' calling only the function
pqr.

Events
z.cs
public delegate void ddd();
class zzz
{
public static void Main()
{
yyy l = new yyy();
l.c += new ddd(l.abc);
xxx x = new xxx();
l.c += new ddd(x.xyz);
l.pqr();
}
}
public class yyy
{
public event ddd c;
public void pqr()
{
c();
}
public void abc()
{
System.Console.WriteLine("abc");
}
}
public class xxx
{
public void xyz()
{
System.Console.WriteLine("xyz");
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (18 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Output
abc
xyz

The delegate ddd is created to call the function abc. Next, we create two objects named 'l' and
'x', that look like classes yyy and xxx, respectively. In the class yyy, we create 'c', which is an
instance of a delegate ddd. Note that the return type is replaced by the word event. Hence, 'c' is
now an event.

The event 'c' is initialized to a delegate instance, which is associated with the function abc from
the same class. Thereafter, we again initialize the event c to a delegate instance, but this time,
we use a different function name i.e. xyz, from the class xxx. Thus, the event 'c' is now
associated with two functions. The command l.pqr() executes the event object as c(). Thus, two
functions belonging to two different classes get executed together. This is the power of an event,
and it is used extensively for notification purposes.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" runat=server/>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz: Control,INamingContainer
{
public int aa
{
get
{
return Int32.Parse(((TextBox)Controls[1]).Text);
}
set
{
((TextBox)Controls[1]).Text = value.ToString();
}
}
protected override void CreateChildControls()
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (19 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

this.Controls.Add(new LiteralControl("Vijay Mukhi: "));


TextBox b = new TextBox();
b.Text = "0";
this.Controls.Add(b);
Button a = new Button();
a.Text = "Add";
a.Click += new EventHandler(abc);
Controls.Add(a);
}
void abc(Object s, EventArgs e)
{
aa++;
}
}
}

Output

Vijay Mukhi:

The above example demonstrates as to how a delegate can be used in a control. In addition to
the two controls that existed previously, we have a third control, which is a button named 'b'.
The text or the label of the button is Add.

The syntax a.Click += new EventHandler(abc) can only be used with a delegate. Click is a
delegate type property in the Button class, and is similar to our delegate objects a, b and c. The
EventHandler class is like our delegate ddd, which represents the function abc. Thus, every
time we click on the button, the function Click() is called. As a result, all the functions
associated with the delegate, get called. Thus, function abc is called, which increments the
value of aa by 1.

b.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz: Control,INamingContainer
{
public int aa
{
get
{
return Int32.Parse(((TextBox)Controls[1]).Text);
}
set
{
((TextBox)Controls[1]).Text = value.ToString();
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (20 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
protected override void CreateChildControls()
{
this.Controls.Add(new LiteralControl("Vijay Mukhi: "));
TextBox b = new TextBox();
b.Text = "0";
this.Controls.Add(b);
Button a = new Button();
a.Text = "Add";
a.Click += new EventHandler(abc);
a.Click += new EventHandler(pqr);
Controls.Add(a);
}
void abc(Object s, EventArgs e)
{
aa++;
}
void pqr(Object s, EventArgs e)
{
aa++;
}
}
}

Each time we click on the button, the number increases by 2. This is because we have
associated the two functions abc and pqr with the delegate object name Click. We could have
called numerous other functions in a similar manner.

The use of delegates offers a cleaner method of calling our code whenever an event takes place.
A composite control can add itself to an event raised by a child control. We guarantee that our
code will get called with a click on a child control, i.e. a button.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{
hi.aa++;
Response.Write(hi.aa.ToString());
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" Onchange="abc" runat=server/>
</form>
</body>
</html>

b.cs

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (21 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz: Control, INamingContainer
{
public event EventHandler Change;
public int aa
{
get
{
return Int32.Parse(((TextBox)Controls[0]).Text);
}
set
{
((TextBox)Controls[0]).Text = value.ToString();
}
}
protected override void CreateChildControls()
{
TextBox b = new TextBox();
b.Text = "0";
Controls.Add(b);
Button a = new Button();
a.Text = "Add";
a.Click += new EventHandler(add1);
Controls.Add(a);
}
void add1(Object sender, EventArgs e)
{
aa++;
Change(this,EventArgs.Empty);
}
}
}

Output
4

This example once again demonstrates an event. Here, we have a tag with an id of 'hi'. Along
with it, a new property called onChange is introduced, which calls the function abc when a
change occurs in our user control. Thus, when anything is entered in the textbox, it will result
in a call to the function abc. This function merely increments the value of the property aa by 1,
and then displays it.

The user control notifies ASP+ about the change, as a result of which, the code that has been

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (22 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

written outside the control, gets called. The onChange property must be initialized to a
function, if we want it to discern any change in the control. The control will simply trigger off an
OnChange event, which results in a call to the function abc. An event object named Change,
which is of delegate type EventHandler, is created. This happens because our property in the
tag is named as OnChange.

A property called aa is added, which gets and sets the value in the textbox, i.e. Child control [0].
The function CreateChildControls creates a textbox, just as it did before, and a button with the
label Add is also added.

The event object Click in the button class is associated with the EventHandler delegate, which
represents the function named add1. The function add1 is executed when the button is clicked.

In this function, we merely add 1 to the property aa and then trigger off the Change event. This
in turn, calls the function abc, since it is associated with the OnChange property in the aspx
file. The program is not aware of this association, because these linkages are given in the aspx
file.

The function abc requires two parameters, namely, a sender and an EventArgs data type. The
sender in this case is the program itself. Hence, the sender and the EventArgs are empty. The
statement aa++ increments the value by 1, and the Write function finally displays this value.
Note that aa has been incremented twice overall.

Thus, it is evident that code can be called in a dll, as well as, in the aspx file. This occurs with
each having no knowledge about the other's existence.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{
if ( hi.aa < 0)
hi.aa=0;
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" Ond="abc" runat=server/>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace nnn
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (23 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

public class zzz: Control, INamingContainer


{
public event EventHandler d;
public int aa
{
get
{
return Int32.Parse(((TextBox)Controls[0]).Text);
}
set
{
((TextBox)Controls[0]).Text = value.ToString();
}
}
protected void ddd()
{
d(this,EventArgs.Empty);
}
protected override void CreateChildControls()
{
TextBox b = new TextBox();
b.Text = "0";
b.TextChanged += new EventHandler(ccc);
Controls.Add(b);
Button a = new Button();
a.Text = "Add";
a.Click += new EventHandler(add1);
Controls.Add(a);
Button s = new Button();
s.Text = "Minus";
s.Click += new EventHandler(sub1);
Controls.Add(s);
}
void ccc(Object sender, EventArgs e)
{
ddd();
}
void add1(Object sender, EventArgs e)
{
aa++;
ddd();
}
void sub1(Object sender, EventArgs e)
{
aa--;
ddd();
}
}
}

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (24 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

In the aspx file, we have now named the property as Ond, instead of OnChange, and it is
assigned to the function abc. This function simply checks whether the property aa holds a
negative number or not. If it does, then aa is set to zero. So, no matter how many times we click
on the button labeled Minus, the textbox value will remain frozen at the value of 0.

The name of the event type has been changed from Change to 'd'. Hence, the name of the
property has also been changed from OnChange to Ond. The textbox has an event called
TextChanged, that calls the function ccc whenever the contents of the textbox are changed. We
have also added an extra button labeled as Minus, which shall call the function sub1.

The three event handler functions finally call the function ddd. We also add or subtract the
property aa by 1. Thus, whenever we click on the button, the function ddd finally gets called.
Here, we carry out a single task i.e. call the event d(). This will result in a call to the event
function, which is associated with the event d or Ond, in the aspx file. Thus, we can call the
property by any name we want, provided, there is an event of the same name. But, we should
not start the name of the aspx tag with the word 'On'.

We have encapsulated all the event handling code in the function ddd, even though it is a single
function call. This is done to enable us to add a large amount of code associated with the
events, in future. The textbox event handling function is not required. It comes into picture only
when the user enters -100, directly into the textbox. Since a change occurs on doing so, the
function abc gets called, which reverts the value back to zero.

State Management
a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c" %>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{
hi.FSize++;
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" FSize=1 runat=server/>
<br>
<asp:button Text="click" OnClick="abc" runat=server/>
</form>
</body>
</html>

b.cs
using System;
using System.Web;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (25 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

using System.Web.UI;
namespace nnn
{
public class zzz: Control
{
public int FSize
{
get
{
return (int) ViewState["FSize"];
}
set
{
ViewState["FSize"] = value;
}
}
protected override void Render(HtmlTextWriter o)
{
o.Write("<font size=" + FSize + ">" + "Vijay Mukhi"+ "</font>");
}
}
}

Output

Vijay Mukhi

Vijay Mukhi

View Source
<html>
<body>
<form name="ctrl2" method="POST" action="a.aspx" id="ctrl2">
<input type="hidden" name="__VIEWSTATE"
value="YTB6LTIwMTg1MDIyMjVfYTB6X2h6NXoyeF9hMHpfaHo1ejF4X2Ew
emh6RlNpXHplXzV6NXh4X194eF94eF94X194e447caf7" />
<font size=5>Vijay Mukhi</font>
<br>
<input type="submit" name="ctrl6" value="click" />
</form>
</body>
</html>

The control zzz displays the text 'Vijay Mukhi'. It has a property called Fsize that controls the
size of the font that is displayed. A button labeled 'click' is displayed, which calls the function
abc, whenever it is clicked. The function abc increments the property Fsiz,e by one. The final

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (26 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

effect that is perceived is an increase in the font size of the text 'Vijay Mukhi' displayed on the
screen.

The Web Server keeps a record of our actions, because the code of the function resides on the
server and not on the client. If you open a new browser window, you will observe that the two
Fsize properties are maintained independent of each other. This concept is similar to the one we
learnt earlier, when we were dealing with the shopping cart.
The protocol used while transferring the files is called HTTP or the Hyper Text Transfer Protocol.
This protocol is stateless, implying that, it does not maintain the history of the interactions
between the client and the server. Each interaction is an independent action, with no
information being stored about the earlier proceedings. Since the protocol does not maintain
any history, the web server is provided with the facility for storing state information.

In the file b.cs, there is a user control with the property Fsize and the overridden Render
function. This function calls the Write function, which simply outputs 'Vijay Mukhi' after
substituting the font size with the property value obtained from Fsize.

Normally, in a property, we store the value that is contained in the hidden parameter called
value in a variable. But, in this case, we have used a different syntax, i.e. State["FSize"] =
value;. This indicates that State is an indexer in the Control class, which is passed a property
called FSize as a string parameter. It is now the Web Server's responsibility to store this value
for every instance of the browser. To retrieve the value, the same indexer called State, is used
with the property of FSize.

The View-Source menuoption reveals a hidden field called __VIEWSTATE that has a different
value for each new copy of the browser. As this field is of type hidden, it does not get displayed
on the screen. However, its value is sent across to the web server. The web server stores the
value of the property Fsize, for every copy of the browser. Thus, if there are 100 connections
that are active, there will be 100 copies of Fsize, each storing different numbers in a double
dimensional array. This is how the information about the state is maintained between a server
and a browser, with the server doing all the grunt work.

The indexer called State is of type System.Web.UI.StateBag, which is a data structure similar to
a hash table. This structure stores values and gives each of them a number or a hash value.
The hash value is used to access these values in a quick and efficient manner. Thus, data in
the State indexer is stored as 'FSize=10', or better still, in the form of name-value pairs. The
value of Fsize is not sent over. Instead, a unique number representing the browser server
connection is sent. The HTML file created at the server, fills up the FSize property using this
hash value.

However, the use of Indexers, such as State, entail a performance overhead. Hence, they should
be used with care, or else, the performance is bound to suffer.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs e)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (27 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

hi.aa++;
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="hi" runat=server/>
<br>
<asp:button text="Vijay" OnClick="abc" runat=server/>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz: Control, IPostBackDataHandler
{
int bb = 0;
String p1;
public int aa
{
get
{
return bb;
}
set
{
bb = value;
}
}
public bool LoadPostData(String p, NameValueCollection v)
{
p1 = p;
bb = Int32.Parse(v[UniqueID]);
return false;
}
public void RaisePostDataChangedEvent ()
{
}
protected override void Render(HtmlTextWriter o)
{
o.Write("<input name=" + UniqueID + " type=text value=" + aa + ">");
o.Write("<br>" + p1);
}
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (28 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

We first add the option /R:System.dll to the compiler command and run it as follows:

>csc /target:library /out:c.dll b.cs /r:System.Web.dll /r:System.dll

Output

In the aspx file, we see a textbox containing the value of 0 and a button labeled 'Vijay'. When we
click on the button, the value increases by 1. We also see the word 'hi' displayed between the
textbox and the button. Have we not performed something similar earlier?
We certainly have, but this time, the control code is very different.

The control zzz is now derived from an interface called IPostBackDataHandler, that has two
functions named LoadPostData and RaisePostDataChangedEvent. Since it is the interface that
we are deriving from, we have to include the code for these functions in our class.

Zzz also contains a property called aa that uses an int variable named bb, to store the value. In
this program, the State indexer is avoided completely. Instead, every time the data is
transferred to the server, or whenever we send the data on a round trip, the function
LoadPostData gets called. It has two parameters:

• a string p stating the id of the contro, i.e 'hi'


• a NameValueCollection object v, which is an indexer that is used to access the property
values.

Thus, the variable p1 in this function will contain the word 'hi'. UniqueId is a reserved word. It
is the name given to the control, which has an id of 'hi'. A variable named 'bb' is used to hold
values for the property. It will now contain this new value returned by the indexer. This is how
the stateful values of the properties are maintained.

Since the value of false is returned, the next function named RaisePostDataChangedEvent does
not get called. Hence, there is no code present in it. If a value of true is returned, it conveys a
message to the system that we want to raise a changed notification. This is known as
implementing post back data.

By deriving from the above interface, we are informing ASP+ about our participation in post
back data handling.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c" %>
<html>
<body>
<form method="POST" action="a.aspx" runat=server>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (29 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

<ttt:zzz id="hi" runat=server/>


</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
using System.Web.UI.WebControls;
namespace nnn
{
public class zzz : Control, IPostBackDataHandler, IPostBackEventHandler
{
int bb = 0;
public int aa
{
get
{
return bb;
}
set
{
bb = value;
}
}
public bool LoadPostData(String p, NameValueCollection v)
{
bb = Int32.Parse(v[this.UniqueID]);
return false;
}
public void RaisePostDataChangedEvent()
{
}
public void RaisePostBackEvent (String e)
{
if (e == "Add")
{
aa++;
}
else
{
aa--;
}
}

protected override void Render(HtmlTextWriter o)


{
o.Write("<input name=" + UniqueID + " type=text value=" + aa + ">");
o.Write("<input type=button value=Add OnClick=\"jscript:"+ Page.GetPostBackEventReference(this,

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (30 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

"Add")+ "\">");
o.Write("<input type=button value=Subtract OnClick=\"jscript:"+ Page.GetPostBackEventReference
(this, "Subtract")+ "\">");
}
}
}

View Source

<html>
<body>
<form name="ctrl0" method="POST" action="a.aspx" id="ctrl0">
<input type="hidden" name="__VIEWSTATE" value="dDwtMTIyNDI1MzU1Njs7Pg==" />

<input name=hi type=text value=2><input type=button value=Add OnClick="jscript:__doPostBack


('hi','Add')"><input type=button value=Subtract OnClick="jscript:__doPostBack('hi','Subtract')">

<input type="hidden" name="__EVENTTARGET" value="" />


<input type="hidden" name="__EVENTARGUMENT" value="" />
<script language="javascript">
<!--
function __doPostBack(eventTarget, eventArgument) {
var theform = document.ctrl0;
theform.__EVENTTARGET.value = eventTarget;
theform.__EVENTARGUMENT.value = eventArgument;
theform.submit();
}
// -->
</script>
</form>
</body>
</html>

Output

We have a very simple aspx file which only displays a user control named ttt:zzz. In the control
code, we are deriving from two interfaces this time, as against one, which was derived from, in
the previous program. The new interface called IPostBackEventHandler has only one function
named RaisePostBackEvent that enables a control to take charge of an event fired by the
control, in the aspx file.

The property aa and the post back data handling code remain the same.

Each time we click on the buttons, the code in the control gets called. The function
RaisePostBackEvent is called with a parameter, which signifies the value of the control. If we
click on the button labeled Add, the string parameter 'e' stores Add. As a result, the property aa
is increased by 1. The Subtract button does the opposite, i.e. it decreases the value by 1.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (31 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Earlier, on an event, code was called in the aspx file. However in this case, code is called in our
control.

In the Render function, we have created a textbox followed by two buttons. Each of these
buttons has a label and an attribute called OnClick, which is initialized to a JavaScript function
named GetPostBackEventReference. This function accepts two parameters, namely, this and
some text viz. Add or Subtract. The text that is supplied as a parameter to this function, is
further passed on as a parameter to the function RaisePostBackEvent.

You will not see any code for the Javascript function in our control. Since it is prefaced with
Page, the code is generated in the HTML file created by the server.

The Render function in turn creates the Javascript function called __doPostBack in our HTML
file. (You could verify it through View-Source). Further, the function name given to the OnClick
property in the Render method, is changed.

Thus, each time we click on the button, the function __doPostBack is called with two
parameters. The first parameter is 'hi', while the second parameter is the string assigned in the
Render function. This function initializes the hidden form variables with the values passed as
parameters. And then, it calls the submit function, thereby, transferring parameters out of the
HTML file to the web server.

To summarise, in order to capture post back events, such as, form submits from a client, the
interface called IPostBackEventHandler is implemented. Each time an event occurs on the
client, the RaisePostBackEvent method in the control, is called. Also, the ASP+ system
generates the client side Javascript, which incorporates customized event handling, such that,
any HTML element can initiate post back.

Attributes
Try out the following C# program to understand, what attributes are all about.

z.cs
class zzz
{
public static void Main()
{
yyy y = new yyy();
}
}
[vijay("hi")]
public class yyy
{
public yyy()
{
System.Console.WriteLine("yyy const");
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (32 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

public class vijay : System.Attribute


{
public vijay(string s)
{
System.Console.WriteLine("vijay const " + s);
}
}

Output
yyy const

An attribute is a class derived from System.Attribute. It can be assigned any name that we like.
Hence, we chose the name 'vijay'. The parameters passed to the attribute 'vijay' are simply
passed on to the constructor.

We could discuss a large number of concepts regarding attributes. Instead, we will make a
simple statement here, and that is "C# likes attributes and it has a large number of attributes".

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" Assembly="c" %>
<script runat=server language=c#>
void Page_Load()
{ DataBind();
}
</script>
<html>
<body>
<form method="POST" runat="server">
<ttt:zzz aa="Hello World!" runat=server/>
<br>
<ttt:zzz aa="Hello World!" runat=server>
<m>
<u> <%# Container.aa %><br> </u>
</m>
</ttt:zzz>
</form>
</body>
</html>

b.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class yyy: Control, INamingContainer
{ private String msg = null;
public yyy(String g) {
msg = g;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (33 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

public String aa {
get {
return msg;
}
set {
msg = value;
}
}
}
[ParseChildren(true)]
public class zzz : Control, INamingContainer
{
ITemplate mm = null;
String s = null;
public String aa
{
get {
return s;
}
set {
s = value;
}
}
[TemplateContainer(typeof(yyy))]
public ITemplate m
{
get {
return mm;
}
set {
mm = value;
}
}
public override void DataBind()
{
EnsureChildControls();
base.DataBind();
}
protected override void CreateChildControls()
{
if (m != null) {
Controls.Clear();
yyy i = new yyy(aa);
m.InstantiateIn(i);
Controls.Add(i);
}
else {
Controls.Add(new LiteralControl(aa));
}
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (34 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Output
Hello World!
Hello World!

Templates in controls help in customizing the display of the output, as per our liking. First, we
display our user control without a template. The control has a property named aa, whose value
'Hello World' is displayed by the control. Then, we use the same syntax, but add the tags with
the template name i.e. <m> and </m>, to customize this display. The template is given the
name 'm', thereby, indicating that we can have many more templates in the file. In this tag, we
use the html tags as they are, at the same time, place C# code, but within the <%# symbol.

A container is an object available in ASP.Net that enables access to the properties of a control.
Thus, Container.aa will result in display of the text "Hello World". As the code is placed within
the HTML underline tag u, the property value is displayed as underlined.

In the file b.cs, zzz has a property named aa. The variable 's' stores the current value of this
property. It also contains an instance variable mm of type ITemplate.

The template 'm' in the a.aspx file, is translated into a property 'm' of type ITemplate. The mm
object stores the value of this property. Notice that an attribute Template has been added to
this property.

An attribute is placed within square brackets[]. Thus, Template is an attribute that accepts one
parameter, which is the name of the class that the code resides in. The attribute too is stored in
the dll as part of the metadata.

Thus, to create a template, we simply need a property of type ITemplate along with the
Template attribute.

In the function CreateChildControls, the control is checked for the existence of a template. If
the property 'm' is null, no template is created in the control. However, if it is not null, a
template is created. In situations where templates are not implemented, a Literal Control is
added. It contains the value of property aa as its text. But, for a control containing a template,
the InstatiateIn function is called with a variable i. i is an object that looks like yyy. No further
coding is required to handle templates. The user is provided with utmost flexibility, so that he
can accomplish what he desires, in this regard.

Templates separate the user or presentation logic from the control or business logic. Therefore,
each user can decide on how properties of the control are to be laid out.

Control Parsing
a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c" %>
<html>
<body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (35 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

<form method="POST" runat=server>


<ttt:zzz aa="2" runat=server>
<ttt:yyy m="a1" runat=server/>
<ttt:yyy m="a2" runat=server/>
<ttt:yyy m="a3" runat=server/>
<ttt:yyy m="a4" runat=server/>
</ttt:zzz>
</form>
</body>
</html>

b1.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class yyy: Control
{
String mm;
public String m
{
get
{
return mm;
}
set
{
mm = value;
}
}
}
}

b.cs
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
namespace nnn {
public class zzz: Control
{
ArrayList i = new ArrayList();
int bb=0;
public int aa
{
get
{
return bb;
}
set

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (36 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

{
bb = value;
}
}
protected override void AddParsedSubObject(Object obj)
{
if (obj is yyy)
{
i.Add(obj);
}
}
protected override void Render(HtmlTextWriter o)
{
if (aa < i.Count)
{
o.Write( ((yyy) i[aa]).m);
}
}
}
}

>csc /target:library /out:c.dll b.cs b1.cs /r:system.web.dll /r:system.dll

Output
a3

We have a total of three files. In the apsx file, there are two user controls. Both the controls are
derived from Control and placed in two different files, but they are finally compiled into one dll.
The first control called zzz is in the file b.cs. It contains one property called aa. The second user
control called yyy has a property called m, and is situated in the file b1.cs. We have
incorporated many instances of the second user control yyy, within the first user control. Since
the property aa has a value of 2, the output is a3, which is the value contained in the property
'm' of the third instance of the user control. A point to be noted here is that the numbering for
controls too start from 0.

Now, let us move on to the internals.


The class yyy has one property called 'm', that stores the string in the variable 'mm'. Further,
no Render method is present. The class yyy represents the most basic and simplest control.

All the action takes place in the file b.cs. The control zzz diverts from the customary manner in
which ASP.NET parses the controls. It calls code within itself to execute customized parsing.

The instance 'i' of ArrayList is created to store multiple values. It has a function called Add, that
simply keeps track of each value. It also has an indexer to retrieve these values. There is
nothing to write home about the property aa.

Every time ASP.Net comes across a user control, it calls the function AddParsedSubObject from
the class Control. This function is given a parameter that represents the control to be added.

An important point to be noted is that, "All classes in the .Net world are derived from Object".

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (37 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

Here, we check the run time data type of the parameter obj. If it is of type yyy, it is added to the
ArrayList, using its Add function.

If we do not override the function AddParsedSubObject, the default behavior of this function
will get added to every control, thereby, making it a child control. We want to prevent this from
happening, since we are interested in adding a control of class yyy, only to the ArrayList. We
are now in a position to decide as to what should ensue for each control.

Finally, the Render function gets called. Here, we simply use the value of the property aa to
index into the ArrayList object i. Then, using the cast of yyy, we retrieve the value stored in the
property m of the selected yyy object. Since array handling is done internally, an ArrayList
makes it easier for us to handle multiple values.

If we have a control within a control, the page parser will add the inner control to the outer
Controls Collection property. This is accomplished by calling the function AddParsedSubObject,
which inserts the child control into the control hierarchy tree. We can override this behavior
with whatever we feel is right.

a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c"%>
<html>
<body>
<form method="POST" runat=server>
<ttt:zzz Si="3" runat=server>
<ct m="a1"/>
<ct m="a2"/>
<ct m="a3"/>
<ct m="a4"/>
</ttt:zzz>
</form>
</body>
</html>

b1.cs
using System;
using System.Web;
using System.Web.UI;
namespace nnn {
public class yyy : Control
{
String mm;
public String m
{
get
{
return mm;
}
set
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (38 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

mm = value;
}
}
}
}
b.cs
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class ccc: ControlBuilder
{
public override Type GetChildControlType(String t, IDictionary a)
{
if (String.Compare(t, "ct", true) == 0)
{
return typeof(nnn.yyy);
}
return null;
}
}
[ControlBuilderAttribute(typeof(ccc))]
public class zzz: Control
{
ArrayList i = new ArrayList();
int s = 0;
public int si
{
get
{
return s;
}
set
{
s = value;
}
}
protected override void AddParsedSubObject (Object obj)
{
if (obj is yyy)
{
i.Add(obj);
}
}
protected override void Render(HtmlTextWriter o)
{
if (si < i.Count)
{
o.Write( ((yyy) i[si]).m );

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (39 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
}
}
}

Output
a4

The aspx file, prima facie appears to be identical to the earlier one. It has a tag zzz, which
contains four instances of another tag called 'ct' nested within it. As the property Si has a value
of 3, a4 is displayed.

The file b1.cs remains the same as before.

In the class zzz, we also have a property named 'si', in conjunction with an ArrayList object 'i'.
Only the name and the datatype of the property have been changed, whereas, the code remains
the same.

The function AddParsedSubObject also remains the same. The Render function has an
additional error check, which is to ensure that the value of the property 'si' does not exceed the
number of items in the ArrayList object. This value is stored in a property called Count.

The most important change brought about in the Control class zzz is, the introduction of an
attribute called ControlBuilderAttribute, to which one parameter is passed. This parameter is
the return value of typeof, on an instance of the class ccc. The class ccc is derived from the
class ControlBuilder. As the attribute is set on our control class, functions from this class will
be called, to decide as to how a control is to be added to the list of controls.

There is a default implementation of the Control Builder called GetChildControlType. It returns


either the type of control or a null, depending upon whether the control is to be added or not,
respectively. As we have overridden this function, the logic incorporated by us in this function,
decides the controls that are deemed necessary to be added.

The first string parameter passed to GetChildControlType, is the name of the control type. The
'if' statement, compares this string variable with ct. If it results in true, the typeof class yyy is
returned. Otherwise, null is returned.

Databound Templated Controls


a.aspx
<%@ Register TagPrefix="ttt" Namespace="nnn" assembly="c" %>
<html>
<script language="C#" runat=server>
public void Page_Load(Object sender, EventArgs e1)
{
if (!IsPostBack)
{
ArrayList v = new ArrayList();
v.Add("10");

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (40 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

v.Add("200");
v.Add("31");
v.Add("423");
l.DataSource = v;
l.DataBind();
IEnumerator e = l.DataSource.GetEnumerator();
while(e.MoveNext())
{
Response.Write(e.Current.ToString());
}
}
}
void abc(Object sender, EventArgs e)
{
}
</script>
<body>
<form method="POST" action="a.aspx" runat=server>
<ttt:zzz id="l" runat=server>
<m>
<asp:textbox id="hi" Text="<%# Container.DataItem %>" runat=server/>
<br>
</m>
</ttt:zzz>
<asp:button Text="nothing" OnClick="abc" runat=server/>
</form>
</body>
</html>

b1.cs
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
namespace nnn
{
public class yyy: Control, INamingContainer
{
int i;
object d;
public yyy(int it, object da)
{
i = it;
d = da;
}
public object DataItem
{
get
{
return d;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (41 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

}
public int ItemIndex
{
get
{
return i;
}
}
}
}

b.cs
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
namespace nnn
{
[ParseChildren(true)]
public class zzz : Control, INamingContainer
{
private ITemplate mm = null;
private ICollection d = null;
public ICollection DataSource
{
get
{
return d;
}
set
{
d = value;
}
}
[TemplateContainer(typeof(yyy))]
public ITemplate m
{
get
{
return mm;
}
set
{
mm = value;
}
}
protected override void AddParsedSubObject(object o)
{
}
protected override void OnDataBinding(EventArgs e1)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (42 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

if (DataSource != null)
{
Controls.Clear();
ClearChildViewState();
IEnumerator e = DataSource.GetEnumerator();
int i = 0;
while(e.MoveNext())
{
yyy i1 = new yyy(i, e.Current);
m.InstantiateIn(i1);
Controls.Add(i1);
i++;
}
ChildControlsCreated = true;
ViewState["ggg"] = i;
}
}
protected override void CreateChildControls ()
{
object o = ViewState["ggg"];
if (o != null)
{
Controls.Clear();
int numItems = (int)o;
for (int i=0; i < numItems; i++)
{
yyy i1 = new yyy(i, null);
m.InstantiateIn(i1);
Controls.Add(i1);
}
}
}}}

Output
1020031423

Although, the above program is considerable in size, it has no worthwhile achievement to offer.
Let us start with the aspx program, like we always do. There is a user control named zzz, which
has an id of l, since we want to replicate a DataList or DataGrid type of user control. We want
you to go through the experience of writing such controls.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (43 of 44)2/13/2007 4:54:29 PM


User Controls - ASP.NET - Beta2

We also have a template called 'm' inside our control, that encompasses a textbox with the id
'hi'. The most important point here is that the text property is equated to the DataItem property
of the control. This DataItem property belongs to the class yyy and not to the class zzz. We also
have a button named nothing. This button calls a function named abc. This function sends the
page back to the server.

In the Page_Load function, an ArrayList object named 'v' is created and initialized to 4 arbitrary
numbers. The next line has l.DataSource, which implies that we are referring to a property
called DataSource, that exists in the class zzz. We consciously named it as DataSource,
because the DataList Control refers to it by the same name. Then, we bind our user control by
calling the DataBind function. This calls the OnDataBinding function in the class zzz.

The DataSource property is of type ICollection that iterates through any collection or list. The
ICollection interface has a member function called GetEnumerator that returns an
IEnumerator, which is stored in the object 'e'. This object 'e' in turn, calls a function MoveNext.
The function MoveNext either returns true, (if there are any more items in the collection), or
returns false, (if there are no more items in the collection). This active item is stored in a
member called Current. It removes all the previous members. Thus, the loop iterates 4 times
because we have 4 members in the list.

In the file b1.cs, we are once again deriving class yyy from Control. We have two properties:

• DataItem, which is an object that gives it the flexibility to store anything.


• ItemIndex, which is an int.

There are no further complications.


The main source code resides in the class zzz. Note that the class has an attribute
[ParseChildren(true)]. The attribute ensures the availability of code in other classes, hence no
error is reported

The class has a property called DataSource, which is of type ICollection. It simply assigns the
value contained in 'value' to the object 'd'. Since we are using templates, the template value is
stored in mm, which is an instance of ITemplate. The yyy class is passed as a parameter, to the
template attribute.

The function AddParsedSubObject is added to override the default, i.e., to avoid the default
implementation from adding the control. Our function does not contain any code.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap6.htm (44 of 44)2/13/2007 4:54:29 PM


CGI Programming - ASP.NET - Beta2

-7-

CGI Programming
This chapter concentrates on the basics of the Internet. By the time you reach the end of this
chapter, you will be comprehensibly conversant with the role of a web server, a web browser
and ASP.Net. You will also be in a position to appreciate the indispensability of ASP.Net, in
writing powerful business applications.

Understanding the samples provided by Microsoft, is akin to viewing ASP from a height of
10000 miles.

At the outset, you are required to create a file called a.cs in the sub-directory c:\inetpub
\scripts. We will explain the relevance of this subdirectory in due course of time.

a.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("<b>hi");
}
}

The above is a short and sweet C# program! Now, compile this program using the csc
command, as in ‘csc a.cs’.
Then, run the executable and your dos screen will simply display 'hi' with the bold tag in front
of it.

To run this exe file from our browser, we key in the following URL in the browser.

http://localhost/scripts/a.exe

This URL seems logical, since we have placed the file a.exe in the scripts sub-directory. But, we
do not seem to get anything right the first time. This is evident from the following errors that
have been generated:

Output
CGI Error
The specified CGI application misbehaved by not returning a complete set of HTTP headers. The
headers it did return are:
hi

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (1 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

The first line indicates that we have written a CGI application. CGI stands for Common Gateway
Interface. And we have not adhered to the rules pertaining to a CGI application. The web
browser expects a complete set of headers, which we have not provided. Subsequently, we see
'hi' displayed in bold.

Before moving into the details about the rules, headers etc. of CGI programming, we shall send
a header across.

a.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/html");
System.Console.WriteLine("<b>hi");
}
}

We compiled the above program as before and provided the same URL in the browser. It is
preferable to load the browser again and provide the URL. You could even click on the refresh
icon instead. Whichever method you follow, the same error is generated again.

In future, we will not repeat these steps, but we do expect you to follow them, so that your
output matches with ours. Writing one more WriteLine function makes no difference at all.

a.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/html\n");
System.Console.WriteLine("<b>hi");
}
}

Output
hi

The mere inclusion of an 'enter', represented by '\n', results in elimination of all the errors. We
now see the word 'hi' displayed in bold in our window. Before we explain as to why everything
suddenly starts working fine, let us make a small modification in the above program.

a.cs
public class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/plain\n");
System.Console.WriteLine("<b>hi");
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (2 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Output
<b>hi

Now, it is time for us to demystify this mystery.

The web or the HTTP protocol is very simple to understand if you follow certain rules. When the
browser requests for a file from the web server, depending upon the extension given to the file,
the Web Server does one of the following:

• It picks the file up from its local hard disk and sends it across
OR
• It executes the executable file which has been requested for, from the disk which
generates this file and sends it over.

In the case of a file with a .exe extension, the server executes the file or program on its
machine. This program is not restricted to producing an HTML file only. It can create a file of
any type. If it were restricted to generating only HTML files, it would have made the web very
restrictive.

The contents of every file vary depending on the file type. For example, an HTML file will contain
tags; a .jpg file will contain images, and so on. The browser must display the files in the right
format, on receiving them.

To inform the browser about the file coming across, the exe file or program creates a header
that signifies the file type or the content type. A header is nothing but a word that is given some
value and which ends with a colon. Thus, the phrase 'Content-Type' is a header since it ends in
a colon, and the value assigned to it is 'text/plain'.

The rules of CGI state that all headers must end with an Enter or '\n' symbol. This is so
because a file can have multiple headers. An 'enter' symbol, when placed by itself on a line,
signifies the end of all the headers. It also marks the start of the content. The Web server is free
to add its own headers to the list of headers generated by the program. This composite data is
then transferred to the browser.

Since the headers were not specified in the first program, an error was generated. The presence
of a Content-Type header in a sense is mandatory for any file that has to be transferred from
the server to the browser.
The second error was reported because we had omitted the 'enter' symbol all by itself, on a
separate line, to mark the end of all headers. Thus, more headers were expected from the
server. When this did not happen, the browser generated an error. The WriteLine function adds
an 'enter' symbol by default, but an additional \n is required all by itself, to indicate an end to
the Header values.

The browser uses the header named Content-Type, to determine the type of data sent by the
web server. Accordingly, it displays the file in the right format.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (3 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

The type text/html refers to a text file containing html tags. Thus, 'hi' was displayed in bold.
However, the header value of text/plain informs the browser that plain text content is being
sent over, and hence, the tags are not parsed.

a.cs
class zzz
{
public static void Main()
{
string s;
System.Console.WriteLine("Content-Type:text/html\n");
s=System.Environment.GetEnvironmentVariable("PATH");
System.Console.WriteLine(s);
}
}

Output
C:\Program Files\Microsoft.Net\FrameworkSDK\Bin\;C:\WINNT\Microsoft.NET\Framewor
k\v1.0.2204\;C:\WINNT\system32;C:\WINNT;C:\WINNT\System32\Wbem;C:\Program Files\Microsoft SQL Server\80\Tools
\BINN

An environmental variable is a word stored by the operating system. In the world of Windows
2000, if we give the command >set in the dos box, a list containing a number of words with
their corresponding values is displayed.

At the command prompt, if we give the command >set aa=hi, it creates an environmental
variable named 'aa' and assigns it a value of 'hi' for the current dos session. On issuing the
same set command again, this recently created variable and its value, get displayed along with
the other environmental values.

The namespace System.Environment has a static function called GetEnvironmentVariable. This


function accepts an environmental variable name and returns its value. In our program, we ask
the function to display the value of the environmental variable named PATH.

These variables are created and maintained by the operating system. The web server too can
ask the operating system to create some variables, before it executes a program.

a.cs
class zzz {
public static void Main()
{
System.Collections.IDictionary i;
i=System.Environment.GetEnvironmentVariables();
System.Collections.IDictionaryEnumerator d;
d=i.GetEnumerator ();
System.Console.WriteLine("Content-Type:text/html\n");
System.Console.WriteLine(i.Count + "<br>");
while (d.MoveNext())
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (4 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

System.Console.WriteLine("{0}={1}<br>",d.Key,d.Value);
}
}
}

The above program shows 46 environmental variables in the browser. An object named i of
datatype IDictionary is defined. It is initialized to the return value of the static function called
GetEnvironmentVariables.

This function returns an object that contains all the environmental variables. We need a
constant way of retrieving data that is similar, but which has multiple occurrences. To do so,
the designers of the C# programming language have given us an enumeration object which
enables us to list the multiples values.
We use the GetEnumerator function from the object 'i', and store its return value in the
enumeration object named 'd'. The object named MoveNext iterates through the list of values.
The object contains two members called Key and Value. Basically, the format is Key=Value.
Thus, Key stands for the variable name and Value is the value contained in the Key.

In the WriteLine function, {0} displays the first parameter, {1} displays the second variable, and
so on. The Count member of IDictonary returns the count of the environmental variables.

Some of the variables are created by the Operating System while it starts execution. The others
are created by the IIS WebServer. We searched the world over, but could not find a variable
named Query_String.

This program will be used in the future. So we want you to make a copy of it and name it as b.
exe: >copy a.exe b.exe

a.html
<html>
<body>
<form action=http://localhost/scripts/a.exe>
<input type = text name = aa>
<input type = text name = bb>
<input type = submit value = click>
</form>
</body>
</html>

The above HTML file is placed in the wwwroot sub-directory and loaded as http://localhost/a.
html. This file shows two textboxes and a button labeled 'Click'. After entering the words 'hi'
and 'bye' in these textboxes, click on the button. You will be surprised to see the browser
displaying the same output as shown in the earlier program. But observe that the count now
displays the number 48, and the address bar now contains the new URL http://localhost/
scripts/a.exe?aa=hi&bb=bye. One of the newly added name-value pair is :

QUERY_STRING=aa=hi&bb=bye

On receiving the new URL from the web browser, the server simply creates an environmental

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (5 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

variable called QUERY_STRING and initializes it with the values that are contained in the URL
after the ? symbol. Thereafter, it calls the program named a.exe given in the URL, from the
relevant directory.

The program on the server can easily identify as to what the user has entered in the textboxes.
It simply has to use the Request class or parse the QUERY_STRING variable.

Cookies
Before taking a leap into this section, we would like you to set a few options in your browser.
First, go to menu option 'Tools' and select the last option named 'Internet Options'. Select the
Security tab. Ensure that you have selected the ‘Local Intranet’ option and click on Custom
level. Scroll down the list box until you see the heading 'Cookies'. For both the sub options,
select the 'Prompt' radio button. The default is 'Enable'. Restart the browser after making the
changes. Now, run the program given below in your browser.

a.cs
class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/html\nSet-Cookie:aa=vijay\n");
System.Console.WriteLine("hi");
}
}

To our utter surprise, we see a dialog box titled 'Security Alert', asking us whether we would be
interested in saving a temporary file sent by the WebServer on our hard disk. This file is termed
as cookie.

Firstly, we click on the button labeled 'More Info'. This extends the dialog box to give us more
information about the cookie. Notice that the cookie is named as aa, and along with other
information, it reveals that the data in this cookie is vijay.
Click on 'yes' and you will see 'hi' in the browser. Subsequently, if you run b.exe in the browser,
it will display all our environmental variables as before. But now, an additional environmental
variable called HTTP_COOKIE is created with the value of aa=vijay.

Before we go further, let us first run the following ASP program in the browser using:

http://localhost/a.aspx?aa=hi&bb=bye

a.aspx
<html>
<%@ language="C#" %>
<body>
<%
Request.SaveAs("c:\\z.txt",true);
%>
</body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (6 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</html>

z.txt
GET /a.aspx?aa=hi&bb=bye HTTP/1.1
Connection: Keep-Alive
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint,
application/vnd.ms-excel, application/msword, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; COM+ 1.0.2204)

For the ones who came in late, whenever we click on a button of type submit, a new URL is
generated. The Web browser calls on the WebServer again, and sends it a packet of data.

To view the contents of this packet, the Request property is used. This property returns an
HttpRequest object. SaveAs is one of the functions in the object that takes two parameters:

• The filename in which it can save the request.


• A bool value of true or false. If the value is true, the header is also saved in the file.

Any packet sent by the browser has two parts to it. It starts with the word GET, followed by the
URL that is to be fetched. The name of the computer, localhost, is removed from the URL, as
the browser connects to it. Following it is the data, as entered in the browser window.

All this is part of the HTTP protocol. The protocol states that the URL is to be followed by the
http version number.

When the web server sends data to the browser, the packet starts with the headers, followed by
a blank line, and finally, followed by the rest of the HTML file. On the other hand, in the packet
sent from the browser, the URL is stated first, followed by the data and finally, there are the
headers. This is exactly the reverse of what happens in the case of the web server!

At first, we run the executable from the browser as http://localhost/scripts/a.exe and accept
the cookie. Thereafter, the file a.aspx is copied from c:\inetpub\wwwroot to c:\inetpub\scripts
and loaded as http://localhost/scripts/a.aspx. The file named z.txt, is shown below.

z.txt
GET /scripts/a.aspx HTTP/1.1
Connection: Keep-Alive
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint,
application/vnd.ms-excel, application/msword, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Cookie: aa=vijay
Host: localhost
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; COM+ 1.0.2204)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (7 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

A cookie has a header named Set-Cookie, which is sent by the server to the client. A point to be
noted here is that the server initiates a cookie, and not a client.

There is a program that runs on the server, which directs the server to send a cookie, which
has a specific name and value. When the client browser, which could be Netscape, IE or any
other browser, sees a header named Set-Cookie, it checks for the cookie-option values. If the
prompt is set on, the browser will display a message, thereby, requesting for permission to
accept or reject the cookie.

If the reply is 'yes', then whenever the client connects to the server, it will contain a header
named Cookie, which it will send to the server. Thus, we see the header Cookie: aa=vijay in the
file z.txt. The text 'Set-' is removed from the Header.

Thus, a cookie is basically a header-value that is sent by the server, and which is returned by
the browser.

These cookies remain in existence only until the browser is alive. If you close the current copy
of the browser and reload it again with the file a.aspx, the cookie header will not be seen.

System.Console.WriteLine("Content-Type:text/html\nSet-Cookie:aa=vijay; path=/aa\n");

A cookie header, along with the name-value, has a path that decides on the sub-directories that
the cookie can be sent to. On running a.exe from the scripts sub-directory, the path parameter
in the cookie dialog box shows the path as /scripts/.

Therefore, if you load a.aspx from the inetpub\wwwroot sub-directory, it will not show the
Cookie: header in the file z.txt. This is because the browser not only stores the domain name or
name of the computer, but also the URL or sub-directories that the cookie should be sent to. As
the path is /scripts, the browser will only send a Cookie: header to the URLs that access files in
the /scripts sub-directory.

Now, we shall see how our cookies can be made eternal, so that they never say die.

a.cs
class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/html\nSet-Cookie:aa=Vijay; expires=Tuesday, 03-04-
2002 12:12:23\n ");
System.Console.WriteLine("hi");
}
}

After leaving a space after the semicolon, we have simply added the word 'expires'. This is
initialized to a date in a certain format, followed by time in hours, minutes and seconds. The
cookie dialog box( that had earlier displayed the Expires as 'end of session), now displays a

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (8 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

specific date.

Upto this date, each time we connect to a certain path on the server called localhost, the
browser will send this cookie. The earlier cookies were termed as 'session cookies', since their
life span extended only till the end of the session. The cookies where 'expires' is mentioned, are
called 'non session cookies'. If we disable the cookies, the browser does not send the Cookie:
header to the server.

Let us now understand the Response and Request objects in ASP.Net, which are introduced
when they are derived from the Page class.

The Request Object


The property Request in the Page class, is of type HttpRequest, and it contains code that
handles the data sent by the browser.

This makes it easier for our aspx program to parse the output sent to us by the browser.

a.aspx
<html>
<%@ language="C#" %>
<body>
<%
String[] s = Request.AcceptTypes;
Response.Write(s.Length.ToString());
for (int i = 0; i < s.Length; i++)
{
Response.Write(s[i] + "<br>");
}
%>
</body>
</html>

Output
8image/gif
image/x-xbitmap
image/jpeg
image/pjpeg
application/vnd.ms-powerpoint
application/vnd.ms-excel
application/msword
*/*

The web server sends the header Content-Type to signify the type of content that is to follow.
The type given after Content-Type is also called the 'MIME type'. The client, i.e. the browser too
sends across the types it supports, by using a header called Accept.

This header is sent as follows:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (9 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint,


application/vnd.ms-excel, application/msword, */*

Thus, the MIME type starts with the name of a family, such as image, text, application etc. This
is followed by a slash /, after which we specify the different types within the family. The symbol
*/* indicates that the browser supports all MIME types.

The Request object has a property called AccessTypes, which returns an array of strings. We
simply display them using a 'for' loop. The Length property gives us the number of members
present in the array.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.ApplicationPath);
%>

Output
/

The property ApplicationPath displays the virtual path to the currently running server
application. Even if you copy the file in the scripts sub-directory and change the URL to http://
localhost/scripts/a.aspx, the result will still be a slash i.e. /.

a.aspx
<%@ language="C#" %>
<%
HttpBrowserCapabilities b = Request.Browser;
Response.Write("Type = " + b.Type + "<br>");
Response.Write("Name = " + b.Browser + "<br>");
Response.Write("Version = " + b.Version + "<br>");
Response.Write("Major Version = " + b.MajorVersion + "<br>");
Response.Write("Minor Version = " + b.MinorVersion + "<br>");
Response.Write("Platform = " + b.Platform + "<br>");
Response.Write("Is Beta = " + b.Beta + "<br>");
Response.Write("Is Crawler = " + b.Crawler + "<br>");
Response.Write("Is AOL = " + b.AOL + "<br>");
Response.Write("Is Win16 = " + b.Win16 + "<br>");
Response.Write("Is Win32 = " + b.Win32 + "<br>");
Response.Write("Supports Frames = " + b.Frames + "<br>");
Response.Write("Supports Tables = " + b.Tables + "<br>");
Response.Write("Supports Cookies = " + b.Cookies + "<br>");
Response.Write("Supports VB Script = " + b.VBScript + "<br>");
Response.Write("Supports Java Script = " + b.JavaScript + "<br>");
Response.Write("Supports Java Applets = " + b.JavaApplets + "<br>");
Response.Write("Supports ActiveX Controls = " + b.ActiveXControls + "<br>");
Response.Write("CDF = " + b.CDF + "<br>");
%>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (10 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Type = IE5
Name = IE
Version = 5.5
Major Version = 5
Minor Version = 0.5
Platform = WinNT
Is Beta = False
Is Crawler = False
Is AOL = False
Is Win16 = False
Is Win32 = True
Supports Frames = True
Supports Tables = True
Supports Cookies = True
Supports VB Script = True
Supports Java Script = True
Supports Java Applets = True
Supports ActiveX Controls = True
CDF = False

The Browser property in the Request Object returns an object of type HttpBrowserCapabilities.
Thus, an object b of this type is created and it stores the return value of this property. We then
display all the members of this class, which consist of the features of the browser that just
connected to the server.

Depending upon the values that are supported and returned by the browser, the aspx file can
be made generic, to enable it to handle the differences among browsers.

The type member returns the name of the browser along with its version number, whereas, the
Browser property returns only the name. The version number is displayed as 5.5. We can even
display the major and the minor version numbers separately. It is mandatory to have the
Version of the Explorer greater than 5.0, otherwise, the .Net framework does not reveal the right
values.
The property named 'Platform' informs us about the Operating System that the browser is
running on. If the browser is currently running on Windows 2000, the platform property still
displays the value as WinNT. Our version of IE is the final copy, and not the beta version,
hence, the value of the property named beta is shown as false.

Search engines crawl all over, looking for websites. Since ours is a simple browser, the property
named IsCrawler is shown as false. America Online is the largest on-line service in the world
and it has its own branded browser. Since we are using IE from Microsoft, the property named
AOL has a value of false.

Earlier, Microsoft had a 16 bit operating system called Windows 3.1. As we are presently
running their 32 bit Operating system, the property Win16 is false, while the property Win32 is
true. An HTML page is divided into smaller parts by frames. Today, all browsers support
frames. Thus, the Frames property has a value of true.

Earlier some browsers could not display tables. Thus, the tables property was introduced in the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (11 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

object. Today, all the browsers fully support tables. However, not every browser can run Java
applets within the browser. In our case, since IE can do so, the JavaApplets property is true.

All browsers support cookies, since it is a standard created by Netscape. We have two main
client side scripting languages, VBScript from Microsoft and Javascript from Netscape. Since
our browser supports both, their properties are true. And since ActiveX was invented by
Microsoft, this property also has a value of true.

Finally, if we want to webcast something, there is a new format called Channel Definition
Format or CDF, which has to be used. For some reason, IE does not support it.

a.aspx
<%@ language="C#" %>
<%
Encoding e = Request.ContentEncoding;
Response.Write(e.EncodingName); %>
Output
Unicode (UTF-8)

The Request.ContentEncoding property returns an Encoding object. This object also has a large
number of properties and methods. One of them is called EncodingName, which reveals the
Character Set that the browser uses to transfer data to and fro.

a.cs
class zzz
{
public static void Main()
{
System.Console.WriteLine("Content-Type:text/html");
System.Console.WriteLine("Set-Cookie:aa=vijay0; expires=Tuesday, 09-09-2001 12:12:23");
System.Console.WriteLine("Set-Cookie:a1=vijay1; expires=Tuesday, 09-09-2001 12:12:23");
System.Console.WriteLine("Set-Cookie:a2=vijay2; expires=Wednesday, 10-10-2001 12:12:23\n");
System.Console.WriteLine("hi");
}
}

We first loaded the following C# executable from the script sub-directory:

http://localhost/scripts/a.exe

This sets three cookies for the browser session, which is currently active.

Then, we ran the aspx program (as given below) from the scripts sub-directory, using:

http://localhost/scripts/a.aspx

a.aspx
<%@ language="C#" %>
<%
HttpCookieCollection cc;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (12 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

cc = Request.Cookies;
Response.Write(cc.Count.ToString() + "<br>");
for (int i = 0; i < cc.Count; i++)
{
HttpCookie c = cc[i];
Response.Write(c.Name + "=" + c.Value + "<br>");
}
%>

Output
4
aa=vijay0
a1=vijay1
a2=vijay2
ASP.NET_SessionId=wnyumy5544u3tj55tdrp0u45

Request.Cookies returns an HttpCookieCollection object that is stored in the object cc. This
object named cc has a member named count, which returns a count of the number of cookies
present in the collection. We have 4 cookies, and hence, the 'for' loop is repeated four times.

HttpCookieCollection has an indexer that allows access to the individual cookies. Thus, cc[0]
refers to the first HttpCookie object, and so on. The HttpCookie class in turn, has two important
members, i.e. Name and Value, which display the name of the cookie and its value, respectively.

a.aspx
<%@ language="C#" %>
<%
HttpCookieCollection cc;
cc = Request.Cookies;
HttpCookie c = cc["a1"];
Response.Write(c.Name + "=" + c.Value + "<br>");
%>

Output
a1=vijay1

The indexer in the HttpCookieCollection object can also accept a string, which is the name of
the cookie. It returns a cookie object that represents that cookie. The Value member will display
the value contained in the cookie. This will retrieve only a single cookie.

a.aspx
<%@ language="C#" %>
<%
HttpCookieCollection cc;
HttpCookie c;
cc = Request.Cookies;
String[] s = cc.AllKeys;
for (int i = 0; i < s.Length; i++)
{

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (13 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Response.Write(s[i] + "<br>");
}
for (int i = 0; i < s.Length; i++)
{
c = cc[s[i]];
Response.Write("Cookie: " + c.Name + " ");
Response.Write("Expires: " +c.Expires + " ");
Response.Write ("Secure:" + c.Secure + " ");
String[] s1 = c.Values.AllKeys;
for (int j = 0; j < s1.Length; j++)
{
Response.Write("Value" + j + ": " + s1[j] + "<br>");
}
}
%>

Output
aa
a1
a2
langpref
ASP.NET_SessionId
Cookie: aa Expires: 1/1/0001 12:00:00 AM Secure:False Value0:
Cookie: a1 Expires: 1/1/0001 12:00:00 AM Secure:False Value0:
Cookie: a2 Expires: 1/1/0001 12:00:00 AM Secure:False Value0:
Cookie: langpref Expires: 1/1/0001 12:00:00 AM Secure:False Value0:
Cookie: ASP.NET_SessionId Expires: 1/1/0001 12:00:00 AM Secure:False Value0:

Just as there are many ways to skin a cat, there are also numerous ways of displaying a cookie.
The HttpCookiecollection class has a member called AllKeys that returns an array of strings,
which represent the names of the cookies or its keys. Thus, in one stroke, we can figure out all
the names of the cookies.

After displaying the individual names of the Cookie in the 'for' loop, the same name is used in
the indexer, to access the individual cookie object. The 'expires' property inexplicably, does not
display the correct date and time. Further, the Values object must be used in place of the Value
property, because a cookie can have multiple values. Thus, c.Values.AllKeys returns an array of
strings. Since in the present case, every cookie has only a single value, the 'for' loop executes
only once.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.FilePath);
%>

Output
/a.aspx

The property named FilePath returns the virtual path of the request. The output reflected is /

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (14 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

aspx, because we are loading this file from the wwwroot sub-directory. If you run the file from
the scripts sub-directory, the output will display /scripts/a.aspx

a.aspx
<%@ language="C#" %>
<%
NameValueCollection c;
c=Request.Headers;
String[] s = c.AllKeys;
for (int i = 0; i < s.Length; i++)
{
Response.Write("Key: " + s[i] + " ");
String[] s1=c.GetValues(s[i]);
for (int j = 0; j<s1.Length; j++)
{
Response.Write("Value " + j + ": " + s1[j] + "<br>");
}
}
%>

Output
Key: Connection Value 0: Keep-Alive
Key: Accept Value 0: */*
Key: Accept-Encoding Value 0: gzip, deflate
Key: Accept-Language Value 0: en-us
Key: Cookie Value 0: langpref=C#; ASP.NET_SessionId=abksbkrxdgjmmj45hasiffzx
Key: Host Value 0: localhost
Key: User-Agent Value 0: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)

The Headers property returns a NameValueCollection object that represents all the headers.
The rules for handling headers are common for all headers. The rules are all in the form of
name=value. The object c has an AllKeys property, which returns a list of keys. As before, we
use a loop and call the function GetValues, which returns an array of strings when it is
supplied with a key value. Most of the time, we only have a single value. Hence, our array s1
has a length of one.

a.aspx
<%@ language="C#" %>
<%
NameValueCollection c;
c=Request.Headers;
String[] s = c.AllKeys;
for (int i = 0; i < s.Length; i++)
{
Response.Write("Key: " + c[i] + " ");
String s1=c.Get(s[i]);
String s2=c.Get(i);
Response.Write("Value " + s1 + " " + s2 + "<br>");
}
%>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (15 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Output
Key: Keep-Alive Value Keep-Alive Keep-Alive
Key: */* Value */* */*
Key: gzip, deflate Value gzip, deflate gzip, deflate
Key: en-us Value en-us en-us
Key: langpref=C#; ASP.NET_SessionId=abksbkrxdgjmmj45hasiffzx Value langpref=C#; ASP.
NET_SessionId=abksbkrxdgjmmj45hasiffzx langpref=C#; ASP.NET_SessionId=abksbkrxdgjmmj45hasiffzx
Key: localhost Value localhost localhost
Key: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914) Value Mozilla/4.0
(compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914) Mozilla/4.0 (compatible; MSIE 5.5;
Windows NT 5.0; .NET CLR 1.0.2914)

The output is the same as before, but it is easier to comprehend now, since a function called
Get is used, which returns a single string value. Every value is displayed twice, because we
have used both the forms of the Get function, i.e. passing it a string and then, passing it a
number. It is the browser that sends these headers. You can easily verify this by inspecting the
file z.txt, which has been created earlier.

Let us first create a simple aspx file that merely writes out the value of a property called
HttpMethod.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.HttpMethod);
%>

a.html
<html>
<body>
<form action=http://localhost/a.aspx METHOD=GET>
<input type = text name = aa>
<input type = text name = bb>
<input type = submit value = click>
</form>
</body>
</html>
In the above HTML file, we have added an attribute called 'METHOD=GET' to the form tag.
When we click on the 'click' button, browser screen loads on, with the address containing the
action value of http://localhost/a.aspx, followed by the ? symbol and the name value pairs. The
word GET is also displayed in the browser window.

Now, we make a small modification in the HTML file. We replace the words GET with POST.
When we load the file, everything remains the same. When we click on the button, the browser
now displays POST. Further, the URL contained in the address bar does not contain either the
question mark or the name-value pairs.

The difference between a GET and POST method is that, in a POST, the data is transmitted as a

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (16 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

separate packet, whereas, in a GET, it is sent as part of the URL. In Get, there is a limit to the
amount of data that can be sent as part of the URL. Passwords and other important
information must always be sent using the POST method and not the GET method.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.IsAuthenticated + "<br>");
Response.Write(Request.IsSecureConnection + "<br>");
%>

Output
False
False

We have neither authenticated our connection, nor have we been using a secure connection. A
secure connection begins with 'https', instead of 'http'.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.Path);
%>

Output
/a.aspx

This property displays the virtual path of the current request.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.PhysicalApplicationPath);
%>

Output
c:\inetpub\wwwroot\

The Web Server can be installed anywhere on the hard disk. The default directory selected by
IIS is C:\inetpub\wwwroot. As we have used the defaults, the property PhysicalApplicationPath
reveals the same path. The PhysicalApplicationPath is called the home directory or the root
directory of IIS. Whenever a file is to be referred to on the hard disk, this value is added to the
filename. Further, the slash symbol /, which represents the virtual directory, finally gets
converted into this physical path, while it is locating or sending files to the browser.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.PhysicalPath);
%>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (17 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Output
c:\inetpub\wwwroot\a.aspx

In this program, we go a step further and ask for the full path name or the physical filename of
our aspx file.

For the next program, we write the following URL in the browser:

http://localhost/a.aspx?aa=hi&bb=bye&aa=no

a.aspx
<%@ language="C#" %>
<%
NameValueCollection c=Request.QueryString;
String[] s = c.AllKeys;
for (int i = 0; i < s.Length; i++)
{
Response.Write(s[i] + " ");
String[] s1 = c.GetValues(s[i]);
for (int j = 0; j < s1.Length; j++)
{
Response.Write("Value " + j + ": " + s1[j] + " ");
}
Response.Write("<br>");
}
%>

Output
aa Value 0: hi Value 1: no
bb Value 0: bye

The QueryString property returns a NameValueCollection. The AllKeys property of this object
returns only two keys, which is because we have repeated the parameter name aa twice. We are
permitted to repeat names in HTML.

The 'for' loop is repeated twice for the two keys. The GetValues function returns an array
consisting of two members for aa, which is because it contains two values i.e. 'hi' and 'no'. The
second 'for' loop displays these values.

Working with ASP+ is a pleasure, since there is an inbuilt code for handling multiple values.

If we run the earlier HTML file with the method as Post, we shall not receive any output,
because the environmental variable QueryString holds values only with the Get method.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.RawUrl);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (18 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

%>

Output
/a.aspx

The RawUrl displays the URL in its most primitive form.

a.aspx
<%@ language="C#" %>
<%
NameValueCollection c;
c=Request.ServerVariables;
String [] s = c.AllKeys;
for (int i = 0; i < s.Length; i++)
{
Response.Write(s[i] + "=");
String [] s1 =c.GetValues(s[i]);
for (int j = 0; j < s1.Length; j++)
{
Response.Write(s1[j] + " ");
}
Response.Write("<br>");
}
%>

Output
ALL_HTTP=HTTP_CONNECTION:Keep-Alive HTTP_ACCEPT:*/* HTTP_ACCEPT_ENCODING:gzip, deflate
HTTP_ACCEPT_LANGUAGE:en-us HTTP_COOKIE:langpref=C#; ASP.
NET_SessionId=abksbkrxdgjmmj45hasiffzx HTTP_HOST:localhost HTTP_USER_AGENT:Mozilla/4.0
(compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)
ALL_RAW=Connection: Keep-Alive Accept: */* Accept-Encoding: gzip, deflate Accept-Language: en-us
Cookie: langpref=C#; ASP.NET_SessionId=abksbkrxdgjmmj45hasiffzx Host: localhost User-Agent:
Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)
APPL_MD_PATH=/LM/W3SVC/1/ROOT
APPL_PHYSICAL_PATH=c:\inetpub\wwwroot\
CONTENT_LENGTH=0
CONTENT_TYPE=
GATEWAY_INTERFACE=CGI/1.1
HTTPS=off
INSTANCE_ID=1
INSTANCE_META_PATH=/LM/W3SVC/1
LOCAL_ADDR=127.0.0.1
PATH_INFO=/a.aspx
PATH_TRANSLATED=c:\inetpub\wwwroot\a.aspx
QUERY_STRING=
REMOTE_ADDR=127.0.0.1
REMOTE_HOST=127.0.0.1
REQUEST_METHOD=GET
SCRIPT_NAME=/a.aspx
SERVER_NAME=localhost
SERVER_PORT=80

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (19 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

SERVER_PORT_SECURE=0
SERVER_PROTOCOL=HTTP/1.1
SERVER_SOFTWARE=Microsoft-IIS/5.0
URL=/a.aspx
HTTP_CONNECTION=Keep-Alive
HTTP_ACCEPT=*/*
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_ACCEPT_LANGUAGE=en-us
HTTP_COOKIE=langpref=C#; ASP.NET_SessionId=abksbkrxdgjmmj45hasiffzx
HTTP_HOST=localhost
HTTP_USER_AGENT=Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)

The server creates a large number of variables. They are too numerous to be displayed. Here,
we are only displaying the variables that have values.

a.aspx
<%@ language="C#" %>
<%
Uri o = Request.Url;
Response.Write("URL Port: " + o.Port + "<br>");
Response.Write("URL Protocol: " + o.Scheme + "<br>");
Response.Write("URL Host: " + o.Host + "<br>");
Response.Write("URL PathAndQuery: " + o.PathAndQuery + "<br>");
Response.Write("URL Query: " + o.Query + "<br>");
%>
Output
URL Port: 80
URL Protocol: http
URL Host: localhost
URL PathAndQuery: /a.aspx?aa=hi&bb=bye
URL Query: ?aa=hi&bb=bye

The Url property in the Request object, returns an HttpUrl object. This object has many
properties, which break up the URL into different components. The port number is related to
the protocol used.

Every packet on the Internet is tagged with a number that signifies the protocol that carries it.
For e.g., the http protocol has the port no. 80, E-Mail read is 25, FTP is 21, etc. Thus, the Port
shows a value of 80 because the URL that has been entered, starts with the syntax http:.
Similarly, the protocol used is http.

Host is the name of our computer. PathAndQuery contains the name of the requested file along
with the querystring.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.UserAgent);
%>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (20 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Output
Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2914)

A user agent is another name for the browser. The internal name for Netscape was Mozilla. So,
IE initially referred to itself by the same name. Many of the websites performed a check on the
browser that was requesting for the file. If it matched IE, the page was not sent across.
However, today it is IE that has eventually won the browser war. We shall talk about it later,
since it is too long an account to be related to you right away.

a.aspx
<%@ language="C#" %>
<%
Response.Write(Request.UserHostAddress);
%>

Output
127.0.0.1

Every computer on the Internet is known by a number, which is technically called an IP


address. It is of a long data type. This implies that it consists 4 numbers, each ranging from 0
to 255. These numbers are separated by dots. This format is known as the decimal dotted
notation.

As every machine is known as localhost and it is given an IP address 127.0.0.1. Thus, when we
write localhost in the IE address bar, it gets converted to 127.0.0.1.

a.aspx
<%@ language="C#" %>
<%
String[] s = Request.UserLanguages;
for (int i = 0; i < s.Length; i++)
{
Response.Write(s[i] + "<br>");
}
%>

Output
en-us

The property UserLanguages returns the languages that the browser supports. In our case, the
browser supports the English language, or more precisely, 'en-us', which stands for American
English and not for British English.

a.aspx
<%@ language="C#" %>
<%
String s = Request.MapPath("/quickstart");
Response.Write(s);

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (21 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

%>

Output
C:\Program Files\Microsoft.Net\FrameworkSDK\Samples\QuickStart

When the .Net sdk installs itself, it creates virtual directories in IIS. Thus, when we write http://
localhost/quickstart, it converts the virtual directory named quickstart to the path displayed
above. The MapPath function in the Request Object, converts a virtual directory to an absolute
path on your hard disk.

The Response Object


a.aspx
<%@ language="C#" %>
<%
Response.Write(Response.BufferOutput.ToString());
%>

Output
True

The first property we delve upon in the HttpResponse class is BufferOutput. This property
returns a logical value of either a True or False. In doing so, it keeps us posted on whether the
output sent to the browser will be buffered or not.

While using the Write function from the Response class, the data doesn't have to be sent to the
browser at once, as this will result in too many small packets being sent across. Therefore, on
grounds of efficiency, the text is collected and sent only when a critical mass is reached. By
default, the buffering option is on. Unless you are equipped with a valid reason, you should not
turn it off.

a.aspx
<%@ language="C#" %>
<%
Response.ContentType = "Text/plain";
Response.Write("<b>hi");
%>
Output
<b> hi

The web server sends a series of headers to the browser. It then follows it up with the actual
content. As explained to you earlier, the most important header is Content-Type. If we avoid
creating this header in our file, IIS defaults to the type value as text/html.
Here, we have changed the Content-Type property in Response to text/plain. Thus, the <b> tag
is treated as text and not a HTML tag.

a.aspx
<%@ language="C#" %>
<%

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (22 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Response.Write(Response.IsClientConnected.ToString());
%>

Output
True

This function simply returns true or false, depending on whether the client is connected or not.
This is one check that is to be performed before we send the file to the browser.

a.aspx
<%@ language="C#" %>
<%
System.IO.FileStream f;
long s;
f = new System.IO.FileStream("c:\\inetpub\\wwwroot\\a.html", System.IO.FileMode.Open);
byte[] b = new byte[(int)f.Length];
f.Read(b, 0, (int)f.Length);
Response.Write("<b>Start a.spx</b>");
Response.BinaryWrite(b);
Response.Write("<b>End a.spx</b>");
%>

Output

In the System.IO namespace, there is a class called FileStream, which has members that can
handle file activity. While creating an object 'f' in the constructor, we state the full path of the
file and also the mode in which the file is to be opened. We then allocate a byte array,
depending upon the size of the file. The file size is acquired using the property called Length in
the FileStream object.

The read function is employed next, to read the file into the byte buffer. Therefore, the first
parameter specified is 'b'. The second parameter is the starting position in the file, the position
from where the reading should begin. And the last parameter is the number of bytes to be read,
from thereon. As we want to read from the beginning of the file, and we also want to read the
entire file in one go, we specify zero as the second parameter and the length of the file is the
third parameter.

Now that the file is available in the byte array, the BinaryWriter function is used to add these
bytes into a stream and subsequently, send them to the browser. As the browser receives an
HTML file, it parses through the file and displays the textboxes. The Write functions before and
after the BinaryWrite, work as normal.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (23 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<%@ language="C#" %>


<%
Response.Write("<b>Start");
Response.ContentType = "Text/plain";
Response.Clear();
Response.Write("<b>End");
%>

Output
<b>End

The Response.ContentType function initially changes the Content-Type header after writing
Start in bold. Thereafter, the Clear function in Response, clears all HTML output, since its job is
to clear the Buffer. So, the output displayed in the browser is that of the final Write. Even
though the documentation states that headers are reset, it does not happen in the case of our
copy.

a.aspx
<%@ language="C#" %>
<%
Response.Write("<b>Start");
Response.ContentType = "Text/plain";
Response.ClearHeaders();
Response.Write("<b>End");
%>

Output
StartEnd

However, the function ClearHeaders, resets all the headers created in the scriptlet. Thus, the
default Content-type header is sent across, before the contents in the buffer are handed over to
the browser. As a result, we see StartEnd displayed in bold.

a.aspx
<%@ language="C#" %>
<%
Response.Write("<b>Start");
Response.End();
Response.Write("<b>End");
%>

Output
Start

The End function states 'enough is enough', and it sends across the HTML file and the headers
immediately. Thereafter, it closes the connection. Thus, all future output to be sent to the
browser, is conveniently ignored.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (24 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<%@ language="C#" %>


<%
Response.Write("<b>Start");
Response.Redirect("a1.aspx");
Response.Write("<b>End");
%>

a1.aspx
<%@ language="C#" %>
<%
Response.Write("<b>a1.aspx");
%>

Output
a1.aspx

The redirect function merely stops executing the current file, a.aspx, and starts executing the
file to which it has been redirected. Thus, in case of a Redirect function, any Write function that
follows the Redirect command, is completely ignored. Also, if you observe the address bar, the
URL does not change in the browser. It remaines as a.aspx.

a.aspx
<%@ language="C#" %>
<%
Response.Write("a.aspx <br>");
Response.WriteFile("a.html");
%>

The output is similar to one of the earlier programs. The WriteFile function writes the file
contents into the http stream and sends it to the browser.

Cookies Revisited
a.aspx
<%@ language="C#" %>
<%
HttpCookie c = new HttpCookie("vijay","mukhi");
Response.AppendCookie(c);
%>

One of the simplest things to do in ASP+, is to send a cookie across. Object 'c' of type
HttpCookie is created by calling the constructor with the name of the cookie vijay, having a
value of mukhi.

Since the cookie option has been set to prompt in the browser, you will see Alert box for the
cookie. Please note that the constructor does not send the cookie across. It is the function
AppendCookie that does so.

a.aspx

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (25 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<%@ language="C#" %>


<%
HttpCookie c = new HttpCookie("vijay","mukhi");
Response.AppendCookie(c);
HttpCookie c1 = new HttpCookie("vijay1","mukhi1");
Response.AppendCookie(c1);
c = new HttpCookie("vijay1","mukhi2");
Response.AppendCookie(c);
%>

By default, the browser sends a cookie for the ASP+ session. In the above program, even though
three cookies have been sent, we see only two boxes, since the second and the third cookies
share the same name. Thus, the cookie with the names of vijay1 and value mukhi2 is not sent
across separately. The point to be considered here is that you are free to send as many cookies
as you like.

a.aspx
<%@ language="C#" %>
<%
HttpCookie c = new HttpCookie("vijay");
c.Values.Add("sonal","wife");
c.Values.Add("zzz","yyy");
Response.AppendCookie(c);
%>

Output
Value in cookie dialog box
sonal=wife&zzz=yyy

a1.aspx
<%@ language="C#" %>
<%
HttpCookieCollection cc;
HttpCookie c;
cc = Request.Cookies;
int i = cc.Count;
for (int k = 0; k < i; k++)
{
c = cc[k];
Response.Write("Cookie: " + c.Name + "<br>");
String[] s1 = c.Values.AllKeys;
for (int j = 0; j < s1.Length; j++)
{
Response.Write("Value" + j + ": " + s1[j] + "<br>");
}
}
%>

Output
Cookie: vijay
Value0: sonal

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (26 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Value1: zzz
Cookie: ASP.NET_SessionId
Value0:

Cookies can be made as complex as we like. We create one cookie named vijay, and then use
the Add function in the Values property of the cookie, to initialize the subnames and values for
the cookie.

The cookie is transferred as one entity, with the key-value pairs within it. The different pairs are
separated by a & sign. a1.aspx simply displays all the cookies. For a cookie named vijay, the
last 'for' loop gets executed twice as it holds two values.

a1.aspx
<%@ language="C#" %>
<%
HttpCookieCollection cc;
HttpCookie c;
cc = Request.Cookies;
c = cc["vijay"];
Response.Write("Cookie: " + c.Name + "<br>");
Response.Write(c.Values["sonal"] + "<br>");
Response.Write(c.Values["zzz"]);
%>

Output
Cookie: vijay
wife
yyy

Rewrite a1.aspx with the code given above. This program first fetches the cookie named vijay
and stores it in 'c'. The Values property, which returns a NameValueCollection, has an indexer
that is supplied with the name of the sub key. Consequently, this indexer returns the value of
the sub key.

a.aspx
<html>
Sonal Mukhi
<a href="a1.aspx">Click here</a>
</html>

a1.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs E)
{
if (!IsPostBack) {
Response.Write(Request.Headers["Referer"]);
ViewState["zzz"] = Request.Headers["Referer"];
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (27 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

void abc(Object sender, EventArgs E) {


Response.Redirect(ViewState["zzz"].ToString());
}
</script>
<form runat="server">
<input type="submit" OnServerClick="abc" Value="Click" runat="server"/>
</form>
</body>
</html>

Output
Sonal Mukhi Click here

http://localhost/a.aspx

The file a.aspx has an anchor tag <a href…> that takes us to page a1.aspx, whenever we click
on it.

The ASP+ program a1.aspx displays a button with the label 'click'. Prior to this, the function
Page_Load is called. This function uses the Request object to access the indexer called Header.
The Header is passed a string called Referer, which informs it about the file of its origin. As a.
aspx was responsible for leading us to a1.aspx from a.aspx, the URL displays the file name a.
aspx.

The WebServer normally keeps a log of the files that lead a user to its site. This value is then
stored in a state variable called zzz. As we are now aware of the site that brought us to the
current one, by clicking on the button, we can Redirect ourselves to the page we came from.

Thus, the above code is generic and goes into a circular loop.

We shall now consider a practical example to demonstrate the utility of cookies.

a.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs E)
{
if (Request.Cookies["vijay"] == null)
{
HttpCookie c = new HttpCookie("vijay");
c.Values.Add("Size","8pt");
c.Values.Add("Name","Verdana");
Response.AppendCookie(c);
}
}
public String abc(String k)
{
HttpCookie c = Request.Cookies["vijay"];

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (28 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

if (c != null)
{
if ( k == "FontSize")
return c.Values["Size"];
else
return c.Values["Name"];
}
return "";
}
</script>
<style>
body
{
font: <%=abc("FontSize")%> <%=abc("FontName")%>
}
</style>
Sonal Mukhi
<a href="a1.aspx">Click here</a>
</body>
</html>

a1.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs E)
{
if (!IsPostBack)
ViewState["zzz"] = Request.Headers["Referer"];
}
void abc(Object sender, EventArgs E)
{
HttpCookie c = new HttpCookie("vijay");
c.Values.Add("Size",s1.Value);
c.Values.Add("Name",s2.Value);
Response.AppendCookie(c);
Response.Redirect(ViewState["zzz"].ToString());
}
</script>
<form runat="server">
<select id="s1" runat="server">
<option>8pt</option>
<option>10pt</option>
<option>12pt</option>
<option>44pt</option>
</select>
<select id="s2" runat="server">
<option>verdana</option>
<option>tahoma</option>
<option>arial</option>
<option>times</option>
</select>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (29 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<input type="submit" OnServerClick="abc" Value="Click" runat="server"/>


</form>
</body>
</html>

Output
Sonal Mukhi Click here

Sonal Mukhi Click here


The above example displays the text 'Sonal Mukhi' and a hyperlink labelled as 'Click Here'. If we
click on the hyper link, we are transported to a new page called a1.aspx. This page contains
two dropdown listboxes and a button. The first listbox displays the font point size and the
second offers the font face name. By default, the values in these text boxes are 8pt for the font
size and Verdana for the font face name, respectively. At this stage, if you modify the font size to
12 and the font face name to Tahoma, and then click on the button, you will be taken back to
the original file named a.aspx. In this file, the text and the Hyperlink will now be displayed in
the newly selected font and size.
Having unravelled the output, let us now shift the spot-light to the internal working of this
program.

The Page_Load function in a.aspx verifies the existence of a cookie named 'vijay'. Since this
page has just been loaded afresh, the cookie is not available at the moment. This condition
results in true only when the client returns the cookie sent by the server, while transmitting the
user data.

Since the Cookies collection returns a null, a cookie named 'vijay' is created with two sub keys
of Size and Name. These sub keys are given the values of 8 pt and Verdana, respectively, which
correspond to the font size and the font face name. This cookie is sent over along with the page
generated by a.aspx.

The code enclosed within the style and /style tags calls the function abc, to adjust the font size
and name as specified by the cookie. Since 'c' has not been currently initialized, the current text
is not displayed in the font and the size specified in the cookie. Depending upon the value of the
parameter 'k', the value of the key Size or Name, as specified in the Cookie 'Vijay', will be put
into service. Thus, the keys in the cookie named 'Vijay' will decide the format of the text
displayed on the page.

If we click on the hyper-link, it will result in a call to a1.aspx. By using the Referer parameter in
the Header's Indexer, the name a.aspx of the aspx file is stored in the state variable named zzz.
When the user clicks on the button, the font name and font size selected by the user, get stored
in the listbox ids of s1 and s2 respectively.

This results in a call to the code in the function abc, where a cookie called 'Vijay' is created. Its
sub keys are initialized to values obtained from the listbox. This cookie is sent over. Thereafter,
using the state variable zzz, we revert back to a.aspx.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (30 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

In the file a.aspx, since the cookie 'vijay' now contains specific values, we use these values to
set the font size and the name. As a consequence, the text is displayed in accordance with the
values selected by the user in the listbox, which are now accessible from the cookie. Thus, we
can conclude that the system takes into account the choices that we make, and each time we
load the file a.aspx, the text displayed on the page is formatted as per the pre-selected font face
and size.

This is the mechanism to display a customized web page. Since by default the page does not
retain these values when the browser is closed, the 'expires' attribute has to be initialized to a
value specified in terms of time or a date. This indicates the duration for which the cookie is to
remain alive. Alternatively, we can store such a value in DateTime.MaxValue, so that the cookie
never expires.

You can verify the retention of pre-set values between different browser sessions by closing the
browser and re-starting it. The browser would have retained the settings specified by you
earlier.

Cookies are employed to enable data to persist between the client and the server. A cookie is
usually stored on the Client’s hard disk. In the case of Netscape Navigator, a file called cookies.
txt is created by the browser to store the cookies. The minimum size per cookie is 4096 bytes.

State Management with Global.asax


a.aspx
<html>
<script language="C#" runat="server">
int p1=0;
void Page_Load(Object sender, EventArgs e)
{
p1++;
Response.Write("Page_Load() " + p1.ToString() + "<br>");
}
void abc(Object sender, EventArgs e)
{
Session.Abandon();
//Response.Redirect("a.aspx");
}
</script>
<body>
<form runat="server">
<input type="submit" Value="Refresh" runat="server"/>
<input type="submit" OnServerClick="abc" Value="End Session" runat="server"/>
</form>
</body>
</html>

global.asax
<script language="C#" runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (31 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

int r1 =0, r2=0, s1=0,s2=0,a1=0,a2=0;


void Application_Start(Object sender, EventArgs E)
{
a1++;
}
void Application_End(Object sender, EventArgs E)
{
a2++;
}
void Session_Start(Object sender, EventArgs E)
{
s1++;
Response.Write("Session_Start " + s1.ToString()+ "<br>");
}
void Session_End(Object sender, EventArgs E)
{
s2++;
Response.Write("Session_End " + s2.ToString()+ "<br>");
}
void Application_BeginRequest (Object sender, EventArgs E)
{
r1++;
Response.Write("Request_Start " + r1.ToString()+ " Application start " + a1.ToString() + "<br>");
}
void Application_EndRequest (Object sender, EventArgs E)
{
r2++;
Response.Write("Request_End "+ r2.ToString()+ " Application end " + a2.ToString() + "<br>");
}
</script>

Output
Request_Start 1 Application start 0
Session_Start 1
Page_Load() 1

Request_End 1 Application end 0

In the above program, we have created two files in the directory c:\inetpub\wwwroot. The file a.
aspx can be christened by any name of our choice, but the second file must be named as global.
asax. Prior to loading a.aspx in the browser, ASP.Net checks for the presence of a file named
global.asax. If it exists in the current directory, a DLL is created with a class called global.asax.
This class holds all the code entered in the asax file. The class resembles the following:

public class global_asax : System.Web.HttpApplication , System.Web.SessionState.


IRequiresSessionState {

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (32 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

We discovered this by consciously committing an error in C#.

There are six functions with pre-defined names that are added to global.asax. They are:

• Application_Start
• Application_End
• Session_Start
• Session_End
• Application_BeginRequest
• Application_EndRequest

We have also created six different variables in this special file and initialized all of them to 0.
Each of these six functions increments one variable each by a value of 1. This signifies the
frequency with which the functions get called. A similar action is repeated in the Page_Load
function within the aspx file.

When we load the file a.aspx, it calls some functions from the file global.asax. But, each of them
gets called only once. The order is as follows: Application_BeginRequest, Session_Start,
Page_Load.

Thereafter, the buttons in the aspx file are displayed. Lastly, Application_EndRequest is
displayed on the screen.

Please note that there is no Write function in Application_Start and Application_End, because
the Response object is neither available, nor has it been created so far. By adding a function, an
error is generated, that gives us information about the global_asax class in the dll.

When we click on Refresh, no code gets called, because it simply results in a post back to the
server.

Output
Request_Start 2 Application start 0
Page_Load() 1

Request_End 2 Application end 0

The order of calling the various functions is as follows:

• First, function Application_BeginRequest with variable r1 as 2,


• Then, function Page_Load with variable p1 as 1
• Finally, function Request_End with variable r2 as 2.

The output proves that the Page_Load function is not called on clicking on the refresh button.
Also, no new session is created. Hence, the Session_Start function is not called.

Now, if you click repeatedly on the 'End Session' button, you will see the following output:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (33 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Output
Request_Start 10 Application start 0
Session_Start 8
Page_Load() 1

Request_End 10 Application end 0

The Session_Start function is called once and the Request_Start is called twice.

If we comment out the Response.Redirect function in the file a.aspx, we obtain the same
number of functions as before, but the Request functions get called only once. What we are
trying to convey here is that, generous amount of code gets called before and after Page_Load.
We can take advantage of these functions and the frequency of their occurrence to execute
certain code at specified intervals.

For the moment, the code in global.asax does not deal with User Interface calls. These calls
handle a much higher level of event handling, where it deals with application events. We can
create our own events in the form of Application_EventName(signature).

We would also like to clarify that the file, global.asax, need not be restricted to the wwwroot sub-
directory alone. The only salient feature to be kept in mind is that it should be placed in the
same sub-directory as the aspx file.

The .Net framework creates a class derived from HttpApplication and places our code in it. Any
modifications made to these files automatically calls for recompiling of the class. We cannot use
a direct URL request to fetch the file, since we are not permitted to view the code written in it.

If you consider yourself to be a maverick, you may attempt to do so. But beware, you will then
have to deal with the error number 404.

a.aspx
<html>
<script language="C#" runat="server">
void abc(Object sender, EventArgs e)
{
throw new Exception();
}
</script>
<body>
<form runat="server">
<input type="submit" OnServerClick="abc" Value="Exception" runat="server"/>
</form>
</body>
</html>

Output

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (34 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

In the above program, An exception of type System.Exception was thrown. The above program
is extremely simple. It displays a button labelled 'Exception'. If we click on this button, an
exception is thrown.

An exception is a synonym for an error. The class, when derived from exception, becomes an
exception class. Functions in today's world throw exceptions rather than errors. We get an ugly
yellow coloured screen containing the exception message.

Now, let us endeavour to execute our own code, whenever an exception is thrown.

We first create a file called web.config in c:\inetpub\wwwroot as follows:

web.config
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="a.htm" />
</system.web>
</configuration>

a.htm
hi

This file, which is used to customize the default workings of ASP.Net, is read each time by the
ASP+ framework. By giving the above tags in the file, we can direct the framework to load a file
named a.htm, whenever an error occurs. The URL, however, changes to the following in the
browser address bar:

http://localhost/a.htm?aspxerrorpath=/a.aspx

a.aspx
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E )
{
DataView s = (DataView)(Application["sss"]);
s1.InnerHtml = s.Table.TableName;
l.DataSource = s;
l.DataBind();
}
</script>
<body>
<span runat="server" id="s1"/></font>
<ASP:DataGrid id="l" runat="server"/>
</body>
</html>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (35 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

global.asax
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>
<script language="C#" runat="server">
void Application_Start(Object sender, EventArgs e)
{
DataSet d = new DataSet();
FileStream f = new FileStream(Server.MapPath("s.xml"),FileMode.Open,FileAccess.Read);
StreamReader r = new StreamReader(f);
d.ReadXml(r);
f.Close();
DataView v = new DataView(d.Tables[0]);
Application["sss"] = v;
}
</script>
s.xml
<root>
<schema id="DocumentElement" targetNamespace="" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xdo="urn:schemas-microsoft-com:xml-xdo" xdo:DataSetName="DocumentElement">
<element name="Products">
<complexType>
<all>
<element name="ProductID" type="int"></element>
<element name="CategoryID" minOccurs="0" type="int"></element>
</all>
</complexType>
</element>
</schema>
<DocumentElement>
<Products>
<ProductID>2002</ProductID>
<CategoryID>2</CategoryID>
</Products>
<Products>
<ProductID>2003</ProductID>
<CategoryID>2</CategoryID>
</Products>
</DocumentElement>
</root>

Output
Products

In the file a.aspx, we begin with the assumption that a DataView object has already been
created. Then, we initialize a span member named InnerHtml to a Table name that is picked up
from the DataView.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (36 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

This explains the display of Products in the browser window. Then, the DataSource property of
the DataGrid named l, is initialized to the DataView object named 's'. Finally, the function
DataBind display the records in a Tabular format.
Now, let us cover up the loopholes in the explanation of the above program.

In the global.asax file, we have added adequate amount of code in the Application_Start
function. A DataSet object named 'd' is created to hold the data. Also, a FileStream object
named 'f' is given a reference to an XML file named s.xml, which is opened for reading purpose
only. The file s.xml resides in the same directory. The StreamReader object named 'r' is given
the FileStream parameter in its constructor, to enable it to read this file. d.Readxml will finally
read the contents of the xml file in its dataset. We are not going into the explanation of s.xml,
since it remains the same as before.

After closing the file, a DataView object 'v' is created. Application variables are similar to State
variables, in the sense that, they are valid only while the application is on. The Application is an
indexer. Hence, we provide a string named 'sss' to hold the DataView object. The variable 'sss' is
now an Application variable.

The Application variable sss, containing the DataView object, is used in the Page_Load function.
It supplies the data contained in the DataSet. The functions Page_Load and Application_Start
are called only once, i.e. when the page is initially loaded. Both perform one-time actions. Thus,
all resource intensive actions, such as, initializing the DataView, which is a one-time effort, are
placed in this function.

There can always be a situation where multiple threads would like to access both, an
application and its objects, concurrently. So, the data that does not change very often, must be
stored with an Application scope. Data that needs to be initialized just once and then it is
required to be only read, is an ideal example of such data.

In the above example, only the first request is resource intensive, and will incur a performance
overhead while creating the DataView. All the other requests will be executed at lightning speed.

Sessions
a.aspx
<html>
<script language="C#" runat="server">
String abc(String k)
{
return Session[k].ToString();
}
</script>
<style>
body
{
font: <%=abc("Size")%> <%=abc("Name")%>
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (37 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</style>
Sonal Mukhi
<a href="a1.aspx">Click here</a>
</body>
</html>

a1.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs E)
{
if (!Page.IsPostBack)
ViewState["zzz"] = Request.Headers["Referer"];
}
void abc(Object sender, EventArgs E)
{
Session["Size"] = s1.Value;
Session["Name"] = s2.Value;
Response.Redirect(ViewState["zzz"].ToString());
}
</script>
<body>
<form runat="server">
<select id="s1" runat="server">
<option>8pt</option>
<option>10pt</option>
<option>12pt</option>
<option>44pt</option>
</select>
<select id="s2" runat="server">
<option>verdana</option>
<option>tahoma</option>
<option>arial</option>
<option>times</option>
</select>
<input type="submit" OnServerClick="abc" Value="Click" runat="server"/>
</form>
</body>
</html>

global.asax
<script language="C#" runat="server">
void Session_Start(Object sender, EventArgs e)
{
Session["Size"] = "8pt";
Session["Name"] = "verdana";
}
</script>

The above example conducts itself in the same manner as the earlier Cookies' example.
However, this one is much simpler. It is next to impossible for the user to detect the method

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (38 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

used to obtain the above output by merely looking at the end result.

Let us start with the file named a.aspx.

The code in a.aspx remains the same, except for modifications made in the function abc. The
Session indexer is used to retrieve the value of a variable that is created in the global.asax file.
In the global.asax file, we have created two variables named Size and Name to store the font
size and the font name respectively. You may have noticed that this code is placed in the
function named Session_Start.

When we click on the button in the file a1.aspx, the Sessions variables get re-initialized with the
values selected in the listboxes. Thereafter, there is a redirection to the original page named a.
aspx.

If we replace Cookies with Session, the entire picture would be more transparent and lucid.

We can configure the state of the session object by using the sessionstate section in the file
named web.config. Adding the line <sessionState timeout="40" /> will increase the default
timeout from 20 minutes to 40 minutes. The timeout parameter ends the session either in 40
minutes or when you close the browser, whichever occurs first.

We now add the following line to the file named web.config

web.config
<configuration>
<system.web>
<sessionState cookieless="true" />
</system.web>
</configuration>

We have selected the cookie option named 'prompt', and in config.web, we have disallowed the
use of a cookie to keep track of sessions. Thus, the web server has no choice but to use the URL
to keep track of sessions. As a result, the new URL looks like the following:

http://localhost/(ybp3byicimzjix3s0veyjb55)/a.aspx

This method is termed as URL rewriting.

ViewState
The illustration given below may be a large program, but it is deceptively simple to understand.

a.aspx
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E )
{
if (!IsPostBack)
ViewState["zzz"] = 0;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (39 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

}
void a1(Object Src, EventArgs E )
{
String pid = "P" + ViewState["zzz"].ToString();
ViewState["zzz"] = (int)ViewState["zzz"] + 1;
String Id = "P" + ViewState["zzz"].ToString();
Panel p = (Panel)FindControl(Id);
p.Visible=true;
p = (Panel)FindControl(pid);
p.Visible=false;
}
void a2(Object Src, EventArgs E )
{
String Id = "P" + ViewState["zzz"].ToString();
ViewState["zzz"] = (int)ViewState["zzz"] - 1;
String pid = "P" + ViewState["zzz"].ToString();
Panel p = (Panel)FindControl(Id);
p.Visible=false;
p = (Panel)FindControl(pid);
p.Visible=true;
}
void a3(Object Src, EventArgs E )
{
String s = "P" + ViewState["zzz"].ToString();
Panel p = (Panel)FindControl(s);
p.Visible=false;
l.Text += "Name: " + na.Value + "<br>";
l.Text += "Address: " + a.Value + "<br>";
l.Text += "Card : " + n.Value + "<br>";
}
</script>
<body">
<form runat="server">
<ASP:Panel id="P0" Visible="true" runat="server">
Name:
<input id="na" type="text" runat="server">
<br>
<input type="submit" Value=" Next >> " OnServerClick="a1" runat="server">
</ASP:Panel>
<ASP:Panel id="P1" Visible="false" runat="server">
Address:
<input id="a" type="text" runat="server">
<input type="submit" Value=" << Back " OnServerClick="a2" runat="server">
<input type="submit" Value=" Next >> " OnServerClick="a1" runat="server">
</ASP:Panel>
<ASP:Panel id="P2" Visible="false" runat="server">
Card Number:
<input id="n" type="text" runat="server"/>
<input type="submit" Value=" << Back " OnServerClick="a2" runat="server">
<input type="submit" Value=" Finish " OnServerClick="a3" runat="server">
</ASP:Panel>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (40 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</form>
<asp:Label id="l" runat="server"/>
</body> </html>

Output

We start our explanation with the code following the script tag, where we have three predefined
Panel controls having the ids P0, P1 and P2. A Panel tag is simply a container for other HTML
controls.

The Visible property for the first panel is set to true, whereas, for the other two, it is set to false.
Thus, only the first panel P0 is displayed, and not the others.

The first panel contains a TextBox called 'na' and a button of type submit and label 'Next >>',
which calls the function a1 when it is clicked.

The Page_Load function creates a ViewState variable named zzz and assigns it a value of 0. In
a1, pid is assigned a value after concatenating "P" to the string value returned by ViewState
["zzz"]. The statement ViewState["zzz"] = (int)ViewState["zzz"] + 1; increases the value by 1,
thereby, making it 1.

A new string is then created with this new value of zzz. Thus, the value in the variable id
becomes P1. The function FindControl, when supplied with the name of the control, returns a
control. We cast it to a Panel, because we want to store this value in a Panel object named 'p'.
The Panel object 'p' currently represents the hidden Panel P1.

We change the visible property of p, i.e. Panel P1, to true. As a result, the second panel is
displayed on the screen. Subsequently, we use the same function named FindControl to find
the Panel P0 and to change its Visible property to false. Thus, the only panel that is displayed
at this stage is P1.

The second panel contains one textbox and two buttons. The button labeled 'Next >>' calls the
function a1, whereas, the one labeled '<< Back' calls the function a2. The function a1
increments the value of zzz by 1, thereby, taking us to the next panel. On the other hand the
function a2 decreases the value of zzz by 1, thereby, taking us to the previous panel.
Accordingly, the current panel is hidden and the new panel is made visible.

In the last panel P3, the function a3 gets called by the button labeled 'Finish'. This function

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (41 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

simply displays the values of the textboxes in the label field.

The user is given the impression that he is moving from one page to the other, but in reality, a
single aspx file is executing certain sections of its code.

The property named ViewState is an instance of the StateBag class, which gives us a dictionary
like interface. It stores objects associated with a key.
Create the b.cs file in the c:\inetpub\wwwroot\bin sub directory.

b.cs
using System.Web;
namespace nnn
{
public class zzz : IHttpHandler
{
public void ProcessRequest(HttpContext c) {
c.Response.Write("Hell");
}
public bool IsReusable {
get {
return true;
}
}
}
}

Compile b.cs as
>csc /target:library /out:c.dll b.cs /R:system.web.dll

Create a file by the name of web.config in c:\inetpub\wwwroot to appear as depicted below:

web.config
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="a1.aspx" type="nnn.zzz,c" />
</httpHandlers>
</system.web>
</configuration>

Now, load the following URL in the browser http://localhost/a1.aspx

Output
Hell

We first create a simple program named b.cs in the c:\inetpub\wwwroot\bin sub-directory. The
class zzz in this file is derived from the interface IhttpHandler. It contains only two functions
named ProcessRequest and IsReusable.

The IsReusable function is called to find out whether the same instance of the class can be

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (42 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

recycled and used for another request, or if a fresh instance of the object needs to be created.
Since the function returns true, the same object is used.

The ProcessRequest function creates the HTML output that is to be sent across to the browser.
It accepts an object 'c' of type HttpContext as a parameter. This object has a function called
Write, which helps the browser in writing output to the screen. Hence, we see 'Hell' displayed in
the browser window.

What if we want to call our own function, instead of the ones supplied by IIS, when we are
working on certain files?

To synchronously process HTTP web requests, the first requirement is that, the class must
derive from IHttpHandler. This interface must be implemented, because it defines a contract
and allows custom URL execution.

ASP.Net provides us with a low-level request and response API (a set of rules), which uses
classes in order to service incoming requests. Thus, the above program is called a handler.
Handlers are used when we want to customize certain features if we are not satisfied with the
methods adopted by the framework that handles web requests.

The interface IHttpHandlerFactory decides on the class that will handle the http request. ASP.
Net is shipped with three factory classes that handle requests. These are:

• PageHandlerFactory
• RestrictedResourceFactory
• WebServiceHandlerFactory

We can either use any one of these three classes or create our own set of classes. If we create
our own classes, we have to register them with the framework and handle the resolution issues.
To change the default behaviour in the .Net world, code has to be placed in the config.web file.
This is a plain and simple text file, which follows the rules of XML. This file has to be placed in
the inetpub\wwwroot sub-directory or the directory of your application.

We can place our options within a tag called <configuration>. Following this, we have to initially
place a tag called system.web which will contain another tag called <httpHandlers>. This tag
accepts the name of a file or a file pattern. This pattern calls our handler when the value
assigned to the property called path, is invoked. HttpHandler also requires the type attribute
containing the namespace name and the class to handle the request. The name of the dll is also
to be specified with the type. Thus, we use a comma as a separator, and then give 'c'. The c.dll
must be present in the bin sub-directory. These settings are inherited by sub-directories also,
implying that the sub-directories are also checked for controls, handlers etc.

Each time we request for a file named a1.aspx, the request for this particular file is not
processed by the web server. Instead, it is handed over to our class named zzz. The class zzz
then decides on the data to be sent over, under the file name of a1.aspx

Thus, handlers and factories are the backbone of the framework, because we are at liberty to
decide on how the HTTP request should be handled. The factory picks up the request and

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (43 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

decides on the handler that is to be called. These handlers are available in the web.config file.
The code for the handlers normally resides in the bin sub-directory. Since the file is placed in
the default root directory, it is picked up by default, hence we request you to delete this file
after having tried the example.

Tracing
a.aspx
<%@ Page Trace="true" language="C#"%>
hi
<%
Response.Write("bye");
%>

Output
hi bye
Request Details

Session Id: dufldc55vabqbd45xof13m55 Request Type: GET


Time of Request: 9/26/2001 6:15:55 PM Status Code: 200
Request Encoding: Unicode (UTF-8) Response Encoding: Unicode (UTF-8)
Trace Information

Category Message From First(s) From Last(s)


aspx.page Begin Init
aspx.page End Init 0.000184 0.000184
aspx.page Begin PreRender 0.000928 0.000744
aspx.page End PreRender 0.001095 0.000168
aspx.page Begin SaveViewState 0.001462 0.000367
aspx.page End SaveViewState 0.001617 0.000154
aspx.page Begin Render 0.001757 0.000141
aspx.page End Render 0.002250 0.000493
Control Tree

Render Size Bytes (including Viewstate Size Bytes (excluding


Control Id Type
children) children)
__PAGE _ASP.a_aspx9 0
Cookies Collection

Name Value Size


ASP.NET_SessionId dufldc55vabqbd45xof13m55 42

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (44 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Headers Collection

Name Value
Connection Keep-Alive
image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
Accept
powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Encoding gzip, deflate
Accept-Languageen-us
Host 127.0.0.1
Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR
User-Agent
1.0.2914)
Server Variables

Name Value
HTTP_CONNECTION:Keep-Alive HTTP_ACCEPT:image/
gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/
vnd.ms-powerpoint, application/vnd.ms-excel, application/
msword, */* HTTP_ACCEPT_ENCODING:gzip, deflate
ALL_HTTP
HTTP_ACCEPT_LANGUAGE:en-us
HTTP_HOST:127.0.0.1 HTTP_USER_AGENT:Mozilla/4.0
(compatible; MSIE 6.0b; Windows NT 5.0; .NET CLR
1.0.2914)
Connection: Keep-Alive Accept: image/gif, image/x-
xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
powerpoint, application/vnd.ms-excel, application/msword,
ALL_RAW
*/* Accept-Encoding: gzip, deflate Accept-Language: en-us
Host: 127.0.0.1 User-Agent: Mozilla/4.0 (compatible; MSIE
6.0b; Windows NT 5.0; .NET CLR 1.0.2914)
APPL_MD_PATH /LM/W3SVC/1/ROOT
APPL_PHYSICAL_PATH c:\inetpub\wwwroot\
AUTH_TYPE
AUTH_USER
AUTH_PASSWORD
LOGON_USER
REMOTE_USER
CERT_COOKIE
CERT_FLAGS
CERT_ISSUER
CERT_KEYSIZE
CERT_SECRETKEYSIZE

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (45 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

CERT_SERIALNUMBER
CERT_SERVER_ISSUER
CERT_SERVER_SUBJECT
CERT_SUBJECT
CONTENT_LENGTH 0
CONTENT_TYPE
GATEWAY_INTERFACE CGI/1.1
HTTPS off
HTTPS_KEYSIZE
HTTPS_SECRETKEYSIZE
HTTPS_SERVER_ISSUER
HTTPS_SERVER_SUBJECT
INSTANCE_ID 1
INSTANCE_META_PATH /LM/W3SVC/1
LOCAL_ADDR 127.0.0.1
PATH_INFO /a.aspx
PATH_TRANSLATED c:\inetpub\wwwroot\a.aspx
QUERY_STRING
REMOTE_ADDR 127.0.0.1
REMOTE_HOST 127.0.0.1
REQUEST_METHOD GET
SCRIPT_NAME /a.aspx
SERVER_NAME 127.0.0.1
SERVER_PORT 80
SERVER_PORT_SECURE 0
SERVER_PROTOCOL HTTP/1.1
SERVER_SOFTWARE Microsoft-IIS/5.0
URL /a.aspx
HTTP_CONNECTION Keep-Alive
image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
HTTP_ACCEPT application/vnd.ms-powerpoint, application/vnd.ms-excel,
application/msword, */*
HTTP_ACCEPT_ENCODING gzip, deflate
HTTP_ACCEPT_LANGUAGEen-us
HTTP_HOST 127.0.0.1
Mozilla/4.0 (compatible; MSIE 6.0b; Windows NT 5.0; .
HTTP_USER_AGENT
NET CLR 1.0.2914)

In a.aspx, we simply added an attribute called Trace and assigned it a value of true. This
resulted in a page full of very useful information. First 'hi' and 'bye' were displayed, and then,
we saw a table where the information was categorized into different sections.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (46 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

The first section is the Request Information where the session id is displayed in the form of a
very long number. It changes with every new browser session. Then, the datetime of the file
request is displayed. The request type can either be GET or POST. Since we have not explicitly
specified the type, it has the default value of GET.

The last is the success/error code. If all goes well, like it has in this case, the code sent to the
browser should be 200. In the case of an error, the error code or error number is reported. For
example, if a file is not found, error number 404 is returned.

We are fully aware that a large number of functions get called from our page. But it is
challenging to figure out as to which functions have been called, and the order in which they
have been executed. The trace gives us a ready rejoinder for this. At first, the Init functions are
called. They are followed by the functions PreRender, SaveState and Render, in that order. A
trace output augments our understanding of ASP+.

In the current file, we have no controls on our page, but if we did have them, they would all
have been displayed.

The next category encompasses the Session State. All the session variables that we create, are
listed here, along with their values. A cookie that expires when the browser session is closed, is
called a session variable.

Following the Session State is the Cookies Collection. Even though our program has not sent
any cookies, ASP+ sends over a cookie to maintain state. All cookies are listed with their names
and values.
Following these categories are the details about the Headers, followed by details about the
Server variables.

The trace output assists in debugging code. When you run the samples provided by Microsoft,
you will witness a large number of functions that are called by the framework, to handle a
database request. We could have added one more property called TraceMode, which specifies
the trace statements. The default behaviour of SortByTime can also be changed to
TraceMode="SortByCategory".

There is a Page-level tracing that writes debugging statements directly to the output of a page. If
tracing is on, it also executes code.

a.aspx
<%@ Page Trace="true" TraceMode="SortByCategory" %>
<html>
<script language="C#" runat="server">
public void Page_Load(Object sender, EventArgs E)
{
Trace.Warn("aaa","bbb");
if (Trace.IsEnabled)
Trace.Write("ccc","vijay");
}
public void abc(Object sender, EventArgs E)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (47 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

{
Trace.Write("ddd","mukhi");
Trace.Warn("eee","sonal");
}
</script>
<body>
<form runat="server">
<input type="Submit" OnServerClick="abc" Value="hi" runat="server"/>
</form>
</body>
</html>

We have a property called Trace of type TraceContext, which executes the functions Warn and
Write. Both these functions display the parameters that are passed to them in red and normal
colour, respectively. This output is placed under the Trace Information. Here, two parameters
are required. The first parameter will get displayed in the column Category and the second,
under the heading Message.

The function Page_Load is called once. It looks for the value contained in the Trace property.
This value is of type Boolean. Hence, it will return true when trace is on, and false, when trace
is off. We can execute trace code only if tracing is enabled.

When we click on the button, the trace output shows plenty of code that has been called, and it
also displays the order in which the functions are being executed. Notice that the Trace
statements in the function Page_Load confirm the fact that Page_Load gets called each time that
we go back to the server.

public void Page_Load(Object sender, EventArgs E)


{
if (!IsPostBack)
{
Trace.Warn("aaa","bbb");
if (Trace.IsEnabled)
Trace.Write("ccc","vijay");
}
}

We have now added an 'if' statement to the Page_Load function to verify whether IsPostBack
has a value of false for the first time or not.

Now, the trace statements will be displayed only once, because when we click on the button,
these statements are not displayed again. This substantiates the point that we are trying to
make. Thus, we advise you to keep the trace on, if you want to figure out the order of execution
of functions.

Application level tracing is turned-on by adding the following line in the web.config file:

web.config
<configuration>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (48 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<system.web>
<trace enabled="false" requestLimit="0" pageOutput="false" traceMode="SortByTime" />
</system.web>
</configuration>

In order to see the tracing output, load a file called trace.asx using http://localhost/trace.asx .
This will first show us the individual requests. Then, we can drill down to the actual tracing
data.

Caching
Hard disks are always slower than memory, since they are mechanical devices. The Internet is
much slower compared to your hard disk. So, it obviously takes much longer for a file to be
displayed in a browser, if it has to travel across the Internet. Retrieving the same file from our
hard disk is a relatively faster process. Caching is a technique used in computers, which helps
in increasing the speed of access. This is done by storing that portion of the data in memory,
which is required to be accessed very often. Thereby, it can be accessed much more quickly.

In the web world, caching has a different meaning. The performance of our web server would
drastically improve, if we held onto the web page between web requests, so that we do not have
to recreate them.

ASP.Net offers us two kinds of caching, namely, Output Caching and Data Caching.

• In Output Caching, the html file created by the aspx application is cached or stored,
instead of sending it across immediately.
• In Data Cache, an object is stored programmatically. ASP.Net provides a full-featured
cache engine. This allows us to hold on to or store an object in such a way that we can re-
use it across http requests.

We use Output Caching whenever the entire page can be cached. A web site that has a large
number of visitors can experience substantial performance gains, if it can cache a frequently
accessed page even for a single minute. Thus, page caching implies that in the case of an http
request, the page is served from the cache. It is not recreated by executing the code that it
contains.

It is not always practical to cache an entire page at a time. Hence, an alternative is to cache
only a portion or some objects on that page. Thus, those objects of a page that take a long time
to be created, should be cached for a longer period.

How does one decide as to when, and for how long an object should be cached? This is not an
easy decision to make. The data might get refreshed at regular intervals, or it may be valid for a
specified time period only. We are allowed to associate an expiration period with an item in the
cache. On doing so, ASP.Net will remove the item from the cache only when the specified
expiration period has elapsed. Thus, a program will first look for data in the cache. Only if it
cannot find the item there, will it re-create it.

In ASP+, the concept of caching is quite advanced. A cache item can depend upon an external

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (49 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

file or another cache item. Thus, if one cache item expires, all the other cache items that are
dependent on it, also expire. Some items may expire when their data source is modified.

a.aspx
<%@ OutputCache Duration="60" VaryByParam="none" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs e)
{
l.Text = DateTime.Now.ToString("r");
}
</script>
<body>
<asp:label id="l" runat="server"/>
</body>
</html>

The above example displays the current data and time, since the value is displayed off the
DateTime object. Open the same file in a Browser, and the time remains the same.
This happens because of the directive OutputCache, where the duration property is set to 60
seconds. The first time One access the aspx program, it is kept in the cache for Sixty seconds.
Thus, when we open the file in a new browser, the value present in the cache is picked up.
Then, after sixty seconds have elapsed, the file gets re-executed. Thus, output caching is a very
powerful technique meant for increasing the performance of the server. Items are placed in
memory and not reloaded from the disk, over and over again. Accessing the hard disk slows
down the program.

The output is cached only when the above directive is employed. In the first round, a valid GET
or HEAD response is sent to the server. So, a cache entry is created internally. Then, for future
requests, the cache is read, until it expires.

The cache also checks the entire URL, including the parameters passed to it. If any of the
parameters passed, or the QueryString is different, the cache is ignored and the value is fetched
from the server. This is known as a Cache Miss.

a.aspx
<%@ OutputCache Duration="15" VaryByParam="none"%>
<html>
<script language="C#" runat="server">
void Page_Load(Object sender, EventArgs e)
{
l.Text = DateTime.Now.ToString("r") + "<br>";
}
</script>
<body>
<form action=a.aspx>
<asp:label id="l" runat="server"/>
<input type=text name=aa>
<input type=submit value="hi">
</body>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (50 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</html>

Output

To explain the above principle, we have a textbox and a button that calls the same form again.
You can enter any text in the textbox and click on the button to submit the value. Since the
page gets reloaded, we see a different date time value. Open a new copy of the browser before
15 minutes are elapsed and you’ll notice that the time does not get updated as the value stored
in the cache is reloaded.

However, if another copy of the browser is loaded after 15 seconds have elaplsed, we see the
current time on the screen.

The output cache maintains the sanctity of the duration specified for which you want the data
to be cached. Under no circumstance will the data be removed from the cache earlier than the
specified duration. This is because, the framework cannot, on its own, comprehend the reason
why you need to place something in the cache for the specified duration. When a page is valid
in the cache for a specified duration of time, it is known as an absolute expiration policy. The
server can also send http headers to the client, which include the duration for which a page is
to remain valid on the browser's side.

VaryByParam can take only three values, namely none, * or parameters. DateTime.Now.
ToString contains the alphabet r as a parameter. This refers to a certain format in which the
date and time are to be displayed. Change the value to G and the output will vary accordingly.

Data Caching
a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E)
{
DataView s;
s = (DataView)Cache["yyy"];

if (s == null)
{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=NorthWind");
SqlDataAdapter co = new SqlDataAdapter("select * from Products", c);
DataSet ds = new DataSet();
co.Fill(ds, "zzz");
s = new DataView(ds.Tables["zzz"]);
Cache["yyy"] = s;
i.Text = "Dataset created ";

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (51 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

}
else
{
i.Text = "Dataset retrieved from cache";
}
l.DataSource=s;
l.DataBind();
}
</script>
<body>
<form method="GET" runat="server">
<asp:label id="i" runat="server"/></i>
<ASP:DataGrid id="l" runat="server"/>
</form>
</body>
</html>

Output
Dataset created

ASP.Net offers us a caching engine that has all the bells and whistles we will ever need. It lets
us store and retrieve any type of arbitrary objects in the cache, across http requests. These
objects are stored in the memory and not on the disk. They are private to each application.
Fortunately, we are provided with a simple dictionary interface, like the ViewState and Session
objects, that let us store some object and equate it with a value.

In the above example, we are using the cache indexer and checking for a variable called yyy.
Since any object can be stored in a cache, we cast it to a DataView object. s returns a value of
null, since we have not placed anything in the cache yet. We populate the DataView with data
from the database. We store the view object that represents the SQL data, into the Cache
property, using the name yyy.

Henceforth, any access made to this page, will result in a non-null value for 's'. Thus, data is
read from the cache without executing the SQL statements. This also works across sessions or
browser instances. Imagine the boost in the performance that results, from not having to go
back to the SQL server.

a.aspx
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<html>
<script language="C#" runat="server">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (52 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

void Page_Load(Object Src, EventArgs E )


{
if(!IsPostBack)
{
xyz();
}
}
void abc(Object sender, EventArgs E) {
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("c.xml"),FileMode.Open, FileAccess.Read, FileShare.
ReadWrite);
StreamReader r = new StreamReader(fs);
ds.ReadXml(r);
fs.Close();
DataRow n = ds.Tables[0].NewRow();
n["auid"] = i.Text;
n["name"] = name.Text;
ds.Tables[0].Rows.Add(n);
fs = new FileStream(Server.MapPath("c.xml"), FileMode.Create, FileAccess.ReadWrite, FileShare.
ReadWrite);
TextWriter w = new StreamWriter(fs);
w = TextWriter.Synchronized(w);
ds.WriteXml(w);
w.Close();
xyz();
}
void pqr(Object sender, EventArgs e)
{
xyz();
}
void xyz()
{
DataView s = (DataView)Cache["yyy"];
if(s == null)
{
DataSet ds = new DataSet();
FileStream fs = new FileStream(Server.MapPath("c.xml"), FileMode.Open,FileAccess.Read);
StreamReader r = new StreamReader(fs);
ds.ReadXml(r);
fs.Close();
s = new DataView(ds.Tables[0]);
Cache.Insert("yyy", s, new CacheDependency(Server.MapPath("c.xml")));
c.Text = "Dataset created explicitly";
}
else
{
c.Text = "Dataset retrieved from cache";
}
l.DataSource = s;
l.DataBind();
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (53 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</script>
<body>
<form runat="server">
<ASP:DataGrid id="l" runat="server"/>
Id:
<ASP:TextBox id=i Text="1" runat=server/>
Last Name:
<ASP:TextBox id=name Text="Mukhi" runat=server/>
<asp:button Text="Add " OnClick="abc" runat=server/>
<asp:button Text="Refresh " OnClick="pqr" runat=server/>
<asp:label id="c" runat="server"/></i></p>
</form>
</body>
</html>

c.xml
<DocumentElement>
<xsd:schema id="DocumentElement" targetNamespace="" xmlns="" xmlns:xsd="http://www.w3.
org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="Table">
<xsd:complexType>
<xsd:all>
<xsd:element name="auid" type="xsd:string"/>
<xsd:element name="name" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="DocumentElement" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="Table"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<Table>
<auid>1</auid>
<name>vijay</name>
</Table>
</DocumentElement>

Output when clicked on Refresh

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (54 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

This program shows us how we can update the data in the cache, if a file has been updated.

Loading a.aspx in the browser, results in a call to the function xyz. This function can be called
from multiple places. It simply populates the DataGrid control, which has the id of l, with data
from the file c.xml. The xml file must reside in the same directory as a.aspx.

Initially, verification is done to confirm the existence of yyy in the Cache object. The first time
around, it will obviously not be present, and hence, the 'if' statement gets called.

Within the 'if' block, a new DataSet object is created. Using the static function MapPath from
the Server class, the full physical path name of c.xml is retrieved. The xml file is then read, and
a new DataView object named 's' is created.

We not only use the Insert function to associate the words yyy with the DataView object 's', but
also to create a CacheDependency object, whose constructor is passed a full path or a file
named c.xml. Thus, whenever this file is modified, the Cache object will remove yyy from the
cache, and its return value will be null. All this happens internally, without any interference
from our side.

Each time we click on the refresh button, the function pqr is called. This function in turn calls
the function xyz. The function xyz notices that the cache object has a valid DataView object,
and hence, it does not read the xml file. The label displays whether we have picked up anything
from the cache or not.

When we click on the add button, a record gets added to the xml file through the function abc.

To add a record, a new DataSet is created, followed by a FileStream. Then the XML data is read.
The file is closed thereafter. In addition to this, a DataRow object having two fields named auid
and name, is created and filled up, using the indexer n. The TextWriter class writes this newly
created row to the file. The function xyz, when called, observes that the xml file has changed.
Hence, it reloads the file. Thus, the new data gets displayed.
Any change to the XML file invalidates the yyy object, and hence, it is removed from the cache.

ASP.Net actually supports three types of caching:

• The Scavenging Method: Scavenging is a process that vultures are adept at. Items that
are not needed must be removed. We cannot let the cache grow too big, since on doing so,
we would use up memory, which is a valuable resource. Thus, items that are not accessed
very often, are removed from the cache. We can associate a cost with each item, thus,
providing the framework with a criterion to decide as to which items are to be removed.

• The Expiration Method: This method has already been explained earlier. In this method,
the lifetime of an item is explicitly stated. We can either state an explicit value, such as
midnight today, or a number that is relative to the time when the item was last accessed,
such as 10 minutes after the item was last accessed. There are innumerable choices
available.

• The File and Key Dependencies Method: If a dependency changes, the item in the cache

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (55 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

is invalidated and removed. The above example invalidates the cache item yyy, when the
xml file changes. Thus, the moment the file changes, its data is retrieved again, and the
Dataview is updated with the new changes. The Insert function can take many more
parameters that specify the time duration for which the item is to remain in the cache. This
can be specified as an absolute time or a time period relative to the instance when it was
last accessed.

Web.Config
Let us go deeper into the world of configuration. As mentioned a couple of times in the past, the
XML file config.web stores all the details of how the web server will behave.

a.aspx
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script language="C#" runat="server">
void Page_Load(Object Src, EventArgs E )
{
String d = (String) ((NameValueCollection) Context.GetConfig("system.web/dsnstore"))["yyy"];
SqlConnection c = new SqlConnection(d);
SqlDataAdapter ma = new SqlDataAdapter();
ma.SelectCommand = new SqlCommand();
ma.SelectCommand.Connection = new SqlConnection(d);
ma.SelectCommand.CommandText = "select * from Products";
DataSet ds = new DataSet();
ma.Fill(ds, "zzz");
l.DataSource=new DataView(ds.Tables[0]);
l.DataBind();
}
</script>
<body>
<ASP:DataGrid id="l" runat="server"/>
</body>
</html>

web.config
<configuration>
<configSections>
<sectionGroup name="system.web">
<section name="dsnstore" type="System.Configuration.NameValueSectionHandler,System" />
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true" />
<dsnstore>
<add key="yyy" value="server=(local)\NetSDK;database=northwind;Trusted_Connection=yes" />
</dsnstore>
</system.web>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (56 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

</configuration>

In the above example, we are simply retrieving data from a database and putting it into a
DataGrid named l. The difference here is that we have used a string 's' as the connection string
and have not hard coded the values, unlike what we had done earlier.

This string 's' gets its value from a function named GetConfig, which in turn, uses the ‘system.
web/dsnstore’. If you look at web.config, it has a section name initialized to dsnstore within the
configSections tags. Also, the name of the class that will handle this section, System.
Configuration.NameValueSectionHandler is specified.

The same tag called dsnstore is used to add a key named yyy. The value assigned to this key is
our connection string that refers to the northwind database on SQLServer. The indexer is then
used to access the value of this key.

The web.config file stores strings that can be retrieved by the programmer later. Those items
that are used by everyone, can be stored in a configuration file. If there is a change in any of
these items, it has to be incorporated in just one place i.e. the configuration file, and thereafter,
the change is displayed to everyone who accesses the page thereafter.

Security

We had considered explaining the security concepts to you with a slightly different approach.
There are a large number of samples available from Microsoft called the Quickstart tutorials.
We have borrowed a considerably large number of these samples from there, and have also
added a sizeable number of our own. By default, all the samples that run, are written in
VBscript and not in C#.

To be able to execute the first security example, we need to write the following URL:

http://localhost/quickstart/aspplus/samples/security/WindowsAuth/CS/windowsauth.aspx

Using Windows Authentication

If you search for a directory called quickstart, you will not be able to trace it. This is because
quickstart is a virtual directory that begins at

C:\Program Files\Microsoft.Net\FrameworkSDK\Samples\QuickStart.

You can verify this by clicking on Start, Programs, Administrative Tools, Internet Services
Manager and then, on the Default web site. If you click on the plus sign for this option, you will
see the word 'quickstart' listed there. Thus, the file windowsauth.aspx starts at the following
location:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (57 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

C:\PROGRA~1\Microsoft.NET\FrameworkSDK\Samples\quickstart
\aspplus\samples\security\windowsauth\cs

Now that we are aware of where our code resides, we will move into this sub-directory and copy
the file windowsauth.aspx as a1.aspx. This will keep the original code intact, and at the same
time, allow us to add our own file. Enter the program given below and provide the URL as
follows:

http://localhost/quickstart/aspplus/samples/security/WindowsAuth/CS/a.aspx

a.apsx
<html>
<script language="C#" runat=server>
void Page_Load(Object Src, EventArgs E )
{
Response.Write(User.Identity.Name + " " + User.Identity.AuthenticationType);
}
</script>
<body>
</body>
</html>

Output
VMCI\Administrator Negotiate

ASP+ needs to identify who we are. This is the first level of security in ASP.Net. We logged into
Windows 2000 as a user called Administrator. Our computer was named as VMCI. Hence, the
above output was displayed.

Next, we go one sub-directory higher and then move down into the sub-directory cookieauth
\cs. Here, we copy the file default.aspx as a.aspx, and write the URL in the browser window as
follows:

http://localhost/quickstart/aspplus/samples/security/CookieAuth/CS/a.aspx

a.aspx
<%@ Import Namespace="System.Web.Security " %>
<html>
<script language="C#" runat=server>
void Page_Load(Object Src, EventArgs E )
{
Response.Write("Hell, " + User.Identity.Name);
}
void abc(Object sender, EventArgs E)
{
FormsAuthentication.SignOut();
Response.Redirect("login.aspx");
}
</script>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (58 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

<body>
<form runat=server>
<asp:button text="Signout" OnClick="abc" runat=server/>
</form>
</body>
</html>

Output

Instead of the file a.aspx being displayed, we are redirected to a file called login.aspx. How did
this happen?

The URL that gets generated in the browser's address bar, is as follows:

http://localhost/quickstart/aspplus/samples/security/CookieAuth/CS/login.aspx?ReturnUrl=http%3a%
2f%2flocalhost%2fquickstart%2faspplus
%2fsamples%2fsecurity%2fCookieAuth%2fCS%2fa.aspx

All characters such as a / symbol, get converted to the ASCII codes displayed in hex. Here, %2f
stands for a / symbol. The parameter ReturnUrl has a value of a.aspx.

The URL changes due to the settings present in the web.config file in the same Directory. These
are definitely worth taking a look at.

web.config
<configuration>
<system.web>
<authentication mode="Forms">
<forms name=".ASPXUSERDEMO" loginUrl="login.aspx" protection="All" timeout="60" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />
</system.web> </configuration>
In this file, the authentication tag has a mode that involves the use of Forms. The Form tag
specifies a file called login.aspx. We have not been authenticated by the framework to load any
file, unless we login. Hence, the file login.aspx is displayed. Thus, any aspx file in this sub-
directory will not get loaded, unless the user logs in through the login.aspx file. We shall now

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (59 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

explore the contents of this file.

Login.aspx
<%@ Import Namespace="System.Web.Security " %>
<html>
<script language="C#" runat=server>
void abc(Object sender, EventArgs E)
{
if ((name.Value == "vijay") && (pwd.Value == "mukhi"))
{
FormsAuthentication.RedirectFromLoginPage (name.Value,Cookie.Checked);
}
else
{
l.Text = "Invalid password mutt Please try again";
}
}
</script>
<body>
<form runat=server>
User Name:
<input id="name" type="text" runat=server/>
<p>
Password:
<input id="pwd" type=password runat=server/>
<p>
<ASP:RequiredFieldValidator ControlToValidate="pwd" Display="Static" ErrorMessage="*" runat=server/
></td>
Persistent Cookie:
<ASP:CheckBox id=Cookie runat="server" />
<p>
<asp:button text="Login" OnClick="abc" runat=server/>
<asp:Label id="l" ForeColor="red" Font-Name="Verdana" Font-Size="10" runat=server />
</form>
</body> </html>
In login.aspx, we have a textbox called name, where the user is expected to type in his name.
Then, an input box called pwd, of the type password, is provided. This ensures that the
password keyed in the textbox, is displayed as a series of asterix. If the user does not enter
anything, the required field validator gets activated and displays an asterix.

If you click on the button labeled 'Login', the function abc gets called, which determines
whether the name is 'vijay' and password is 'mukhi', or otherwise. If it is, a static function
called RedirectFromLoginPage from the FormsAuthentication.class is called, which loads the
original file of a.aspx. Moreover, a cookie with the funny name ..ASPXUSERDEMO, is also sent
across. This name can be seen in the file config.web. You can verify this by changing the cookie
options to the 'prompt' mode.

The second parameter to the RedirectFromLoginPage function decides whether the cookie
should be made persistent, i.e., saved on the user's hard disk, so that it can be sent across
each time. The default type of cookie is a session cookie.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (60 of 61)2/13/2007 4:54:45 PM


CGI Programming - ASP.NET - Beta2

Thereafter, we reach the original file named a.aspx. When we click on the button in this file, the
function abc gets called again. This function in turn, calls the SignOut function from the class
FormsAuthentication which kills the cookie. Hence, we are redirected back to the login page.

Thus, implementation of security issues is much more straightforward and clear-cut in ASP.
NET. If we have not been authenticated, a default file gets called. On valid authentication, we
are directed back to the original file that we had requested for. Once the user is authenticated,
a set of rules can be applied to restrict accessibility to certain features. This also helps in
customization of the interface.

In the web.config file, the authorization tag can be used with the word 'deny', initialized to those
users who are to be permanently denied access. The ? value signifies anonymous users, and it
forbids all anonymous users from logging into the site.

web.config
<configuration>
<system.web>
<authentication mode="Forms">
<forms name=".ASPXUSERDEMO" loginUrl="login.aspx" protection="All" timeout="60" />
</authentication>
<authorization>
<deny users="vijay" />
</authorization>
<globalization requestEncoding="UTF-8" responseEncoding="UTF-8" />
</system.web>
</configuration>

In the authorization tag, if the 'deny users' is initialized to vijay, then any user who logs in as
'vijay'is denied access. Thus, 'vijay' is not permitted to view a.aspx. There is no way to bypass
the login page, even though we have keyed in the right password. Thus, we first need to get
authenticated and thereafter, we need to have the relevant authorization to put our intentions
into practice.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap7.htm (61 of 61)2/13/2007 4:54:45 PM


Web Services - ASP.NET - Beta2

-8-

Web Services
The .Net framework recognizes and acknowledges files with an extension of asmx as a Web
Service. Therefore, in order to cater to the prerequisites of .Net framework, we design a file
called a.asmx, with a class named zzz.

a.asmx
public class zzz
{
public int abc(int i)
{
return i*2;
}
}

Output
Parser Error Message: The page must have a <%@ webservice class="MyNamespace.MyClass" ... %>
directive

The class zzz has a function called abc, that accepts an int as a parameter and returns a value,
after multiplying the parameter by 2. No class can be more uncomplicated and clear-cut than
the one we have written. Yet, we get an error when the file is loaded as http://localhost/a.
asmx in the browser. This is because, a Web service is a special file, and the framework is
required to handle this exceptional file, a little differently. So, we need to supplement this file by
making some more additions, as shown below.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
public class zzz
{
public int abc(int i)
{
return i*2;
}
}

In the previous program, since the directive named WebService was missing, an error was
reported. The directive WebService is followed by the name of the language which has been
initialized to C#, because we will be writing the Web Service, using the C# programming
language. An asmx file may contain a numerous classes, but only one of them represents the
Web Service. Thus, the class property is made equal to zzz. We spot the following output in the

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (1 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

browser:

Output
zzz WebService

zzz
The following operations are supported. For a formal definition, please review the Service Description.

----------------------------------------------------------------------------
This web service is using http://tempuri.org/ as its default namespace.
Recommendation: Change the default namespace before the web service is made public.
Each web service needs a unique namespace to identify it so that client applications can distinguish it
from other ..............
......................
For more details on XML namespaces, see the W3C recommendation on Namespaces in XML.
For more details on WSDL, see the WSDL Specification.
For more details on URIs, see RFC 2396.

The class zzz is now acknowledged as a Web Service. For the moment, there are no web
methods exposed by our class. A Web Service permits others to execute code in our class. We
want the function abc to be called with a number, so that it can majestically return the
numbers twice over, than it had been served with.

No web methods are shown, since at this point in time, the function abc is inaccessible.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
using System.Web.Services;
public class zzz
{
[WebMethod]
public int abc(int i)
{
return i*2; } }

Output
zzz

The following operations are supported. For a formal definition, please review the Service Description.

abc

Click on abc and the screen changes to accept values in a text box

Click here for a complete list of operations.

abc

Test
To test, click the 'Invoke' button.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (2 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

Parameter Value
i:

SOAP

The following is a sample SOAP request and response. The placeholders shown need to be
replaced with actual values.

POST /a.asmx HTTP/1.1


Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/abc"

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.
w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<abc xmlns="http://tempuri.org/">
<i>int</i>
</abc>
</soap:Body>
</soap:Envelope>
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.
w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<abcResponse xmlns="http://tempuri.org/">
<abcResult>int</abcResult>
</abcResponse>
</soap:Body>
</soap:Envelope>

HTTP GET
The following is a sample HTTP GET request and response. The placeholders shown need to be
replaced with actual values.

GET /a.asmx/abc?i=string HTTP/1.1


Host: localhost

HTTP/1.1 200 OK

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (3 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

Content-Type: text/xml; charset=utf-8


Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<int xmlns="http://tempuri.org/">int</int>

HTTP POST
The following is a sample HTTP POST request and response. The placeholders shown need to be
replaced with actual values.

POST /a.asmx/abc HTTP/1.1


Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length

i=string
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>


<int xmlns="http://tempuri.org/">int</int>

To convert a function into a web method, we have to add an attribute named WebMethod from
the namespace System.Web.Services. When the asmx file is now loaded, the screen is flashed
with the name of the function, its parameter names and their data types. In addition, we get an
input box to enter a number. This number becomes the value of the parameter i. When we
keyed in the number 12 and clicked on the Invoke button, to our utter amazement, we saw the
number 24 displayed, as shown below.

Output
<?xml version="1.0" encoding="utf-8" ?>
<int xmlns="http://tempuri.org/">24</int>

This happens to be an xml file. Since the return value of our function is an int, the number 24
is enclosed within the int tag. The html file that we had taken notice of, and had attended to,
was honestly, all smokes and mirrors.

Whenever the framework stumbles upon a file with an asmx extension, it treats it very
differently from an aspx file. It finds out all the functions in the Web Service class that are
tagged with an attribute of WebMethod. It then creates an HTML file. Clicking on the invoke
button results in the execution of a URL by passing it parameters.

Next, we are interested in calling the function abc, with a parameter i, which has a value of 23.
However, when we actually call the function abc, which has to be summoned from the Web
Service zzz in the file a.asmx, the following URL has to be entered in the IE address bar: http://
localhost/a.asmx/abc?i=23

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (4 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

The output window displays the following:

Output
<?xml version="1.0" ?>
<int xmlns="http://tempuri.org/">46</int>

Thus, if we are aware about the existence of a Web Service and are responsive towards its nuts
and bolts, we can easily call the code from it, using a URL. The parameters to the functions are
passed as HTML parameters. Assuming that we had two parameters named i and j in the
function abc, we would enter the URL as follows: http://localhost/a.asmx/abc?i=12&j=10.

On placing an error in the above C# program, we noticed that our Web Service is actually a dll.
No extra code is added to the Web Service file, unlike in a control. Also, a Web Service does not
derive from any other class. A Web Service internally uses SOAP, or the Simple Object Access
Protocol, to bring this magic into being!

One more thing that you should be well conversant with, is the Service Description (WSDL file).
If you click on the Service Description link, you will see an XML file that has obviously not been
written by us. Let us now try to appreciate, what goes into this file.

WSDL file
<?xml version="1.0" encoding="utf-8" ?>
- <definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.
org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tm="http://microsoft.
com/wsdl/mime/textMatching/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:
soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="http://tempuri.org/"
targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">
- <types>
- <s:schema attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
- <s:element name="abc">
- <s:complexType>
- <s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="i" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
- <s:element name="abcResponse">
- <s:complexType>
- <s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="abcResult" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="int" type="s:int" />
</s:schema>
</types>
- <message name="abcSoapIn">
<part name="parameters" element="s0:abc" />
</message>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (5 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

- <message name="abcSoapOut">
<part name="parameters" element="s0:abcResponse" />
</message>
- <message name="abcHttpGetIn">
<part name="i" type="s:string" />
</message>
- <message name="abcHttpGetOut">
<part name="Body" element="s0:int" />
</message>
- <message name="abcHttpPostIn">
<part name="i" type="s:string" />
</message>
- <message name="abcHttpPostOut">
<part name="Body" element="s0:int" />
</message>
- <portType name="zzzSoap">
- <operation name="abc">
<input message="s0:abcSoapIn" />
<output message="s0:abcSoapOut" />
</operation>
</portType>
- <portType name="zzzHttpGet">
- <operation name="abc">
<input message="s0:abcHttpGetIn" />
<output message="s0:abcHttpGetOut" />
</operation>
</portType>
- <portType name="zzzHttpPost">
- <operation name="abc">
<input message="s0:abcHttpPostIn" />
<output message="s0:abcHttpPostOut" />
</operation>
</portType>
- <binding name="zzzSoap" type="s0:zzzSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
- <operation name="abc">
<soap:operation soapAction="http://tempuri.org/abc" style="document" />
- <input>
<soap:body use="literal" />
</input>
- <output>
<soap:body use="literal" />
</output>
</operation>
</binding>
- <binding name="zzzHttpGet" type="s0:zzzHttpGet">
<http:binding verb="GET" />
- <operation name="abc">
<http:operation location="/abc" />
- <input>
<http:urlEncoded />

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (6 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

</input>
- <output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
- <binding name="zzzHttpPost" type="s0:zzzHttpPost">
<http:binding verb="POST" />
- <operation name="abc">
<http:operation location="/abc" />
- <input>
<mime:content type="application/x-www-form-urlencoded" />
</input>
- <output>
<mime:mimeXml part="Body" />
</output>
</operation>
</binding>
- <service name="zzz">
- <port name="zzzSoap" binding="s0:zzzSoap">
<soap:address location="http://localhost/a.asmx" />
</port>
- <port name="zzzHttpGet" binding="s0:zzzHttpGet">
<http:address location="http://localhost/a.asmx" />
</port>
- <port name="zzzHttpPost" binding="s0:zzzHttpPost">
<http:address location="http://localhost/a.asmx" />
</port>
</service>
</definitions>

This XML file gives us all the details about the Web Service. It represents the Web Service, but
without the code.

Let us explain the how's and why's of it.


A WSDL document defines services as collections of network endpoints, or ports. The tag called
definition describes the Web Service, but in a non-programming manner. All Web Services are
based on SOAP.

A Service Definition Language is made up of six major elements:

• types, which provides data type definitions used to describe the messages exchanged.
• message, which represents an abstract definition of the data being transmitted. A
message consists of logical parts, each of which is associated with a definition within some
type system.
• portType, which is a set of abstract operations. Each operation refers to an input
message and output messages.
• binding, which specifies concrete protocol and data format specifications for the
operations and messages defined by a particular portType.
• port, which specifies an address for a binding, thus defining a single communication

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (7 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

endpoint.
• service, which is used to aggregate a set of related ports.

The WSDL file that has been generated, helps us to figure out the number of functions in the
Web Service. The parameters, their data types and the return value are also specified along with
the function names. This description is sufficient to execute a function. Observe that there is no
sign of any code in the asmx file. Thus, the WSDL file is not concerned about whether the code
is in Java or C# or in any other language. Since the file is machine generated, we will not spend
more time deciphering it.

Let us now summon the Web Service from our program, which is written in C#.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
using System.Web.Services;
public class zzz
{
[WebMethod]
public int abc(int i)
{
return i*2;
}
}

Firstly, we write the following URL and click on the Service Description link, and then copy
whatever file is displayed in the file named, a.wsdl in the c:\inetpub\wwwroot\bin sub-
directory.

We now want some program to generate a C# program, which can act like our Web Service. The
program that we shall be running, using the command laid down below, is called
WebServiceUtil. Very soon, we shall be explaining as to what the various options in this
command signify.

>wsdl.exe /l:CS /n:nnn a.wsdl

This will create a file called zzz.cs, since our Web Service class was called zzz. /n:nnn adds
namespace nnn to the class. In case you receive any errors, you should ensure that the first
line, <?xml version="1.0" ?>, begins at the first column, and the file thereafter starts with a tag
on every line. Also if you have selected and copied the file from your browser, you will have to
remove the ‘-’ sign preceeding every line.

The contents of zzz.cs are as follows:

zzz.cs
//--------------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Runtime Version: 1.0.2914.16
//

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (8 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

// Changes to this file may cause incorrect behavior and will


// be lost if the code is regenerated.
// </autogenerated>
//--------------------------------------------------------------------------
//
// This source code was auto-generated by wsdl, Version=1.0.2914.16.
namespace nnn {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.Web.Services;

[System.Web.Services.WebServiceBindingAttribute(Name="zzzSoap", Namespace="http://tempuri.
org/")]
public class zzz : System.Web.Services.Protocols.SoapHttpClientProtocol {

[System.Diagnostics.DebuggerStepThroughAttribute()]
public zzz() {
this.Url = "http://localhost/a.asmx";
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/abc",
Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.
Protocols.SoapParameterStyle.Wrapped)]
public int abc(int i) {
object[] results = this.Invoke("abc", new object[] {
i});
return ((int)(results[0]));
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
public System.IAsyncResult Beginabc(int i, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("abc", new object[] {
i}, callback, asyncState);
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
public int Endabc(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((int)(results[0]));
}
}
}
This program has been generated by the wsdl program. The name of the class is given as zzz,
which is derived from System.Web.Services.Protocols.SoapHttpClientProtocol. The function abc
accepts one parameter i.e. int i. Before we go on to explain how this code gets generated, let us
first convert this machine generated code into a library zzz.dll, with the help of the following csc
command:

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (9 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

>csc /t:library /r:system.web.services.dll zzz.cs

Next, we have to call code from our Web Service. For this, we create a file a.aspx in the inetpub/
wwwroot sub-directory.

a.aspx
<%@ Import Namespace="nnn" %>
<%@ language=C# %>
<form action="a.aspx" method="post" runat="server">
<script language="C#" runat=server>
void abc(Object a1, EventArgs e)
{
zzz a = new zzz();
int i = a.abc(Int32.Parse(aaa.Text));
Response.Write(i.ToString());
}
</script>
<asp:textbox id="aaa" runat="server"/>
<asp:button type=submit text="Click" OnClick="abc" runat="server"/>
</form>

The framework looks into the bin sub-directory for the code of the objects. On sighting it, the
code gets executed.

The above program will generate a compilation error, if zzz.dll is not present in the bin sub-
directory or if there are more dlls in the directory. This is because, the code for the class zzz
resides in the zzz.dll, moreover, the compiler is not informed about the location and the name of
the dll name. This can be done using the /R: option.

To solve the mystery of locating the dll, we take the assistance of the web.config file.

web.config
<configuration>
<system.web>
<compilation debug="false">
<assemblies>
<add assembly="zzz"/>
</assemblies>
</compilation>
</system.web>
</configuration>

To change the default behavior of anything in the ASP.Net world, we have to turn to the
configuration file. The 'add assembly' option adds the dll that has been assigned to it, to the csc
compiler. To be precise, it appends the dll with the /r: option to the compiler, while compiling
any cs file. This assembly can be present anywhere on our hard disk. The /bin sub-directory is
a special directory, which is checked only for our business objects. This is how the framework
can be customized to work with our files.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (10 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

Now, if you load the aspx file using http://localhost/a.aspx, you will notice a button and a
textbox. If you type in the number 12 and click on the button, the abc function in the aspx file
will be called. In the function abc, a new zzz object called a, is created, and the function abc is
called off it. This function is supplied with a parameter, which is the text entered in the
TextBox, after converting it into an int. The return value of this function is displayed through
the Write function. Any number that we enter is multiplied by 2, and then the value is
returned.

Note that the code for the multiplication is not present in the zzz class. To further prove this
point, we merely open the asmx file and multiply by 3, instead of 2. Now, if we click on the
button, we will observe the numbers being multiplied by 3. Are you feeling perplexed already? If
so, it would be sensible for you to revise the above text, before proceeding any further.

We are doing the following to prove to you that, you can easily change the way ASP+ looks at
the world.

The VB sample in the documentation derives from the WebService class, while, the C# sample
does not.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
using System;
using System.Web.Services;
public enum yyy
{
b1 = 10,
b2 = 20
}
public class xxx
{
public int i1;
public double d1;
}
public class zzz
{
[WebMethod]
public String a1()
{
return "vijay";
}
[WebMethod]
public int[] a2()
{
int[] a = new int[2];
a[0] = 10;
a[1] = 20;
return a;
}
[WebMethod]

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (11 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

public yyy a3()


{
return yyy.b1;
}
[WebMethod]
public xxx a4()
{
xxx x = new xxx();
x.i1=10;
x.d1 = 10.1;
return x;
}
[WebMethod]
public xxx[] a5()
{
xxx [] x = new xxx[2];
x[0] = new xxx();
x[0].i1=3;
x[0].d1=3.1;
x[1] = new xxx();
x[1].i1=9;
x[1].d1 = 9.1;
return x;
}
}

We have created 5 functions named a1 to a5 in our Web Service. The display order may not be
in the order of creation. The point we are making here is that, we are allowed to return any data
types that we like. Let us start by clicking on each function and understanding the output. The
first function, a1, simply returns a string.

Output
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://tempuri.org/">vijay</string>

The value 'vijay' is placed within a tag called string, since our function returns a string. The
next function, a2, returns an array of ints.

Output
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.
org/2001/XMLSchema" xmlns="http://tempuri.org/">
<int>10</int>
<int>20</int>
</ArrayOfInt>

The individual ints are tagged with the int tag, and the entire array is enclosed in an ArrayOfInt
tag. Thus, we can also return an array of any data type.

The next click will call function a3, which returns the value of an enum. An enum is a class

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (12 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

that contains names that represent values.

Output
<?xml version="1.0" encoding="utf-8" ?>
<yyy xmlns="http://tempuri.org/">b1</yyy>

The enum member that is returned, is placed in a tag, that is the name of the enum class yyy.

Function a4 returns an object of a class xxx. This class has two members, i1 and d1. Hence,
the output is displayed as follows:

Output
<?xml version="1.0" encoding="utf-8" ?>
<xxx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/
XMLSchema" xmlns="http://tempuri.org/">
<i1>10</i1>
<d1>10.1</d1>
</xxx>

The last function, a5 is like the one above, but it returns an array of xxx objects.

Output
<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfXxx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.
org/2001/XMLSchema" xmlns="http://tempuri.org/">
<xxx>
<i1>3</i1>
<d1>3.1</d1>
</xxx>
<xxx>
<i1>9</i1>
<d1>9.1</d1>
</xxx>
</ArrayOfXxx>

The tag, ArrayOfXxx encloses the entire output. Each member of the array is placed within the
tag xxx, and the individual members are placed within their own tags. By making use of a Web
Service, we are at a liberty to pass any data types, as return values or as parameters. Thus,
there are no restrictions. We will leave it as an exercise for you to run the same Web Service
from an aspx file.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web.Services;
public class zzz
{
[WebMethod]

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (13 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

public DataSet abc()


{
SqlConnection c = new SqlConnection("server=localhost;uid=sa;pwd=;database=NorthWind");
SqlDataAdapter co = new SqlDataAdapter("select productid,productname from Products where
productid='1'",c);
SqlDataAdapter co1 = new SqlDataAdapter("select customerid,companyname from Customers where
customerid='BOLID'", c);
DataSet ds = new DataSet();
co.Fill(ds, "zzz");
co1.Fill(ds, "yyy");
return ds;
}
}

Output
<?xml version="1.0" encoding="utf-8" ?>
<DataSet xmlns="http://tempuri.org/">
<xsd:schema id="NewDataSet" targetNamespace="" xmlns="" xmlns:xsd="http://www.w3.org/2001/
XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="NewDataSet" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="zzz">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productid" type="xsd:int" minOccurs="0" />
<xsd:element name="productname" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="yyy">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="customerid" type="xsd:string" minOccurs="0" />
<xsd:element name="companyname" type="xsd:string" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-
microsoft-com:xml-diffgram-v1">
<NewDataSet xmlns="">
<zzz diffgr:id="zzz1" msdata:rowOrder="0">
<productid>1</productid>
<productname>Chai</productname>
</zzz>
<yyy diffgr:id="yyy1" msdata:rowOrder="0">
<customerid>BOLID</customerid>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (14 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

<companyname>Bólido Comidas preparadas</companyname>


</yyy>
</NewDataSet>
</diffgr:diffgram>
</DataSet>

One thing that is very evident is that, Microsoft is in love with XML and finds it irresistable.
Hence, we see XML popping out of everywhere.

In the above Web Service, we are connecting to the database NorthWind and creating two SQL
statements that will return one record each, from two separate tables. These select statements
are added to our dataset object and the object is then returned. The output is in the form of an
appealingly formatted XML file.

Let us try to understand this file now.


As usual, the XML file starts with the xml version number. It is then followed by a tag called
DataSet. DataSet informs us that the data given within it is from a database. The first dataset
with the name zzz, becomes the name of our element. This is succeeded by the field names or
the schema.

The same procedure is repeated for the second table in the data set. Then, we have a tag called
NewDataSet, followed by the name of the first dataset zzz, in a tag form. Then, we have the
values from the database enclosed by the field names, once again in tags. The same process is
reiterated for the other table too.

a.asmx
<%@ WebService Language="C#" Class="zzz" %>
using System;
using System.Web.Services;
public class zzz : WebService
{
[WebMethod(EnableSession=true)]
public String abc()
{
if (Session["aa"] == null)
{
Session["aa"] = 1;
}
else
{
Session["aa"] = ((int) Session["aa"]) + 1;
}
return "Session " + Session["aa"].ToString() + " times.";
}
[WebMethod(EnableSession=false)]
public String pqr()
{
if (Application["aa"] == null)
{
Application["aa"] = 1;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (15 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

}
else
{
Application["aa"] = ((int) Application["aa"]) + 1;
}
return "Application " + Application["aa"].ToString() + " times.";
}
}

In the above Web Service, we use two functions, named abc and pqr. The function abc has a
parameter called EnableSession=true, added to the WebMethod. This parameter switches on
the session tracking. The function pqr is similar to this, with an exception of the session
tracking being disabled. Thereafter, a Session Variable aa, is created in the function abc and an
Application Variable by the same name aa is created in pqr to store a value. This value is
incremented by 1, each time, and is finally returned as a string.

The Application and Session objects are framework intrinsic. To understand the above example,
select the 'prompt' radio button for the cookie. Now, each time we click on abc, a cookie is
received by the browser. However, such is not the case with the Application.

Now, close all instances of the browser and open only one browser copy. Rewrite the same URL
in the address bar and click on abc. The session count begins from 1. If you click on pqr, you
will notice that the application remembers its last count, which, it now increments by 1. By
disabling the session support for a particular web function, the web server now has less work to
do. Thus, the web method will be served up faster.

We first start with the WSDL file named a.wsdl in the c:\inetpub\wwwroot\bin sub-directory.

a.wsdl
<?xml version="1.0"?>
<definitions xmlns:s="http://www.w3.org/1999/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/
wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.
xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s0="http://
tempuri.org/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="http://tempuri.org/"
attributeFormDefault="qualified" elementFormDefault="qualified">
<s:element name="abc">
<s:complexType derivedBy="restriction"/>
</s:element>
<s:element name="abcResult">
<s:complexType derivedBy="restriction">
<s:all>
<s:element name="result" type="s:string" nullable="true"/>
</s:all>
</s:complexType>
</s:element>
<s:element name="string" type="s:string" nullable="true"/>
</s:schema>
</types>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (16 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

<message name="abcHttpGetIn"/>
<message name="abcHttpGetOut">
<part name="Body" element="s0:string"/>
</message>
<portType name="zzzHttpGet">
<operation name="abc">
<input message="s0:abcHttpGetIn"/>
<output message="s0:abcHttpGetOut"/>
</operation>
</portType>
<binding name="zzzHttpGet" type="s0:zzzHttpGet">
<http:binding verb="GET"/>
<operation name="abc">
<http:operation location="/a.html"/>
<input>
<http:urlEncoded/>
</input>
<output>
<text xmlns="http://microsoft.com/wsdl/mime/textMatching/">
<match name='Title' pattern='TITLE&gt;(.*?)&lt;'/>
<match name='Vijay' pattern='&gt;(.*?)&lt;'/>
</text>
</output>
</operation>
</binding>
<service name="zzz">
<port name="zzzHttpGet" binding="s0:zzzHttpGet">
<http:address location="http://localhost" />
</port>
</service>
</definitions>

a.html
<HTML>
<HEAD>
<TITLE>Hello!</TITLE>
</HEAD>
<BODY>
<Vijay>Mukhi</Vijay>
</BODY>
</HTML>

We then run the following two commands:

>wsdl /l:CSharp /n:nnn a.wsdl

The above command creates a file called zzz.cs for us.

>csc /t:library zzz.cs

This creates a file by the name of zzz.dll in the bin sub directory.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (17 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

zzz.cs
//----------------------------------------------------------------------
// <autogenerated>
// This code was generated by a tool.
// Runtime Version: 1.0.2914.16
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </autogenerated>
//----------------------------------------------------------------------
//
// This source code was auto-generated by wsdl, Version=1.0.2914.16.
//
namespace nnn {
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.Web.Services;
public class zzz : System.Web.Services.Protocols.HttpGetClientProtocol {

[System.Diagnostics.DebuggerStepThroughAttribute()]
public zzz() {
this.Url = "http://localhost/a.html";
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Web.Services.Protocols.HttpMethodA
ttribute(typeof(System.Web.Services.Protocols.TextReturnReader), typeof(System.Web.Services.
Protocols.UrlParameterWriter))]
public abcMatches abc() {
return ((abcMatches)(this.Invoke("abc", (this.Url + "/QuickStart/aspplus/samples/services/
TextMatching/CS/MatchServer.html"), new object[0])));
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public System.IAsyncResult Beginabc(System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("abc", (this.Url + "/QuickStart/aspplus/samples/services/TextMatching/CS/
MatchServer.html"), new object[0], callback, asyncState);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
public abcMatches Endabc(System.IAsyncResult asyncResult)
{
return ((abcMatches)(this.EndInvoke(asyncResult)));
}
}
public class abcMatches {
[System.Web.Services.Protocols.MatchAttribute("TITLE>(.*?)<")]
public string Title;
[System.Web.Services.Protocols.MatchAttribute(">(.*?)<")]
public string Vijay;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (18 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

a.aspx
<%@ Import Namespace="nnn" %>
<html>
<script language="C#" runat="server">
public void Abc(Object Src, EventArgs E)
{
zzz m= new zzz();
abcMatches ma = m.abc();
ma.Vijay = "mukhi";
Response.Write(ma.Title + "." + ma.Vijay);
}
</script>
<body>
<form runat="server">
<input type="submit" OnServerClick="Abc" runat="server"/>
</form>
</body>
</html>

Output

After clicking on the button:


Hello!.mukhi

For the first time, we are creating a WSDL file manually.

<operation name="abc">
<http:operation location="/a.html"/>

We have a tag called operation that sets the name property to the function abc and the http
operation location is set to a file named a.html.

The text tag encloses two occurrence of another tag called 'match'. The name 'property' is set to
'Title' and 'Vijay', respectively. Moreover, a pattern or wild card is specified for each of them. It
specifies a certain pattern or a rule.

Now, the question that vexes our wits, is : From where will the value of 'Title' be obtained?

The value lies in the html file. The value of 'Hello', which is enclosed in the Title tag in the
HTML file, is picked up and assigned to the 'Title' variable in a.aspx. The same procedure is
followed for 'Vijay'. The tag name match is a special tag. It is available as a class called
abcMatches, in the aspx file.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (19 of 20)2/13/2007 4:54:21 PM


Web Services - ASP.NET - Beta2

In the .cs file that is generated, the constructor saves the URL in a variable called Url, for future
reference. The function abc returns an instance of the abcMatches class. The class abcMatches
created in zzz.cs, contains two instance variables, 'Title' and 'Vijay', with or without the pattern.

In the aspx file, when a button is clicked, the function Abc is called. In this function, we create
a new zzz instance, and then call the function abc from it. The output is an abcMatches object
which we store in an object named ma. Thereafter, the value in 'Vijay' is initialized to 'mukhi'.
Finally, both the variables are displayed, using the Write function. Thus, without creating any
asmx file, using our code, we have been able to read data within tags in an HTML file. We are
thus, doing things in a way that is a drastic departure from what we have been doing so far.

As we reiterated many times in the past, you are allowed to configure everything in case of ASP
+. The main web.config file informs the framework about the aspx file that handles a Web
Service, or a file with an asmx extension.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap8.htm (20 of 20)2/13/2007 4:54:21 PM


The Class Browser - ASP.NET - Beta2

-9-

The Class Browser


In this chapter, we have picked up one of the Microsoft samples called the Class Browser and
presented it to you in a straightforward and uncomplicated format, stripped of all its
convolutions.
This sample displays the following:

• all the namespaces


• the classes within each namespace
• the functions within each class
• the parameters of each function, and so on.

It is a considerably large program, and hence appears intimidating. As is customary, we shall


first partition this program into smaller programs and after deciphering every small part, we
shall coalesce them together to form one composite program.

At the end of this explanation, you would not only be in a position to write complex ASP.Net
code, but you would also have unraveled the mysteries of the Reflection API, which is a
technique used to determine the contents of a class.

We have retained the function names and variable names as given in the original code, with the
anticipation that sooner or later, you would be motivated enough to read the source code
written by the programmers at Microsoft. Our example will work as effectively, sans the comely
appearance of the original code.

Our first program displays a series of namespaces in a single column. These names are
displayed as hyperlinks. Before we dive headlong into the program, we first need to create the
file named web.config in the sub-directory c:\inetpub\wwwroot.

web.config
<configuration>
<configSections>
<sectionGroup name="system.web">
<section name="ClassBrowser" type="System.Configuration.NameValueSectionHandler,System"/>
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true"/>
<ClassBrowser>
<add key="Data Library" value="System.Data" />
<add key="ASP.NET Class Library" value="System.Web" />

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (1 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

<add key=".NET Framework class Library" value="mscorlib" />


</ClassBrowser>
</system.web>
</configuration>

a.aspx
<%@ Import NameSpace="System.Collections" %>
<%@ Import NameSpace="System.Collections.Specialized" %>
<%@ Import NameSpace="System.Reflection" %>
<html>
<head>
<script runat="server" language="C#">
ArrayList ModuleName = new ArrayList();
void Page_Load(Object Sender, EventArgs e)
{
NameValueCollection ConfigSettings;
ConfigSettings = (NameValueCollection)Context.GetConfig("system.web/ClassBrowser");
Response.Write(ConfigSettings.Count.ToString() + "<br>");
for (int i = 0; i < ConfigSettings.Count; i++)
{
Response.Write(ConfigSettings[i].ToString() + "<br>");
ModuleName.Add(ConfigSettings[i].ToString());
}
DisplayNamespaces();
}
void DisplayNamespaces()
{
ArrayList NameSpaceList = new ArrayList();
Hashtable NameSpaceHash = new Hashtable();
Response.Write(ModuleName.Count.ToString() + "<br>");
for (int y = 0; y < ModuleName.Count; y++)
{
Assembly a = Assembly.Load(ModuleName[y].ToString());
Module[] CorRuntime = a.GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
Response.Write(ModuleName[y].ToString() + " Modules:" + CorRuntime.Length.ToString() + " Type:" +
CorClasses.Length.ToString() + "<br>" );

for( int x=0; x < CorClasses.Length; x++ )


{
if ( CorClasses[x].Namespace != null )
{
if (!NameSpaceHash.ContainsKey(CorClasses[x].Namespace) && CorClasses[x].IsPublic)
{
NameSpaceHash.Add(CorClasses[x].Namespace,"");
NameSpaceList.Add(CorClasses[x].Namespace);
}
}
}
}
NameSpaceList.Sort();

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (2 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

Namespace1.DataSource = NameSpaceList;
Namespace1.DataBind();
}
</script>
</head>
<body>
<form runat="server">
<asp:DataList runat=server id="Namespace1" RepeatLayOut="flow">
<headertemplate>
Namespaces <br>
</headertemplate>
<itemtemplate>
<asp:HyperLink runat="server" text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?namespace="
+ Container.DataItem %> />
</itemtemplate>
<selecteditemtemplate>
<b><asp:HyperLink runat=server text=<%# Container.DataItem %>/></b>
</selecteditemtemplate>
</asp:DataList>
</form>
</body>
</html>

Output
3
System.Data
System.Web
mscorlib
3
System.Data Modules:1 Type:427
System.Web Modules:1 Type:663
mscorlib Modules:1 Type:1410

Namespaces

Microsoft.Win32
System
System.Collections
System.Configuration.Assemblies
System.Data
System.Data.Common
System.Data.OleDb
System.Data.SqlClient
System.Data.SqlTypes
System.Diagnostics
System.Diagnostics.SymbolStore
System.Globalization
System.IO
System.IO.IsolatedStorage
System.Reflection
System.Reflection.Emit

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (3 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

System.Resources
System.Runtime.CompilerServices
System.Runtime.CompilerServices.CSharp
System.Runtime.InteropServices
System.Runtime.InteropServices.Expando
System.Runtime.Remoting
System.Runtime.Remoting.Activation
System.Runtime.Remoting.Channels
System.Runtime.Remoting.Contexts
System.Runtime.Remoting.Lifetime
System.Runtime.Remoting.Messaging
System.Runtime.Remoting.Metadata
System.Runtime.Remoting.Metadata.W3cXsd2001
System.Runtime.Remoting.Proxies
System.Runtime.Remoting.Services
System.Runtime.Serialization
System.Runtime.Serialization.Formatters
System.Runtime.Serialization.Formatters.Binary
System.Security
System.Security.Cryptography
System.Security.Cryptography.X509Certificates
System.Security.Permissions
System.Security.Policy
System.Security.Principal
System.Text
System.Threading
System.Web
System.Web.Caching
System.Web.Configuration
System.Web.Handlers
System.Web.Hosting
System.Web.Mail
System.Web.Security
System.Web.SessionState
System.Web.UI
System.Web.UI.HtmlControls
System.Web.UI.WebControls
System.Web.Util
System.Xml

In the web.config file, within the configSections tags, we have added the name ClassBrowser
and specified the type of information that it will contain. Thereafter, all the data is inserted
within the ClassBrowser tag. The data within this tag is in the key-value pair format. It is
always a good idea to store all the data in a file, and then read this file at runtime. How we
exploit these key-value pairs, will be substantiated in the ASP+ program, whose explanation
follows.

In a.aspx, we commence with the usual suspect, the import namespaces command. An
instance variable named ModuleName of type ArrayList is initially created outside all the
functions. It is done to enable apportioning and sharing of this type ArrayList by all functions.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (4 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

In our example, this ArrayList will store strings.

In the function Page_Load that gets called at the server end, initially a variable named
ConfigSettings is created, which is an instance of a NameValueCollection class. A
NameValueCollection class stores the key-value pairs in an efficient way, so that retrieval of the
values is more rapid compared to an ArrayList. The principal advantage of this is that we can
effectively figure out whether a key-value pair entry already exists or not.

In the aspx file, it is our intention to access all the key-value pairs that are defined within the
ClassBrowser tag in the configuration file. The Context property in the Page class, returns an
HttpContext object. This Object has a function called GetConfig, whose only task is to return
the configuration of the name supplied as a parameter. The Object returned by this function is
then cast into a NameValueCollection.

In order to verify that the values have been actually placed, we display the Count member of the
NameValueCollection object. We see a value of 3, since we have 3 key-value pairs in the
ClassBrowser tag, within the web.config file.

<add key="Data Library" value="System.Data" />


<add key="ASP.NET Class Library" value="System.Web" />
<add key=".NET Framework class Library" value="mscorlib" />

To display the values contained in the web.config file, the for loop is used thrice, to iterate
through all the 3 values.

In the loop, we add the variable ModuleName to the ArrayList, with the values retrieved from
the web.config file. At the conclusion of the execution of the for loop, the ArrayList contains the
names of the 3 modules or dll's, whose details are to be displayed. These details include the
namespaces contained in them, the classes in the namespaces, et al. You may recall that, the
System.Web.dll contains all the Web classes that we have been working on.

The ArrayList now holds the three module names. Hence, the for loop iterates thrice. The class
called Assembly in the namespace System.Reflection has a static function named Load, which
accepts the name of a module and loads it into memory. The module gets loaded into the
address space of the program that is running this function, and returns an Assembly object
that represents the assembly. The function GetModules in the assembly class returns an array
of modules that are currently present in the assembly.

In our program, CorRuntime, which is an array variable of type Module, contains the modules
in the assembly. An assembly can easily contain more than one module, the first module being
the most significant, at the moment. This module object returns the number of types using the
GetTypes function. We store the types in the CorClasses array variable of type Types. Thus, the
hierarchy is assembly, modules and then, types.

The output very unambiguously conveys to us the following:

• System.Web assembly has 1 module and 663 types.


• System.Data assembly has 1 module and 427 types.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (5 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

• mscorlib has 1 module and 1410 types.

Within the for loop, we add one more for loop for every type, because we intend to include all
the unique namespaces from the assemblies in the ArrayList called NameSpaceList. The crucial
word in the above statement is 'unique'. The Add function in HashTable and ArrayList is used
to add the namespace in NameSpaceHash and the NameSpaceList object respectively. If we stop
at this stage, the list will contain duplicate Namespaces. Hence, we first employ the
ContainsKey function to check whether the namespace is already added or not. If it does, then
the namespaces are not added again. ContainsKey returns true if a name already exists. The
property IsPublic is employed to discover whether the type of the namespace is public or not.

Thus, namespaces marked public in the assembly, are added only if they don't already exist in
the list. The Type class has a member called Namespace that returns the namespace that the
type belongs to. A type is a synonym for a class or interface, etc.

The array list is then sorted and assigned to the DataSource member of the DataList called
Namespace1. Finally, using the DataBind function, a list of namespaces is displayed.

In our presentation logic, our DataList Namespace1 now contains a list of namespaces. The
template is executed for each item in the DataList. However, the template named
headertemplate is executed only once, thereby, showing the word Namespaces only once in the
window. It is the template named itemtemplate that is called thrice. The HyperLink tag displays
the namespaces like a URL. A URL is generated each time we click on a link. This URL is
decided by the NavigateUrl property and looks like http://localhost/a.aspx?
namespace=Microsoft.Win32 . This is so because the Container.DataItem contains the
namespace name that we clicked on, and the ?namespace is given as a literal. The Text
property displays the name of the namespace. Also, the items that we have selected in the past,
will be displayed as per the template named selecteditemtemplate. This template displays the
namespace name in a bold tag.

Let us proceed to the next example, where we propose to display a list of classes belonging to
the namespace.

a.aspx
<%@ Import NameSpace="System.Collections" %>
<%@ Import NameSpace="System.Reflection" %>
<html>
<head>
<script runat="server" language="C#">
public String SelectedNameSpace;
public ArrayList ModuleName = new ArrayList();
void Page_Load(Object Sender, EventArgs e)
{
NameValueCollection ConfigSettings = new NameValueCollection();
ConfigSettings = (NameValueCollection)Context.GetConfig("system.web/ClassBrowser");

for (int i = 0; i < ConfigSettings.Count; i++)


{
ModuleName.Add(ConfigSettings[i].ToString());

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (6 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

}
DisplayNamespaces();
if (Request.QueryString["namespace"] == null)
SelectedNameSpace = "System";
else
SelectedNameSpace = Request.QueryString["namespace"];
if (Request.QueryString["class"] != null)
DisplayClass(Request.QueryString["class"]);
else
DisplayClassList(SelectedNameSpace);
}
private void DisplayNamespaces()
{
ArrayList NameSpaceList = new ArrayList();
Hashtable NameSpaceHash = new Hashtable();
for (int y = 0; y < ModuleName.Count; y++) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for( int x=0; x < CorClasses.Length; x++ ) {
if ( CorClasses[x].Namespace != null )
{
if (!NameSpaceHash.ContainsKey(CorClasses[x].Namespace) && CorClasses[x].IsPublic ) {
NameSpaceHash.Add(CorClasses[x].Namespace,"");
NameSpaceList.Add(CorClasses[x].Namespace);
}
}
}
}
NameSpaceList.Sort();
Namespace1.DataSource = NameSpaceList;
Namespace1.DataBind();
}
private void DisplayClassList (String CurrentNameSpace)
{
ArrayList ClassList = new ArrayList();
ArrayList InterfaceList = new ArrayList();
for( int y=0; y < ModuleName.Count; y++ ) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for (int x=0; x < CorClasses.Length; x++ ) {
if ( CorClasses[x].Namespace == CurrentNameSpace && CorClasses[x].IsPublic) {
if ( CorClasses[x].IsInterface )
InterfaceList.Add(CorClasses[x].Name);
else
ClassList.Add(CorClasses[x].Name);
}
}
}
if (InterfaceList.Count > 0)
IHeader.Visible = true;
if (ClassList.Count > 0)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (7 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

CHeader.Visible = true;
ClassList.Sort();
Classes.DataSource = ClassList;
Classes.DataBind();
InterfaceList.Sort();
Interfaces.DataSource = InterfaceList;
Interfaces.DataBind();
}
private void DisplayClass(String className)
{
}
public String GetUrl(Hashtable table) {
return "a.aspx?namespace=" + table["Namespace"] + "&class=" + table["GetType"];
}
</script>
</head>
<body>
<form runat="server">
<table>
<td width=25% bgcolor=#CCCCFF valign=top >
<br>
<asp:DataList runat=server id="Namespace1" RepeatLayOut="flow">
<headertemplate>
Namespaces <br>
</headertemplate>
<itemtemplate>
<asp:HyperLink runat="server" text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?namespace="
+ Container.DataItem %> />
</itemtemplate>
<selecteditemtemplate>
<b>
<asp:HyperLink runat=server text=<%# Container.DataItem %>/>
</b>
</selecteditemtemplate>
</asp:DataList>
<p>
<td valign=top >
<span runat=server id="CHeader" visible="false" style="text-indent:8">
<b>
<font size=4 color=#000666>Classes in
<%= SelectedNameSpace %> </b>
</font>
</span>
<asp:DataList EnableViewState="false" runat=server id="Classes" RepeatColumns="3" Gridlines=None
borderstyle=none borderwidth=0 >
<itemtemplate>
<asp:HyperLink runat=server text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?namespace=" +
SelectedNameSpace + "&class=" + Container.DataItem %> />
</itemtemplate>
</asp:DataList>
<span runat=server id="IHeader" visible="false" style="text-indent:8">

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (8 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

<b>
<font size=4 color=#000666>Interfaces in <%= SelectedNameSpace %>
</font>
</b>
</span>
<asp:DataList EnableViewState="false" runat=server id="Interfaces" RepeatColumns="4" Gridlines=None
borderstyle=none borderwidth=0 >
<itemtemplate>
<asp:HyperLink runat=server text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?namespace=" +
SelectedNameSpace + "&class=" + Container.DataItem %>/>
</itemtemplate>
</asp:DataList>
</form>
</body>
</html>

In the above program, two panes are displayed. The pane on the left hand side has a list of
namespaces, while the pane on the right hand side contains a list of classes in the Systems
namespace. If you click on any of the namespaces, the classes displayed in the right pane will
change correspondingly. The URL generated reads as follows: http://localhost/a.aspx?
namespace=Microsoft.Win32.

We shall only explain the extra lines of code that have been added to the program, to display in
the right pane, only those classes that are contained in a specific namespace.

The DisplayNamespaces function has not been altered. It displays the namespaces contained in
the three dlls. Thereafter, we verify if the namespace variable contains any value. Similar to the
functioning of Request.QueryString, here also it is assumed that the form is reloaded with the
namespace variable containing a value. Since we have loaded the file for the first time, the
namespace parameter does not come into existence. Hence, the string variable named
SelectedNameSpace is initialized to System. It is for this reason that we see the classes
belonging to the System namespace, at startup.

Since we do not have a parameter called class with our URL, the next function to be called is
DisplayClassList. This function displays a list of classes belonging to the namespace name,
which is currently stored in SelectedNamespace.

In the DisplayClassList function, two ArrayList objects named ClassList and InterfaceList are
created. ClassList holds the list of classes and InterfaceList holds the list of interfaces. As
always, we go through the rigmarole of fetching each and every type, just as we did earlier, and
then checking whether the class or type belongs to the namespace specified in the parameter
named CurrentNameSpace. If it is so, then using the IsInterface property, we determine
whether the type is a class or an interface, as follows:

• If the IsInterface property returns a value of true, it means that the type is an interface.
Hence, it gets added to the InterfaceList.
• If the IsInterface property returns a value of false, it means that the type is a class.
Hence, it gets added to the ClassList.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (9 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

Once the ArrayLists have been filled up, we determine the number of entries in them, using
their Count member. If the value returned by Count in the Interface List is greater than zero,
the visible property of a span IHeader is set to true. In this situation, the static text 'Interfaces
in' is displayed, followed by the name of the namespace, in a bold format. The same procedure
is repeated for the ClassList also. A span is useful when many items have to be placed together,
because all of them can be manipulated as a single item.

Finally, we have two more DataList objects named Classes and Interfaces. Their DataSource
members are initialized to the list of classes and interfaces stored in the two ArrayList objects
named ClassList and InterfaceList, respectively.

Thus, as you can see in the above program, we have created an ArrayList and filled it up with
data. Then, we request the DataSource property of some DataList to display it.

The output in the browser should show the namespaces and the list of classes, concurrently.
This can be accomplished only by means of a table. So, we have a table tag containing two table
columns.

The first table column called td has a background color and occupies 25% of the table width.
This ensures that the first DataList is in one column.

In the next td, the names of the classes and the interfaces are displayed side by side.

The template itemtemplate is repeated for all the classes in the DataSource. Each class name is
displayed as a hyperlink, and the URL that is required to navigate to it, contains the following:

• the file name a.aspx.


• the name of the namespace.
• the name of the class given to parameters namespace and class.

http://localhost/a.aspx?namespace=System.Collections&class=ArrayList

The same process is repeated for the interfaces.

Let us now attempt to display the list of functions in a class.

a.aspx
<%@ Import NameSpace="ClassInfo" %>
<%@ Import NameSpace="System.Collections" %>
<%@ Import NameSpace="System.Collections.Specialized" %>
<%@ Import NameSpace="System.Reflection" %>
<html>
<head>
<script runat="server" language="C#">
public String SelectedAssembly;
public String SelectedNameSpace;
public ArrayList ModuleName = new ArrayList();
protected void Page_Load(Object Sender, EventArgs e) {

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (10 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

NameValueCollection ConfigSettings = (NameValueCollection)Context.GetConfig("system.web/


ClassBrowser");
for (int i = 0; i < ConfigSettings.Count; i++)
ModuleName.Add(ConfigSettings[i].ToString());
DisplayNamespaces();
if (Request.QueryString["namespace"] == null)
SelectedNameSpace = "System";
else
SelectedNameSpace = Request.QueryString["namespace"];
if (Request.QueryString["assembly"] == null )
SelectedAssembly = "mscorlib";
else
SelectedAssembly = Request.QueryString["assembly"];

if (Request.QueryString["class"] != null && Request.QueryString["assembly"] != null)


DisplayClass(Request.QueryString["assembly"], Request.QueryString["class"]);
else
DisplayClassList(SelectedNameSpace);
}
private void DisplayNamespaces() {
ArrayList NameSpaceList = new ArrayList();
Hashtable NameSpaceHash = new Hashtable();
for (int y = 0; y < ModuleName.Count; y++) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for( int x=0; x < CorClasses.Length; x++ )
{
if ( CorClasses[x].Namespace != null )
{
if (!NameSpaceHash.ContainsKey(CorClasses[x].Namespace) && CorClasses[x].IsPublic ) {
NameSpaceHash.Add(CorClasses[x].Namespace,"");
NameSpaceList.Add(CorClasses[x].Namespace);
}
}
}
}
NameSpaceList.Sort();
Namespace1.DataSource = NameSpaceList;
Namespace1.DataBind();
}
private void DisplayClassList(String CurrentNameSpace) {
ArrayList ClassList = new ArrayList();
ArrayList InterfaceList = new ArrayList();
for( int y=0; y < ModuleName.Count; y++ ) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for (int x=0; x < CorClasses.Length; x++ )
{
if ( CorClasses[x].Namespace == CurrentNameSpace && CorClasses[x].IsPublic) {
SortTable props = new SortTable("GetType");
props["GetType"] = CorClasses[x].Name;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (11 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

props["Namespace"] = CorClasses[x].Namespace;
props["Assembly"]= CorClasses[x].Assembly.GetName().Name;
if ( CorClasses[x].IsInterface )
InterfaceList.Add(props);
else
ClassList.Add(props);
}
}
}
if (InterfaceList.Count > 0)
IHeader.Visible = true;
if (ClassList.Count > 0)
CHeader.Visible = true;
ClassList.Sort();
Classes.DataSource = ClassList;
Classes.DataBind();
InterfaceList.Sort();
Interfaces.DataSource = InterfaceList;
Interfaces.DataBind();
}
private void DisplayClass(String asmName, String className) {
Assembly a = Assembly.Load(asmName);
Type ClassType = a.GetType(SelectedNameSpace.ToString() + "." + className, false, true);
if ( ClassType == null ) {
DisplayClassList(SelectedNameSpace);
return;
}
DisplayMethods MethodDetails = new DisplayMethods(ClassType, className);
if(MethodDetails.Count != 0 )
Methods.DataSource = MethodDetails;
DataBind();
if (ClassType.IsInterface)
spnClassName.InnerHtml = "Interface " + SelectedNameSpace + "." + className;
else
spnClassName.InnerHtml = "Class " + SelectedNameSpace + "." + className;
NameSpacePanel.Visible=false;
ClassPanel.Visible=true;
}
public String GetUrl(Object objTable) {
if ( objTable is String ) {
return "a.aspx?assembly=" + SelectedAssembly + "&namespace=" + SelectedNameSpace + "&class="
+ objTable;
}
if ( ! (objTable is Hashtable) ) {
Response.Write(objTable.GetType().ToString());
Response.End();
}
Hashtable table = (Hashtable) objTable;
return "a.aspx?assembly=" + table["Assembly"] + "&namespace=" + table["Namespace"] + "&class=" +
table["GetType"];
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (12 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

</script>
</head>
<body>
<form runat="server">
<table>
<tr>
<td width=25% bgcolor=#CCCCFF valign=top >
<br>
<asp:DataList EnableViewState="false" runat=server id="Namespace1" RepeatLayOut="flow">
<HeaderTemplate>Namespaces <br> </HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat="server" text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?
namespace=" + Container.DataItem %> />
</ItemTemplate>
<SelectedItemTemplate>
<b><asp:HyperLink runat=server text=<%# Container.DataItem %>/></b>
</SelectedItemTemplate>
</asp:DataList>
<p>
</td>
<td valign=top >
<div id="ClassPanel" style="margin-top:15;margin-left:10" visible="false" runat="server">
<b><font size=4 color="000666"><span style="text-indent:8" id="spnClassName" EnableViewState="false"
runat="server"/></font></b>
</div>
<div id="NameSpacePanel" runat="server">
<table class="main" width=100%>
<tr>
<td class="main_header">
<span runat=server id="CHeader" visible="false" style="text-indent:8"> <b><font size=4
color=#000666>Classes in <%= SelectedNameSpace %> </b> </font></span>
</td> </tr>
<tr>
<td align="left">
<asp:DataList EnableViewState="false" runat=server id="Classes" RepeatColumns="3" Gridlines=None
borderstyle=none borderwidth=0>
<ItemTemplate>
<asp:HyperLink runat=server text=<%# ((SortTable) Container.DataItem)["GetType"] %> NavigateUrl=<%
# GetUrl(Container.DataItem) %> />
</ItemTemplate>
</asp:DataList>
</td>
</tr>
</table>
<table class="main" width=100% >
<tr>
<td class="main_header" >
<span runat=server id="IHeader" visible="false" style="text-indent:8"> <b>
<font size=4 color=#000666>Interfaces in <% =SelectedNameSpace %> </font> </b> </span>
</td>
</tr>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (13 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

<tr>
<td align="left">
<asp:DataList EnableViewState="false" runat=server id="Interfaces" RepeatColumns="4" Gridlines=None
borderstyle=none borderwidth=0>
<ItemTemplate>
<asp:HyperLink runat=server text=<%# ((SortTable) Container.DataItem)["GetType"] %> NavigateUrl=<%
# GetUrl(Container.DataItem) %>/>
</ItemTemplate>
</asp:DataList>
</td>
</tr>
</table>
</div>
<p>
<asp:DataList EnableViewState="false" id="Methods" runat="server"
Gridlines=None borderstyle="none" borderwidth="0" width="100%">
<HeaderTemplate>
<table cellspacing=0 >
<tr><td class="class_header"><b><font size=2> Methods </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="75" ><b><u>Visibility</td>
<td width="100"><b><u>Return </td>
<td width="100"><b><u>Name</td>
<td width="600"><b><u>Parameters</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="75"><nobr><span runat=server InnerHtml=<%# ((SortTable)
Container.DataItem)["Access"]%> /></nobr></td>
<td width="100">
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["Type"]%>/>
</td>
<td width="100"><span runat=server InnerHtml=<%# ((SortTable)
Container.DataItem)["Name"]%>/></td>
<td width="900">
<asp:DataList EnableViewState="false" runat=server
datasource=<%# ((SortTable) Container.DataItem)["Params"] %>
RepeatLayout=Flow RepeatDirection="Horizontal" showfooter=true >
<HeaderTemplate>
(
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink text=<%# ((SortTable) Container.DataItem)["ParamType"].ToString() %> NavigateUrl=<%
# GetUrl(Container.DataItem) %> runat=server />
<span InnerHtml=<%# ((SortTable) Container.DataItem)["ParamName"] %> runat=server />
</ItemTemplate>
<SeparatorTemplate> ,</SeparatorTemplate>
<FooterTemplate> ) </FooterTemplate>
</asp:DataList>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (14 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p><p>
<asp:DataList EnableViewState="false" id="Interface1" runat=server style="margin-left:10"
RepeatDirection="horizontal"
RepeatLayout="Flow" width="100%">
<HeaderTemplate>
<font size=2><b> Implements </b></font> <br>
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["FullName"]%> />
</ItemTemplate>
<SeparatorTemplate>
<font face="Verdana" style="font-size:8pt">,
</SeparatorTemplate>
</asp:DataList>
<p>
<p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>

b.cs
using System ;
using System.Web;
using System.Web.UI;
using System.Collections;
using System.Reflection;
namespace ClassInfo {
public class SortTable : Hashtable, IComparable {
public String sortField;
public SortTable() : this(null) {
}
public SortTable(String sField) {
sortField = sField;
}
public int CompareTo(Object b) {
if ( sortField == null ) {
return 0;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (15 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

}
return ((String)this[sortField]).CompareTo((String)((SortTable)b)[sortField]);
}
}
public class DisplayMethods : ArrayList {
public DisplayMethods(Type classType, String myclassname) {
System.Reflection.MethodInfo[] methodInfos = classType.GetMethods() ;
if (methodInfos == null)
return;
for (int x=0; x<methodInfos.Length; x++) {
if((String.Compare(myclassname,methodInfos[x].DeclaringType.Name )==0)&&(methodInfos[x].IsPublic
|| methodInfos[x].IsFamily) && (!(methodInfos[x].IsSpecialName)) ) {
SortTable MethodDetails = new SortTable("Name");
MethodDetails["Assembly"] = methodInfos[x].GetType().Assembly.GetName().Name;
MethodDetails["Name"] = methodInfos[x].Name;
MethodDetails["Type"] = methodInfos[x].ReturnType.Name;
if(( methodInfos[x].ReturnType.IsArray && methodInfos[x].ReturnType.Name !="Array") ||
methodInfos[x].ReturnType.IsPointer) {
Type ReturnElementType = methodInfos[x].ReturnType.GetElementType();
while(ReturnElementType.IsArray) {
ReturnElementType = ReturnElementType.GetElementType();
}
MethodDetails["GetType"] = ReturnElementType.Name ;
MethodDetails["Namespace"] = ReturnElementType.Namespace ;
} else {
MethodDetails["GetType"] = methodInfos[x].ReturnType.Name;
MethodDetails["Namespace"] = methodInfos[x].ReturnType.Namespace ;
}
if (methodInfos[x].IsPublic == true) {
MethodDetails["Access"] = "public ";
} else if (methodInfos[x].IsPrivate == true) {
MethodDetails["Access"] = "private ";
} else if (methodInfos[x].IsFamily == true) {
MethodDetails["Access"] = "protected ";
}
if (methodInfos[x].IsStatic == true) {
MethodDetails["Access"] = ((String) MethodDetails["Access"]) + "static ";
}
System.Reflection.ParameterInfo[] paramInfos = methodInfos[x].GetParameters();
if (paramInfos != null) {
ArrayList paramTable = new ArrayList();
for (int y=0; y<paramInfos.Length; y++) {
SortTable paramDetails = new SortTable();
paramDetails["Assembly"] = paramInfos[y].GetType().Assembly.GetName().Name;
paramDetails["ParamName"] = paramInfos[y].Name;
paramDetails["ParamType"] = paramInfos[y].ParameterType.Name;
if(( paramInfos[y].ParameterType.IsArray && paramInfos[y].ParameterType.Name != "Array" ) ||
paramInfos[y].ParameterType.IsPointer) {
paramDetails["GetType"] = paramInfos[y].ParameterType.GetElementType().Name ;
paramDetails["Namespace"] = paramInfos[y].ParameterType.GetElementType().Namespace ;
} else {

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (16 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

paramDetails["GetType"] = paramInfos[y].ParameterType.Name;
paramDetails["Namespace"] = paramInfos[y].ParameterType.Namespace ;
}
paramTable.Add(paramDetails);
}
MethodDetails["Params"] = paramTable;
}
this.Add(MethodDetails);
}
}
this.Sort();
}
}
}

To run the above program, you need to first place the file b.cs in the sub-directory c:\inetpub
\wwwroot\bin and compile it as follows:

>csc /target:library b.cs


When a.aspx is loaded in the browser, the list of namespaces is displayed on the left, and the
list of classes belonging to the System namespace is seen on the right. If you click on any class,
a list of functions belonging to that class will be displayed. The data is displayed in a tabular
format in four columns.

• The first column represents the visibility. The values contained in it, are either public, or
private or protected.
• The second column indicates the return data type.
• The third column displays the names of the functions.
• The fourth column holds the parameters with their names and data types.

All types are hyper linked, so when we click on any one of them, a screen comes forth,
displaying the functions or methods that the specified type supports.

When we click on the name of a class, the following URL gets generated:

http://localhost/a.aspx?assembly=mscorlib&namespace=System&class=Exception

The Page_Load function calls the DisplayClass function, since the class and the assembly
parameter contains a value. This proves that the DisplayClassList function is called only in the
first round, while loading the page.

In the DisplayClass function, we first need the type of the object. The static function called
GetType, belonging to the Type class, returns a type when it is supplied with the full name of
the class. So, we concatenate the namespace name stored in the instance variable
SelectedNameSpace, with the parameter className, and then pass the full name to this
function. The Type returned by the GetType function is stored in a variable called ClassType.

Next, we create an object called MethodDetails of type DisplayMethods, which requires two
parameters, the Type and the className. DisplayMethods is, in turn, derived from the class

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (17 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

ArrayList. The ArrayList object named MethodDetails, obviously contains the details about the
methods. Using the Count member, we can determine the total number of methods in the class.
If the value returned is greater than 0, we initialize the DataSource member called Methods, of
the DataList, to this ArrayList. The span control called spnClassName, then displays the name
of the namespace and that of the class.

We have two div tags having the ids ClassPanel and NameSpacePanel. Their visible property is
set to either true or false, thereby, ensuring that all the div contents are either displayed or
hidden from view. In the DisplayClass, we have hidden the data contained within these tags by
setting the Visible property to false. Thus, in one stroke, we can conceal or reveal a large
number of entities. These tags are extremely useful because our browser's real estate is
restricted, and we do not have the space to display everything.

Let us now scrutinize the presentation logic. As we mentioned earlier, the DataList called
Methods displays all the method names neatly formatted. You may have been ambushed by the
revelation that a simple DataList was able to display everything. The template named
headertemplate is called once, to display the four column headers of the table. The table tag
does not end with the template, as each method is now displayed as a table row. The bold and
underline tags have been provided to produce visually stunning output.

The DisplayMethods class uses the indexer method to retrieve the values of the Visible and
Type members. Thus, in the span tag, we use the array syntax to display the Access and Type
members. The function GetUrl navigates to the relevant type by creating a URL, followed by the
parameters called assembly, namespace and class, filled up with relevant values. From the
browser's point of view, it does not make any difference whether we click on the class name in
the first screen or in the second one.

Life is not very straightforward now, since we have made an endeavor to display the parameters
of the method, which could number from nil to infinity. In order to achieve this, we create
another DataList within the Methods DataList and initialize the DataSource parameter to the
Params value in the DisplayMethods object. To display the parameters, a template with a hyper
link is utilized. It shows the data type or ParamType as a hyperlink. The URL to this link is
generated by the GetUrl function. The ParamName is displayed as normal text.

The whole code is enclosed in open and close brackets, and is available in the headertemplate
and footertemplate. The template named separatortemplate supplies the commas to separate
the individual parameter names and values. To summarize, we are using a nested DataList to
display an array of values within another array.

We have a confession to make at this juncture. The class named DisplayMethods has not been
supplied by Microsoft. It is created in the file b.cs. This class is derived from ArrayList and gives
us all the details of every method that exists in a type.

Let us now focus on the class DisplayMethods in the file b.cs.


This is a perfect example of a two-tier illustration, where the presentation logic is placed in one
file, and the C# code that handles Reflection, is placed in another file.

The class DisplayMethods has to extend the ArrayList class, because in the aspx file, we are

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (18 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

initializing the DataSource member of the Methods DataList to this data type. Also, the
constructor in the DisplayClass function has been supplied with two parameters, namely, the
Type and className.

DisplayMethods MethodDetails= new DisplayMethods(ClassType, className);

There exists a static method called GetMethods in the Type class, that returns a MethodInfo
array. The methodInfos array reveals every aspect of the function. No parameter is supplied
indicating that the default rules are to be applied when locating a function. In case there are no
methods available in a class, a null value is stored in the array variable.

The Length member of the array stores a count of the number of methods contained in the
array. Thereafter, using a for loop we iterate through each and every method. A 'foreach' loop
could also be used to achieve the same functionality. In the loop, we use a Compare function of
the String class, to verify the validity of the method. The property DeclaringType returns a Type
or the class that consists of this method. Type in turn, has a property called Name, that
represents the name of the class. Compare takes this name and checks it with the parameter
myclassname, which is a parameter passed to the constructor. It is just an additional check.

We also ensure that the method is public or it belongs to the family (current of derived class)
that can access it. The compiler treats functions that possess special names, differently. For
example, the constructor is given a special name, i.e. .ctor. These methods are not to be
included in our list of methods, and hence, the ! sign is used. The method must successfully
pass all the above conditions, or else, it will not be incorporated as a part of the methods list
that is returned.

On passing the above test, the next task is to gain access to the template in the aspx file. To
accomplish this, an indexer or an array is employed. It returns an object that is an instance of
a Hashtable. For the ones who walked in late, the Hashtable class lets us access data in an
efficient manner, and also offers us an indexer support.

MethodDetails is an instance of the SortTable class, which consecutively extends the class
Hashtable. The single parameter constructor of the SortTable is called using the Name
parameter. The constructor stores the value contained in the Name variable, in a public
variable called sortField. Thereafter, using the indexer features of the Hashtable class, the
following is achieved:

• The name of the assembly is stored in an indexer variable called Assembly.


• The name of the method is stored in an indexer variable called Name.
• The name of the return type is stored in the indexer variable called Type.

The name of the return type or class is obtained as follows:


The MethodInfo class has a property called ReturnType that returns the Type of the return
value. The Type in turn, has a member called Name that holds the name of the Type.

There are instances where a multi-dimension array or a pointer is returned. These being
exceptional cases, separate 'if 'statements are required to handle them. First, using the property
IsArray, the name property in ReturnType is checked. If the name contains the word 'Array' or

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (19 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

the ReturnType is a pointer, we can safely conclude that the function returns a Multi-
Dimensional array. So, we use the function GetElementType in ReturnType, to return the Type
of the object encompassed, or referenced by either an array, or a pointer, or by ByRef.

The predicament with arrays is that their dimensions could range from 2 to infinity, which
could put us in a tight spot. To tide over this situation, we use a loop construct like a while or a
for loop. Thus, using IsArray, we keep looping, until the Type becomes an array. All arrays,
multi-dimensional or otherwise, have a Type name. Ignoring the fact that it is an array, we
initialize the indexer variable GetType to this Type name, and initialize the namespace variable
to the namespace of this type. This course of action is essential if we aspire to display the final
data type of the array.

Under normal circumstances, the return type is generally a Type object. In such cases, we can
use the same Name and Namespace properties to retrieve its value and store it in the
MethodDetail Indexer.

The next task in sequence is to store the access modifiers, which our function has been tagged
with. We intend to determine whether the method is public, private or protected. To achieve
this, we use the three properties named, IsPublic, IsPrivate and IsFamily. Accordingly, the
relevant access modifier is stored in the indexer variable called Access. The function is also
checked to establish if it is static. To accomplish this, the property IsStatic is used. If it returns
a value of true, the string static is added to the Access indexer variable.

Now, we have arrived at a relatively uncomplicated part.


The names and the data types of the parameters have to be retrieved. The number of
parameters to a function can range from zero to infinity. We initialize an object called
paramInfos by calling the GetParameters function, which returns a ParameterInfo array. A
separate ArrayList is now required to store this variable set of data. So, we create a separate
ArrayList object called paramTable, which stores certain information about the parameters,
such as the name and type.

Depending upon the length of the array, the loop is repeated a specific number of times,
wherein, the Name property of a ParameterInfo object, is assigned to an indexer variable called
ParamName. The ParameterInfo class also contains a property called ParameterType, whose
Type member holds the name of the Type. Thereafter, as before, we check if the return type is a
Multi-dimensional array. If so, the final type of the Multi-Dimensional array is figured out.
Eventually, the GetType and Namespace are initialized from the normal types of the multi-
dimensional arrays, to the return type of the function and the namespace of the type,
respectively. Thereafter, this single record of paramDetails is added to the paramTable
ArrayList. This loop is repeated for every method in the class. Once the loop terminates, the
indexer variable Params in MethodDetails, is initialized to the paramTable object.

Finally, the MethodDetails is added to the ArrayList and the ArrayList is sorted. Sortng of the
list is not obligatory.

To recapitulate, the MethodDetails class consists of multiple records that can be accessed
through an indexer, using parameter names like GetType and Namespace. The Params
parameter in the MethodDetail indexer is made up of another ArrayList, and has members like

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (20 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

ParamName and ParamType.

The interface IComparable attains significance because it contains the CompareTo function
from the string class.

Now, for the grand finale! We shall delve upon the class browser application from the Microsoft
Samples.

web.config
<configuration>
<configSections>
<sectionGroup name="system.web">
<section name="ClassBrowser" type="System.Configuration.NameValueSectionHandler,System"/>
</sectionGroup>
</configSections>
<system.web>
<ClassBrowser>
<add key="WinForms Library" value="System.Windows.Forms" />
<add key="Drawing Library" value="System.Drawing" />
<add key="Data Library" value="System.Data" />
<add key="Xml Library" value="System.Xml" />
<add key="Messaging Library" value="System.Messaging" />
<add key="Directory Services Library" value="System.DirectoryServices" />
<add key="ASP.NET Class Library" value="System.Web" />
<add key=".NET Framework class Library" value="mscorlib" />
</ClassBrowser>
</system.web>
</configuration>

a.aspx
<%@ Page Language="C#" Debug="True" %>
<%@ Import NameSpace="ClassInfo" %>
<%@ Import NameSpace="System.Collections" %>
<%@ Import NameSpace="System.Collections.Specialized" %>
<%@ Import NameSpace="System.Reflection" %>
<html><head>
<script runat="server" language="C#">
public String SelectedAssembly;
public String SelectedNameSpace;
public ArrayList ModuleName = new ArrayList();
protected void Page_Load(Object Sender, EventArgs e) {
NameValueCollection ConfigSettings = (NameValueCollection)Context.GetConfig("system.web/
ClassBrowser");
for (int i = 0; i < ConfigSettings.Count; i++) {
ModuleName.Add(ConfigSettings[i].ToString());
}
DisplayNamespaces();
if (Request.QueryString["namespace"] == null)
SelectedNameSpace = "System";

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (21 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

else
SelectedNameSpace = Request.QueryString["namespace"];

if (Request.QueryString["assembly"] == null )
SelectedAssembly = "mscorlib";
else
SelectedAssembly = Request.QueryString["assembly"];
if (Request.QueryString["class"] != null && Request.QueryString["assembly"] != null)
DisplayClass(Request.QueryString["assembly"], Request.QueryString["class"]);
else
DisplayClassList(SelectedNameSpace);
}
private void DisplayNamespaces() {
ArrayList NameSpaceList = new ArrayList();
Hashtable NameSpaceHash = new Hashtable();
for (int y = 0; y < ModuleName.Count; y++) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for( int x=0; x < CorClasses.Length; x++ ) {
if ( CorClasses[x].Namespace != null ) {
if (!NameSpaceHash.ContainsKey(CorClasses[x].Namespace) && CorClasses[x].IsPublic ) {
NameSpaceHash.Add(CorClasses[x].Namespace,"");
NameSpaceList.Add(CorClasses[x].Namespace);
}
}
}
}
NameSpaceList.Sort();
Namespace1.DataSource = NameSpaceList;
Namespace1.DataBind();
}
private void DisplayClassList(String CurrentNameSpace) {
ArrayList ClassList = new ArrayList();
ArrayList InterfaceList = new ArrayList();
for( int y=0; y < ModuleName.Count; y++ ) {
Module[] CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
Type[] CorClasses = CorRuntime[0].GetTypes();
for (int x=0; x < CorClasses.Length; x++ ) {
if ( CorClasses[x].Namespace == CurrentNameSpace && CorClasses[x].IsPublic) {
SortTable props = new SortTable("GetType");
props["GetType"] = CorClasses[x].Name;
props["Namespace"] = CorClasses[x].Namespace;
props["Assembly"] = CorClasses[x].Assembly.GetName().Name;

if ( CorClasses[x].IsInterface )
InterfaceList.Add(props);
else
ClassList.Add(props);
}
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (22 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

if (InterfaceList.Count > 0)
IHeader.Visible = true;

if (ClassList.Count > 0)
CHeader.Visible = true;

ClassList.Sort();
Classes.DataSource = ClassList;
Classes.DataBind();

InterfaceList.Sort();
Interfaces.DataSource = InterfaceList;
Interfaces.DataBind();
}

private void DisplayClass(String asmName, String className) {

Assembly a = Assembly.Load(asmName);
Type ClassType = a.GetType(SelectedNameSpace.ToString() + "." + className, false, true);
if ( ClassType == null ) {
DisplayClassList(SelectedNameSpace);
return;
}
ArrayList SubClassDetails = new DisplaySubClasses(ClassType, ModuleName);
DisplayConstructors ConstructorDetails = new DisplayConstructors(ClassType);
DisplayFields FieldDetails = new DisplayFields(ClassType);
DisplayProperties PropertyDetails = new DisplayProperties(ClassType);
DisplayMethods MethodDetails = new DisplayMethods(ClassType, className);
DisplaySuperclasses SuperClassDetails = new DisplaySuperclasses(ClassType);
DisplayInterfaces InterfaceDetails = new DisplayInterfaces(ClassType);
DisplayEvents EventDetails = new DisplayEvents(ClassType);
if(ConstructorDetails.Count != 0 )
Constructors.DataSource = ConstructorDetails;
if(SubClassDetails.Count != 0 )
SubClasses.DataSource = SubClassDetails;
if(FieldDetails.Count != 0 )
Fields.DataSource = FieldDetails;
if(PropertyDetails.Count != 0 )
Properties.DataSource = PropertyDetails;
if(MethodDetails.Count != 0 )
Methods.DataSource = MethodDetails;
if(InterfaceDetails.Count != 0 )
Interface1.DataSource = InterfaceDetails;
if(SuperClassDetails.Count != 0 )
SuperClasses.DataSource = SuperClassDetails;
if(EventDetails.Count != 0 )
Events.DataSource = EventDetails;
DataBind();
if (ClassType.IsInterface)
spnClassName.InnerHtml = "Interface " + SelectedNameSpace + "." + className;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (23 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

else
spnClassName.InnerHtml = "Class " + SelectedNameSpace + "." + className;
NameSpacePanel.Visible=false;
ClassPanel.Visible=true;
}

public String GetUrl(Object objTable) {


if ( objTable is String ) {
return "a.aspx?assembly=" + SelectedAssembly + "&namespace=" + SelectedNameSpace + "&class=" +
objTable;
}
if ( ! (objTable is Hashtable) ) {
Response.Write(objTable.GetType().ToString());
Response.End();
}
Hashtable table = (Hashtable) objTable;
return "a.aspx?assembly=" + table["Assembly"] + "&namespace=" + table["Namespace"] + "&class=" +
table["GetType"];
}
</script>
</head>
<body>
<form runat="server">
<table width=100% height=700 cellpadding=0 cellspacing=0>
<tr>
<td width=25% bgcolor=#CCCCFF valign=top > <br>
<asp:DataList EnableViewState="false" runat=server id="Namespace1" RepeatLayOut="flow" ItemStyle-
Font-Size="9pt" HeaderStyle-Font-Size="12pt" >
<HeaderTemplate>
<div left-margin="10"> Namespaces <br>
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat="server" text=<%# Container.DataItem %> NavigateUrl=<%# "a.aspx?namespace="
+ Container.DataItem %> />
</ItemTemplate>
<SelectedItemTemplate>
<b><asp:HyperLink runat=server text=<%# Container.DataItem %>/></b>
</SelectedItemTemplate>
</asp:DataList>
<p>
</td>
<td valign=top >
<div id="ClassPanel" style="margin-top:15;margin-left:10" visible="false" runat="server">
<b><font size=4 color="000666"><span style="text-indent:8" id="spnClassName"
EnableViewState="false" runat="server"/></font></b>
</div>
<div id="NameSpacePanel" runat="server">
<table class="main" width=100%>
<tr> <td class="main_header">
<span runat=server id="CHeader" visible="false" style="text-indent:8"> <b><font size=4
color=#000666>Classes in

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (24 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

<%= SelectedNameSpace %> </b> </font></span>


</td> </tr>
<tr>
<td align="left">
<asp:DataList EnableViewState="false" runat=server id="Classes" RepeatColumns="3" Gridlines=None
borderstyle=none borderwidth=0 >
<ItemTemplate>
<asp:HyperLink runat=server text=<%# ((SortTable) Container.DataItem)["GetType"] %> NavigateUrl=<%
# GetUrl(Container.DataItem) %> />
</ItemTemplate>
</asp:DataList>
</td>
</tr>
</table>
<table class="main" width=100% >
<tr>
<td class="main_header" >
<span runat=server id="IHeader" visible="false" style="text-indent:8"> <b><font size=4
color=#000666>Interfaces in
<%= SelectedNameSpace %> </font> </b> </span>
</td>
</tr>
<tr>
<td align="left">
<asp:DataList EnableViewState="false" runat=server id="Interfaces" RepeatColumns="4"
Gridlines=None borderstyle=none borderwidth=0 >
<ItemTemplate>
<asp:HyperLink runat=server text=<%# ((SortTable) Container.DataItem)["GetType"] %> NavigateUrl=<%
# GetUrl(Container.DataItem) %>/>
</ItemTemplate>
</asp:DataList>
</td>
</tr>
</table>

</div>

<table class="main" width=100% cellpadding=0 cellspacing=0 >


<tr>
<td class="main_header" valign="top" >
<asp:DataList EnableViewState="false" id="Constructors" runat="server" Gridlines=None
borderstyle="none" borderwidth=0 width="100%">
<HeaderTemplate>
<table cellspacing=0 width="100%">
<tr><td class="class_header"><b><font size=2> Constructors </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="75" > <b><u> Visibility </u> </td>
<td width="100"> <b><u> Constructor </u> </td>
<td> <b><u> Parameters </u> </td>
</tr>
</HeaderTemplate>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (25 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="75">
<span runat=server InnerHtml=<%# ((SortTable) Container.DataItem)["Access"] %> />
</td>
<td width="100">
<span runat=server InnerHtml =<%# ((SortTable) Container.DataItem)["Name"] %> />
</td>
<td width="1000">
<asp:DataList
EnableViewState="false"
runat=server
RepeatDirection="Horizontal"
RepeatLayout=Flow
showfooter=true datasource=<%# ((SortTable) Container.DataItem)["Params"]%> >
<HeaderTemplate> ( </HeaderTemplate>
<ItemTemplate>
<asp:HyperLink text=<%# ((SortTable) Container.DataItem)["ParamType"] %> NavigateUrl=<%# GetUrl
(Container.DataItem) %> runat=server />
<span innerhtml=<%# ((SortTable) Container.DataItem)["ParamName"] %> runat=server />
</ItemTemplate>
<SeparatorTemplate>, </SeparatorTemplate>
<FooterTemplate> ) </FooterTemplate>
</asp:DataList>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="Fields" runat="server" Gridlines=None BorderStyle="none"
width="100%" BorderWidth=0>
<HeaderTemplate>
<table cellspacing=0 width="100%">
<tr><td class="class_header"><b><font size=2> Fields </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="120" ><b><u> Visibility </td>
<td width="100"><b><u> Type </td>
<td ><b><u> Name </td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="120">
<nobr><span InnerHTML=<%# ((SortTable) Container.DataItem)["Access"]%> runat=server /></nobr>
</td>
<td width="100">
<asp:HyperLink text=<%# ((SortTable) Container.DataItem)["Type"] %> NavigateUrl=<%# GetUrl

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (26 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

(Container.DataItem) %> runat=server/>


</td> <td>
<span InnerHTML=<%# ((SortTable) Container.DataItem)["Name"] %> runat=server />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="Events" runat="server" Gridlines=None BorderStyle="none"
width="100%" BorderWidth=0>
<HeaderTemplate>
<table cellspacing=0 width="100%">
<tr><td class="class_header"><b><font size=2> Events </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="120" ><b><u> Multicast </td>
<td width="100"><b><u> Type </td>
<td ><b><u> Name </td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="120">
<nobr><span InnerHTML=<%# ((SortTable) Container.DataItem)["Access"]%> runat=server /></nobr>
</td>
<td width="100">
<asp:HyperLink text=<%# ((SortTable) Container.DataItem)["Type"] %> NavigateUrl=<%# GetUrl
(Container.DataItem) %> runat=server/>
</td>
<td>
<span InnerHTML=<%# ((SortTable) Container.DataItem)["Name"] %> runat=server />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="Properties" runat="server" Gridlines=None
BorderStyle="none" BorderWidth=0 width="100%">
<HeaderTemplate>
<table cellspacing=0 width="100%" >
<tr><td class="class_header"><b><font size=2> Properties </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="75"><b><u>Visibility</td>
<td width="100"><b><u>Type</td>
<td width="150"><b><u>Name</td>
<td><b><u>Accessibility</td>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (27 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

</tr>
</HeaderTemplate>
<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="75"><span InnerHTML=<%# ((SortTable) Container.DataItem)["Visibility"] %>
runat=server /> </td>
<td width="100">
<asp:HyperLink runat=server runat="server" text=<%# ((SortTable) Container.DataItem)["Type"] %>
NavigateUrl=<%# GetUrl(Container.DataItem) %>/> </td>
<td width="150"><span InnerHTML=<%# ((SortTable) Container.DataItem)["Name"]%> runat=server/>
<asp:DataList EnableViewState="false" runat=server RepeatLayout="Flow"
ShowFooter=true RepeatDirection="Horizontal" datasource=<%# ((SortTable) Container.
DataItem)["Params"] %>>
<ItemTemplate>
( <asp:HyperLink runat=server text=<%# ((SortTable) Container.DataItem)["ParamType"]%>
NavigateUrl=<%# GetUrl(Container.DataItem) %> />
<span InnerHtml=<%# ((SortTable) Container.DataItem)["ParamName"] %> runat=server /> )
</ItemTemplate>
</asp:DataList>
</td><td><span InnerHTML=<%# ((SortTable) Container.DataItem)["Access"]%> runat=server/></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="Methods" runat="server" Gridlines=None borderstyle="none"
borderwidth="0" width="100%">
<HeaderTemplate>
<table cellspacing=0 >
<tr><td class="class_header"><b><font size=2> Methods </font></b></td></tr>
<tr bgcolor="eeeeee">
<td width="75" ><b><u>Visibility</td>
<td width="100"><b><u>Return </td>
<td width="100"><b><u>Name</td>
<td width="600"><b><u>Parameters</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr bgcolor="eeeeee">
<td width="75"><nobr><span runat=server InnerHtml=<%# ((SortTable) Container.DataItem)["Access"]%
> /></nobr></td>
<td width="100">
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["Type"]%>/>
</td>
<td width="100"><span runat=server InnerHtml=<%# ((SortTable) Container.DataItem)["Name"]%>/></
td>
<td width="900">
<asp:DataList EnableViewState="false" runat=server

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (28 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

datasource=<%# ((SortTable) Container.DataItem)["Params"] %>


RepeatLayout=Flow RepeatDirection="Horizontal" showfooter=true >
<HeaderTemplate>
(
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink text=<%# ((SortTable) Container.DataItem)["ParamType"].ToString() %> NavigateUrl=<%
# GetUrl(Container.DataItem) %> runat=server />
<span InnerHtml=<%# ((SortTable) Container.DataItem)["ParamName"] %> runat=server />
</ItemTemplate>
<SeparatorTemplate> ,</SeparatorTemplate>
<FooterTemplate>
)
</FooterTemplate>
</asp:DataList>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="SuperClasses" style="margin-left:10" runat="server"
RepeatLayout="Flow"
RepeatDirection="horizontal" width="100%">
<HeaderTemplate>
<font size=2><b> Hierarchy </b></font> <br>
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["FullName"]%> />
</ItemTemplate>
<SeparatorTemplate>
<font face="Verdana" style="font-size:8pt"><nobr>---></nobr>
</SeparatorTemplate>
</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="Interface1" runat=server style="margin-left:10"
RepeatDirection="horizontal"
RepeatLayout="Flow" width="100%">
<HeaderTemplate>
<font size=2><b> Implements </b></font> <br>
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["FullName"]%> />
</ItemTemplate>
<SeparatorTemplate>
<font face="Verdana" style="font-size:8pt">,
</SeparatorTemplate>

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (29 of 40)2/13/2007 4:54:34 PM


The Class Browser - ASP.NET - Beta2

</asp:DataList>
<p>
<asp:DataList EnableViewState="false" id="SubClasses" style="margin-left:10" runat=server
RepeatLayout="Flow" RepeatDirection="horizontal" width="100%">
<HeaderTemplate>
<font size=2> <b>Subclassed By </b></font> <br>
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink runat=server NavigateUrl=<%# GetUrl(Container.DataItem) %> text=<%# ((SortTable)
Container.DataItem)["FullName"]%> />
</ItemTemplate>
<SeparatorTemplate>
<font face="Verdana" style="font-size:8pt">,
</SeparatorTemplate>
</asp:DataList>
<p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</form>
</body>
</html>

b.cs
using System ;
using System.Web;
using System.Web.UI;
using System.Collections;
using System.Reflection;
namespace ClassInfo {
public class SortTable : Hashtable, IComparable {
public String sortField;
public SortTable() : this(null) {
}
public SortTable(String sField) {
sortField = sField;
}
public int CompareTo(Object b) {
if ( sortField == null ) {
return 0;
}
return ((String)this[sortField]).CompareTo((String)((SortTable)b)[sortField]);
}
}
public class DisplayEvents : ArrayList {
public DisplayEvents(Type classType) {
System.Reflection.EventInfo[] eventInfos = classType.GetEvents();
if (eventInfos == null)

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (30 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

return;
ArrayList eventTable = new ArrayList();
for (int x=0; x<eventInfos.Length; x++) {
SortTable eventDetails = new SortTable("Name");
eventDetails["Assembly"] = eventInfos[x].EventHandlerType.Assembly.GetName().Name;
eventDetails["Name"] = eventInfos[x].Name;
eventDetails["Type"] = eventInfos[x].EventHandlerType.Name;
eventDetails["GetType"] = eventInfos[x].EventHandlerType.Name;
eventDetails["Namespace"] = eventInfos[x].EventHandlerType.Namespace;
if (eventInfos[x].IsMulticast == true) {
eventDetails["Access"] = "multicast ";
}
this.Add(eventDetails);
}
this.Sort();
}
}
public class DisplayFields : ArrayList
{
public DisplayFields(Type classType)
{
System.Reflection.FieldInfo[] fieldInfos = classType.GetFields();
if (fieldInfos == null)
return;
ArrayList fieldTable = new ArrayList();
for (int x=0; x<fieldInfos.Length; x++) {
SortTable fieldDetails = new SortTable("Name");
fieldDetails["Assembly"] = fieldInfos[x].GetType().Assembly.GetName().Name;
fieldDetails["Name"] = fieldInfos[x].Name;
fieldDetails["Type"] = fieldInfos[x].FieldType.Name;
if(( fieldInfos[x].FieldType.IsArray && fieldInfos[x].FieldType.Name != "Array") || fieldInfos[x].
FieldType.IsPointer) {
fieldDetails["GetType"] = fieldInfos[x].FieldType.GetElementType().Name;
fieldDetails["Namespace"] = fieldInfos[x].FieldType.GetElementType().Namespace;
}
else {
fieldDetails["GetType"] = fieldInfos[x].FieldType.Name;
fieldDetails["Namespace"] = fieldInfos[x].FieldType.Namespace;
}
if (fieldInfos[x].IsPublic == true){
fieldDetails["Access"] = "public ";
}
else if (fieldInfos[x].IsPrivate == true){
fieldDetails["Access"] = "private ";
}
else if (fieldInfos[x].IsFamily == true){
fieldDetails["Access"] = "protected ";
}
if (fieldInfos[x].IsStatic == true){
fieldDetails["Access"] = ((String) fieldDetails["Access"]) + "static ";
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (31 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

if (fieldInfos[x].IsLiteral == true){
fieldDetails["Access"] = ((String) fieldDetails["Access"]) + "const ";
}
this.Add(fieldDetails);
}
this.Sort();
}
}
public class DisplayConstructors : ArrayList {
public DisplayConstructors(Type classType) {
System.Reflection.ConstructorInfo[] constructorInfos = classType.GetConstructors();
if (constructorInfos == null)
return;
for (int x=0; x<constructorInfos.Length; x++) {
SortTable constructorDetails = new SortTable();
constructorDetails["Assembly"] = constructorInfos[x].GetType().Assembly.GetName().Name;
constructorDetails["Name"] = classType.Name;
if (constructorInfos[x].IsPublic == true) {
constructorDetails["Access"] = "public ";
}
else if (constructorInfos[x].IsPrivate == true) {
constructorDetails["Access"] = "private ";
}
else if (constructorInfos[x].IsFamily == true) {
constructorDetails["Access"] = "protected ";
}
System.Reflection.ParameterInfo[] paramInfos = constructorInfos[x].GetParameters();
if (paramInfos != null) {
ArrayList paramTable = new ArrayList();
for (int y=0; y<paramInfos.Length; y++) {
SortTable paramDetails = new SortTable();
paramDetails["Assembly"] = paramInfos[y].GetType().Assembly.GetName().Name;
paramDetails["ParamName"] = paramInfos[y].Name;
paramDetails["ParamType"] = paramInfos[y].ParameterType.Name;
if ( ( paramInfos[y].ParameterType.IsArray && paramInfos[y].ParameterType.Name !
="Array" ) || paramInfos[y].ParameterType.IsPointer ) {
paramDetails["GetType"] = paramInfos[y].ParameterType.GetElementType().Name ;
paramDetails["Namespace"] = paramInfos[y].ParameterType.GetElementType().
Namespace ;
}
else {
paramDetails["GetType"] = paramInfos[y].ParameterType.Name;
paramDetails["Namespace"] = paramInfos[y].ParameterType.Namespace ;
}
paramTable.Add(paramDetails);
}
constructorDetails["Params"] = paramTable;
}
this.Add(constructorDetails);
}
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (32 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

}
public class DisplayProperties : ArrayList {
public DisplayProperties(Type classType) {
System.Reflection.PropertyInfo[] propertyInfos = classType.GetProperties();
if (propertyInfos == null)
return;
ArrayList propertyTable = new ArrayList();
for (int x=0; x<propertyInfos.Length; x++) {
SortTable propertyDetails = new SortTable("Name");
if(propertyInfos[x].GetGetMethod() != null) {
if(( propertyInfos[x].GetGetMethod().ReturnType.IsArray && propertyInfos[x].GetGetMethod
().ReturnType.Name !="Array" ) || propertyInfos[x].GetGetMethod().ReturnType.IsPointer ) {
propertyDetails["GetType"] = propertyInfos[x].GetGetMethod().ReturnType.
GetElementType().Name;
propertyDetails["Namespace"] = propertyInfos[x].GetGetMethod().ReturnType.
GetElementType().Namespace;

} else {
propertyDetails["GetType"] = propertyInfos[x].GetGetMethod().ReturnType.Name;
propertyDetails["Namespace"] = propertyInfos[x].GetGetMethod().ReturnType.Namespace;
}
propertyDetails["Type"] = propertyInfos[x].GetGetMethod().ReturnType.Name;
propertyDetails["Assembly"] = propertyInfos[x].GetGetMethod().ReturnType.Assembly.
GetName().Name;
propertyDetails["Name"] = propertyInfos[x].Name;

if (propertyInfos[x].GetGetMethod().IsPublic == true) {
propertyDetails["Visibility"] = "public";
} else if (propertyInfos[x].GetGetMethod().IsPrivate == true) {
propertyDetails["Visibility"] = "private";
} else if (propertyInfos[x].GetGetMethod().IsFamily == true) {
propertyDetails["Visibility"] = "protected";
}
if (propertyInfos[x].GetGetMethod().IsStatic == true) {
propertyDetails["Visibility"] = ((String) propertyDetails["Visibility"]) + " static";
}
if (propertyInfos[x].GetSetMethod() == null) {
propertyDetails["Access"] = "[Get]" ;
} else {
propertyDetails["Access"] = "[Get , Set]" ;
}
System.Reflection.ParameterInfo[] paramInfos = propertyInfos[x].GetGetMethod().GetParameters();
if (paramInfos != null) {
ArrayList paramTable = new ArrayList();
for (int y=0; y<paramInfos.Length; y++) {
SortTable paramDetails = new SortTable();
paramDetails["Assembly"] = paramInfos[y].GetType().Assembly.GetName().Name;
paramDetails["ParamName"] = paramInfos[y].Name;
paramDetails["ParamType"] = paramInfos[y].ParameterType.Name;
if (( paramInfos[y].ParameterType.IsArray && paramInfos[y].ParameterType.Name !="Array") ||
paramInfos[y].ParameterType.IsPointer ) {

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (33 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

paramDetails["GetType"] = paramInfos[y].ParameterType.GetElementType().Name ;
paramDetails["Namespace"] = paramInfos[y].ParameterType.GetElementType().Namespace ;
} else {
paramDetails["GetType"] = paramInfos[y].ParameterType.Name;
paramDetails["Namespace"] = paramInfos[y].ParameterType.Namespace ;
}
paramTable.Add(paramDetails);
}
propertyDetails["Params"] = paramTable;
}
} else if(propertyInfos[x].GetSetMethod() != null) {
propertyDetails["GetType"] = propertyInfos[x].GetSetMethod().ReturnType.Name;
propertyDetails["Namespace"] = propertyInfos[x].GetSetMethod().ReturnType.Namespace;
propertyDetails["Type"] = propertyInfos[x].GetSetMethod().ReturnType.Name;
propertyDetails["Assembly"] = propertyInfos[x].GetGetMethod().ReturnType.Assembly.
GetName().Name;
propertyDetails["Name"] = propertyInfos[x].Name;
if (propertyInfos[x].GetSetMethod().IsPublic == true) {
propertyDetails["Visibility"] = "public";
} else if (propertyInfos[x].GetSetMethod().IsPrivate == true) {
propertyDetails["Visibility"] = "private";
} else if (propertyInfos[x].GetSetMethod().IsFamily == true) {
propertyDetails["Visibility"] = "protected";
}
if (propertyInfos[x].GetSetMethod().IsStatic == true) {
propertyDetails["Visibility"] = ((String) propertyDetails["Visibility"]) + " static";
}
propertyDetails["Access"] = "[ Set ]" ;
System.Reflection.ParameterInfo[] paramInfos = propertyInfos[x].GetSetMethod().GetParameters();
if (paramInfos != null) {
ArrayList paramTable = new ArrayList();

for (int y=0; y<paramInfos.Length; y++) {


SortTable paramDetails = new SortTable();
paramDetails["Assembly"] = paramInfos[y].GetType().Assembly.GetName().Name;
paramDetails["ParamName"] = paramInfos[y].Name;
paramDetails["ParamType"] = paramInfos[y].ParameterType.Name;
if(( paramInfos[y].ParameterType.IsArray && paramInfos[y].ParameterType.Name !
="Array") || paramInfos[y].ParameterType.IsPointer) {
paramDetails["GetType"] = paramInfos[y].ParameterType.GetElementType().Name ;
paramDetails["Namespace"] = paramInfos[y].ParameterType.GetElementType().
Namespace ;
} else {
paramDetails["GetType"] = paramInfos[y].ParameterType.Name;
paramDetails["Namespace"] = paramInfos[y].ParameterType.Namespace ;
}
paramTable.Add(paramDetails);
}

propertyDetails["Params"] = paramTable;
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (34 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

}
this.Add(propertyDetails);
}
this.Sort();
}
}

public class DisplayMethods : ArrayList {


public DisplayMethods(Type classType, String myclassname) {
System.Reflection.MethodInfo[] methodInfos = classType.GetMethods() ;

if (methodInfos == null)
return;
for (int x=0; x<methodInfos.Length; x++) {
if((String.Compare(myclassname,methodInfos[x].DeclaringType.Name )==0)&&(methodInfos
[x].IsPublic || methodInfos[x].IsFamily) && (!(methodInfos[x].IsSpecialName)) ) {
SortTable MethodDetails = new SortTable("Name");
MethodDetails["Assembly"] = methodInfos[x].GetType().Assembly.GetName().Name;
MethodDetails["Name"] = methodInfos[x].Name;
MethodDetails["Type"] = methodInfos[x].ReturnType.Name;
if(( methodInfos[x].ReturnType.IsArray && methodInfos[x].ReturnType.Name !="Array") || methodInfos
[x].ReturnType.IsPointer) {
Type ReturnElementType = methodInfos[x].ReturnType.GetElementType();
while(ReturnElementType.IsArray) {
ReturnElementType = ReturnElementType.GetElementType();
}
MethodDetails["GetType"] = ReturnElementType.Name ;
MethodDetails["Namespace"] = ReturnElementType.Namespace ;
} else {
MethodDetails["GetType"] = methodInfos[x].ReturnType.Name;
MethodDetails["Namespace"] = methodInfos[x].ReturnType.Namespace ;
}
if (methodInfos[x].IsPublic == true) {
MethodDetails["Access"] = "public ";
} else if (methodInfos[x].IsPrivate == true) {
MethodDetails["Access"] = "private ";
} else if (methodInfos[x].IsFamily == true) {
MethodDetails["Access"] = "protected ";
}
if (methodInfos[x].IsStatic == true) {
MethodDetails["Access"] = ((String) MethodDetails["Access"]) + "static ";
}
System.Reflection.ParameterInfo[] paramInfos = methodInfos[x].GetParameters();
if (paramInfos != null) {
ArrayList paramTable = new ArrayList();
for (int y=0; y<paramInfos.Length; y++) {
SortTable paramDetails = new SortTable();
paramDetails["Assembly"] = paramInfos[y].GetType().Assembly.GetName().Name;
paramDetails["ParamName"] = paramInfos[y].Name;
paramDetails["ParamType"] = paramInfos[y].ParameterType.Name;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (35 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

if(( paramInfos[y].ParameterType.IsArray && paramInfos[y].ParameterType.Name != "Array" ) ||


paramInfos[y].ParameterType.IsPointer) {
paramDetails["GetType"] = paramInfos[y].ParameterType.GetElementType().Name ;
paramDetails["Namespace"] = paramInfos[y].ParameterType.GetElementType().Namespace ;
} else {
paramDetails["GetType"] = paramInfos[y].ParameterType.Name;
paramDetails["Namespace"] = paramInfos[y].ParameterType.Namespace ;
}
paramTable.Add(paramDetails);
}
MethodDetails["Params"] = paramTable;
}
this.Add(MethodDetails);
}
}
this.Sort();
}
}
public class DisplayInterfaces : ArrayList {
public DisplayInterfaces(Type classType) {
Type[] classInterfaces = classType.GetInterfaces();
for(int x = 0 ; x < classInterfaces.Length ; x++) {
SortTable interfaceDetails = new SortTable();
interfaceDetails["Assembly"] = classInterfaces[x].Assembly.GetName().Name;
interfaceDetails["FullName"] = classInterfaces[x].FullName;
interfaceDetails["GetType"] = classInterfaces[x].Name;
interfaceDetails["Namespace"] = classInterfaces[x].Namespace;
this.Add(interfaceDetails);
}
}
}
public class DisplaySuperclasses : ArrayList {
public DisplaySuperclasses(Type classType) {
Type SuperClass ;
SortTable classDetails = new SortTable();
classDetails["Assembly"] = classType.Assembly.GetName().Name;
classDetails["FullName"] = classType.FullName;
classDetails["GetType"] = classType.Name;
classDetails["Namespace"] = classType.Namespace;
this.Add(classDetails);
while (classType.BaseType != null) {
SortTable superclassDetails = new SortTable();
SuperClass = classType.BaseType ;
classType = SuperClass ;
superclassDetails["Assembly"] = SuperClass.Assembly.GetName().Name;
superclassDetails["FullName"] = SuperClass.FullName;
superclassDetails["GetType"] = SuperClass.Name;
superclassDetails["Namespace"] = SuperClass.Namespace;
this.Add(superclassDetails) ;
}
this.Reverse() ;

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (36 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

}
}
public class DisplaySubClasses : ArrayList {
private Type classType ;
private Module[] CorRuntime ;
private Type[] CorClasses;
private String myclassname ;
private Type[] classInterfaces;
public DisplaySubClasses(Type classtype, ArrayList ModuleName) {
this.classType = classtype;
myclassname = classType.FullName ;
if (classType.IsInterface ) {
for(int y = 0 ; y < ModuleName.Count ;y++) {
CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
CorClasses = CorRuntime[0].GetTypes() ;
for(int x= 0 ; x < CorClasses.Length; x++) {
classType = CorClasses[x];
classInterfaces = classType.GetInterfaces() ;
for(int i = 0 ; i < classInterfaces.Length ; i++) {
if(String.Compare(myclassname , classInterfaces[i].FullName )==0) {
SortTable subclassDetails = new SortTable("FullName");
subclassDetails["Assembly"] = classType.Assembly.GetName().Name;
subclassDetails["FullName"] = classType.FullName;
subclassDetails["GetType"] = classType.Name;
subclassDetails["Namespace"] = classType.Namespace;
this.Add(subclassDetails) ;
}
}
}
}
} else {
for(int y = 0; y < ModuleName.Count ; y++) {
CorRuntime = Assembly.Load(ModuleName[y].ToString()).GetModules();
CorClasses = CorRuntime[0].GetTypes();
for( int x= 0 ; x< CorClasses.Length ;x++) {
classType = CorClasses[x].BaseType ;
if ( null != classType ) {
if( String.Compare(classType.FullName, myclassname)==0) {
SortTable subclassDetails = new SortTable("FullName");
subclassDetails["Assembly"] = CorClasses[x].Assembly.GetName().Name;
subclassDetails["FullName"] = CorClasses[x].FullName;
subclassDetails["GetType"] = CorClasses[x].Name;
subclassDetails["Namespace"] = CorClasses[x].Namespace;
this.Add(subclassDetails) ;
}
}
}
}
}
this.Sort();
}

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (37 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

}
}

In the web.config file, there are far more assemblies than is desirable, to carry out a search for
the names of namespaces. In the a.aspx, we have not introduced too many structural changes.
The code is voluminous, but most of it has been explained earlier. Hence, we shall make a
quick run through.

In the Page_Load function, where life originates for our aspx application, we first display the
namespaces, depending upon the existence of a parameter called class in the Url.

• If the class parameter is available, all the details of that class are displayed, using the
function DisplayClass.
• If it is not present, a set of classes from the namespace, are displayed using the function
DisplayClassList.

The DisplayClassList function remains the same as before. Modifications have been
incorporated in the DisplayClass function. Where we had created one object earlier, which was
an instance of DisplayMethods, we now have created seven objects. All these classes reside in
the file b.cs. We therefore, have seven occurrences of the 'if' statement. They initialize seven
DataList objects DataSource members by these ArrayList types, when the Count property is
greater than zero. In their order of appearance, we have ArrayList objects that store details of
the following:

• Sub-classes
• Constructors
• Fields
• Methods
• Superclasses
• Interfaces

We start with a DataList named Namespace1 that displays the list of Namespaces in the first
column. Then, we have a div spnClassName that either displays the interface name or the class
name. As mentioned earlier, the table, td and tr tags are utilized for display purposes.

The DataList Classes store the class names, while the DataList Interfaces store the names of
the Interfaces belonging to a Namespace. To display the list of constructors, we use a DataList
called Constructors. In the template named headertemplate for constructors, we simply display
the headings' Visibility and Parameters in a tabular format. In the class DisplayConstructors,
indexers with names like Access and Name, are created and used in the itemtemplate.

There is always a likelihood of a complication stirring in situations, where the number can vary.
Here, the number of parameters passed to the constructor, varies. Hence, we need a DataList
within a DataList. The inner DataList is not assigned any name, but its DataSource member is
initialized to the indexer variable called Params. Params is an ArrayList with members having
the name of ParamType, etc. This is exactly what we had done earlier, in the case of methods.
There is no alteration in the basic ground rules.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (38 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

The mechanism employed to display different items, is as follows:

• To display the fields, a DataList called Fields is put into action.


• To display properties, a DataList called Properties is used.
• Superclasses are retrieved by a DataList called SuperClasses.
• Interfaces are retrieved by a DataList called Interface1.
• Sub-classes need their own DataList called SubClasses.

It is definitely not our concern, as to how the code that figured out the sub-classes, was written.
We are not going to get distracted by the C# code written by someone else. We shall primarily
focus on the presentation logic in the aspx file. The central idea of a class browser is that, some
C# code is responsible for creating an ArrayList. Thereafter, the DataList in the aspx file
displays it in a presentable form.

The main chunk of the source code lies in the classes present in the file b.cs. We have already
seen as to how methods are to be retrieved. The rest of the code is quite similar. Let us
commence with the mechanism for retrieving the constructors that are present in a specific
type.

The class that retrieves fields is called DisplayFields. It is derived from ArrayList. The GetFields
function is used to return an array of FieldInfo objects. The code to fill up the ArrayList object
remains the same as that used for methods. The class named DispalyConstructors uses the
function GetConstructors to generate a list of ConstructorInfo objects. Similarly, the class
called DisplayProperties uses the function GetPropeties to return a PropertyInfo array. Here,
one more function named GetSetMethod is added, which returns a null value, if the property
accessor has only a get accessor. The class DisplayInterfaces is similar to the method class.

We need to be acquainted with the class hierarchy, which consists of the list of all the classes
that a specific class is derived from, and also, all the classes that derive from it. The class
DisplaySuperclasses meets the requirement, but uses a very original approach.

We create an object SuperClass, derived from Type and a Hashtable object classDetails. We
initialize three indexer variables named FullName, GetType and Namespace, to the properties
FullName, Name and Namespace, which are present in the class Type, respectively. Then, we
append this data to the ArrayList class.

A Type has a property called dBaseType, which is set to null, whenever the Type has no base
Type. Putting it differently, only the Objects type will have the BaseType property set to null,
since all types are finally derived from the class Object. The while loop will repeat itself for the
number of types that we have derived from.

For each type, a Hashtable called superclassDetails is created and the SuperClass Type object
is initialized to the BaseType. This value is also stored in the parameter variable named
ClassType, because we shall lose the earlier value of SuperClass, in the next iteration of the
while loop. Once again, the FullName, GetType and Namespace indexer variables are initialized,
and thereafter, the new Hashtable object is added to the ArrayList.

The while loop stores data in the ArrayList in the reverse order. We intend to display the class

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (39 of 40)2/13/2007 4:54:35 PM


The Class Browser - ASP.NET - Beta2

Object first, leading upto the class whose details we are interested in. Thus, we need to reverse
the order of the data in the ArrayList.

file:///E|/STUDY/BOOKS/asp.net%20%20....%20vijay%20mukhi/chap9.htm (40 of 40)2/13/2007 4:54:35 PM