Sie sind auf Seite 1von 120

1

What is the .NET Framework?


(Page 1 of 6 )

".NET may be new to some of you, but it is there for more than 3 years. It was first shown to
industry in year 2000. Since then it has been making news. Well of course there are many fans and
many critics. What we want to know is what it is." This piece comes to us from December Contest
Finalist Naranjan Babu Kalla. Did he win? Check out this week's Developer Shed Newsletter to find
out!

What is .NET Framework?

.NET may be new to some of you, but it is there for more than 3 years. It was first shown to
industry in year 2000. Since then it has been making news. Well of course there are many fans and
many critics. What we want to know is what it is.

.NET is the framework for which we develop applications. It sits in between our application
programs and operating system. Applications developed for .NET run inside .NET and are controlled
by .NET. It supports both Windows and web applications.

Applications developed for .NET make use of the features of .NET. We will see more of features of
.NET later in this piece.

.NET provides an object oriented environment. It ensures safe execution of the code by performing
required runtime validations. For example, it is never possible to access an element of an array
outside the boundary. Similarly, it is not possible to a program to write into another programs area,
etc. The runtime validations performed by .NET makes the entire environment robust.

What is the .NET Framework? - Components of .NET


(Page 2 of 6 )

.NET framework has two main components. They are:

1. Common Language Runtime


2. .NET class library

Common Language Runtime

The Common Language Runtime (CLR) is the environment where all programs in .NET are run. It
provides various services, like memory management and thread management. Programs that run in
the CLR need not manage memory, as it is completely taken care of by the CLR. For example, when
a program needs a block of memory, CLR provides the block and releases the block when program
is done with the block.
3

All programs targeted to .NET are converted to MSIL (Microsoft Intermediate Language). MSIL is the
output of language compilers in .NET (see figure 2). MSIL is then converted to native code by JIT
(Just-in Time Compiler) of the CLR and then native code is run by CLR.

As every program is ultimately converted to MSIL in .NET, the choice of language is pure personal.
A program written in VB.NET and a program written in C# are both converted to MSIL. Then MSIL
is converted to native code and run. So, whether you write program in C# or VB.NET at the end it is
MSIL all that you get.

It is believed VB6.0 programmers will migrate to VB.NET and C++ and Java programmers switching
to .NET will prefer to use C# as it more resembles those languages.

For Java programmers, MSIL in .NET is same as Bytecode in concept. CLR is same as JVM (Java
virtual machine).

So the inevitable question is “Is .NET platform independent like Java?” The answer is technically
YES. A program written for .NET can run on any platform as long as .NET is made available on that
platform. As of now, .NET runs only on Windows. So, .NET is technically platform independent but
not reall, at least not now. Efforts are on to make .NET run on Linux. The project is called as Mono
and is currently being developed. Though some people doubt the seriousness of Microsoft, I will not
be surprised if Microsoft comes out with .NET on Linux in future. If that happens, all your VB.NET,
and C# programs can run as they are on both Windows and Linux. Who knows what more in store?

Figure-2: MSIL and CLR in .NET Framework

The code that is run under CLR is called Managed code.

What is the .NET Framework? - .NET Class Library


(Page 3 of 6 )

.NET comes with thousands of classes to perform all important and not-so-important operations. Its
library is completely object oriented, providing around 5000 classes to perform just about
everything.

The following are the main areas that are covered by Class library.

1. Data Structures
2. IO management
3. Windows and Web Controls
4. Database access
4

5. Multithreading
6. Remoting
7. Reflections

The above list is comprehensive and only to provide you an instant idea regarding how
comprehensive the library is.

The most fascinating part of .NET is the class library; it's common to all language of .NET. That
means the way you access files in VB.NET will be exactly same in C#, and in fact all other languages
of .NET. You learn library only for once, but use it in every language.

Also the library is common for all types of applications. The following are different types of
applications that can make use of .NET class library.

1. Console applications.
2. Windows GUI applications.
3. ASP.NET applications – web applications.
4. XML Web services.
5. Windows services.

So, you can leverage your knowledge of library irrespective of language and type of application you
are developing. I think it is the best thing that can happen to programmers. Imagine moving from
COBOL to C and then from C to VB. You learned how to perform common operations three times
because those three languages didn’t have any function in common.

What is the .NET Framework? - Features of .NET


(Page 4 of 6 )

The following are major features of .NET. We will use these features throughout out journey. Here
is just a brief introduction to all key features of .NET.

Assemblies

An assembly is either a .DLL or .EXE that forms a part of an application. It contains MSIL code that
is executed by CLR. The following are other important points related to an assembly:

1. It is the unit on which permissions are granted.


2. Every assembly contains a version
3. Assemblies contain interfaces and classes. They may also contain other resources such as
bitmaps, file etc.
4. Every assembly contains assembly metadata, which contains information about assembly.
CLR uses this information at the time of executing assembly.
5. Assemblies may be either private, which are used only by the application to which they
belong or Global assemblies, which are used by any application in the system.
6. Two assemblies of the same name but with different versions can run side-by-side allowing
applications that depend on a specific version to use assembly of that version.

The four parts of an assembly are:

Assembly Manifest - Contains name, version, culture, and information about referenced
assemblies.

Type metadata - Contains information about types defined in the assembly.

MSIL – MSIL code.

Resources - Files such as BMP or JPG file or any other files required by application.
5

Note: Assembly that contains only resources is called as Satellite assembly.

Common Type System

Common Type System (CTS) specifies the rules related to data types that languages must follow. As
programs written in all languages are ultimately converted to MSIL, data types in all languages
must be convertible to certain standard data types.

CTS is a part of cross-language integration, which allows classes written in one language to be used
and extended by another language.

Cross-language Interoperability

.NET provides support for language interoperability. However, it doesn’t mean every program written
in a language can be used by another language. To enable a program to be used with other
languages, it must be created by following a set of rules called Cross Language Specifications (CLS).

Cross-language inheritance is the ability to create a class in C# from a class created in VB.NET.

When an exception is raised by a program written in C#, the exception can be handled by VB.NET.
This kind of exception handling is called cross-language exception handling

What is the .NET Framework? - Application Development in .NET


(Page 5 of 6 )

.NET has brought a set of new features which are to be understood by every programmer
developing applications for Windows. There is no way any Windows programmer can ignore .NET,
unless he is desperate to be outdated. Microsoft will provide .NET as part of its operating systems in
future releases. It is the platform for programmers. It is not new OS from Microsoft or a new
language. It is the environment for which you develop applications. It is rich in terms of features.
Believe me, programming using VB.NET is fun and it is more productive than VB 6.0.

The following are different types of applications that can be developed in .NET:

Windows applications – typical Client/Server applications.

Web applications – Web sites and Intranet applications.

Web services – Programs that are accessible from anywhere using universal protocols like HTTP
and SOAP.

Console Applications – Simple console based applications without any GUI. Run from command
prompt. Best suited to learn fundamentals and also for applications such as server sockets.

Mobile Applications – Contain web pages that run in mobile devices such as PDAs (Personal
Digital Assistant) and Cell phones.

Though .NET supports many languages, I believe only two languages will dominate programming in
.NET: VB.NET and C#.

VB.NET is the successor to VB 6.0, but language wise, it was modified substantially as it became
complete OOPL – no more "object-based language."

C# resembles Java. Though Microsoft claims, C# resembles C++, but let's face it: it resembles Java
more than C++.
6

What is the .NET Framework? - Visual Studio.NET


(Page 6 of 6 )

VS.NET is the application development tool to develop applications for .NET. It supports
development of all types of applications that .NET supports. It also provides support for VB.NET
,C#, Visual C++.Net and Visual J# languages. VS.NET is a single environment that provides all tools
required to develop and debug applications.

The following are key features of Visual Studio.NET.

Languages supported - VS.NET supports application development using the language of your
choice. It also allows mixed language solutions.

IntelliSence - IntelliSense provides options that make programming in VS.NET easier than ever
before.

The following are important functions of intellisense.

1. Allows you to see the syntax of the method that you are calling
2. Completes the variable, command, or function name once you have entered enough
characters to disambiguate the term.
3. Displays the list of valid members for the class, structure or namespace you type so that
you can select one form the list. It places the selected member in your code.
4. Automatically brace matching allows whether ending brace is given after opening brace is
given.

If VS.NET finds any error in the code, it underlines the code with red line to remind user about the
error.

Editions of Visual Studio.Net

VS.NET comes in different editions. Each edition is meant for a specific kind of customers. The
following are different editions of VS.NET.

1. Professional
2. Enterprise Developer
3. Enterprise Architect
4. Academic

Both Enterprise Developer and Enterprise Architect editions come with extra features, such as
Commerce Server Developer Edition 2000, Exchange Server 2000 Developer Edition, and Visual
SourceSafe etc.

Enterprise Architect comes with Biztalk server 2000 developer edition, Visio-based software
modeling and database modeling.

The academic edition comes with tools for faculty related to assignment management, code samples
for faculty, and application wizards for students.

Creating a Nested Master Page


(Page 1 of 4 )
7

Master pages are a very useful new feature of ASP.NET 2.0. If you want to create web pages that
have a consistent look and feel, you can do so by using nested master pages. This article explains
how to go about it.

Introduction

In a professionally created web site, web pages have a consistent look and feel displaying the
graphics, controls, navigational features, and so on. Serving visually appealing rich content with
consistent functionality whether it is for navigation or other usability features is a must for a
satisfactory user experience. This has gone through an evolution of its own as mentioned in the
previous tutorial on Master Pages, a new feature you find in ASP.NET 2.0.

The present tutorial builds on the previous one, but for reader experience it can be read
independently. However, a reading of the previous tutorial would be very helpful. This tutorial takes
two master pages and plugs them into a master; you may call it the top or the parent. Now each of
these plugged-in master pages may show pages from their own module or compartment, sharing
the parent for a higher level look and feel. These three may very well be appropriate for a
corporation and two of its subsidiaries.

Before we look at the nested master pages, it may be instructive to look at a single master shown
schematically in the next picture (taken from the previous tutorial). The content page and the
master together are displayed when the content page is browsed. The content page is bare of HTML
and other namespace references. The displayed page is therefore a merged page as far as displayed
content goes.

Creating a Nested Master Page


- Nested Master Project
(Page 2 of 4 )

The following picture shows the files in the NestedMaster project. If you associate this file
structure with the schematic shown in the next sub-section you will immediately notice the way the
aspx files will be displayed.
8

The next picture shows schematically the arrangement of the pages and the relationship between
them in the context of how they get displayed. In the rest of the tutorial the code listing and the
screen shots are related to the file structure and the schematic arrangement shown.

There is one master page, the top.master, which has some content of its own. This is displayed by
the MPage.aspx.

Code for top.master

<%@ Master Language="VB" CodeFile="top.master.vb" Inherits="top" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
9

<title>Nested Master With Two Children</title>


</head>
<body>
<form id="form1" runat="server">
<h2 style="color:Maroon">Welcome to a Nested Master</h2>
<div>
<asp:contentplaceholder id="ContentPlaceHolder1"
runat="server">
</asp:contentplaceholder>
</div>
<h4 style="font-style:italic; color:Maroon;">

This was designed by Jay Krishnaswamy </h4>


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

Code for MPage.aspx

<%@ Page Language="VB"


AutoEventWireup="false"
CodeFile="Mpage.aspx.vb"
Inherits="Mpage"
MasterPageFile="~/top.master" %>
<asp:Content ID="content1"
ContentPlaceHolderID="ContentPlaceHolder1"
runat="server">
<h3 style="color:Blue;"> Welcome to the Visual Basic .NET Tutorials

</h3>
</asp:Content>
10

Creating a Nested Master


Page - Embedded master pages
(Page 3 of 4 )

In addition to the master page, there are two embedded master pages in the master, individually
called FChild.master and SChild.master. The listing shown in the next section is for the
FChild.master. Observe that the source of this page follows very nearly the same form as any other
content page, but it has another ContentPlaceHolder of its own. The FChild.master cannot be
displayed in the design view, as it is a kind of a virtual page.

Code for FChild.master

<%@ Master Language="VB"


MasterPageFile="~/top.master"
CodeFile="FChild.master.vb"
Inherits="FChild" %>
<asp:Content ID="Content2"
runat="server"
ContentPlaceHolderID="ContentPlaceHolder1">
<h3 style="color:Navy">Master's First Child </h3>
<asp:ContentPlaceHolder ID="Content1" runat="server" />
<h4 style="font-style:italic; color:Navy;">First Child
Designer</h4>
</asp:Content>

The FChild.master design page cannot be displayed; if you try, you will get the following message.
However you can code an aspx page to reveal it as shown in the following section. FPage.aspx
provides the content for the nested master file, FChild.master.

Source of FPage.aspx

<%@ Page Language="VB"


MasterPageFile="~/FChild.master"
AutoEventWireup="false"
CodeFile="FPage.aspx.vb"
Inherits="FPage" %>
<asp:Content ContentPlaceHolderID="Content1" runat="server">
<h4>Content for the Master's First Child</h4>
<table style="border-style:solid;border-width:medium;">
<tr style="background-color:yellow">
<td>Name</td><td>EMAIL</td>
</tr>
11

<tr>
<td>Jay Krishnaswamy</td><td>htek@mysorian.com</td>
</tr>
</table>
</asp:Content>

Code for SChild.master

<%@ Master Language="VB"


MasterPageFile="~/top.master"
CodeFile="SChild.master.vb"
Inherits="SChild" %>
<asp:Content runat="server"
ContentPlaceHolderID="ContentPlaceHolder1">
<h3 style="font-weight:500; color:Fuchsia;"> Master's Second Child </h3>
<asp:contentplaceholder id="Content2"
runat="server">
</asp:contentplaceholder>
<h4 style="font-style:italic;color:Fuchsia;"> Second Child Designer</h4>
</asp:Content>

As discussed in the previous section, this SChild.master cannot be displayed in the design view.
However we can develop some content to show this nested master page by using the code shown in
the next section.

Source of SPage.aspx

<%@ Page Language="VB"


MasterPageFile="~/SChild.master"
AutoEventWireup="false"
CodeFile="SPage.aspx.vb"
Inherits="SPage" %>
<asp:Content ID="Content3"
ContentPlaceHolderID="Content2"
runat="server">
<h4>Content for the Master's Second Child</h4>
<img src=http://images.devshed.com/af/stories/images/usa-small.gif
12

alt="US Flag"/>
</asp:Content>

This page will be displayed as shown when it is opened by Internet Explorer.

Creating a Nested Master Page - What


can go wrong?
(Page 4 of 4 )

It is important that you establish the container and the contents correctly, otherwise you may have
unexpected results. The following shows the relationships that must exist for the above displayed
pages:

Master (Parent) has a ContentPlaceHolder1


------------------------------------------------------------------
First Child (FChild):
Content's ContentPlaceHolderID=ContentPlaceHolder1
ContentPlaceHolder ID=Content1
Second Child (SChild):
Content's ContentPlaceHolderID=ContentPlaceHolder1
ContentPlaceHolder ID=Content2
-------------------------------------------------------------------
Mpage.aspx points to -->MasterPageFile="~/top.master"
FPage.aspx points to--->MasterPageFile="~/FChild.master", Content1
SPage.aspx points to--->MasterPageFile="~/SChild.master", Content2

However the good news is that you get ample help from drop-down cues and only the appropriate
control will be shown as seen in the next picture when the developer is about to set the
MasterPageFile. Presently he is trying to set this attribute for the MPage.aspx which should be
top.master from the drop-down.
13

Summary

The Master Page feature in ASP.NET 2.0 makes it very easy to create web pages which have
a consistent look and feel. The other features like web wizard, themes, skins, and so forth make it
extremely useful for composing rich web pages. Nested pages are an example of visual inheritance
and shown only for one level of nesting, but nesting can be extended for more levels as well.

Developing XSLT-based Applications in ASP.NET 2.0


(Page 1 of 7 )

This is the first article in a series focused on developing XSLT-oriented applications using ASP.NET
2.0. Even though the title includes ASP.NET 2.0, I use it only as a transformation engine. The entire
focus will be on working with XSLT. You can use any transformation engine according to your
requirements (such as Java or others).
A downloadable zip file is available for this article.

The entire solution (source code) for this article is available as a free download in the form of a zip
file. All the applications in this series have been developed using Microsoft Visual Studio 2005
Professional Edition on Microsoft Windows Server 2003 Standard Edition together with Microsoft SQL
Server 2005 Developer Edition as the database. I didn’t really test any of the code in any of the
other tools/IDEs/servers/editions/versions. If you have any problems, please feel free to post in
the discussion area.

How to transform XML to XSLT using ASP.NET 2.0

Transforming XML to XSLT using ASP.NET 2.0 is quite easy. Working with the XML control (available
in the toolbox) makes it easy to transform any XML document to the specified XSLT.

As it is a bit tedious to always author XML documents, I simply converted the output of a result set
(or dataset) to an XML document by using the following method:

Private Function getXMLContent(ByVal SQL As String) As XmlDocument

Dim ds As New DataSet("SQLData")

Dim da As New SqlDataAdapter(SQL, "data


source=laptop2k3sql2k5;initial catalog=AdventureWorks;user
id=sa;password=eXpress2005")

da.Fill(ds, "Rows")

da.Dispose()

Dim sw As New System.IO.StringWriter


14

ds.WriteXml(sw)

ds.Dispose()

Dim docXML As New XmlDocument

docXML.LoadXml(sw.ToString())

sw.Close()

Return docXML

End Function

The above method accepts a SELECT query and returns XML in the form of an object of type
“XmlDocument.” You may need to modify the above method to suit your production requirements.

Now, let us see how to transform the XML document to the specified XSLT. The following is the code
used to achieve the same:

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As


System.EventArgs) Handles Button1.Click

Dim docXML As XmlDocument = getXMLContent("select EmployeeID,


FirstName, JobTitle from HumanResources.vEmployee")

Me.txtXML.Text = docXML.InnerXml

Dim xp As New XPath.XPathDocument(New XmlTextReader(New


IO.StringReader(docXML.InnerXml)))

Xml1.XPathNavigator = xp.CreateNavigator

Xml1.TransformSource = Server.MapPath("XSLTFile01.xsl")

End Sub

To work with the above code, you need to drag and drop an XML control from the toolbox onto the
web page. You may have to modify the name of the XSLT file according to your design or theme.

Developing XSLT-based Applications in ASP.NET 2.0 - Testing XSLT using ASP.NET 2.0
(Page 2 of 7 )

When the button is clicked (as given in previous section), it generates an XML document (from the
database), which is similar to the following hierarchy:

<SQLData>

<Rows>

<EmployeeID>1</EmployeeID>
15

<FirstName>Guy</FirstName>

<JobTitle>Production Technician - WC60</JobTitle>

</Rows>

<Rows>

<EmployeeID>2</EmployeeID>

<FirstName>Kevin</FirstName>

<JobTitle>Marketing Assistant</JobTitle>

</Rows>

</SQLData>

The following is the first sample XSLT to test:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<b>

<xsl:value-of select="SQLData/Rows/FirstName"/>

</b>

</xsl:template>

</xsl:stylesheet>

When the XML document gets transformed based on the above XSLT, it displays the “FirstName” of
the first employee in bold. The result of the above transformation would be similar to the following:

<b>

Guy
16

</b>

The first and the most important construct is the following:

<xsl:template match="/">

</xsl:template>

Any construct starting with “xsl:template” is called a “template.” The template is a blueprint for
transformation. In the above case, it checks whether the current “context” is at “root” or not. If the
“context” is at root, the template available within the construct is applied.

The following is the body of above template:

<b>

<xsl:value-of select="SQLData/Rows/FirstName"/>

</b>

The above transforms the first value (or text) available in “SQLData/Rows/FirstName” to display as
bold.

Developing XSLT-based Applications in ASP.NET 2.0 - Separating templates from the root
template
(Page 3 of 7 )

Let us consider the following XSLT:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>

</b>

</xsl:template>

</xsl:stylesheet>
17

The above XSL simply transforms only the text available in the “FirstName” tag (at any location in
the document). All the rest would be directly displayed without any transformation.

If you wanted to handle the “FirstName” separately from root, you can rewrite the above XSLT as
follows:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates />

</xsl:template>

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>

</b>

</xsl:template>

</xsl:stylesheet>

The above includes both root and “FirstName” templates. According to the above XSLT, when it
finds “FirstName,” it goes to the template defined outside the root template.

If you forget to provide the following statement:

<xsl:apply-templates />

it would be a blank template and nothing would get displayed (or transformed).

Developing XSLT-based Applications in ASP.NET 2.0 - Defining templates for particular


tags
(Page 4 of 7 )

In the previous section, we observed that we can include any number of templates according to our
requirements. Now, let us consider how we would extract only the “FirstName” (without any other
data) and transform it using the template. The following code handles this task:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"
18

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates select="SQLData/Rows/FirstName" />

</xsl:template>

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>

</b>

<br />

</xsl:template>

</xsl:stylesheet>

You need to observe only the following statement from the above XSLT:

<xsl:apply-templates select="SQLData/Rows/FirstName" />

That statement particularly says that it needs to apply a separate template (if available) if it finds
“FirstName” at the path “SQLData/Rows.”

In the above case, it searches for “FirstName” only at the path “SQLData/Rows.” Let us
consider defining and applying a template for “FirstName” available at any path. You may need to
modify the above code to the following to achieve the same:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates select="//FirstName" />

</xsl:template>

<xsl:template match="FirstName">

<b>
19

<xsl:value-of select="."/>

</b>

<br />

</xsl:template>

</xsl:stylesheet>

When you precede the path with “//” it reflects to “any path.”

Developing XSLT-based Applications in ASP.NET 2.0 - Working with all siblings available
at a particular path
(Page 5 of 7 )

Let us now consider working with more than one tag at a time (belonging to the same row or
siblings). The following code sample achieves the same:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates select="SQLData/Rows" />

</xsl:template>

<xsl:template match="SQLData/Rows">

<xsl:value-of select="EmployeeID"/>,

<b>

<xsl:value-of select="FirstName"/>,

</b>

<br />

</xsl:template>

</xsl:stylesheet>

From the above you can understand that I defined a new template for “SQLData/Rows.” Within that
template, I am extracting “EmployeeID” and “FirstName” and transforming them according to our
needs.
20

Let us now further extend the above XSLT to have sibling level and tag level templates as shown in
the following:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates select="SQLData/Rows" />

</xsl:template>

<xsl:template match="SQLData/Rows">

<xsl:value-of select="EmployeeID"/>,

<xsl:apply-templates select="FirstName" />

<br />

</xsl:template>

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>,

</b>

</xsl:template>

</xsl:stylesheet>

As you can see, you can define and work with any number of templates at various levels according
to your needs.

Developing XSLT-based Applications in ASP.NET 2.0 - Transforming XML data to HTML


tables using XSLT
(Page 6 of 7 )

Since we are now a bit more familiar with templates, let us go for a practical example. I would like
to display employee information in the form of an HTML table (by using only templates). The
following code achieves the same:

<?xml version="1.0" encoding="utf-8"?>


21

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<table border="1">

<xsl:apply-templates select="SQLData/Rows" />

</table>

</xsl:template>

<xsl:template match="SQLData/Rows">

<tr>

<td><xsl:value-of select="EmployeeID"/> </td>

<td><xsl:apply-templates select="FirstName" /></td>

</tr>

</xsl:template>

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>

</b>

</xsl:template>

</xsl:stylesheet>

In the root tag, I am simply emitting a TABLE tag. In the “Rows” template, I am emitting TR and TD
tags. The TD tags will be filled with the values extracted using “xsl:value-of.”

Is there any possibility of achieving this without using templates at all? Yes. You can still do it. Go
through the following example:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
22

<xsl:template match="/">

<table width="50%" cellspacing="0" cellpadding="0" style="font-


family:verdana;font-size:X-Small" border="1">

<tr bgcolor="#336699">

<th align="left">

<font color="White">EmployeeID</font>

</th>

<th align="right">

<font color="White">FirstName</font>

</th>

</tr>

<xsl:for-each select="SQLData/Rows">

<tr>

<td align="left">

<xsl:value-
of select="EmployeeID" />

</td>

<td align="right">

<xsl:value-
of select="FirstName" />

</td>

</tr>

</xsl:for-each>

</table>

</xsl:template>

</xsl:stylesheet>
23

The above is only for your understanding. My upcoming articles will explain these new concepts in a
detailed fashion.

Developing XSLT-based Applications in ASP.NET 2.0 - Parsing through previous and next
siblings using XSLT
(Page 7 of 7 )

Let us consider the following XSLT:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<xsl:apply-templates select="SQLData/Rows/FirstName" />

</xsl:template>

<xsl:template match="FirstName">

<b>

<xsl:value-of select="."/>

</b>

<br />

</xsl:template>

</xsl:stylesheet>

From the above you can understand that it displays all “FirstName” related information in
bold. What if I want to display the “EmployeeID” along with the “FirstName?” In the above path, I
didn’t specify “EmployeeID” at all and the template simply belongs to “FirstName.”

Now within the “FirstName” template, I would like to access the “EmployeeID.” It is the previous tag
at the same level (or it is simply a preceding sibling). The following will help you understand how to
access previous and next siblings:

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
24

<xsl:apply-
templates select="SQLData/Rows/FirstName" />

</xsl:template>

<xsl:template match="FirstName">

<xsl:value-of select="./preceding::EmployeeID[1]"/> -

<b>

<xsl:value-of select="."/>

</b> -

<xsl:value-of select="./following::JobTitle[1]"/>,

<br />

</xsl:template>

</xsl:stylesheet>

The power of using XSLT solely depends on your grasp of XPath. I strongly suggest you to learn
XPath before you learn XSLT. You can also find different utilities on this web site for learning
XPath. Good luck.

Building a Loan Payment Calculator using ASP.NET 2.0


(Page 1 of 5 )

Making payments to loans for a home or a car is a fact of life. This tutorial is about creating a loan
calculator using ASP.NET 2.0. We will be looking at fixed interest loans which are normally quoted
for 30, 15, and 10 years.

This type of loan requires you to pay back equal installments over the period of the loan. In the
early part of your loan you will be paying more interest and less principal, and towards the end of
the loan period more principal and less interest. There is a plethora of financial loan products apart
from this kind of loan. What is assumed in the fixed interest loan is that the rate does not vary
during the life of the loan.

In this tutorial we will be asking the question, suppose one borrows $10,000.00 at an interest
of eight percent per annum (per year), to be paid back in 10 months -- what will the monthly
payment be? Since banks and loan companies want you to pay on a fixed date each month, your
payment may vary depending on whether you make the payment at the beginning of the pay period
or the end.

The interest rate, present value of a loan, future value of a loan, the agreed-to number of payments
and the payment per payment period are all inter-related. These are represented by functions in
Microsoft Visual Basic. The graphic user interface packages this function in an application with some
validation.

The Financial Web Site


25

Start a new web site from the file menu. In this tutorial it is called the Financials, at
http://localhost/Financials. Add a web page. This page will be named finPMT.aspx and is the
container for your loan payment calculator. In ASP.NET 2.0, in addition to other system namespaces
you also have the Microsoft.VisualBasic. The various financial variables used in this application can
all be located on the Object Browser as shown in this picture. The highlighted object is the PMT
function that will be used. There is a lengthy explanation of how this function works. The arguments
that go into this function are clearly explained.

The PMT Function basics

The definition of this function as seen in the object browser is as follows:

Public Function Pmt (ByVal Rate As Double,


ByVal Nper As Double,
ByVal PV As Double,
26

Optional ByVal FV As Double = 0.0


Optional ByVal Due As
Microsoft.VisualBasic.DueDate = _
EndOfPeriod) As Double

The graphic user interface will take the input from the text boxes for the Rate, Nper, PV, FV, and
DueDate. This is inserted into the above formula and the result is the payment (PMT) that must be
paid each period. Since the values that are entered into text boxes are of the string type you will
need to convert them to the proper data type. Hence some data conversions are necessary.

Building a Loan Payment Calculator using ASP.NET 2.0 - The description of the payment
calculator
(Page 2 of 5 )

The design view of the finPMT.aspx page is shown in the next picture. In order to enter the
arguments for the function there are text boxes; these are all placed in table cells. After inserting
the Table control from the Toolbox, you can change the number of rows and columns, add a
border, color the body of the table, and so forth. Also by highlighting columns or rows to be merged,
you can merge columns and rows from the drop-down menu which pops up when you click the Table
menu item in the main menu.

The future value has been taken as optional since we all wish our loan to be completely paid
off. Also whether you pay at the beginning of the month or at the end of the month makes some
difference. But all these points will be included in our calculator. At run time you enter values for
Rate, Nper, present (PV) and future (FV) values, pick a method of payment and click the button to
get your answer. Loan and annuity are interchangeably used.

In the design view, you also see various items in the messages column as well as below the button.
These will be described a little later in the tutorial. Also you see a set of test values that you can use
to test your calculator. If things are working right, these test input values should give the loan
payment shown
27

finPMT.aspx page
(Page 3 of 5 )

This code file is called the finPMT.aspx.vb. It contains the code for the events that are invoked by
the finPMT.aspx page, like loading the page, clicking the mouse, and so forth. The next paragraph
shows the code that is executed when the button is clicked.

Partial Class finPMT


Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, ByVal _
e As System.EventArgs) Handles Button1.Click
Dim dfpmt As Double
If rbStart.Checked Then
dfpmt = Pmt(CDbl((txtRate.Text) * (0.01 / 12)), _
CDbl(txtNper.Text), CDbl(txtPV.Text), _
CDbl(txtFV.Text), DueDate.BegOfPeriod)
Else
If rbEnd.Checked Then
dfpmt = Pmt(CDbl((txtRate.Text) * (0.01 / 12)), _
CDbl(txtNper.Text), CDbl(txtPV.Text), _
28

CDbl(txtFV.Text), DueDate.EndOfPeriod)
End If
End If
TextBox1.Text = Format(dfpmt, "$##,######.00")
End Sub
End Class

Testing the page

Right click the finPMT.aspx in the solution explorer and click on the drop-down menu item named
View in Browser. This brings up the aspx page in the IE browser. For starters just insert the test
values and verify that the payment from the payment calculator matches the one shown under Test
Values.

Building a Loan Payment


Calculator using ASP.NET 2.0 - Use of validation controls
(Page 4 of 5 )
29

Validation controls have been added to the design view to make sure values are inserted into the
required text boxes and inserted values do not violate some basic rules. The validator controls can
be dragged and dropped into the required cells in the Messages column of the table.

RequiredFieldValidators

In the design view of the finPMT.aspx page you may see a number of validation controls in the
Messages column. For example, "Enter a number" for all the text boxes relates to the
RequiredFieldValidators. Although they read "Enter a number," what is really meant by the
RequiredFieldValidator is that the text boxes should not be empty. These are checked as you enter
the values. To test them just hit the button without making entries to any of the boxes. You will be
asked to enter a number before you can proceed. The properties of the RequiredFieldValidator1 in
the first row are as shown in the next picture.

RegularExpressionValidator

You will find this validator in the first row, which has the error message, "Only numbers allowed."
The reason for this is that, since this text box takes a rate, some users may enter something like
7% instead of 7. This validator would caution the user to change it to a number. The w in the
Validator Expression property would trigger any violation of this rule. The regular expression for
30

number is w. If you need to know more about regular expressions that you can use in the VS 2003
IDE you need to look up the regex classes located in the namespace
System.Text.RegularExpressions.

RangeValidator

In the second row in the design view, in addition to a RequiredFieldValidator there is an additional
RangeValidator. This calculator is configured for a loan life of 30 years which is 360 pay periods. Its
value can range from 1 to 360. Any other number in this text box will not be validated. The
RangeValidator property in the second row is shown in the next picture.
31

Building a Loan Payment Calculator using ASP.NET 2.0 -


Source code for the finPMT.aspx page
(Page 5 of 5 )

<%@ Page Language="VB"


AutoEventWireup="false"
CodeFile="finPMT.aspx.vb"
Inherits="finPMT" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body><h2 style="color:Navy;">Periodic Payment on a Loan</h2>
<form id="form1" runat="server">
32

<table style="width: 506px; height: 312px; font-weight: bold;


color: #009999; background-color: #ccffff;"
border="1" cellpadding="1" cellspacing="2"
title="Periodic Payment on a Loan">
<tr>
<td style="width: 260px">
Loan related item</td>
<td style="width: 25px">
Entries / <span style="color: #ff0066">Result</span>

</td>
<td style="width: 82px">
Messages</td>
</tr>
<tr>
<td style="width: 260px">
Rate of interest per period</td>
<td style="width: 25px">
<asp:TextBox ID="txtRate" runat="server">

</asp:TextBox></td>
<td style="width: 82px">
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="txtRate"
ErrorMessage="Enter a number">
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator

ID="RegularExpressionValidator1"
runat="server" ControlToValidate="txtRate"
ErrorMessage="Only numbers allowed"
ValidationExpression="w">
</asp:RegularExpressionValidator></td>
</tr>
<tr>
<td style="width: 260px">
Total number of payment periods in an annuity (Loan)

</td>
<td style="width: 25px">
<asp:TextBox ID="txtNper" runat="server">

</asp:TextBox></td>
<td style="width: 82px">
<asp:RequiredFieldValidator ID=

"RequiredFieldValidator2"
runat="server" ControlToValidate="txtNper"
ErrorMessage="Enter a number">
</asp:RequiredFieldValidator>
<asp:RangeValidator ID="RangeValidator1" runat="server"
ControlToValidate="txtNper"
ErrorMessage="Should be between 1 and 360"

MaximumValue="360"
MinimumValue="1">
</asp:RangeValidator></td>
</tr>
<tr>
<td style="width: 260px">
Present Value of annuity (Loan)</td>
<td style="width: 25px">
33

<asp:TextBox ID="txtPV" runat="server">

</asp:TextBox></td>
<td style="width: 82px">
<asp:RequiredFieldValidator ID=

"RequiredFieldValidator3"
runat="server" ControlToValidate="txtPV"
ErrorMessage="Enter a number" Width="100px">
</asp:RequiredFieldValidator></td>
</tr>
<tr>
<td style="width: 260px">
Future value of annuity (Loan)</td>
<td style="width: 25px">
<asp:TextBox ID="txtFV" runat="server">

</asp:TextBox></td>
<td style="width: 82px">
<asp:RequiredFieldValidator ID=

"RequiredFieldValidator4"
runat="server" ControlToValidate="txtFV"
ErrorMessage="Enter a number">

</asp:RequiredFieldValidator></td>
</tr>
<tr>
<td style="width: 260px">
When payment due, at the beginning or end of pay

period</td>
<td colspan="2">
<asp:RadioButton ID="rbStart" runat="server"

Checked="True"
GroupName="opt" Text="Start" /><br />
<br />
<asp:RadioButton ID="rbEnd" runat="server"
GroupName="opt" Text="End" /></td>
</tr>
<tr>
<td style="width: 260px">
<asp:Label ID="Label1" runat="server"
Text="Payment per Period" Width="161px"
ForeColor="#C00000">
</asp:Label></td>
<td colspan="3">
<asp:TextBox ID="TextBox1" runat="server"
Width="256px">
</asp:TextBox></td>
</tr>
</table>
<br />
<asp:Button ID="Button1" runat="server"
Text="What is the payment per period?" /><br />
<br />
<br />

<br />
</form>
<span style="color:red; font-weight:bold; text-decoration:underline">
Test Values<br />
34

</span>
<span style="color:blue;font-weight:300">
Rate of Interest 7%<br />
Present Value of Loan: 165000<br />
Future value of Loan: 0.0<br />
Number of Payments (30 Years): 360<br />
DueDate: End<br />
<span style="color: red">
Payment=1097.75<br />
</span>
</span>
</body>
</html>

Summary

In ASP.NET 2.0 you can directly use Microsoft's Visual Basic functions, of which the Financials is a
subset. Some validation controls are implemented; these are by no means complete as one cannot
foresee all kinds of user inputs. The calculator must function as designed. These functions may also
be implemented as a web service.

Binding Data to the ReportViewer Control Dynamically in


ASP.NET 2.0
(Page 1 of 6 )

This is the second article in a series focusing on designing and presenting native reports using
ASP.NET 2.0. Throughout this series, I will focus on working with the “ReportViewer” control in local
mode to develop web-based applications.
A downloadable zip file is available for this article.

If you are new to working with the ReportViewer control, I strongly suggest you go through my first
article in this series. That article really gives you a step-by-step approach to working with the
ReportViewer control.

The entire source code for this article is available in the form of a downloadable zip file. The solution
was developed using Microsoft Visual Studio 2005 Professional Edition on Microsoft Windows Server
2003 Enterprise Edition together with Microsoft SQL Server 2005 Developer Edition. I didn’t really
test the solution with any other or previous editions.

Binding a SELECT statement to a ReportViewer control in ASP.NET 2.0: design

I discussed several types of reporting strategies to implement in ASP.NET 2.0 applications in my first
article. I also gave a step-by-step approach to working with the ReportViewer control in the same
article. So I will not be repeating any of that material here.

In my previous article, I developed reports by directly connecting to database tables/views. That


scenario won't be helpful every time. Let us imagine that I would like to develop a report based on a
dynamic SELECT statement. This is a little bit tricky when compared to the approach I discussed in
my previous article.

First of all, we need to keep in mind that any “table” in a report (at local mode) must adhere to a
structure. This structure will generally be a “strongly-typed-dataset.” Without creating a strongly-
typed-dataset, it is very difficult to design a report. Creating a strongly-typed-dataset was covered
in my previous article.
35

Even now, to bind a report to a SELECT statement, we need to create a strongly-typed-dataset


which contains exactly the same columns we retrieve using the SELECT statement. In other words,
we will make filters, joins, sorting etc. dynamic, but not the structure (or set of columns). The
structure (or set of columns) must always remain the same when designing or developing reports.

For this scenario, I created a strongly-typed-dataset (called SalesData.xsd) as follows.

It is simply a data table (dragged from the toolbox) with user specific columns. It has no relation to
any database, and no tableadapters are created.

I added a new report (called SampleReport.rdlc) to the project and attached it to the dataset as
follows:

Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0 - Binding a SELECT
statement to a ReportViewer control in ASP.NET 2.0: code
(Page 2 of 6 )

Once you have created the datasets and reports as given in the previous section, we need to work
with the ReportViewer control to render the data based on the dynamic SELECT.

Drag a ReportViewer control onto the default.aspx and modify your code-behind file in such a way
that it looks something like the following:

ImportsMicrosoft.Reporting.WebForms

ImportsSystem.Data

ImportsSystem.Data.Sqlclient

PartialClass _Default

Inherits System.Web.UI.Page
36

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)


Handles Me.Load

'Set the processing mode for the ReportViewer to Local

ReportViewer1.ProcessingMode = ProcessingMode.Local

Dim rep As LocalReport = ReportViewer1.LocalReport

rep.ReportPath = "SampleReport.rdlc"

Dim ds As DataSet = GetSalesData()

'Create a report data source for the sales order data

Dim dsSalesOrder As New ReportDataSource()

dsSalesOrder.Name = "SalesData_Data"

dsSalesOrder.Value = ds.Tables("SalesData")

rep.DataSources.Add(dsSalesOrder)

End Sub

Private Function GetSalesData()

Dim ds As New DataSet

Dim sqlSalesData As String = _

"SELECT SalesPersonID, FirstName, " & _

" SalesQuota, SalesYTD, SalesLastYear " & _

"FROM Sales.vSalesPerson "

Using connection As New SqlConnection( _

"Data Source=(local)sql2k5; " & _

"Initial Catalog=AdventureWorks; " & _

"Integrated Security=SSPI")

Dim command As New SqlCommand(sqlSalesData,


connection)

Dim salesOrderAdapter As New SqlDataAdapter(command)

salesOrderAdapter.Fill(ds, "SalesData")

salesOrderAdapter.Dispose()

command.Dispose()
37

End Using

Return ds

End Function

EndClass

Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0 - Binding an XML
document to a ReportViewer control in ASP.NET 2.0
(Page 3 of 6 )

XML Document

In previous sections, I demonstrated how to work with a simple SELECT statement and bind it to
the ReportViewer control. Now, I shall demonstrate how to bind an XML document to the
ReportViewer control.

Before binding, we need to add an XML document to our project (called SalesDataFile.xml) with a
structure that exactly matches that of the dataset created in the previous sections. It is also
recommended that we have the schema reference the same dataset.

The following is the simple XML document I created for the purpose of this demonstration.

<?xml version="1.0" encoding="utf-8"?>

<SalesData xmlns="http://tempuri.org/SalesData.xsd">

<Data>

<SalesPersonID>1001</SalesPersonID>

<FirstName>Jag</FirstName>

<SalesQuota>20000</SalesQuota>

<SalesYTD>21000</SalesYTD>

<SalesLastYear>19000</SalesLastYear>

</Data>

<Data>

<SalesPersonID>1002</SalesPersonID>

<FirstName>Chat</FirstName>

<SalesQuota>30000</SalesQuota>

<SalesYTD>32000</SalesYTD>

<SalesLastYear>15000</SalesLastYear>
38

</Data>

<Data>

<SalesPersonID>1003</SalesPersonID>

<FirstName>Winner</FirstName>

<SalesQuota>25000</SalesQuota>

<SalesYTD>19000</SalesYTD>

<SalesLastYear>25000</SalesLastYear>

</Data>

<Data>

<SalesPersonID>1004</SalesPersonID>

<FirstName>Dhan</FirstName>

<SalesQuota>15000</SalesQuota>

<SalesYTD>30000</SalesYTD>

<SalesLastYear>21000</SalesLastYear>

</Data>

</SalesData>

From the above document you can observe that the root element will be nothing but the dataset
name. Each row gets stored in the form of “Data” (or data table within the dataset). And every
row is framed with the columns exactly matching the dataset we created earlier.

Source Code

Add a new web form (called XMLbasedReport) and drag a ReportViewer control onto it. Modify your
code-behind file in such a way that it looks something like the following:

ImportsMicrosoft.Reporting.WebForms

ImportsSystem.Data

PartialClass XMLbasedReport

Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)


Handles Me.Load
39

'Set the processing mode for the ReportViewer to Local

ReportViewer1.ProcessingMode = ProcessingMode.Local

Dim rep As LocalReport = ReportViewer1.LocalReport

rep.ReportPath = "SampleReport.rdlc"

Dim ds As DataSet = GetSalesData()

'Create a report data source for the sales order data

Dim dsSalesOrder As New ReportDataSource()

dsSalesOrder.Name = "SalesData_Data"

dsSalesOrder.Value = ds.Tables("Data")

rep.DataSources.Add(dsSalesOrder)

End Sub

Private Function GetSalesData()

Dim ds As New DataSet

'ds.ReadXml(Server.MapPath("SalesDataFile.xml"))

ds.ReadXml(HttpContext.Current.Request.MapPath("SalesDataFile.xml"))

Return ds

End Function

EndClass

The heart of the above code is the following statement:

ds.ReadXml(HttpContext.Current.Request.MapPath
("SalesDataFile.xml"))

The above statement reads the entire XML document and gets populated in the form of a dataset.

You can also work with the XMLDataSource control to deal with this scenario. I shall cover that in
my upcoming articles.

Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0 - Binding an XML
document to a ReportViewer control in ASP.NET 2.0
(Page 3 of 6 )

XML Document

In previous sections, I demonstrated how to work with a simple SELECT statement and bind it to
the ReportViewer control. Now, I shall demonstrate how to bind an XML document to the
ReportViewer control.
40

Before binding, we need to add an XML document to our project (called SalesDataFile.xml) with a
structure that exactly matches that of the dataset created in the previous sections. It is also
recommended that we have the schema reference the same dataset.

The following is the simple XML document I created for the purpose of this demonstration.

<?xml version="1.0" encoding="utf-8"?>

<SalesData xmlns="http://tempuri.org/SalesData.xsd">

<Data>

<SalesPersonID>1001</SalesPersonID>

<FirstName>Jag</FirstName>

<SalesQuota>20000</SalesQuota>

<SalesYTD>21000</SalesYTD>

<SalesLastYear>19000</SalesLastYear>

</Data>

<Data>

<SalesPersonID>1002</SalesPersonID>

<FirstName>Chat</FirstName>

<SalesQuota>30000</SalesQuota>

<SalesYTD>32000</SalesYTD>

<SalesLastYear>15000</SalesLastYear>

</Data>

<Data>

<SalesPersonID>1003</SalesPersonID>

<FirstName>Winner</FirstName>

<SalesQuota>25000</SalesQuota>

<SalesYTD>19000</SalesYTD>

<SalesLastYear>25000</SalesLastYear>

</Data>
41

<Data>

<SalesPersonID>1004</SalesPersonID>

<FirstName>Dhan</FirstName>

<SalesQuota>15000</SalesQuota>

<SalesYTD>30000</SalesYTD>

<SalesLastYear>21000</SalesLastYear>

</Data>

</SalesData>

From the above document you can observe that the root element will be nothing but the dataset
name. Each row gets stored in the form of “Data” (or data table within the dataset). And every
row is framed with the columns exactly matching the dataset we created earlier.

Source Code

Add a new web form (called XMLbasedReport) and drag a ReportViewer control onto it. Modify your
code-behind file in such a way that it looks something like the following:

ImportsMicrosoft.Reporting.WebForms

ImportsSystem.Data

PartialClass XMLbasedReport

Inherits System.Web.UI.Page

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)


Handles Me.Load

'Set the processing mode for the ReportViewer to Local

ReportViewer1.ProcessingMode = ProcessingMode.Local

Dim rep As LocalReport = ReportViewer1.LocalReport

rep.ReportPath = "SampleReport.rdlc"

Dim ds As DataSet = GetSalesData()

'Create a report data source for the sales order data

Dim dsSalesOrder As New ReportDataSource()

dsSalesOrder.Name = "SalesData_Data"

dsSalesOrder.Value = ds.Tables("Data")
42

rep.DataSources.Add(dsSalesOrder)

End Sub

Private Function GetSalesData()

Dim ds As New DataSet

'ds.ReadXml(Server.MapPath("SalesDataFile.xml"))

ds.ReadXml(HttpContext.Current.Request.MapPath("SalesDataFile.xml"))

Return ds

End Function

EndClass

The heart of the above code is the following statement:

ds.ReadXml(HttpContext.Current.Request.MapPath
("SalesDataFile.xml"))

The above statement reads the entire XML document and gets populated in the form of a dataset.

You can also work with the XMLDataSource control to deal with this scenario. I shall cover that in
my upcoming articles.

Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0 - Binding a


customized ObjectDataSource (or business logic) to a ReportViewer control in ASP.NET
2.0
(Page 5 of 6 )

In general, every project contains several classes to deal with business logic. Sometimes I may
need reports based on the logic/data given through business logic classes. I try to cover this
scenario in this section.

Let us now develop some simple business logic to retrieve information from a text file and provide
itself as a data source (or report data source) to the ReportViewer control. The following is the
class (SalesInfo.vb), which imitates the columns of the dataset created earlier:

ImportsMicrosoft.VisualBasic

PublicClass SalesInfo

Dim _SalesPersonID As String

Dim _FirstName As String

Dim _SalesQuota As String

Dim _SalesYTD As String

Dim _SalesLastYear As String


43

Public Property SalesPersonID() As String

Get

Return _SalesPersonID

End Get

Set(ByVal value As String)

_SalesPersonID = value

End Set

End Property

Public Property FirstName() As String

Get

Return _FirstName

End Get

Set(ByVal value As String)

_FirstName = value

End Set

End Property

Public Property SalesQuota() As String

Get

Return _SalesQuota

End Get

Set(ByVal value As String)

_SalesQuota = value

End Set

End Property

Public Property SalesYTD() As String

Get

Return _SalesYTD
44

End Get

Set(ByVal value As String)

_SalesYTD = value

End Set

End Property

Public Property SalesLastYear() As String

Get

Return _SalesLastYear

End Get

Set(ByVal value As String)

_SalesLastYear = value

End Set

End Property

EndClass

The above class simply contains all the properties which get logically mapped to the dataset
columns. Now we need to create another class, which can expose several objects based on the
above class. The next section will deal with this issue.

Binding Data to the ReportViewer Control Dynamically in ASP.NET 2.0 - Binding a


customized ObjectDataSource (or business logic) to a ReportViewer control in ASP.NET
2.0: code
(Page 6 of 6 )

This is an extension from the previous section. Add one more class (Sales.vb), which is mainly used
to expose the objects based on the above class. The code should look like the following:

ImportsMicrosoft.VisualBasic

ImportsSystem.Data

ImportsSystem.Collections.Generic

PublicClass Sales

Public Function ListSales() As ArrayList

Dim Sales As New ArrayList

Dim fileName As String =


HttpContext.Current.Request.MapPath("SalesData.csv")
45

Using parser As New FileIO.TextFieldParser(fileName)

parser.Delimiters = New String() {","}

parser.HasFieldsEnclosedInQuotes = False

Dim fields As String()

fields = parser.ReadFields()

Do While fields IsNot Nothing

Dim info As New SalesInfo

With info

.SalesPersonID = fields(0)

.FirstName = fields(1)

.SalesQuota = fields(2)

.SalesYTD = fields(3)

.SalesLastYear = fields(4)

End With

Sales.Add(info)

fields = parser.ReadFields()

Loop

End Using

Return Sales

End Function

EndClass

Now, add a new web form (ObjectBasedReport.aspx), drag a ReportViewer control and finally set
“SampleReport.rdlc” at the “Choose Report” option in the Smart Tag.
46

That automatically adds an “ObjectDataSource” control to your designer.

Using the “ObjectDataSource,” open the smart tag menu and choose “Configure Data Source.”

You will be provided with a wizard. Provide “Sales” as your “business object” and click "Next."

In the next screen, for the SELECT tab, choose “ListSales(), returns ArrayList” as the method.
47

For all the rest of the tabs, you can select “none.” Finally click “Finish.” When you execute, your
reports get bound to the customized business logic object source!

More about Stored Procedures using ASP.NET 2.0 with


the Microsoft Data Access Application Block
(Page 1 of 4 )

This is the fifth article in a series focusing on developing applications using ASP.NET 2.0 and the
Data Access Application Block available in the Microsoft Enterprise Application Block Library for .NET
2.0. In this article, I shall go through the routines that are used most (with simple examples) to
work with stored procedures and parameters in Microsoft SQL Server database. I shall also cover
INPUT, OUTPUT and RETURN parameters in this contribution.

If you are new to Microsoft application blocks, I strongly suggest you refer to my first article in this
series titled “Developing ASP.NET 2.0 Applications with the Microsoft Data Access Application Block."
It gives a solid foundation for beginners.

If you are not aware of how to select and use a proper “database” class, I suggest you go through
my second article in this series titled “Connecting to Different Databases using ASP.NET 2.0 with the
Microsoft Data Access Application Block.” In this article, I focus on working with Microsoft SQL
Server. If you are new to working with stored procedures using the Data Access Application Block,
you can refer to my fourth article in this series.

This article works on the same environment as discussed in my previous article. For table
structures and more, I suggest you to refer to that article.

Retrieving a single value from a stored procedure using ASP.NET 2.0 and the Data Access
Application Block

In my previous article, I introduced several ways to work with stored procedures using the Data
Access Application Block. In this section, I shall focus on retrieving a single value from a stored
procedure using the Data Access Application Block.
48

Before going to the code to execute a stored procedure, we need to create a simple stored
procedure for this demonstration. The following is the code for the stored procedure I created:

CREATE PROCEDURE dbo.p_GetEmployeeCount

AS

SELECT count(*) from emp

RETURN

The above stored procedure is named “p_GetEmployeeCount” and it simply returns the number of
rows available in the “emp” table.

The following is the complete code needed to execute the above stored procedure using ASP.NET
2.0 through the Data Access Application Block

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


btnConnect.Click

Try

Me.lblMsg.Text = SPExecute("p_GetEmployeeCount") & " Employees exist"

Catch ex As Exception

Me.lblMsg.Text = ex.Message

End Try

End Sub

Private Function SPExecute(ByVal Name As String) As String

Try

Dim db As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase("AdventureWorks"),


SqlDatabase)

Dim v As String = db.ExecuteScalar(Name, New Object() {})

Return v

Catch ex As Exception
49

Throw New Exception("Unable to execute:" & ex.Message)

End Try

End Function

EndClass

From the above code, you can observe that I worked with the method “ExecuteScalar,” which is
optimized to execute and return single values from databases.

More about Stored Procedures using ASP.NET 2.0 with the Microsoft Data Access
Application Block - Retrieving a RETURN value from a stored procedure using ASP.NET 2.0
and the Data Access Application Block
(Page 2 of 4 )

In the previous section, I simply issued a SELECT statement. There could be times where you really
need to make use of a RETURN statement in stored procedures. This section handles this scenario
by retrieving that value.

Before going to the code to execute a stored procedure, we need to create a simple stored
procedure (with a single parameter) for this demonstration. The following is the code for the stored
procedure I created:

CREATE PROCEDURE dbo.isEmployeeExist

@empno int

AS

if exists (select empno from emp where empno = @empno)

begin

return 1

end

else

begin

return 0

end

You can observe that the above stored procedure simply returns 1 if the employee exists or 0 if no
employee exists.
50

The following is the complete code needed to execute the above stored procedure using ASP.NET
2.0 through the Data Access Application Block

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass Sample2

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


btnConnect.Click

Try

Dim r As Integer = SPExecute("isEmployeeExist", "1001")

If r = 1 Then

Me.lblMsg.Text = "Exists"

Else

Me.lblMsg.Text = "Does not exist"

End If

Catch ex As Exception

Me.lblMsg.Text = ex.Message

End Try

End Sub

Private Function SPExecute(ByVal Name As String, ByVal empno As String) As String

Try

Dim db As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase("AdventureWorks"),


SqlDatabase)

Dim cmd As SqlClient.SqlCommand = db.GetStoredProcCommand(Name, New Object()


{empno})

db.ExecuteNonQuery(cmd)

Dim v As String = cmd.Parameters("@return_value").Value

Return v
51

Catch ex As Exception

Throw New Exception("Unable to execute:" & ex.Message)

End Try

End Function

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles


Me.Load

End Sub

EndClass

The most important issue to remember from the above code is that I am using “@return_value,”
which is already built for the purpose!

More about Stored Procedures using ASP.NET 2.0 with the Microsoft Data Access
Application Block - Retrieving a complete row from a stored procedure using ASP.NET 2.0
and the Data Access Application Block
(Page 3 of 4 )

In previous sections, we worked with only single values. Now, in this section, we shall look into
retrieving a complete row returned by a stored procedure.

Before going to the code to execute a stored procedure, we need to create a simple stored
procedure (with a single parameter) for this demonstration. The following is the code for the stored
procedure I created:

CREATE PROCEDURE dbo.p_GetEmployee

@empno int

AS

select * from emp where empno = @empno

RETURN

You can observe that the above stored procedure simply returns a complete row from the “emp”
table based on the “empno” sent as parameter.

The following is the complete code needed to execute the above stored procedure using ASP.NET
2.0 through the Data Access Application Block

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
52

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass Sample3

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


btnConnect.Click

Try

Dim dr As DataRow = SPExecute("p_GetEmployee", "1001")

Me.lblMsg.Text = dr("ename") & ", " & dr("sal")

Catch ex As Exception

Me.lblMsg.Text = ex.Message

End Try

End Sub

Private Function SPExecute(ByVal Name As String, ByVal empno As String) As DataRow

Try

Dim db As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase("AdventureWorks"),


SqlDatabase)

Dim ds As DataSet = db.ExecuteDataSet(Name, New Object() {empno})

Return ds.Tables(0).Rows(0)

Catch ex As Exception

Throw New Exception("Unable to execute:" & ex.Message)

End Try

End Function

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles


Me.Load

End Sub

EndClass

Even though the above code works pretty well, not everyone likes the above methodology, because
it works with dataset. The other way to make this work is by using OUTPUT parameters. The next
section concentrates on this.
53

More about Stored Procedures using ASP.NET 2.0 with the Microsoft Data Access
Application Block - Retrieving an OUTPUT parameter value from a stored procedure using
ASP.NET 2.0 and the Data Access Application Block
(Page 4 of 4 )

In previous sections, we worked with only single values. Now, in this section, we shall look into
retrieving a complete row returned by a stored procedure.

Before going for the code to execute a stored procedure, we need to create a simple stored
procedure (with a single parameter) for this demonstration. The following is the code for the stored
procedure I created:

CREATE PROCEDURE dbo.p_GetEmployeeAnnualSal

@empno int,

@AnnSal float OUTPUT

AS

select @AnnSal = (sal*12) from emp where empno = @empno

RETURN

You can observe that the above stored procedure simply returns a complete row from the “emp”
table based on the “empno” sent as parameter.

The following is the complete code needed to execute the above stored procedure using ASP.NET
2.0 through Data Access Application Block

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass Sample4

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


btnConnect.Click

Try

Me.lblMsg.Text = SPExecute("p_GetEmployeeAnnualSal", "1001") & " is annual salary"

Catch ex As Exception

Me.lblMsg.Text = ex.Message
54

End Try

End Sub

Private Function SPExecute(ByVal Name As String, ByVal empno As String) As String

Try

Dim db As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase("AdventureWorks"),


SqlDatabase)

Dim cmd As SqlClient.SqlCommand = db.GetStoredProcCommand(Name)

db.AddInParameter(cmd, "@empno", SqlDbType.Int, empno)

db.AddOutParameter(cmd, "@AnnSal", SqlDbType.Float, 5)

db.ExecuteNonQuery(cmd)

Return db.GetParameterValue(cmd, "@AnnSal") & ""

Catch ex As Exception

Throw New Exception("Unable to execute:" & ex.Message)

End Try

End Function

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles


Me.Load

End Sub

EndClass

The most important part to understand from the above is that I am using two methods,
“AddInParameter” and “AddOutParameter” to work with parameters while calling the stored
procedure. To retrieve the OUTPUT parameter value, I am using the “GetParameterValue” method.

Interacting with Databases Using ASP.NET 2.0 with the


Microsoft Data Access Application Block
(Page 1 of 6 )

This is the third article in a series focusing on developing applications using ASP.NET 2.0 and the
Data Access Application Block available in the Microsoft Enterprise Application Block Library for .NET
2.0. In this article, I shall go through the most used routines in almost every .NET application with
several examples.
A downloadable file for this article is available here.
55

If you are new to Microsoft application blocks, I strongly suggest you refer to my first article in this
series titled Developing ASP.NET 2.0 Applications with Microsoft Data Access Application Block. It
gives a solid foundation for beginners.

If you are unsure of how to select and use the proper database class, I suggest that you go through
my second article in this series titled Connecting to Different Databases using ASP.NET 2.0. In this
article, I focus on working with Microsoft SQL Server.

Retrieving a table of rows in the form of a dataset using the Data Access Application
Block

In this section, we shall retrieve a dataset by passing a SELECT statement to the Data Access
Application Block. Before we begin, modify your web.config in such a way that it looks something
like the following:

<configuration>
      <appSettings/>
      <connectionStrings>            <add name="AdventureWorks" connectionString=
"Database=AdventureWorks;
Server=(local)SQL2k5;Integrated
Security=SSPI;" providerName="System.Data.SqlClient"/> 
      </connectionStrings>

The following is the complete code needed to retrieve a dataset by passing a SELECT statement to
the Data Access Application Block.

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Me.GridView1.DataSource = getDataset("select * from
HumanResources.department").Tables(0)
        Me.GridView1.DataBind()
    End Sub
    Private Function getDataset(ByVal SQL As String) As DataSet
        Dim db As SqlDatabase = DirectCast
(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
        Dim ds As DataSet = db.ExecuteDataSet(CommandType.Text,
SQL)
        Return ds
    End Function    

EndClass

You can observe that in the above code, I defined my own function “getDataset,” which accepts a
SELECT statement as a parameter and returns a “Dataset” object. This lets us reuse the function
any number of times within the same form very easily.

You can also observe that I am assigning only the data table as the data source to the GridView
control (as shown in the following):

Me.GridView1.DataSource = getDataset("select * from
HumanResources.department").Tables(0)
        Me.GridView1.DataBind()
56

Interacting with Databases Using ASP.NET 2.0 with the Microsoft Data Access Application
Block - Retrieving a table of rows in the form of a data table using the Data Access
Application Block
(Page 2 of 6 )

In previous section, we worked with a dataset. In this section, we shall retrieve a data table by
passing a SELECT statement to the Data Access Application Block.

The following is the complete code needed to retrieve a data table by passing a SELECT statement
to the Data Access Application Block.

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Me.GridView1.DataSource = getDataTable("select * from
HumanResources.department")
        Me.GridView1.DataBind()
    End Sub
    Private Function getDataTable(ByVal SQL As String) As
DataTable
        Dim db As SqlDatabase = 
DirectCast(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
        Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,
SQL).Tables(0)
        Return dt
    End Function
EndClass

You can observe that in the above code, I defined my own function, “getDatatable,” which accepts a
SELECT statement as a parameter and returns a “Datatable” object. This lets us reuse the function
any number of times within the same form very easily.

You can also observe that I am returning only the data table from within the function
“getDataTable,” by selecting only the first table in the dataset as follows:

        Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,
"select * from HumanResources.department").Tables(0)
        Return dt

Interacting with Databases Using ASP.NET 2.0 with the Microsoft Data Access Application
Block - Retrieving a single row in the form of a data row using the Data Access
Application Block
(Page 3 of 6 )

In previous sections, we worked with datasets and data tables. In this section, we shall retrieve a
single row in the form of a data row, by passing a SELECT statement to the Data Access Application
Block.

The following is the complete code needed to retrieve a data row by passing a SELECT statement to
the Data Access Application Block.

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
57

PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Dim dr As DataRow = getDataRow("select * from
HumanResources.department where departmentid=2")
        Me.lblMsg.Text = dr("Name") & ", " & dr("GroupName")
    End Sub
    Private Function getDataRow(ByVal SQl As String) As DataRow
        Dim db As SqlDatabase = DirectCast
(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
        Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,
SQl).Tables(0)
        Dim dr As DataRow = dt.Rows(0)
        Return dr
    End Function
EndClass

You can observe that in the above code, I defined my own function, “getDataRow,” which accepts a
SELECT statement as a parameter and returns a “Datarow” object. This lets us reuse the function
any number of times within the same form very easily.

Let me explain it a bit. First, I retrieve a data table using the following code:

        Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,
"select * from HumanResources.department").Tables(0)

Once the data table is filled, we can select only the first row in that table and return to the calling
method using the following:

        Dim dr As DataRow = dt.Rows(0)
        Return dr

Interacting with Databases Using ASP.NET 2.0 with the Microsoft Data Access Application
Block - Retrieving a single value using the Data Access Application Block
(Page 4 of 6 )

In this section, we shall retrieve a single value onto the form by passing a SELECT statement to the
Data Access Application Block.

The following is the complete code:

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Me.lblMsg.Text = getSingleValue("select count(*) from
HumanResources.department")
    End Sub
    Private Function getSingleValue(ByVal SQl As String) As
String
        Dim db As SqlDatabase = DirectCast
(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
        Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,
SQl).Tables(0)
58

        Return dt.Rows(0)(0) & ""
    End Function
EndClass

In the above code, there is nothing much to explain. Up to now, I didn’t implement exception
handling in any of the above code. Just to help you understand, we can even handle errors
efficiently by rewriting the above program as follows:

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Try
            Me.lblMsg.Text = getSingleValue("select count(*) from
HumanResources.department")
        Catch ex As Exception
            Me.lblMsg.Text = ex.Message
        End Try
    End Sub
    Private Function getSingleValue(ByVal SQl As String) As String
        Try
            Dim db As SqlDatabase = DirectCast
(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
            Dim dt As DataTable = db.ExecuteDataSet
(CommandType.Text, SQl).Tables(0)
            Return dt.Rows(0)(0) & ""
        Catch ex As Exception
            Throw New Exception("Unable to retrieve value:" &
ex.Message)
        End Try
    End Function
EndClass

Interacting with Databases Using ASP.NET 2.0 with the Microsoft Data Access Application
Block - Executing a DML statement using the Data Access Application Block
(Page 5 of 6 )

In all of the previous sections, we only retrieved information from a SQL Server database using the
Data Access Application Block. Now, we shall work on executing any DML statement using the Data
Access Application Block.

The following is the complete code needed to execute any DML statement using the Data Access
Application Block.

ImportsSystem.Data
ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql
ImportsMicrosoft.Practices.EnterpriseLibrary.Data
PartialClass _Default
    Inherits System.Web.UI.Page
    Protected Sub btnConnect_Click(ByVal sender As Object, ByVal
e As System.EventArgs) Handles btnConnect.Click
        Try
            Me.lblMsg.Text = SQLExecute("delete from
HumanResources.department") & " rows deleted"
59

        Catch ex As Exception
            Me.lblMsg.Text = ex.Message
        End Try
    End Sub
    Private Function SQLExecute(ByVal SQL As String) As String
        Dim RowsAffected As Integer
        Try
            Dim db As SqlDatabase = DirectCast
(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)
            RowsAffected = db.ExecuteNonQuery(CommandType.Text,
SQL)
            Return RowsAffected
        Catch ex As Exception
            Throw New Exception("Unable to execute DML:" &
ex.Message)
        End Try
    End Function
EndClass

In the above code, you can understand that I am executing a DML statement using the
“ExecuteNonQuery” method available in the class “SqlDatabase.” As we are executing only DML and
not any stored procedure, we need to specify that the “CommandType” is “Text.” The
“ExecuteNonQuery” also returns the number of rows affected, once a DML command is
executed. The same is being returned from the “SQLExecute” method

Connecting to Different Databases Using ASP.NET 2.0


(Page 1 of 5 )

This is the second article in a series focusing on developing applications using ASP.NET 2.0 and the
Data Access Application Block available in Microsoft's Enterprise Application Block Library for .NET
2.0. In this article, I shall introduce you to all the database classes existing in Microsoft's Enterprise
Library 2.0 along with examples.
A downloadable file for this article is available here.

If you are new to Microsoft application blocks, I strongly suggest you refer to my first article in this
series titled “Developing ASP.NET 2.0 Applications with Microsoft Data Access Application Block.” It
gives a solid foundation for beginners.

Database classes included in Microsoft Enterprise Library 2.0

The database classes are the main classes used to work with databases. The following are the
classes included in Microsoft Enterprise Library 2.0.

• Database
• SqlDatabase
• OracleDatabase
• GenericDatabase

Let us start with the “Database” class. It is basically an abstract class. It cannot be directly
instantiated. The following is the declaration for the database class.

Public MustInherit Class Database

Inherits System.Object
60

The above class is defined in the “Microsoft.Practices.EnterpriseLibrary.Data” namespace. You can


also observe the keyword “MustInherit,” which confirms that it is an abstract class.

You can create new database classes by inheriting from the database class. That will give the entire
functionality of the Database class to your customized classes and you can further enhance them
according to your requirements. This is generally used when you want to deal with any other
database not included in “Microsoft Enterprise Library 2.0” (ex: Sybase). If you wanted to use the
Database class directly to work with your existing databases, you need to use another class,
“DatabaseFactory,” to instantiate a “Database” object.

Let us deal with another declaration:

Public Class SqlDatabase

Inherits Microsoft.Practices.EnterpriseLibrary.Data.Database

You can observe that the class SqlDatabase gets inherited from the previous class Database. It is
available in the “Microsoft.Practices.EntepriseLibrary.Data.Sql” namespace. It has the total
functionality of the Database class and has been optimized (and enhanced) to work with Microsoft
SQL Server databases. This class internally uses the Microsoft SQL Server .NET managed provider
available through System.data.SqlClient.

Similarly, we have another database class, “OracleDatabase,” defined similarly to the above class. It
is mainly used to optimize applications with only Oracle databases. It is placed in the
“Microsoft.Practices.EnterpriseLibrary.Data.Oracle” namespace.

Finally, we have another database class, “GenericDatabase,” which again gets inherited from
“database” class. This is generally used when you do not know to which database you are
connecting to. It is placed in the “Microsoft.Practices.EnterpriseLibrary.Data” namespace.

Connecting to Different Databases Using ASP.NET 2.0 - Connecting to Microsoft SQL


Server database using the database class: source code
(Page 2 of 5 )

The previous section explained in detail every database class existing in “Microsoft Enterprise
Library 2.0.” In this section, I shall introduce you to connecting to Microsoft SQL Server database
using the database class.

To start with, modify your web.config class to look something like the following:

<configuration>

<appSettings/>

<connectionStrings>

<add name="AdventureWorks" connectionString=


"Database=AdventureWorks;Server=(local)SQL2k5;Integrated
Security=SSPI;" providerName="System.Data.SqlClient"/>

</connectionStrings>

<system.web>

The following code uses the database class to connect to a Microsoft SQL Server database.
61

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal e As


System.EventArgs) Handles btnConnect.Click

Dim db As Database

db = DatabaseFactory.CreateDatabase("AdventureWorks")

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

End Sub

EndClass

The next section will explain the above code.

Explaining the source code

This section explains the code listed in the previous section. Let us go part by part. Consider the
following:

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

To work with datatable or dataset objects, we need to import the “System.Data” namespace. To
deal with the database class (of Enterprise Library), we need to import the
“Microsoft.Practices.EnterpriseLibrary.Data” namespace.

Further proceeding we have the following:

Dim db As Database

db = DatabaseFactory.CreateDatabase("AdventureWorks")

You can observe that I am using the DatabaseFactory class to instantiate a database object. We
cannot directly create an object of class database using the “new” operator as it is an abstract
class. The DatabaseFactory class has a “static” (or “shared”) method named “CreateDatabase,”
which is mainly used to create database objects.
62

Once a database object is instantiated, we can get or view the connection string information using
the following statement:

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Further proceeding, we have the following:

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

The above executes a “SELECT” statement and finally returns a data table, which contains all the
rows retrieved by that statement. Finally, I show all those rows on a “GridView” using the following
two statements:

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

That ends the explanation for the code given in the previous section.

Connecting to Different Databases Using ASP.NET 2.0 - Connecting to Microsoft SQL


Server database using the SqlDatabase class
(Page 3 of 5 )

The previous two sections concentrated on the database class to connect and work with Microsoft
SQL Server. In this section, I shall introduce you to connecting to a Microsoft SQL Server database
using the SqlDatabase class.

The following code uses the SqlDatabase class to connect to a Microsoft SQL Server database.

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal


e As System.EventArgs) Handles btnConnect.Click

Dim db As New SqlDatabase


(ConfigurationManager.ConnectionStrings
("AdventureWorks").ConnectionString)

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()
63

End Sub

EndClass

There exists not much difference between the code in the previous section and this section, except
that I used the SqlDatabase class available in the “Microsoft.Practices.EnterpriseLibrary.Data.Sql”
namespace. You can also observe that I am using “ConfigurationManager” to retrieve connection
string from the “web.config” file.

If you wanted to use the DatabaseFactory class to instantiate a SqlDatabase object, you can do it as
follows:

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data.Sql

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal


e As System.EventArgs) Handles btnConnect.Click

Dim db As SqlDatabase = DirectCast


(DatabaseFactory.CreateDatabase("AdventureWorks"), SqlDatabase)

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

End Sub

EndClass

Connecting to Different Databases Using ASP.NET 2.0 - Connecting to Microsoft SQL


Server database using the GenericDatabase class
(Page 4 of 5 )

The previous sections concentrated on database and SqlDatabase classes to connect and work with
Microsoft SQL Server. In this section, I shall introduce you to connecting to Microsoft SQL Server
database using the GenericDatabase class.

The following code uses the GenericDatabase class to connect to a Microsoft SQL Server database.

ImportsSystem.Data
64

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal


e As System.EventArgs) Handles btnConnect.Click

Dim db As New GenericDatabase


(ConfigurationManager.ConnectionStrings
("AdventureWorks").ConnectionString,
System.Data.SqlClient.SqlClientFactory.Instance)

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

End Sub

EndClass

There is not much difference between the code in the previous sections and this section, except that
I used the GenericDatabase class available in the “Microsoft.Practices.EnterpriseLibrary.Data”
namespace. You can also observe that I am using “ConfigurationManager” to retrieve connection
string from the “web.config” file.

Connecting to OLEDB data sources using the GenericDatabase class

The previous section concentrated on using the GenericDatabase class to connect and work with
Microsoft SQL Server. In this section, I shall continue with the same class and work with OLEDB
data sources.

Before you begin, modify your web.config as follows:

<configuration>

<appSettings/>

<connectionStrings>

<!--<add name="AdventureWorks"
connectionString="Database=AdventureWorks;Server=(local)
SQL2k5;Integrated Security=SSPI;"
providerName="System.Data.SqlClient"/> -->
65

<add name="AdventureWorks" connectionString="Provider=


sqloledb;Data Source=.sql2k5;Initial
Catalog=AdventureWorks;Integrated Security=SSPI;"/>

</connectionStrings>

The following code uses the GenericDatabase class to connect to Microsoft SQL Server database
using an OLEDB connection string.

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal


e As System.EventArgs) Handles btnConnect.Click

Dim db As New GenericDatabase


(ConfigurationManager.ConnectionStrings
("AdventureWorks").ConnectionString,
System.Data.OleDb.OleDbFactory.Instance)

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from HumanResources.department").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

End Sub

EndClass

Connecting to Different Databases Using ASP.NET 2.0 - Connecting to an Oracle database


using the GenericDatabase class
(Page 5 of 5 )

The previous section concentrated on using the GenericDatabase class to connect and work with
Microsoft SQL Server. In this section, I shall continue with the same class and work with Oracle
databases.

Before you begin, modify your web.config as following:

<configuration>

<appSettings/>

<connectionStrings>
66

<!--<add name="AdventureWorks"
connectionString="Database=AdventureWorks;Server=(local)
SQL2k5;Integrated Security=SSPI;"
providerName="System.Data.SqlClient"/> -->

<add name="MyOracleDB" connectionString= "Provider=msdaora;Data


Source=MyOracleDB;User Id=UserName;Password=asdasd;" />

</connectionStrings>

The following code uses the GenericDatabase class to connect to a Microsoft SQL Server database
using OLEDB connection string.

ImportsSystem.Data

ImportsMicrosoft.Practices.EnterpriseLibrary.Data

PartialClass _Default

Inherits System.Web.UI.Page

Protected Sub btnConnect_Click(ByVal sender As Object, ByVal


e As System.EventArgs) Handles btnConnect.Click

Dim db As New GenericDatabase


(ConfigurationManager.ConnectionStrings
("MyOracleDB").ConnectionString,
System.Data.OleDb.OleDbFactory.Instance)

Me.lblMsg.Text = db.ConnectionStringWithoutCredentials

Dim dt As DataTable = db.ExecuteDataSet(CommandType.Text,


"select * from Scott.emp").Tables(0)

Me.GridView1.DataSource = dt

Me.GridView1.DataBind()

End Sub

EndClass

Even though I used the GenericDatabase class to connect to Oracle, you can also connect using the
OracleDatabase as follows:

Dim db As OracleDatabase = DirectCast


(DatabaseFactory.CreateDatabase("MyOracleDb"), OracleDatabase)

It all depends on your needs. In my upcoming contributions, we shall look into the most used
routines in the Data Access Application Block (along with accessing stored procedures). Don’t forget
to check back or sign up for a newsletter to notify you!
67

Developing T-SQL Stored Procedures to Deal with


Lookup Tables
(Page 1 of 5 )

In this article, I shall go through a set of Transact-SQL stored procedures which are very frequently
used for CRUD operations on lookup tables. My upcoming articles will deal with DAL (Data Access
Layers) in .NET based on these stored procedures.

As I wanted to demonstrate stored procedures which do not modify existing data in


AdventureWorks/Northwind, I created a table “emp” with the following columns and data types:

• Empno (int)
• Ename (nvarchar(50))
• Sal (float)
• Deptno (int)

I pushed the following sample rows into that table:

How to insert a row into a table using a T-SQL stored procedure

The following is the stored procedure which deals with inserting a particular row into a table.

CREATEPROCEDURE [dbo].[p_emp_Insert]
@empno int,
@ename varchar(50),
@sal float,
@deptno int
AS
INSERTINTO [dbo].[emp] (
[empno],
[ename],
[sal],
[deptno]
)VALUES (
@empno,
@ename,
@sal,
@deptno
)
RETURN

The above is a stored procedure named “p_emp_insert” which accepts four parameters (according
to the columns available in the table). Once all the parameters are passed in, it executes an
INSERT statement to insert those values in the form of a row.
68

To test the above stored procedure, you can issue the following statement in Query Analyzer or SQL
Server Management Studio.

executedbo.p_emp_Insert 2001, 'zzz', 4500, 20

The next section will give the code for updating a row.

Developing T-SQL Stored Procedures to Deal with Lookup Tables - How to update/delete
a row in a table using a T-SQL stored procedure
(Page 2 of 5 )

The following is the stored procedure which deals with updating a particular row in a table.

CREATEPROCEDURE [dbo].[p_emp_Update]
@empno int,
@ename varchar(50),
@sal float,
@deptno int
AS
UPDATE[dbo].[emp] SET
[ename] = @ename,
[sal] = @sal,
[deptno] = @deptno
WHERE
[empno] = @empno
RETURN

The above is a stored procedure named “p_emp_update” which accepts four parameters (according
to the columns available in the table). Once all the parameters are passed in, it executes an
UPDATE statement to replace the existing values in a row identified by the given employee number.

To test the above stored procedure, you can issue the following statement in Query Analyzer or SQL
Server Management Studio.

executedbo.p_emp_Update 2001, 'bbb', 5600, 10

Once you execute the above statement, it will automatically modify the information of employee
identified with the employee number 2001. Deleting a row is very similar to the above; it could be
written something like this:

CREATEPROCEDURE [dbo].[p_emp_Delete]
@empno int
AS
DELETEFROM [dbo].[emp]
WHERE
[empno] = @empno
RETURN

You can observe that to delete a row (or employee), the employee number alone is enough. That is
the reason I have only one parameter to pass to the above stored procedure. To execute the above
store procedure, you can give a command something like the following:

executedbo.p_emp_Delete 2001

How to insert/update using a single T-SQL stored procedure


69

Let us consider that you wanted to insert a row, if it's not available, or update a row, if it is
available, using a single stored procedure. The following is the stored procedure which deals with
this:

CREATEPROCEDURE [dbo].[p_emp_save]
@empno int,
@ename varchar(50),
@sal float,
@deptno int
AS
IFEXISTS(SELECT [empno] FROM [dbo].[emp] WHERE [empno] = @empno)
BEGIN
UPDATE [dbo].[emp] SET
[ename] = @ename,
[sal] = @sal,
[deptno] = @deptno
WHERE
[empno] = @empno
END
ELSE
BEGIN
INSERT INTO [dbo].[emp] (
[empno],
[ename],
[sal],
[deptno]
) VALUES (
@empno,
@ename,
@sal,
@deptno
END
RETURN

The above is a stored procedure named “p_emp_save” which accepts four parameters (according to
the columns available in the table). Once all the parameters are passed in, it executes an INSERT
statement if the given employee number does not exist within the table. It executes an UPDATE
statement if a row exists with the given employee number.

To test the above stored procedure, you can issue the following statement in Query Analyzer or SQL
Server Management Studio.

executedbo.p_emp_save 2002, 'aaa', 4500, 20

Once you execute the above, it will insert a row with employee number 2002 (if it doesn’t exist).

executedbo.p_emp_save 2002, 'bbb', 5400, 10

Once you execute the above, just after the previous one, you will see that the values are updated
instead of inserted.

Developing T-SQL Stored Procedures to Deal with Lookup Tables - How to retrieve one or
all rows in a table using a T-SQL stored procedure
(Page 3 of 5 )
70

Let us consider that we would like to retrieve all the details of a particular employee based on the
given employee number. The following would be the stored procedure to use for retrieving the
same.

CREATEPROCEDURE [dbo].[p_emp_details]
@empno int
AS
SETTRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT
[empno],
[ename],
[sal],
[deptno]
FROM
[dbo].[emp]
WHERE
[empno] = @empno
RETURN

If we wanted to retrieve all rows, we might use the following stored procedure:

CREATEPROCEDURE [dbo].[p_emp_list]
AS
SETTRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT
[empno],
[ename],
[sal],
[deptno]
FROM
[dbo].[emp]
RETURN

How to retrieve a set of rows in a table, using a custom condition in a T-SQL stored
procedure

Let us consider that you want to retrieve a set of rows based on an unknown WHERE condition. That
means the WHERE condition should be made dynamic (using a parameter). The following is an
example for the same:

CREATEPROCEDURE [dbo].[p_emp_listByCriteria]
@WhereCondition nvarchar(500)
AS
DECLARE@SQL nvarchar(3250)
SET@SQL = '
SELECT * FROM
[dbo].[emp]
WHERE
'+ @WhereCondition
EXECsp_executesql @SQL
RETURN

From the above, you can observe that I am executing the SELECT statement dynamically using
“sp_executesql,” which is a built-in. To test the above stored procedure, try to execute the following
statement, which should return to you all the employees belonging to department 10:
71

executep_emp_listByCriteria 'deptno = 10'

You can further enhance the above stored procedure so that it will work even when not providing
any condition. The following would be the code for this:

CREATEPROCEDURE [dbo].[p_emp_listByCriteria]
@WhereCondition nvarchar(500) = null
AS
DECLARE@SQL nvarchar(3250)
IF@WhereCondition is NULL
BEGIN
SET @SQL = 'SELECT * FROM [dbo].[emp]'
END
ELSE
BEGIN
SET @SQL = 'SELECT * FROM [dbo].[emp] WHERE ' +
@WhereCondition
END
EXECsp_executesql @SQL
RETURN

The above code accepts a default parameter. If the parameter is provided with a value (or WHERE
condition), it will execute SELECT with WHERE. If the parameter is not provided (or NULL), it would
execute SELECT without any WHERE.

Developing T-SQL Stored Procedures to Deal with Lookup Tables - How to retrieve a set of
rows in a particular order using a T-SQL stored procedure
(Page 4 of 5 )

Sometimes, we may need a set of rows based on a particular order, and that too may mean
different columns. The following is the stored procedure to help you achieve the same:

CREATEPROCEDURE [dbo].[p_emp_Sortedlist]
@OrderByExpression nvarchar(250) = NULL
AS
SETTRANSACTION ISOLATION LEVEL READ COMMITTED
DECLARE@SQL nvarchar(3250)
SET@SQL = 'SELECT [empno], [ename], [sal], [deptno]
FROM [dbo].[emp] '
IF@OrderByExpression IS NOT NULL
BEGIN
SET @SQL = @SQL + ' ORDER BY ' + @OrderByExpression
END
EXECsp_executesql @SQL
RETURN

Sometimes, we may need to filter and order the rows based on user customization. The following is
the code you need to do the same:

CREATEPROCEDURE [dbo].[p_SelectempsDynamic]
@WhereCondition nvarchar(500) = NULL,
@OrderByExpression nvarchar(250) = NULL
AS
SETTRANSACTION ISOLATION LEVEL READ COMMITTED
DECLARE@SQL nvarchar(3250)
IF@WhereCondition is NULL
72

BEGIN
SET @SQL = 'SELECT * FROM [dbo].[emp] '
END
ELSE
BEGIN
SET @SQL = 'SELECT * FROM [dbo].[emp] WHERE ' +
@WhereCondition
END
IF@OrderByExpression IS NOT NULL AND LEN(@OrderByExpression) > 0
BEGIN
SET @SQL = @SQL + ' ORDER BY ' + @OrderByExpression
END
EXECsp_executesql @SQL
RETURN

How to check whether a row exists in table or not using a T-SQL stored procedure

Sometimes, we may need to just check whether a row exists in a table or not using a stored
procedure. The following is the stored procedure for dealing with the same:

CREATEPROCEDURE [dbo].[p_emp_isExists]
@empno int
AS
IFexists (SELECT [empno] FROM [dbo].[emp] WHERE [empno] = +
@empno)
BEGIN
RETURN 1
END
ELSE
BEGIN
RETURN 0
END

The above returns 1 if the employee exists or 0 if it does not exist. In the above stored procedure, I
am using a RETURN statement to return back to the calling program. You can also achieve the same
without using a RETURN statement using the following:

CREATEPROCEDURE [dbo].[p_emp_isExists]
@empno int,
@isExists bit OUT
AS
IFexists (SELECT [empno] FROM [dbo].[emp] WHERE [empno] = +
@empno)
BEGIN
SET @isExists = 1
END
ELSE
BEGIN
SET @isExists = 0
END

Instead of using a RETURN statement, I used an OUTPUT parameter to return the value to the
calling program. It all depends on the necessity and use of stored procedures in our applications.
73

Developing T-SQL Stored Procedures to Deal with Lookup Tables - How to retrieve a set of
rows page by page using a T-SQL stored procedure
(Page 5 of 5 )

If you need to retrieve a set of rows on a page-by-page basis, you may need to consider the
following stored procedure:

CREATEPROCEDURE dbo.db_emp_ListByPage
@CurrentPage As tinyint,
@PageSize As tinyint
AS
Declare@FirstRec int
Declare@LastRec int
Set@FirstRec = (@CurrentPage - 1) * @PageSize
Set@LastRec = (@CurrentPage * @PageSize + 1)
CREATETABLE #empTemp
(
AutoId int IDENTITY PRIMARY KEY,
empno int,
ename nvarchar(50),
sal float,
deptno int
)
INSERTINTO #empTemp
(
empno,ename,sal,deptno
)
SELECT
empno,ename,sal,deptno
FROM emp
SELECT
empno, ename, sal, deptno
FROM #empTemp
WHERE
AutoID > @FirstRec
AndAutoID < @LastRec

The above code uses a temporary table in the database to page the rows. For huge tables, the
above method may not work well. And there exists several efficient ways to deal with the paging of
rows using stored procedures. I shall dedicate one article exclusively to the paging of rows using T-
SQL stored procedures.

Any feedback, suggestions, bugs, errors, improvements etc., are highly appreciated at
jag_chat@yahoo.com.

TreeView Navigation in ASP.Net 2.0


(Page 1 of 5 )

If you want to create a menu organized by hierarchy in ASP.Net 2.0, you can use a TreeView
Navigation control, whose menu you can populate three different ways. This tutorial explains how to
populate the menu using two of those ways.
74

Introduction

ASP.Net 2.0 offers a TreeView Navigation control that allows you to display a hierarchical menu. The
TreeView’s menu items can be populated:

• declaratively
• via an XML datasource
• through a database datasource.

In this tutorial we’ll explore populating a TreeView control declaratively and through an XML
datasource. The code in this tutorial runs in an ASP.Net web site project. Our goal is to create the
menu in figure 1:

Figure 1 A TreeView Control at Runtime

TreeView Navigation in ASP.Net 2.0 - TreeView Declarative Binding


(Page 2 of 5 )

If your web site is relatively small and stable then it’s probably safe to declaratively populate the
TreeView. Use the declarative method if the menu is not likely to ever change. The navigation nodes
will be placed directly inside the TreeView declaration. Figure 2 shows the minimum code required to
create a TreeView. We’ll define the nodes where the figure says “[menu items are declared here]”:

The TreeView declaration itself is pretty simple: the ID and runat are required tags for any web
control.

Node Types
75

The TreeView menu has three node types: Root, Parent and Leaf.

Root nodes have null parent nodes. Shelters and Humane Societiesare root nodes.

Parent nodes have a parent and a child. Local is a parent node.

Leaf nodes have a parent but not a child: Municipal, Private, Mixed, Private and Public are leaf
nodes.

To illustrate the differences, let’s color the Root blue, the Parent black and the Leaf red.

Figure 4 shows the Root, Parent and Leaf colored variations.

Figure 4 Root, Parent and Leaf Illustration

TreeView Navigation in ASP.Net 2.0 - Declaring the TreeView Nodes


(Page 3 of 5 )

In this step we’ll add the TreeView nodes. A <nodes> element surrounds the individual nodes.
Figure 5 declares the <Nodes> element.

Figure 5: The Nodes Element


76

Each menu item is an <asp:TreeNode> element. We will use attributes to define the menu item’s
navigation address and anchor text. We are purposely using the bare minimum code to show how
the TreeView works.

Figure 6: The TreeViews Nodes

Note how the hierarchy is formed in Figure 6. If a node has a child then it does not close the
asp:TreeNode tag. First it defines the children and then the TreeNode is closed:

Figure 7: Using the XML Hierarchical Structure to Create TreeView Node Parent-Child
Relationships
77

The Shelters element is not closed, so everything under it is a child node. Each of the child nodes is
closed, so the hierarchy stops descending for each of them. When the Shelters element is closed,
the Parent-Child relationships are complete: Municipal, Private and Mixed are children of the
Shelters node.

TreeView Navigation in ASP.Net 2.0 - Treeview DataSource Binding


(Page 4 of 5 )

There are two types of TreeView xml binding: XmlDataSource and SiteMapDataSource. The
XmlDataSource allows you to define complex XM for your menu; the SiteMapDataSource gives you
the benefit of a pre-defined XML schema.

Binding to an XmlDataSource

There are two major advantages to using an XmlDataSource. First, your can change the XML file
without interrupting the rest of the code. The declarative TreeView required editing of the web form.
Second, you can create complex menu structures with relatively little code.

There are three components to the TreeView that is mapped to an XmlDataSource:

• the TreeView
• a datasource
• the menu data in an xml file

The datasource is the connection between the TreeView and the XML data. The TreeView points to
ds_xml datasource, and the ds_xml datasource points to the therapuppy.xml file containing the
menu. See Figure 8.

Figure 8: The TreeView binds to the datasource which references the xml menu
78

So what is the form of the XML menu file? For our menu it can be any valid XML that names the
anchor text and navigation URL. Let’s just make one up (see Figure 9):

Figure 9: The XmlDataSource file can have any valid xml

So if we made up our own XML schema, what will we get running this code? How does the TreeView
know what the menu, name and URL fields are? Right now, it doesn’t know what they are. It finds
valid XML and binds to it in TreeView fashion:

Figure 10: No connection between the TreeView and its Bindings


79

We’ll fix this by telling the TreeView how to interpret the XML file. We use the DataBindings
mechanism. See Figure 11.

We need to define two fields: the menu anchor text and the navigation URL. In our XML file, these
are the name and url attributes of the menu nodes.

So we create a DataBinding that maps the menu name to our anchor text and the menu url to our
anchor URL. Again, see Figure 11.

Figure 11: The DataBinding element goes inside the TreeView definition.

Now the TreeView binds the data in those fields to the TreeView, to render an almost correct menu
(figure 12):

Figure 12: The TreeNodeBinding Provides Anchor Text and Url

The problem, of course, is the word “root” at the top of our menu. One way to deal with this is to
define an XPath statement in datasource. A simple one would instruct the TreeView to navigate to
the second level of data in the XML source (figure 13).

Figure 13: XPath Limits TreeView Display


80

The XPath could also be expressed as “everything at the menu level,” as we want to display all of
the menu items and their menu children: XPath="/root/menu."

TreeView Navigation in ASP.Net 2.0 - Binding to a SiteMapDataSource


(Page 5 of 5 )

A new ASP.Net application does not have a web.config file. All of its configuration directives are
inherited from the Framework installation machine.config and web.config files. The topmost is
machine.config, and web.config overrides it. A web.config file in your application directory will
override any settings in your local file.

The path to your global application web.config will look something like this:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config

Inside that web.config is a siteMap section. It creates a default sitemap file for your web site called
“web.sitemap.” We will take advantage of this definition’s XML schema to create the
SiteMapDataSource-bound TreeView. See Figure 14.

Figure 14: The Framework’s web.config file creates a default sitemap file

<siteMap>

<providers>

<addsiteMapFile="web.sitemap"

name="AspNetXmlSiteMapProvider"

type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0,


Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
81

</providers>

</siteMap>

We’ll create a new sitemap file in our project. The default filename is exactly what we want:
“web.sitemap.” The file’s template gives us the starter code for the sitemap (figure 15):

Figure 15: The Default web.sitemap File

<?xmlversion="1.0"encoding="utf-8"?>

<siteMapxmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">

<siteMapNodeurl=""title="" description="">

<siteMapNodeurl=""title="" description=""/>

<siteMapNodeurl=""title="" description=""/>

</siteMapNode>

</siteMap>

The advantage of having a SiteMapProvider is that we don’t need to map the TreeView DataBinding
to the XML elements and attributes. The URL is the anchor URL, the title is the menu text and the
description is the menu tooltip.

The SiteMapDataSource setup is similar to the XmlDataSource setup, except we have less work to
do. The DataFile is presumed to be web.sitemap (Figure 14), and the web.sitemap’s data is already
mapped to the URL and text in our menu items. Figure 15 shows the web.sitemap file, and Figure
16 shows the TreeView and datasource that use the web.sitemap data.

Figure 15: The web.sitemap has a Pre-defined Schema


82

Figure 17: The TreeView that binds to a web.sitemap file doesn’t need to declare its
DataBindings or xml DataFile.

As with our XmlDataSource, our output incorrectly shows the root node (figure 18):

Figure 18: The default SiteMapDataSource Displays the Root Node


83

Unlike the XmlDataSource, the SiteMapDataSource doesn’t have an XPath attribute. Instead, we will
set the ShowStartingNode attribute to false (figure 19):

Figure 19: Do Not Show the SiteMapDataSource’s Root Node

<asp:SiteMapDataSource

ShowStartingNode="false"

ID="ds_therapuppy_sitemap"

runat="server"/>

Conclusion

We looked at two ways to populate the ASP.Net 2.0 TreeView control. The declarative method is
good for small web sites. The DataSource method is good for separating the menu content from the
rest of site. The TreeView is a powerful navigation control that requires very little code to create. We
went over the bare minimum constructs to make individual points. The TreeView is a powerful
control and worth looking into further.

Creating a Chart using Data from a Database with MS


Chart Control
(Page 1 of 4 )

We have seen earlier how to bring in a Microsoft Chart Control to a VB 6 project and configure some
of its properties. The data displayed by the chart was hard-coded. In real life scenarios, the data will
be generated by a program and the format of the output must be fed to the chart programmatically.
Again this is one of the frequently asked popular questions on many forums: how do you use the MS
Chart Control with data retrieved from a database?

Introduction
84

This tutorial shows you step-by-step how you may use the Microsoft Chart Control with data
retrieved from a database, explaining the logic used. The data is retrieved by a suitable query run
against a database on the localhost, XPHTEK, a SQL 2000 Server. The VB6 program and the SQL
Server are both running on a Windows XP Professional machine.

Retrieving data from a database

Using ADO objects and a suitable connection string, the data will be retrieved from the database.
The chart will be using the data from the SQL 2000 Server and therefore the SQL Server must be
running.

Database details

The details of a simple table called 'Products' on the TestWiz database will be used. The next picture
shows the database, 'TestWiz' on the left, the table in the tables list on the right and all the data it
contains at the bottom. It has four rows of data on six columns.

Creating a Chart using Data from a Database with MS Chart Control - Visual Basic Project
to retrieve data
(Page 2 of 4 )

Adding a Microsoft Chart Control

Create a standard exe project and going from Project-->Components, add a reference to the MS
Chart Control as shown in the next picture.
85

This control, Microsoft Chart Control 6.0 (SP4)(OLE DB)[mschrt20.ocx] is located at


C:windowssystem32 directory. With this added you will be able to access its properties and
methods. It has a large number of properties and methods out of which we will be using only a few.
The object browser shows all the properties and methods. Interestingly enough, the DataSource
class is not found, a property used in one of Microsoft's own examples. This is very interesting in
light of the fact that Microsoft considers MS Chart a control to which data can be bound.
86

Adding a reference to the ADO 2.8 library

Going from Project-->References in the drop-down, the References window can be accessed, which
shows the large number of library references that VB 6 programs can access. Make sure that the
Microsoft Activex Data Objects 2.8 library has a check mark against it before you close this window.
There are a large number of tutorials on the ASPFree.com site where you can find details about the
various objects represented by the ADO object model.
87

Creating a Chart using Data from a Database with MS Chart Control - Connecting the chart
to data
(Page 3 of 4 )

Code to retrieve data using DataSource binding

Drag and drop a Microsoft Chart control onto the form, Form1 as shown.

From the properties window some of the following properties were set as shown:

Series Type: 1 - VtChSeriesType2Bar


RowCount: 4
Row: 1
RowLabel :R1
ShowLegend: False
ColumnCount: 3
88

Column:1
ColumnLabel:C1

It could happen that the design time settings can override run time settings and you should test the
control's behavior at run time and tune it appropriately.

You could also access the Property pages for this ActiveX control to set some of the properties.

In the form's Form_OnLoad () event use the following snippet to retrieve and connect the data
using the DataSource property of the MS Chart Control. The snippet in purple is Microsoft's
suggestion to bind data to the MS Chart Control (this is Microsoft's example adopted for this
tutorial).

Private rsProducts As ADODB.Recordset


Private cn As ADODB.Connection

Private Sub Form_Load()


Set cn = New ADODB.Connection
MSChart1.ToDefaults

' Establish the connection using the connection string.


cn.ConnectionString =
_"Provider=SQLOLEDB.1;Password=XXXXXXX;" & _
"Persist Security Info=True; User ID=sa;" & _
"Initial Catalog=TestWiz; Data Source=XPHTEK"

' Open the connection.


cn.Open
Dim strQuery As String ' SQL query string.

' Create a query that retrieves only four fields.


'strQuery = "SELECT ProductName, UnitPrice,
'UnitsInStock, UnitsOnOrder FROM Products"
strQuery = "SELECT ProductName, UnitPrice, UnitsInStock,

UnitsOnOrder FROM Products"


Set rsProducts = New ADODB.Recordset
' Open the recordset.

rsProducts.CursorLocation = adUseClient
rsProducts.Open strQuery, cn, adOpenKeyset

' Set the DataSource to the recordset.


With MSChart1
.ShowLegend = True
Set .DataSource = rsProducts
End With

End Sub

When the program runs without any errors, you get a chart as shown in the next picture. Instead of
four rows there are only three. Also the display of the legend is not complete. This display is
irrespective of the changes you make either in the Properties window, or the Property Pages.
89

The databinding to MS Chart is less than satisfactory as it does not give a correct picture of the
data.

Creating a Chart using Data from a Database with MS Chart Control - Assigning retrieved
data to an array to display on the chart
(Page 4 of 4 )

MS Chart Control can also use data in an array and display it. The following code can be used to
display data after assigning the recordset to the array. The same query as in the previous case is
used for retrieving data from the same database.

Private rsProducts As New ADODB.Recordset


Private cn As New ADODB.Connection

Private Sub Form_Load()

MSChart1.ToDefaults
' declare variable to hold query string
Dim strQuery As String

'This Connection string is specific to the SQL 2000 on this machine


cn.ConnectionString =
_"Provider=SQLOLEDB.1;Password=XXXXX; Persist Security Info=True;" & _
"User ID=sa; Initial Catalog=TestWiz; Data Source=XPHTEK"

' Open the connection.


cn.Open

' this Query retrieves only four fields.


strQuery = "SELECT ProductName, UnitPrice, UnitsInStock,

UnitsOnOrder FROM Products"


' Open the recordset.
rsProducts.CursorLocation = adUseClient
rsProducts.Open strQuery, cn, adOpenKeyset
'this array will contain data for the 4 columns and variable number of rows
ReDim chrtarr(1 To rsProducts.RecordCount, 1 To 4)
MSChart1.ShowLegend = True
MSChart1.chartType = VtChChartType2dBar
'relate array to the recordset returned
For X = 1 To rsProducts.RecordCount
chrtarr(X, 1) = rsProducts("ProductName")
90

chrtarr(X, 2) = rsProducts("UnitPrice")
chrtarr(X, 3) = rsProducts("UnitsInStock")
chrtarr(X, 4) = rsProducts("UnitsOnOrder")
rsProducts.MoveNext
Next X
'feed chart from this array
With MSChart1
.ChartData = chrtarr
'only the three columns, 2,3 4 will provide data
.ColumnCount = 3
.ColumnLabelCount = 1
.Column = 1
End With
End Sub

With this code the chart display is as shown in the next picture. The important lines are explained
with the comments before the statement.

This agrees with the number of rows and columns with values that can be verified.

Summary

This tutorial has shown some pitfalls in using this control to display data retrieved from a database.
The simple table was specially created to test the functionality. All said and done, this is not an easy
control to configure. The chart size will not accommodate to the form size. Column and row labels
have to be assigned by code. ADO does not bind to this control as it is claimed. However you can
bind the data to an array, the first field will be assigned to the x-axis of the bar graph. I recommend
the readers of this article read my basic MS Chart article on this site.
91

Generating a Simple Crystal Report using VS 2005


(Page 1 of 7 )

Crystal Reports has become a very versatile application for generating reports, particularly if you
use Visual Studio. This article will guide you through generating a report using this tool. It takes the
wizard approach, and uses copious screen shots to keep you on track.

Crystal Report

It is relatively easy to retrieve data from a database and display it using any of the bound controls.
This is especially so in ASP.NET 2.0 where the amount of code you need to write has been drastically
reduced. However, to present the data in a formal, board-room friendly format and distribute it in
hard copy, or for look-up, or both is challenging. Crystal Reports does this remarkably well.
Microsoft has been bundling Crystal reports ever since the VB days, and it ships with every version
of VS 2005. It is well integrated with Visual Studio 2005 as we shall see shortly. For highly
functional and aesthetically pleasing report generation, Crystal Report is ideally suited. It is very
versatile and can use data from a variety of databases as well as non-traditional sources.

Crystal Report comes with its own SDK which can be used to programmatically create reports and
interact with them at run time, if one desires do so. Crystal Reports can be us in either Windows or
a web application. It can be stand alone or made available over the Internet. These reports can be
utilized in many different ways: application embedded reports; reports from web servers; as web
services; and so forth. In VS 2005 you find two Crystal Report objects, the CrystalReportViewer and
the ReportDocument as shown in the next picture.

The Object Browser reveals the various classes that are integrated with the Visual Studio application
as shown in the next picture.
92

The Objective of this tutorial

The main objective of this tutorial is to give the reader enough guidance in generating a report
easily using this tool. This hands-on approach should give enough confidence for the user so that he
can experiment himself using this basis. In this tutorial, the report document will retrieve a filtered
set of data from the back end SQL 2005 Server using an OLEDB connection. This tutorial uses the
wizard approach to report generation as this is the simplest of the methods. There are basically
three major steps in report creation, and these are described exhaustively with screen shots that
the reader will encounter while creating the report.

Generating a Simple Crystal Report using


VS 2005 - Creating a Crystal Report Project
(Page 2 of 7 )

In this tutorial a Windows application with the Crystal Report will be created. The application's form
will have the report contained in it after the report is created.

Create a new project, accessing it from the File menu. This opens the New Project window listing
Business Intelligence Projects at the top as shown. In the Visual Studio Installed templates area,
highlight Crystal Reports Application. The default has been changed to Diamond in the Name: field
as shown. This application will have a Windows interface for a Crystal Report.
93

Project Folder Contents

The next picture shows the folder created by this application. It has a form, Form1.vb, and a yet to
be completed CrystalReport1.rpt. This is just a template of a report; when the wizard completes the
tasks, it will be filled with all the necessary information.

Generating a Simple Crystal Report using VS 2005 - Report


Generation
(Page 3 of 7 )

Invoking the Report Wizard

When the application is created, the CrystalReport1.rpt tab will be in the default view with the
window Crystal Reports Gallery contained in it as shown. As you can see from this you have three
options to choose from. For this tutorial, the first option is chosen.
94

Accessing the Data

When you click on the OK button, you will get to the Standard Report Creation Wizard window as
shown. There are lots of locations and sources that the data can come from, including the possibility
to create a new connection.
95

Creating a New Connection

For this tutorial a new connection will be established to get the data. When you expand the Create
New Connection node you will see even more options.

Choosing an OLEDB Provider

We will be using an OLEDB provider, so click on the OLEDB (ADO) folder which shows the OLEDB
Providers available in the drop-down in the right pane. We plan to get the data from the SQL 2005
Server using the SQL Native Client. Highlight the SQL Native Client. Place a check mark in the
checkbox Use DataLink file. Well, you might not have a DataLink file ready to be used. However, in
96

the next sub-section we will create a DataLink file, and when this is created, we will browse to it by
clicking the ellipsis button (...) in the Ole DB Provider screen.

Generating a Simple
Crystal Report using VS 2005 - Creating a DataLink file
(Page 4 of 7 )

The Microsoft DataLink utility can be used to create a DataLink file with the *.udl extension. If you
create a new text document and change its extension from *.txt to *udl, a DataLink file will be
created. This can be configured by double clicking the icon of the file. This opens the DataLink
Properties window as shown with the Connection tab in the default view. Click on the Provider tab,
and then scroll up or down until you locate the SQL Native Client. Highlight the SQL Native Client
and click Next, or change to the Connection tab.
97

The data source is the SQL 2005 Server which in this case is Hodentek/Mysorian where Hodentek
is the Windows XP machine and Mysorian is the SQL 2005 Server instance. The logon information is
what is appropriate for the SA user. You may save the password with the connection. If the
information up to this point is correct, you will be able to access all the databases on this server as
shown in the drop-down box. For this report the Northwind database will be used. The reader will
benefit from the earlier SQL 2005 articles on the ASPFree.com site. At this point you can also verify
that the connection is correct by clicking the test button.
98

Make sure that after this task you go back to the OleDB Provider screen and browse and locate this
file.

Connecting to the Data Server

After locating the file, click on the Finish button. This brings up the next screen where you make the
connection by providing the authentication information.
99

Do you want to change something?

When you click on the Next button, the OLEDB(AD0) screen presents some advanced information.
You could "Edit" or "Remove the Property" altogether. For this tutorial the default is accepted.
100

Generating a Simple
Crystal Report using VS 2005 - Selecting the Data
(Page 5 of 7 )

When you click on the Finish button in the above screen, you enter the next step of the report
creation wizard. You will be choosing the source of the data on the server you logged on. Here the
Northwind database will be used. You may access any of the objects; that includes some of the
system objects as well.
101

Selecting a table(s) from the database

We will be using one of the tables on this database, in particular, the Employees table. Expand the
Table node, highlight the Employees table, and click on the button marked ">". This will take the
Employees table to the Selected Tables: area as shown. Instead of a single table, multiple tables
can also be used.

Selecting Columns (Fields) from the table

A table can have a large number of columns, also called Fields. In a report, depending on the
requirement, one may or may not need all the columns. In this case, out of all the available fields
only a subset is chosen to be displayed. Transfer all these fields to be displayed from left pane to
right pane by clicking one-by-one, or highlighting them as a bunch and using the ">" button. By
using the Up/Down arrows in the Fields to Display pane, they can be reordered top to bottom.
102

Grouping the data

When you click on the Next button, you will be taken to the Grouping area. The Employees may
come from different cities and in this case they can be grouped on the basis of the city they come
from. In this screen you would choose the Employees. City and click on the ">" button to transfer it
to the Group By: column. In the background, the wizard is creating an appropriate SQL Select
statement.

Summarizing the data


103

When you click on the Next button, you will bring up the window shown where you may summarize
the data. The data fields we have chosen do not require summarizing, therefore you go the next
task by clicking the Next button on the following screen.

Selecting only required fields

Although this section is optional you may still want to make a change to the record selection. For
example FirstName was not chosen in the initial selection, but here it was added.

Generating a Simple
Crystal Report using VS 2005 - Choosing a Style for the Report
(Page 6 of 7 )
104

When you click on the Finish button in the above screen you will have completed all the tasks
related to data to be displayed. In this step you will choose the style from an available list of styles.
Here the last in the list, Maroon/Teal box, is chosen.

Design View of generated report

When you click Finish you will have created the report. At this point you will see two new windows,
which are described here. These two windows show the various report fields in a node tree, and the
design pane of the report.

Accessing various report fields

The Fields Explorer window shows all the different fields. This is the same as the ones you would
find in the earlier versions of Crystal Report, such as Crystal Report 8.5. In a more elaborate and
complex report you may need a combination of all of these fields.

Design pane of the report

The design pane of the report is also similar to the ones you would find in the earlier Crystal Report
versions, such as 8.5. This is the well know banded report with header, footer, and data-related
sections. You could drag and drop fields from the Field Explorer onto these sections if you were to
design a report from scratch.
105

Generating a Simple
Crystal Report using VS 2005 - Displaying the Report
(Page 7 of 7 )

Providing authentication

In order to display the report, when you build and run the project, you will have to provide the
authentication information which will be presented to you. The Main Report will be embedded
in Form1, and will be revealed when you are properly authenticated.

Displayed Report

After you click the Finish button, the report displays as shown in the next picture. On the left pane
you see the Grouping, in this case the various cities the employees come from, and on the right you
see the related personal information of the employee.
106

From the above window's main menu at the top, you can export the report; print the report; refresh
the report; toggle the Group tree; search for text; zoom up and down; and navigate the report.

Class View of the Report

Since the report finds itself on a form, which is a class, you may also find the class view by right
clicking the Form1.vb in the Solution Explorer and choosing the View Class Diagram menu item.

Summary
107

This tutorial describes the very basic steps needed to create a report using the wizard. The Crystal
Report creation process is extremely easy and fast. The interface is very intuitive. If you have
worked on any other reporting software such as the earlier versions of Crystal Report, creating
Crystal Reports in VS 2005 is a piece of cake.

Basic Usage of MultiView and View Controls in ASP.NET


(Page 1 of 5 )

This article introduces the use of View and MultiView controls. It discusses their properties and
methods, and illustrates how they work with some simple web pages containing these controls.

Introduction

MultiView and View controls together provide a wizard-like functionality in ASP.NET pages. The
MultiView control is a container control that can house only View Controls. The View Controls, which
are also container controls, can only be housed in MultiView controls; any attempt to place them on
a web page shows up as a design time error. Hence they will be used together with the MultiView
control which may contain a number of View controls. Within the View control, one may place any of
the other standard controls. That one may even place a MultiView control in a View Control opens
the way for providing a complex navigational functionality in web pages.

The client application can only interact with one of the View controls at any one time. This should
remind the reader of only one browser window being active at any time, or any one form active at a
time in VB 6 applications. All the controls in all the views are on the same web page and easy to
access. Each time the page postbacks, one view will be displayed and the validators within that view
are the only ones active. Hence the View State changes can be easily accounted for regardless of
how many postbacks were made.

About this tutorial

The main objective of this tutorial is to introduce these controls by way of some simple web pages
containing these controls. The tutorial also discusses the properties and methods of these controls
using the information from the Object Browser.

The next paragraph shows the object hierarchy of the MultiView control and its relation to
the System.Object. Most of the properties and methods are inherited from System.Web.UI.Controls,
though there are some properties and methods intrinsic to these controls.

System.Object
System.Web.UI.Control
System.Web.UI.WebControls.MultiView
Basic Usage of MultiView and View Controls in ASP.NET - Creating a web page with
MultiView and View controls
(Page 2 of 5 )

Create a web site project from file -->New Website... This opens up the New Web Site window from
which you choose the ASP.NET Web Site from Visual Studio installed templates. A web site called
PageLife was created for this tutorial. The MultiView and View controls are available in the toolbox
as shown.

Basic Usage of MultiView and View Controls in ASP.NET - Design time properties of View
Control
(Page 3 of 5 )
108

While the ID and runat attributes are added by default, you could access other properties and
invoke events of the View control as shown in the next picture.

The run time properties and methods of View1 can be accessed from the code page as shown. It
may be noticed that there is no style property for a view. The controls' style, or style applied from
skins, may be used.

In the following design view of the web page, you may use one of several ways to make View1
display when the page is browsed.
109

You may use the Form_Load() event to make View1 display using either of the following statements.
The one that is commented out displays the required View as an argument, whereas the other uses
the ActiveViewIndex property, which refers to the 0 based index property of collection of the Views
in the MultiView container.

Protected Sub form1_Load(ByVal sender As Object, ByVal e As _


System.EventArgs) Handles form1.Load 'MultiView1.SetActiveView(View1)

MultiView1.ActiveViewIndex = 0
End Sub

It is also possible and sometimes important to script this action in the script together with the
source code by adding the following to the source code between the <head/> <script/> sections. In
this code the .vb page is devoid of any code.

<script type="text/vbscript" runat="server"> Protected Overloads Sub

form1_Load(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles form1.Load
MultiView1.SetActiveView(View1)
'MultiView1.ActiveViewIndex = 0
End Sub </script>

Yet another way of making View1 visible is to declaratively make it display in the attribute tag of the
MultiView Control, as shown in a later example.

Adding MultiView and View Controls

To the default page add a MultiView control from the ToolBox. This adds a MultiView control visible
in the design view, and a corresponding control tag to the source code in the form as shown.

<form id="form1" runat="server">


<div>
<asp:MultiView ID="MultiView1" runat="server">
</asp:MultiView>
</div>
110

</form>

Currently there is no View control in the MultiView Control. Now with the cursor placed inside the
MultiView, double click a View Control in the Toolbox. This adds the View1 control to the default
page inside the MultiView Control as shown.

Since the MultiView control is a container for the View control, the source view content changes to
reflect this addition as shown. The MultiView and View controls provide design time support, which
means going from source to design is completely reversible.

<form id="form1" runat="server">


<div> <asp:MultiView ID="MultiView1" runat="server">

<asp:View ID="View1" runat="server">

<!-- controls that go in View 1 here--> </asp:View> </asp:MultiView> </div>


</form>
Basic Usage of MultiView and View Controls in ASP.NET - Container Properties of View
and MultiView Controls
(Page 4 of 5 )

Just as you can access the properties of controls in forms in Visual Basic, or controls in the <form/>
of a web page, you can access the controls placed in the View control and the Views placed in the
111

MultiView control programmatically. This is done as shown in the next snippet for the design view
shown here.

Protected Sub MultiView1_Load(ByVal sender As Object, ByVal e _


As System.EventArgs) Handles MultiView1.Load
'This displays the view
MultiView1.SetActiveView(View1)
Response.Write("Number of View Controls in this MultiView : " & _
MultiView1.Controls.Count & "<br>")
Response.Write("Number of controls in the View control" & _
"whose index is 0 : " & _
MultiView1.Controls(0).Controls.Count & "<br>")
Response.Write("Type of Control in View1 with index 0 : " & _
MultiView1.Controls(0).Controls(0).GetType.ToString & "<br>")
Response.Write("Type of Control in View1 with index 1 : " & _
MultiView1.Controls(0).Controls(1).GetType.ToString & "<br>")
Response.Write("Type of Control in View1 with index 2 : " & _
MultiView1.Controls(0).Controls(2).GetType.ToString & "<br>")
Response.Write("Type of Control in View1 with index 3 : " & _
MultiView1.Controls(0).Controls(3).GetType.ToString & "<br>")
Response.Write("Type of Control in View1 with index 4 : " & _
MultiView1.Controls(0).Controls(4).GetType.ToString & "<br>")
Response.Write("Type of Control in View1 with index 5 : " & _
MultiView1.Controls(0).Controls(5).GetType.ToString & "<br>")
End Sub

The displayed output of this web page is shown in the next picture. Although there are three
controls in View1, there are six controls in the display, with three extra Literal controls. The page
has two View controls. The controls and the Views can access their containers using the parent
property.
112

Once you access the control you may control its properties using the code support given by
intellisense as shown.

Basic Usage of MultiView and View Controls in ASP.NET - Presenting a user preferred
View
(Page 5 of 5 )

One of the advantages of using the MultiView/View pair of controls is the ability to present a view
based on user preference without going to another page. The next picture shows a web page with a
MultiView Control containing two View controls. Depending on the choice made by the user, one or
the other view will be presented to the user. The web page Choices.aspx shown next has two views,
one showing an animal, and the other showing a flower.

The radio button group with the GroupName Test offers the user an opportunity to make a choice.
The user makes a choice and clicks the What do you want to see? button. The code shown here
displays the View based on user choice.
113

Protected Sub Button1_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Button1.Click
If RadioButton1.Checked Then
'MultiView1.ActiveViewIndex = 0
MultiView1.SetActiveView(View1)
End If
If RadioButton2.Checked Then
MultiView1.SetActiveView(View2)
'MultiView1.ActiveViewIndex = 1
End If
End Sub

Only after clicking the button is one or the other view displayed, otherwise you will see the controls
on the page, but not the controls on the views. The next picture shows the display when View1 is
chosen.

Moving from View to View from within the MultiView Control

When there are a number of views it is possible to move from one view to another within the views
using the properties, methods and events raised of the View Control or controls in the views. The
next design shows a web page with two views.
114

View1 is displayed because the ActiveViewIndex is set to 0 in the MultiView control. When the "Go
to View 2(Button2)" is clicked, the view displayed changes from View1 to View2 following the code
shown in the next paragraph. In View 2, when the 'Greet' button is clicked the greeting's text is
displayed in the textbox shown in View2.

Protected Sub Button1_Click(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles Button1.Click
TextBox1.Text = "Welcome to View2"
End Sub
Protected Sub Button2_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button2.Click
MultiView1.ActiveViewIndex = 1
End Sub

Properties and methods of the MultiView Control

Intellisense support provides support for coding as shown, revealing the available properties and
methods of the MultiView Control. However, declarative syntax can also be used. The next picture
shows how you may access the properties and methods from the code page. The paragraph that
follows the declarative syntax of the MultiView control is copied from Microsoft's documentation.

<asp:MultiView
ActiveViewIndex="integer"
EnableTheming="True|False"
EnableViewState="True|False"
115

ID="string"
OnActiveViewChanged="ActiveViewChanged event handler"
OnDataBinding="DataBinding event handler"
OnDisposed="Disposed event handler"
OnInit="Init event handler"
OnLoad="Load event handler"
OnPreRender="PreRender event handler"
OnUnload="Unload event handler"
runat="server"
SkinID="string"
Visible="True|False"/>

Summary

MultiVew and View controls add functionality to web pages similar to the wizard control discussed in
a previous tutorial. Only some of the very basic features are discussed; some of the properties,
such as the CommndName property which can automatically switch from one view to the next
without writing any code, are not discussed.

While placing controls on the Views some of the functionality needed for placement, such as
alignment and spacing of controls from the menu item Format, are not available, but can be set
using the property pages for the controls. The functionality provided by these controls may be used
for taking surveys, presenting user defined and user based views.

It is possible sometimes that even when the View is added it does not show up in the drop-down in
the .vb page. In this case it is necessary to close the application and re-open. Reproducibility of this
errant behavior has not been tested.

Visual Studio
Walkthrough: Using a Custom Action to Create a Database
During Installation
The following walkthrough demonstrates the use of a custom action and the CustomActionData property
to create a database and database table during installation.

Note This walkthrough requires SQL Server on the computer where you will deploy the application.

To create an installer class

1. On the File menu, point to New, and then choose Project.

2. In the New Project dialog box, select Visual Basic Projects in the Project Type pane, and then
choose Class Library in the Templates pane. In the Name box, type DBCustomAction.

3. Click OK to close the dialog box.

4. On the Project menu, choose Add New Item.

5. In the Add New Item dialog box, choose Installer Class. In the Name box, type
DBCustomAction.

6. Click OK to close the dialog box.


116

To create a data connection object

1. In Server Explorer, select Data Connections. Right-click and choose Add Connection.

2. In the Data Link Properties dialog box, do the following:

a. Enter the server name.

b. Select Use Windows NT Integrated Security.

c. In the database box, type master.

d. Click OK to close the dialog box.

3. Drag the new connection and drop it on the DBCustomAction.vb designer to create a
sqlConnection1 object.

To create a text file that contains a SQL statement to create a database

1. In Solution Explorer, select the DBCustomAction project. On the Project menu, choose Add New
Item.

2. In the Add New Item dialog box, choose Text File. In the Name box, type sql.txt (must be in
lower case).

3. Click OK to close the dialog box.

4. Add the following to the sql.txt file:

5. CREATE TABLE [dbo].[Employees] (


6. [Name] [char] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
7. [Rsvp] [int] NULL ,
8. [Requests] [nvarchar] (4000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
9. ) ON [PRIMARY];
10.
11. ALTER TABLE [dbo].[Employees] WITH NOCHECK ADD
12. CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED
13. (
14. [Name]
) ON [PRIMARY];

15. In Solution Explorer, select sql.txt. In the Properties window, set the BuildAction property to
Embedded Resource.

To add code to the installer class to read the text file

1. In Solution Explorer, select DBCustomAction.vb. On the View menu, choose Code.

2. Add the following Imports statement at the top of the module:

3. Imports System.IO
Imports System.Reflection
117

4. Add the following code to the class:

5. Private Function GetSql(ByVal Name As String) As String


6. Try
7.
8. ' Gets the current assembly.
9. Dim Asm As [Assembly] = [Assembly].GetExecutingAssembly()
10.
11. ' Resources are named using a fully qualified name.
12. Dim strm As Stream = Asm.GetManifestResourceStream(Asm.GetName().Name + "." +
Name)
13.
14. ' Reads the contents of the embedded file.
15. Dim reader As StreamReader = New StreamReader(strm)
16. Return reader.ReadToEnd()
17. Catch ex As Exception
18. MsgBox("In GetSQL: " & ex.Message)
19. Throw ex
20. End Try
21.
22. End Function
23.
24. Private Sub ExecuteSql(ByVal DatabaseName As String, ByVal Sql As String)
25. Dim Command As New SqlClient.SqlCommand(Sql, sqlConnection1)
26.
27. Command.Connection.Open()
28. Command.Connection.ChangeDatabase(DatabaseName)
29. Try
30. Command.ExecuteNonQuery()
31. Finally
32. ' Finally, blocks are a great way to ensure that the connection
33. ' is always closed.
34. Command.Connection.Close()
35. End Try
36. End Sub
37.
38. Protected Sub AddDBTable(ByVal strDBName As String)
39. Try
40. ' Creates the database.
41. ExecuteSql("master", "CREATE DATABASE " + strDBName)
42.
43. ' Creates the tables.
44. ExecuteSql(strDBName, GetSql("sql.txt"))
45.
118

46. Catch ex As Exception


47. ' Reports any errors and abort.
48. MsgBox("In exception handler: " & ex.Message)
49. Throw ex
50. End Try
51. End Sub
52.
53. Public Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)
54. MyBase.Install(stateSaver)
55. AddDBTable(Me.Context.Parameters.Item("dbname"))
End Sub

56. On the Build menu, choose Build DBCustomAction.

To create a deployment project

1. On the File menu, choose Add Project, New Project.

2. In the Add Project dialog box, select Setup and Deployment Projects in the Project Type pane,
and then choose Setup Project in the Templates pane. In the Name box, type DBCustomAction
Installer.

3. Click OK to close the dialog box.

4. In the Properties window, select the ProductName property and type DB Installer.

5. In the File System Editor, select the Application Folder. On the Action menu, choose Add,
Project Output.

6. In the Add Project Output Group dialog box, select the primary output for the DBCustomAction
project. Click OK to close the dialog box.

To create a custom installation dialog

1. Select the DBCustomAction Installer project in Solution Explorer. On the View menu, point to
Editor, and choose User Interface.

2. In the User Interface Editor, select the Start node under Install. On the Action menu, choose Add
Dialog.

3. In the Add Dialog dialog box, select the Textboxes (A) dialog, then click OK to close the dialog
box.

4. On the Action menu, choose Move Up. Repeat until the Textboxes (A) dialog is above the
Installation Folder node.

5. In the Properties window, select the BannerText property and type Specify Database Name.

6. Select the BodyText property and type This dialog allows you to specify the name of the
database to be created on the database server.

7. Select the Edit1Label property and type Name of DB:.


119

8. Select the Edit1Property property and type CUSTOMTEXTA1.

9. Select the Edit2Visible, Edit3Visible, and Edit4Visible properties and set them to false.

To create a custom action

1. Select the DBCustomAction Installer project in Solution Explorer. On the View menu, point to
Editor, and choose Custom Actions.

2. In the Custom Actions Editor, select the Install node. On the Action menu, choose Add Custom
Action.

3. In the Select item in project dialog box, double-click the Application Folder.

4. Select the Primary output from DBCustomAction(Active) item, then click OK to close the dialog
box.

5. In the Properties window, select the CustomActionData property and type


/dbname=[CUSTOMTEXTA1].

6. On the Build menu, choose Build DBCustomActionInstaller.

To install on your development computer

• Select the DBCustomAction Installer project in Solution Explorer. On the Project menu, choose

Install.

This will run the installer on your development computer.

Note You must have install permissions on the computer in order to run the installer.

To deploy to another computer

1. In Windows Explorer, navigate to your project directory and find the built installer. The default path
will be \documents and settings\yourloginname\DBCustomAction Installer\project
configuration\DBCustomAction Installer.msi. The default project configuration is Debug.

2. Copy the DBCustomAction Installer.msi file and all other files and subdirectories in the directory to
another computer.

Note To install on a computer that is not on a network, copy the files to traditional media such as
CD-ROM.

On the target computer, double-click the Setup.exe file to run the installer.

Note You must have install permissions on the computer in order to run the installer.

To uninstall the application

1. In the Windows Control Panel, double-click Add/Remove Programs.


120

2. In the Add/Remove Programs dialog box, select DBCustomAction Installer and click Remove,
then click OK to close the dialog box.

Tip To uninstall from your development computer, on the Project menu, choose Uninstall.

See Also

Custom Actions Management in Deployment | CustomActionData Property | Connecting to Data Sources


with ADO.NET | Error Handling in Custom Actions

Das könnte Ihnen auch gefallen