Professional Documents
Culture Documents
".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!
.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.
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?
.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.
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:
Assembly Manifest - Contains name, version, culture, and information about referenced
assemblies.
Resources - Files such as BMP or JPG file or any other files required by application.
5
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
.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:
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
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.
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.
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.
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.
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.
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.
</h3>
</asp:Content>
10
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.
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
<tr>
<td>Jay Krishnaswamy</td><td>htek@mysorian.com</td>
</tr>
</table>
</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
alt="US Flag"/>
</asp:Content>
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:
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.
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.
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:
da.Fill(ds, "Rows")
da.Dispose()
ds.WriteXml(sw)
ds.Dispose()
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:
Me.txtXML.Text = 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>
</Rows>
<Rows>
<EmployeeID>2</EmployeeID>
<FirstName>Kevin</FirstName>
<JobTitle>Marketing Assistant</JobTitle>
</Rows>
</SQLData>
<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>
<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.
<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 )
<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:
<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.
<xsl:apply-templates />
it would be a blank template and nothing would get displayed (or transformed).
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:
<xsl:stylesheet version="1.0"
18
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
</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:
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:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
</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:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
</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:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
</xsl:template>
<xsl:template match="SQLData/Rows">
<xsl:value-of select="EmployeeID"/>,
<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.
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:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table border="1">
</table>
</xsl:template>
<xsl:template match="SQLData/Rows">
<tr>
</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:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
22
<xsl:template match="/">
<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 )
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
</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:
<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.
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.
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 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.
CDbl(txtFV.Text), DueDate.EndOfPeriod)
End If
End If
TextBox1.Text = Format(dfpmt, "$##,######.00")
End Sub
End Class
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.
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
</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></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.
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.
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.
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
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
ReportViewer1.ProcessingMode = ProcessingMode.Local
rep.ReportPath = "SampleReport.rdlc"
dsSalesOrder.Name = "SalesData_Data"
dsSalesOrder.Value = ds.Tables("SalesData")
rep.DataSources.Add(dsSalesOrder)
End Sub
"Integrated Security=SSPI")
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.
<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
ReportViewer1.ProcessingMode = ProcessingMode.Local
rep.ReportPath = "SampleReport.rdlc"
dsSalesOrder.Name = "SalesData_Data"
dsSalesOrder.Value = ds.Tables("Data")
rep.DataSources.Add(dsSalesOrder)
End Sub
'ds.ReadXml(Server.MapPath("SalesDataFile.xml"))
ds.ReadXml(HttpContext.Current.Request.MapPath("SalesDataFile.xml"))
Return ds
End Function
EndClass
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.
<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
ReportViewer1.ProcessingMode = ProcessingMode.Local
rep.ReportPath = "SampleReport.rdlc"
dsSalesOrder.Name = "SalesData_Data"
dsSalesOrder.Value = ds.Tables("Data")
42
rep.DataSources.Add(dsSalesOrder)
End Sub
'ds.ReadXml(Server.MapPath("SalesDataFile.xml"))
ds.ReadXml(HttpContext.Current.Request.MapPath("SalesDataFile.xml"))
Return ds
End Function
EndClass
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.
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
Get
Return _SalesPersonID
End Get
_SalesPersonID = value
End Set
End Property
Get
Return _FirstName
End Get
_FirstName = value
End Set
End Property
Get
Return _SalesQuota
End Get
_SalesQuota = value
End Set
End Property
Get
Return _SalesYTD
44
End Get
_SalesYTD = value
End Set
End Property
Get
Return _SalesLastYear
End Get
_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.
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
parser.HasFieldsEnclosedInQuotes = False
fields = parser.ReadFields()
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
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!
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:
AS
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
Try
Catch ex As Exception
Me.lblMsg.Text = ex.Message
End Try
End Sub
Try
Return v
Catch ex As Exception
49
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:
@empno int
AS
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
Try
If r = 1 Then
Me.lblMsg.Text = "Exists"
Else
End If
Catch ex As Exception
Me.lblMsg.Text = ex.Message
End Try
End Sub
Try
db.ExecuteNonQuery(cmd)
Return v
51
Catch ex As Exception
End Try
End Function
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:
@empno int
AS
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
Try
Catch ex As Exception
Me.lblMsg.Text = ex.Message
End Try
End Sub
Try
Return ds.Tables(0).Rows(0)
Catch ex As Exception
End Try
End Function
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:
@empno int,
AS
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
Try
Catch ex As Exception
Me.lblMsg.Text = ex.Message
54
End Try
End Sub
Try
db.ExecuteNonQuery(cmd)
Catch ex As Exception
End Try
End Function
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.
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.
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
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.
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
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.
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.
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>
</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
Dim db As Database
db = DatabaseFactory.CreateDatabase("AdventureWorks")
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
End Sub
EndClass
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.
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
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.
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
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
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
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
End Sub
EndClass
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
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
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.
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.
<configuration>
<appSettings/>
<connectionStrings>
<!--<add name="AdventureWorks"
connectionString="Database=AdventureWorks;Server=(local)
SQL2k5;Integrated Security=SSPI;"
providerName="System.Data.SqlClient"/> -->
65
</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
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
Me.GridView1.DataSource = dt
Me.GridView1.DataBind()
End Sub
EndClass
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.
<configuration>
<appSettings/>
<connectionStrings>
66
<!--<add name="AdventureWorks"
connectionString="Database=AdventureWorks;Server=(local)
SQL2k5;Integrated Security=SSPI;"
providerName="System.Data.SqlClient"/> -->
</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
Me.lblMsg.Text = db.ConnectionStringWithoutCredentials
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:
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
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.
• Empno (int)
• Ename (nvarchar(50))
• Sal (float)
• Deptno (int)
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.
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.
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
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.
Once you execute the above, it will insert a row with employee number 2002 (if it doesn’t exist).
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
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.
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:
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.
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.
In this step we’ll add the TreeView nodes. A <nodes> element surrounds the individual nodes.
Figure 5 declares the <Nodes> element.
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.
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.
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.
• 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):
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:
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):
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).
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."
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"
</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):
<?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 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):
Unlike the XmlDataSource, the SiteMapDataSource doesn’t have an XPath attribute. Instead, we will
set the ShowStartingNode attribute to false (figure 19):
<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.
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.
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 )
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
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 )
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:
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).
rsProducts.CursorLocation = adUseClient
rsProducts.Open strQuery, cn, adOpenKeyset
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.
MSChart1.ToDefaults
' declare variable to hold query string
Dim strQuery As String
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
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 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.
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
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.
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
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
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.
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.
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
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
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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>
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.
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.
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
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.
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.
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.
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.
5. In the Add New Item dialog box, choose Installer Class. In the Name box, type
DBCustomAction.
1. In Server Explorer, select Data Connections. Right-click and choose Add Connection.
3. Drag the new connection and drop it on the DBCustomAction.vb designer to create a
sqlConnection1 object.
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).
15. In Solution Explorer, select sql.txt. In the Properties window, set the BuildAction property to
Embedded Resource.
3. Imports System.IO
Imports System.Reflection
117
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.
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.
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.
9. Select the Edit2Visible, Edit3Visible, and Edit4Visible properties and set them to false.
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.
• Select the DBCustomAction Installer project in Solution Explorer. On the Project menu, choose
Install.
Note You must have install permissions on the computer in order to run the installer.
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.
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