Enable page-level tracing
Add the Trace attribute to the @ Page directive and set its value to True .
Enable application-level tracing
Add the < trace > configuration section to Web.config with the desired attributes. At a minimum, the enabled attribute is required and should be set to True .
Write to the trace output
Call either the Trace.Write or Trace.Warn method, passing the appropriate arguments.
View detailed error information or prepare for using the runtime debugger
Compile your page or pages in Debug mode by either adding the Debug attribute to the @ Page directive with a value of True or adding the < compilation > section to the Web.config file and setting its debug attribute to True .
Invoke the runtime debugger
Locate the file DbgCLR.exe and execute it.
Debug a page using the Visual Studio .NET debugger
Ensure that the page is set to compile in debug mode, which is the default in Visual Studio .NET. Set breakpoints by clicking on the gray bar on the left side of the code window.
Make a breakpoint conditional
Set a breakpoint as described earlier in the chapter, and then right-click on the line and select Breakpoint Properties from the context menu. Set a condition (to break only when a condition is met) or a hit count (to break only after some number of
To disable debugging when moving an application to production
In Web.Config, in the < compilation > tag, set debug to False . In the Build menu, select Configuration, change the configuration for the project involved to Release , and then rebuild the application.
In this chapter, you will learn how to:
Recognize issues common to the migration process.
Migrate a page that
Use programming practices with classic ASP that will make migration easier.
Migrating classic ASP code to ASP.NET will be a relatively painless process in many cases, particularly if good programming practices were followed in writing the code, such as separating the code into procedures wherever possible. Because of the changes to both the ASP.NET object model and the Microsoft Visual Basic language, which is used in ASP.NET in place of Visual Basic Scripting Edition, you will likely have to make some changes to most (if not all) of your classic ASP pages to make them run in ASP.NET.
Almost all of the issues you’ll encounter in migrating your classic ASP applications to ASP.NET will fall into two categories: page structure changes and language changes. The
The page structure changes from classic ASP to ASP.NET can be further broken down into two areas: changes in the structure of code blocks and changes to the syntax of page directives.
As discussed in Chapter 7, there are significant changes between how code could be structured in classic ASP and how it can be structured in ASP.NET. These changes, which are designed to make your code more readable and
In classic ASP, you could write server-side code in either code render blocks, indicated by the syntax <
>, or in code declaration blocks, indicated by the <
One problem was that it could be difficult to tell which code would execute when, leading to unnecessary
In ASP.NET, the purposes of render blocks and code declaration blocks have been narrowed considerably. Render blocks in ASP.NET can contain only executable statements, not procedures, while code declaration blocks can contain only global variable declarations and/or procedures.
Another significant difference is that in classic ASP, you could use multiple < script runat=“server” > code declaration blocks on a page, and each one could use a different language through the language attribute, which you could set to VBScript or JScript. ASP.NET only supports a single language per page, which is Visual Basic .NET by default.
Classic ASP pages using render blocks always executed from top to bottom, with code in <
> render blocks being executed and output to the response stream as it was
ASP.NET code is compiled into an instance of the
class, and execution is
In classic ASP, the primary directive used in pages was the @ Language directive, which specified the language to be used for render blocks. Other less commonly used directives included @ Codepage , @ EnableSessionState , @ LCID , and @ Transaction .
In ASP.NET, these directives are attributes of the @ Page directive, which should appear at the top of each ASP.NET Web Form page. See Chapter 7 for a full discussion of the @ Page directive and its attributes.
One new attribute of the
directive that is important to discuss in this context is the
attribute. By default, ASP.NET runs as a multi- threaded apartment (MTA) process. This means that components that run as single-threaded apartment (STA) components, such as those written in Visual Basic 6.0, are not compatible with ASP.NET. This includes the ADO components, which are installed to run as STA
In addition to changes in the structure of pages in ASP.NET, some significant changes to the Visual Basic language will likely require modifications to your code. These include the following:
Set and Let are no longer needed or supported. Object references can be set by simple assignment:
Object1 = Object2
Parentheses are now required for calling
procedures as well as
The Variant data type does not exist in Visual Basic .NET. The replacement is Object .
Default properties are not supported, unless they take arguments, so it’s best to call all properties explicitly:
MyString = TextBox1.Text
Property declaration syntax has changed. Instead of
, Visual Basic .NET uses the following syntax. (You can use any
Public Property MyProperty() As String Get Return MyInternalVariable End Get Set (ByVal Value as String) MyInternalVariable = Value End Set End Property
The default for passing parameters to procedures has changed from ByRef to ByVal . To pass values by reference, you must explicitly add the ByRef keyword. (Reference parameters allow you to change their values in the procedure to which they’re passed and retrieve their values outside the procedure.)
Sub MySub(ByRef MyValue As String) MyValue = "Hello!" End Sub
<%@ Language=VBScript %> <html> <head> <% Dim objConn Dim objCmd Dim objRS Dim strConn ' Do NOT use the sa account in data access code, as shown in ' the connection string below! Doing so is a MAJOR security risk! ' Change the connection string to either use a trusted connection, ' Or to use a less-privileged account to access the database. strConn = "PROVIDER=SQLOLEDB;INITIAL CATALOG=PUBS; "_ &"SERVER=(local)\VSdotNet;uid=sa;pwd=;" Set objConn = Server.CreateObject("ADODB.Connection") Set objCmd = Server.CreateObject("ADODB.Command") Set objRS = Server.CreateObject("ADODB.Recordset") objCmd.CommandText = "SELECT * FROM Authors" objConn.Open strConn Set objCmd.ActiveConnection = objConn Set objRS = objCmd.Execute Sub FormatTable Dim objField If Not objRS.EOF Then Response.Write "<table border=2 cellspacing=0>" Do While Not objRS.EOF Response.Write "<tr>" For Each objField In objRS.Fields Response.Write "<td>" & objField & "</td>" Next Response.Write "</tr>" objRS.MoveNext Loop Response.Write "</table>" Else Response.Write "No Records!" End If End Sub Sub CleanUp() objConn.Close Set objConn = Nothing Set objCmd = Nothing Set objRS = Nothing End Sub %> </head> <body> <% FormatTable() CleanUp() %> </body> </html>
The following illustration shows the output of this page.
The page in the previous listing accesses the Authors table of the Pubs SQL Server sample database (in this case in the VSdotNET MSDE instance installed with Visual Studio .NET). The page then calls a render function to write the data to the page as an HTML table, and then calls a clean-up function, which
One thing this sample code has in common with much of the sample code (and,
, under any circumstances, use the
account for accessing data from a page. All it takes is a single bad page to compromise an entire server,
If you cannot use a trusted connection to SQL Server, you should set up one or more special
Another security issue in the sample is the placing of user ID and password information directly in the page. In practice, if you are connecting to a database with an explicit username and password, you should store connection string information somewhere more secure. In order of increasing security, options include: storing it as an appSetting in Web.config, storing it as an appSetting in machine.config (not appropriate in a shared server environment), and hard coding it as a private member of a compiled component. See the section entitled “Storing Database Connection Strings Securely” at http://msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch12.asp for more information on this topic.
In the short term, your goal might be to simply move your pages over to ASP.NET while still using most of the existing logic in the page. Though this choice has performance implications, it can make your migration easier by letting you do it in stages. Making the code in the previous listing work as an ASP.NET page is largely a matter of modifying it to
The first thing you should do is save a copy of the page to be
As you can see in the
The following example will take a more structured approach and correct all of the structural and language incompatibilities before attempting to rerun the code.
If you haven’t already done so, save the code in the GetAuthors.asp listing. (Change the user ID and password to one that is set up on your machine or use a trusted connection, if desired.) Once you have that running, save a copy as GetAuthors.aspx.
Make an ASP page work in ASP.NET
Starting from the top of the page, modify the @ Language directive to @ Page to use Visual Basic as the language, and add the AspCompat attribute so that you can use the ADO components in STA mode:
<%@ Page Language="VB" AspCompat="True" %>
Although the code that creates and instantiates the ADO objects will run in a render block without modification in ASP.NET, the FormatTable and CleanUp procedures will not. You need to move them into a < script > block. Since leaving the ADO code in a render block will not allow you to control when it executes, move it into a < script > block as well and run it in the Page_Load event handler. Move the clean-up code to the Page_Unload handler. (You no longer need the Set obj = Nothing statements because ASP.NET takes care of this clean-up for you.) Note that you must also remove the Set statements from the code and add parentheses to the objConn.Open and objConn.Close calls.
<head> <script runat="server"> Dim objConn Dim objCmd Dim objRS Sub Page_Load() Dim strConn ' Do NOT use the sa account in data access code, as shown in ' the connection string below! Doing so is a MAJOR security risk! ' Change the connection string to either use a trusted connection, ' or to use a less-privileged account to access the database. strConn = "PROVIDER=SQLOLEDB;INITIAL CATALOG=PUBS;" _ & "SERVER=(local)\VSdotNET;uid=sa;pwd=;" objConn = Server.CreateObject("ADODB.Connection") objCmd = Server.CreateObject("ADODB.Command") objRS = Server.CreateObject("ADODB.Recordset") objCmd.CommandText = "SELECT * FROM Authors" objConn.Open(strConn) objCmd.ActiveConnection = objConn objRS = objCmd.Execute End Sub Sub FormatTable Dim objField If Not objRS.EOF Then Response.Write("<table border=2 cellspacing=0>") Do While Not objRS.EOF Response.Write("<tr>") For Each objField In objRS.Fields Response.Write("<td>" & objField.Value & _ "</td>") Next Response.Write("</tr>") objRS.MoveNext Loop Response.Write("</table>") Else Response.Write("No Records! ") End If End Sub Sub Page_Unload() objConn.Close() End Sub </script> </head>
Remove the call to CleanUp from the render block in the body of the page.
Save the page and browse it. The output should be the same as in the illustration on page 506.
Techniques such as using
to allow use of STA components in ASP.NET can help you get pages up and running in ASP.NET more quickly. But in the long run, it’s best to fully migrate your code to take advantage of the features
<%@ Page Language="VB" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <html> <head> <script runat="server"> Sub Page_Load() Dim myDS As New DataSet() Dim ConnStr As String ConnStr = "server=(local)\VSdotNET;database=pubs;" ConnStr &= "Trusted_Connection=yes" Dim SQLSelect As String SQLSelect = "SELECT * FROM Authors" Dim mySqlConn As New SqlConnection(ConnStr) Dim mySqlDA As New SqlDataAdapter(SQLSelect, ConnStr) mySqlDA.Fill(myDS) MyGrid.DataSource = myDS.Tables(0).DefaultView DataBind() End Sub </script> </head> <body> <form runat="server"> <asp:label id="title" text="ASP to ASP.NET Migration: Step 2" font-
size="18" runat="server"/> <asp:datagrid id="MyGrid" autogeneratecolumns="true" border="2" cellpadding="0" runat="server"/> </form> </body> </html>
When you save and run the code in the GetAuthors.aspx listing, you should see results in output similar to the following illustration.
To use a trusted connection to connect to SQL Server as shown in the preceding listing, you will need to either enable Windows authentication and impersonation or set up the ASPNET worker process account as a SQL Server login, as described in Chapter 9.
The code in the preceding listing offers better performance because it does not rely on AspCompat to run. It takes advantage of ADO.NET instead of using ADO through COM Interop (which carries some performance overhead). The code could be made even more efficient by using an ADO.NET DataReader to access the data. The code in the preceding listing also provides greater flexibility for modifying the look of the rendered table. Now you can modify the output format by adding attributes to the DataGrid tag (or using predefined styles). Using an ASP.NET DataGrid also provides built-in support for paging, editing, and filtering. See Chapter 9 for more information on these features.
As you can see from this appendix, migrating from classic ASP to ASP.NET does not need to be terribly painful. However, a lot depends on how your classic ASP code is written in the first place. Code that is written with a great deal of intermingled HTML and render blocks will be more difficult to migrate, as will code that does not follow good coding practices. If you use the following coding practices in your ongoing classic ASP development, migrating to ASP.NET will be easier:
For procedures that take parameters, use ByVal or ByRef to explicitly state which type of parameter is desired. This will prevent code that relies on the default assumption of ByRef in classic ASP from breaking when migrated to ASP.NET.
Write all procedures in < script > code declaration blocks rather than in render blocks.
Use render blocks sparingly, particularly when intermingled with HTML tags.
Do not rely on default properties. Instead, explicitly name properties such as objRS.Value .
Do not use multiple languages in server-side < script > blocks. Choose the language you’re most comfortable with and use it exclusively on a per-page basis.