Comparing ASP.NET 2.0 and Visual Basic 6 WebClasses

 

Bill Sempf

May 2006

Applies to:
   ASP.NET 2.0
   Visual Basic 6

Summary: This article looks at the difference between Visual Basic 6 WebClasses and ASP.NET 2.0, and talks about some strategies for upgrading your legacy projects. (14 printed pages)

Contents

Introduction
The Web Application in Question
Creating a Template
Generating a Placeholder
Building a Class for the Control
Deploying and Getting It Working
Looking Back, and Forward

Introduction

WebClasses in Visual Basic 6 are a great way to make scalable, easily maintainable Web applications with a focus on Visual Basic rather than VB Script. If your skill set runs more toward Windows applications than Web applications, or if you need something distributable, with obfuscated code, then WebClasses provide a useful solution.

Though it seems at first blush that WebClasses are a totally different beast than ASP.NET 2.0, they are actually very much the same. Don't let the .NET Framework confuse the issue; you really just have three components:

  • A server processed template
  • A tag added to HTML to act as a placeholder for your custom content
  • A library of code created to manage your custom content

This isn't a trivial architecture in any language, but Visual Basic makes it fairly simple in both Visual Basic 6 and Visual Basic 2005. While ASP.NET 2.0 in any language looks quite sophisticated, and seems to make it harder to do the things you might have been used to in Visual Basic 6 WebClasses, it is actually quite similar.

What I would like to do is take each of the three components of template style development, and look at how they are implemented in Visual Basic 6 using ASP 3.0, and in Visual Basic 2005 using ASP.NET 2.0. I'll show the page we are shooting for, and explain how it might be developed using WebClasses. Then I'll put up some side-by-side code to show the real similarities between these architectures.

The Web Application in Question

In my experience, one of the most common uses for WebClasses is for Web-based reporting that is simple enough that Crystal Reports is overkill. WebClasses are great for that, because you don't need to concern yourself with a lot of input or output, which ISAPI filters are better suited for anyway.

Nonetheless, a little bit of input would be good for the common order, so we will select a category of products from Northwind by using a Select tag, and get a simple sales report. The SalesByCategory view will give you an idea of what we are after. I altered it a little, and made it into a stored procedure that actually does the grouping.

CREATE PROCEDURE dbo.usp_CategorySales 

AS
SELECT      Categories.CategoryName, 
         SUM([Order Details].UnitPrice) AS TotalSales
   FROM      Categories INNER JOIN
         Products ON 
         Categories.CategoryID = Products.CategoryID INNER JOIN
         [Order Details] ON 
         Products.ProductID = [Order Details].ProductID
   GROUP BY   Categories.CategoryName

Creating a Template

No matter how you slice it, you can't do Web development without a bit of knowledge of HTML. This isn't an article about HTML, so you will have to take my word for it, but a template is a template is a template. It doesn't matter whether you are using Visual Basic 6, ASP.NET 2.0, or Cold Fusion—your HTML will look the same. The only difference is the markup for the preprocessing language. They each have their own set of tags, some of which are more complex, and some less complex.

For our purposes, a simple HTML template will do. The interesting point is how we will develop it. When working in Visual Basic 6, you get to use Visual Interdev or FrontPage to write your template, or you can just do it in Notepad. ASP.NET is built into Visual Studio, which is the development tool for Visual Basic 2005. Listing 1 shows the respective default pages for Visual Interdev 6.0 and Visual Studio 2005.

Listing 1. The default HTML

Visual Interdev 6.0 Default Page

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
</HEAD>
<BODY>

<P>&nbsp;</P>

</BODY>
</HTML>

Visual Studio 2005 Default Page

<%@ Page Language="VB" AutoEventWireup="false" 
CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>

The Visual Studio edition of this code is… shall we say, longer. There is a lot more information to be stored in the HTML template, because it handles the user events for us (more on that in another article). Actions such as the change of the selected item in a drop-down list, for example, are handled in Visual Basic 2005 like the same event in a Windows form is handled in Visual Basic 6. Additionally, a lot of HTML has changed since 1998, and those changes are reflected as well.

All in all, though, the templates are essentially the same. For this simple example, we get to use the default page for each respective tool. In ASP.NET, we don't have to change tools, because Visual Studio is used for both the library and the HTML, whereas Visual Basic 6 required the use of Interdev or a text editor; this is a small issue though. The two platforms essentially have the same tactic.

Generating a Placeholder

Things start to get interesting here. In Visual Basic 6, the placeholder is a variable, essentially. In Visual Basic 2005, there is a standard in place, called a Web User control. Listing 2 shows the code from Listing 1, revised to have the placeholder.

Listing 2. The token

WebClass Example Token

<%@ Language=VBScript %>
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
</HEAD>
<BODY>

 <P>
  <WC@REPORT> </WC@REPORT>
 </P>

</BODY>
</HTML>

ASP.NET User Control

<%@ Page Language="VB" AutoEventWireup="false" 
CodeFile="Default.aspx.vb" Inherits="_Default" %>

<%@ Register Src="ReportControl.ascx" 
TagName="ReportControl" TagPrefix="uc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <uc1:ReportControl ID="ReportControl1" runat="server" />
    
    </div>
    </form>
</body>
</html>

In a Visual Basic 6 WebClass, the HTML generated by my library will be inserted at the WC@REPORT tag that I have inserted in the paragraph in the default template. The WC@ is a special prefix that Internet Information Server (IIS) will use to help the WebClass weave in its output code. When I add the HTML page to the design in Visual Basic 6, it will actually create a method that writes out the values in the template on-demand. During the process of generating the output, you have the option to manipulate the value of the placeholder.

Really, though, the idea that this is what the server uses is a misconception. Beneath the sheets, the IIS Application designer that you use to import the HTML is going to make some ASP 3 code that really runs the class for you. Your mileage will vary, I am sure, but mine looks like the following.

<%
Response.Buffer=True
Response.Expires=0

If (VarType(Application("~WC~WebClassManager")) = 0) Then
   Application.Lock
   If (VarType(Application("~WC~WebClassManager")) = 0) Then
      Set Application("~WC~WebClassManager") = _
Server.CreateObject("WebClassRuntime.WebClassManager")
   End If
   Application.UnLock
End If

Application("~WC~WebClassManager" _
).ProcessNoStateWebClass "Project1.WebClass1", _
      Server, _
      Application, _
      Session, _
      Request, _
      Response
%>

So, while it looks like we are starting with HTML, we really have some server code going on that is doing most of the work, hidden from view. A problem with this that many have discovered is that the number of layers involved was causing memory leaks. After a few people used the class, the IIS session on the Web server just gets bigger, and bigger… You get the idea. Some of that was mitigated in IIS 6, but that's what you sometimes get with machine-authored code.

In the ASP.NET 2.0 code, note that not much has really changed. Where we had the WC@REPORT tag, we now have the uc1:ReportControl, all of which is configurable, thanks to the <%@Register %> directive at the top of the page. This gives us something that we don't have in the Visual Basic 6 version—an actual text template.

The User control in ASP.NET 2.0 is the power behind this feature. To see what I mean, start within a Web project, and add a new User control to the application. You can do this by right-clicking the project, and then clicking Add New Item (see Figure 1).

Aa479047.bldwebapps01(en-us,MSDN.10).gif

Figure 1. Creating a new User control

Then, select Web User Control, and name it Report.ascx. This will create an .ascx file, which is the file that will be added in the place of the placeholder variable. To use it, open the default .aspx page, and drag the control onto the page in the Design view (see Figure 2).

Aa479047.bldwebapps02(en-us,MSDN.10).gif

Figure 2. Adding the User control to the Web page

Here is where things get very useful in ASP.NET. The HTML template code for the page, which we imported into the Visual Basic 6 designer, and the HTML template code for the control, which we coded directly into the Visual Basic 6 class, are both just text. The design has been truly separated from the logic.

The smart tag gives you the option to edit the control once it is in place, if you wish. You also have the source code in the .asmx file to work with, and the template code. In ASP.NET, the HTML template is an .aspx file, and the DLL is a Visual Basic file—in this case, Report.ascx.vb. You can get to the Visual Basic code by right-clicking the control and clicking View Code, just as you would do for a form in Visual Basic 6.

Building a Class for the Control

Now we have an HTML template that will be our page, and a placeholder that will put the generated content into that template. The last step to development will be writing a class that generates the dynamic content that replaces the placeholder in the template in Listing 2.

In Visual Basic 6, you would handle the ProcessTag event and write Visual Basic code to generate the HTML that you wanted to appear. Using a Select Case statement, you iterate through the tags in the template, and insert the text using the output variable.

In ASP.NET, though, the content of the template placeholder is a program unto itself. ASP.NET User controls have their own codebehind, which is translated into the application-wide DLL that is compiled when you build your Web project. This is a lot like the Visual Basic 6 WebClasses method, except that the templates remain in static text, as you'll see in the "Deploying and Getting It Working" section.

Let's dig into some code. Listing 3 shows the code for both the Visual Basic 6 version and the ASP.NET version in Visual Basic 2005 to generate the ASP.NET page.

Listing 3. The class file

Visual Basic 6

Private Sub BuildingWebs_ProcessTag(ByVal TagName As String, _
TagContents As String, SendTags As Boolean)

Select Case TagName
Case "WC@REPORT"
    'Connect to Northwind
    Dim MainDatabase As ADODB.Connection
    MainDatabase.Open _
"Driver={SQLServer};Server=Gryphon;Database=Northwind;Trusted_Connection=yes;"
    Dim cmdTemp As ADODB.Command
    'Get a recordset
    Dim SalesRs As ADODB.Recordset
    cmdTemp.CommandText = "usp_CategorySales"
    cmdTemp.CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
    cmdTemp.ActiveConnection = MainDatabase
    SalesRs.Open cmdTemp, , adOpenDynamic, adLockOptimistic
    TagContents = "<TABLE>"
    TagContents = TagContents + "<TR><TD>Category</TD><TD>Sales</TD></TR>"
    'populate the table
    Do While Not SalesRs.EOF
        TagContents = TagContents + "<TR><TD>"
        TagContents = TagContents + SalesRs("CategoryName")
        TagContents = TagContents + "</TD></TR><TR><TD>"
        TagContents = TagContents + SalesRs("TotalSales")
        TagContents = TagContents + "</TD></TR>"
        SalesRs.MoveNext
    Loop
    TagContents = TagContents + "</TABLE>"
End Select

End Sub

ASP.NET 2.0

<%@ Control Language="VB" AutoEventWireup="false" 
CodeFile="Report.ascx.vb" Inherits="Report" %>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" 
DataSourceID="SqlDataSource1">
    <Columns>
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
 SortExpression="CategoryName" />
        <asp:BoundField DataField="TotalSales" HeaderText="TotalSales" 
ReadOnly="True" SortExpression="TotalSales" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" 
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
    SelectCommand="usp_CategorySales" 
SelectCommandType="StoredProcedure"></asp:SqlDataSource>

Yes, OK, I did a little trickery. The code on the top is compiled Visual Basic 6 code, and the code on the bottom is ASP.NET markup. In ASP.NET, you have access to a wonderful group of controls for Web development—such as the form controls that you are used to in Visual Basic forms. One of them is a datagrid, and the other is a database connection. They can be entirely managed using the WYSIWYG interface.

Now, you can do a bunch of behind-the-scenes code using ADO.NET if you want, or you can drag and drop like you do in Visual Basic 6 when you are working for windows—but Visual Basic 6 WebClasses don't have this functionality! Here's how I did this.

  1. Open Report.ascx in the Design view.
  2. Drag in a GridView from the Toolbox.
  3. In the Grid View Tasks smart tag (the little left-facing arrow in the right-hand corner), click the Choose Data Source drop-down, and click Add New Connection.
  4. When asked where the application will get data from, select Database. Accept the default name.
  5. When asked which data connection to use, select New Connection, and make a connection to the Northwind database to which you added the stored procedure.
  6. Save the connection string using the default name.
  7. In the Configure the Select Statement dialog box, select Specify a custom SQL Statement.
  8. In the Define Statements dialog box, select the Stored Procedure radio button, and select usp_CategorySales.
  9. Test the query.

Figure 3 shows the finished datagrid.

Aa479047.bldwebapps03(en-us,MSDN.10).gif

Figure 3. The finished datagrid

What is happening here is the creation of the HTML that will appear in the placeholder. We already have an HTML template for the ASP.NET version. It is just a matter of getting data and filling the control.

Aah, the control. In ASP-NET, we have Server controls to do the heavy HTML lifting for us. The Data Grid control, on the template side of our ASP.NET User control, will handle the presentation of the table to the user. In Visual Basic 6, we have to build the table the old-fashioned way.

Let's look in more detail at this business of a ASP.NET page containing a User control containing a Server control. The templates, with their reference and page statements, tie together the controls with the class that's compiled out of their codebehind. The page-load event handler of the ASPX page and the ASCX control are used to populate the page initially (see Figure 4).

Aa479047.bldwebapps04(en-us,MSDN.10).gif

Figure 4. 1000-meter view of the ASPX control model

Architecturally, this differs dramatically from the WebClass model. In that model, it is directly determined what method in the compiled WebClass is to be called. It is significantly less flexible.

Deploying and Getting It Working

Deployment is another significant improvement of ASP.NET over the Visual Basic 6 model. With Visual Basic 6, the DLLs, or libraries, need to be registered on the server. In Visual Basic 2005 using ASP.NET, they don't. It's that simple.

Let's take a simple example. Say you needed to deploy the preceding Visual Basic 6 WebClass to a remote server, with Front Page series Extensions. You would need to register the DLL on the server, know the ClassId, and follow a litany over and over that is quite frustrating. Deployment to Web servers is one of the reasons the term "DLL Hell" was invented.

Now, to deploy the ASP.NET version, you just need to XCopy the templates and the bin directory to an application on IIS. To do this, I like to use the Copy Web Site command (see Figure 5).

Aa479047.bldwebapps05(en-us,MSDN.10).gif

Figure 5. Copy Web Site command

To use the Copy Web Site command, make sure that your project is selected. Then, click the Copy Web Site button to open the Copy Web tab. When the Copy Web tab opens, click Connect in the Connections ribbon bar, and the Open Web Site dialog box will open (see Figure 6).

Aa479047.bldwebapps06(en-us,MSDN.10).gif

Figure 6. Open Web Site dialog box

As your situation requires, you can connect to any of the service providers in the left panel—using WINFS, FPSE, FTP, or HTTP. I used the Local IIS server for this example. Once that is set up, it is just a matter of right-clicking the source website and clicking Copy Site to Remote (see Figure 7).

Aa479047.bldwebapps07(en-us,MSDN.10).gif

Figure 7. Copy Site to Remote

After deployment, you have all of the benefits of .NET—templates are editable, DLLs are not registered, changes don't require cycling the server… You get the idea. It really is a good way to deploy an application.

Looking Back, and Forward

I hope you agree that there are significant similarities in developing WebClasses and developing ASP.NET 2.0, especially with the User control model. There are three similar components that need to be built:

  • An HTML template
  • A placeholder for the code-generated content
  • A class file that generates our content

ASP.NET 2.0 has quite a few improvements over the WebClass model, however. The use of Server controls such as SqlConnection and GridView make displaying data in an HTML table much more straightforward. Their openness, however, makes the experience much less like 'black box' coding.

The static nature of the markup templates in ASP.NET also makes lives a lot easier. As we saw, the ASP.NET project deployed to markup pages with known names and a single DLL.

Deployment is also a lot more straightforward, because Web development is more part of Visual Studio than is was for Visual Basic 6. The Copy Web Site command makes deployment a snap; or even XCopy can be used, because DLLs don't need to be registered.

Generally speaking, ASP.NET is loosely based on the WebClass model—but the improvements over eight years of work are very impressive. I hope that new development in ASP.NET 2.0 will make your coding life much easier!

Show: