Migrating to ASP.NET: Key Considerations
Updated November 2001
Summary: This article explores some basic considerations for moving existing ASP applications to the ASP.NET environment as quickly and efficiently as possible. (18 printed pages)
Core API Changes
Visual Basic Language Changes
Application Configuration Changes
Preparation for ASP.NET
Although the designers of Microsoft® ASP.NET have done an excellent job in preserving backward compatibility with ASP applications, there are a few key items you need to be aware of before undertaking the effort of moving a Web application from ASP to ASP.NET. A solid understanding of the technologies that have changed or been introduced with the .NET platform and ASP.NET will go a long way in making this process a whole lot easier.
This article explores a number of areas of change to give a clear understanding of the efforts involved in getting an ASP application up and running in the ASP.NET environment. At the same time, it points out some of the new features of ASP.NET that can be leveraged to improve an existing application. This is by no means a comprehensive look at all of the new features in ASP.NET. Instead, it focuses on areas that you need to know now for successful migration.
I am assuming that since the majority of ASP applications use Microsoft® Visual Basic® Scripting Edition (VBScript), most of you will elect to migrate to ASP.NET using Visual Basic .NET. This is obviously not a requirement, but changing languages at the same time you decide to migrate will take some additional effort and most likely will include design and architectural changes as well.
Before we get into discussing specific compatibility and migration issues, it is important that you understand how ASP and ASP.NET can coexist. Both ASP and ASP.NET applications can run side by side on a server without adversely affecting each other. This is primarily due to the fact that separate file extensions (.asp versus .aspx) and separate configuration models (metabase/registry versus XML-based configuration files) are used between the two technologies. The two systems have totally separate processing engines.
It is entirely possible to have part of one application running ASP and another part of the same application running ASP.NET. This is very beneficial if you need to move a large, rapidly changing site to ASP.NET one piece at a time. Some would argue that you may be better off porting and deploying the entire site all at once. This may be the case for certain classes of Web applications, but I think that there are a lot of sites out there where this may not be feasible due to the sheer size, complexity, and rapid evolution of the site's content and presentation. After all, if you are sitting on a profitable Web site, chances are the people paying the bills will not allow you to stop implementing their new features so that you can move things over to this hot new technology. Additionally, if you are going to put forth the effort to move to ASP.NET as a long-term investment, you will want to use this chance to make as many architectural and design improvements as you can. For these types of situations, coexistence using a phased-in approach is an absolute must.
Migrating your application to ASP.NET may not be easy; however, it should not be that difficult either. ASP.NET is very much compatible with ASP. This is impressive given the fact that ASP.NET is a complete overhaul of ASP. The designers of ASP.NET had an initial goal of being 100 percent backwards compatible with ASP but subsequently had to back off this goal in favor of improving the platform for the long haul. Not to worry—the changes made were for the better and should not require a lot of work on your part to implement. The actual changes made can be categorized into the following sections:
- Core API changes
- Structural changes
- Visual Basic language changes
- COM-related changes
- Application configuration changes
- State management issues
- Security-related changes
- Data access
Each of these areas will be discussed in detail.
The core APIs of ASP consist of a few intrinsic objects (Request, Response, Server, etc.) and their associated methods. With the exception of a few simple changes, these APIs continue to function correctly under ASP.NET. All of the changes are related to the Request object and are shown in Table 1:
Table 1. API Changes
|Request(item)||In ASP, this property is a Collection. In ASP.NET, Request is a NameValueCollection property that returns a string based on the passed in item key.|
|Request.QueryString(item)||In ASP, this property is a Collection. In ASP.NET, QueryString is a NameValueCollection property that returns a string based on the passed in item key.|
|Request.Form(item)||In ASP, this property is a Collection. In ASP.NET, Form is a NameValueCollection property that returns a string based on the passed in item key.|
As you can see, the changes are basically the same for all properties involved.
If the item you are accessing contains exactly one value for the specified key, you do not need to modify your code. However, if there are multiple values for a given key, you need to use a different method to return the collection of values. Also, note that collections in Visual Basic .NET are zero-based, whereas the collections in VBScript are one-based.
For example, in ASP the individual query string values from a request to http://localhost/myweb/valuetest.asp?values=10&values=20 would be accessed as follows:
<% 'This will output "10" Response.Write Request.QueryString("values")(1) 'This will output "20" Response.Write Request.QueryString("values")(2) %>
In ASP.NET, the QueryString property is a NameValueCollection object from which you would need to retrieve the Values collection before retrieving the actual item you want. Again, note the first item in the collection is retrieved by using an index of zero rather than one:
<% 'This will output "10" Response.Write (Request.QueryString.GetValues("values")(0)) 'This will output "20" Response.Write (Request.QueryString.GetValues("values")(1)) %>
In both the case of ASP and ASP.NET, the follow code will behave identically:
<% 'This will output "10", "20" Response.Write (Request.QueryString("values")) %>
Structural changes are those that affect the layout and coding style of Active Server Pages. You need to be aware of several of these to ensure your code will work in ASP.NET.
Code Blocks: Declaring Functions and Variables
In ASP, you can declare subroutines and global variables in between your code delimiters.
<% Dim X Dim str Sub MySub() Response.Write "This is a string." End Sub %>
In ASP.NET, this is no longer allowed. You must instead declare all of your functions and variables inside a
<script language = "vb" runat = "server"> Dim str As String Dim x, y As Integer Function Add(I As Integer, J As Integer) As Integer Return (I + J) End Function </script>
Mixing Programming Languages
In ASP, you basically have two choices for your programming language: VBScript or Microsoft® JScript®. You are free to mix and match blocks of script in the same page at will.
In ASP.NET, you can use any Common Language Runtime-compliant language. C#, Visual Basic .NET, and JScript are the current languages provided by Microsoft. Note that I said Visual Basic .NET instead of VBScript. This is because VBScript does not exist in the .NET platform. It has been fully subsumed by Visual Basic .NET. Although you are free to pick any of these languages, it is important to note that you cannot mix languages on the same page as you could do in ASP. It is certainly possible to have Page1.aspx of your application contain C# code while Page2.aspx of the same application contains Visual Basic .NET code. You just cannot mix them together in a single page.
New Page Directives
In ASP you must place all directives on the first line of a page within the same delimiting block. For example:
In ASP.NET, you are now required to place the Language directive with a Page directive, as follows:
<%@Page Language="VB" CodePage="932"%> <%@QutputCache Duration="60" VaryByParam="none" %>
You can have as many lines of directives as you need. Directives may be located anywhere in your .apsx file but standard practice is to place them at the beginning of the file.
Several new directives have been added in ASP.NET. I encourage you to look these up in the ASP.NET documentation to see how they may benefit your application.
In ASP, developers figured out that they could do clever things by using what is termed a "Render Function." A Render Function is basically a subroutine that contains chunks of HTML embedded throughout its body. For example:
<%Sub RenderMe() %> <H3> This is HTML text being rendered. </H3> <%End Sub RenderMe %>
Although you can do some cool things using these types of functions, this type of coding is no longer allowed in ASP.NET. This is probably for the better. I am sure you have seen functions that quickly become unreadable and unmanageable when you start to mix and match code and HTML like this. The simplest way to make this work in ASP.NET is to replace your HTML outputs with calls to Response.Write as follows:
<script language="vb" runat="server"> Sub RenderMe() Response.Write("<H3> This is HTML text being rendered. </H3>") End Sub </script> <% Call RenderMe() %>
Note that I said "simplest way." This does not necessarily mean it is the best way. Depending on the complexity and amount of your rendering code, it may be beneficial for you to look into using custom Web controls, which allow you to programmatically set your HTML attributes and truly separate your code from your content. Doing so makes for much more readable code.
As I mentioned earlier, VBScript has been deprecated in favor of the more complete and more powerful Visual Basic .NET. In this section, I will highlight some of the issues you are likely to encounter related to Visual Basic language changes. It is important to note that this is not meant to be an exhaustive list of all of the changes made to Visual Basic. Instead, I have focused on the items that you as an ASP/VBScript programmer will likely encounter moving to ASP.NET using Visual Basic .NET. Consult the Visual Basic .NET documentation for a complete list of all language changes that have been made.
Farewell to the Variant Data Type
We know it, we love it, we love to hate it. I am speaking of a VARIANT data type, of course. VARIANTs are not a part of .NET and thus are not supported in Visual Basic .NET. What this means is that all of your ASP variables are silently going to move from VARIANT types to Object types. Most variables used in your application can and should be changed to a corresponding primitive type depending on your needs. If your variable is really an object type in Visual Basic terms, simply explicitly declare it as an Object type in ASP.NET.
Visual Basic Date Type
One VARIANT type that warrants some special attention is the VT_DATE type, which manifests itself in Visual Basic as a Date type. In Visual Basic, a Date is stored in a Double format using four bytes. In Visual Basic .NET, Date uses the Common Language Runtime DateTime type, which has an eight byte integer representation.
Since everything is a VARIANT in ASP, your intended Date variables will compile and may continue to work depending on how they are used. It is possible, however, that you will run into some unexpected problems performing certain operations with the variable because the underlying type has been changed. Pay attention to areas where you may be passing the date value into COM objects as long integer values or performing certain casting operations on date types using CLng.
Option Explicit Is Now the Default
In ASP, the Option Explicit keywords were available but were not enforced as the default. In Visual Basic .NET, this has changed. Option Explicit is now the default so all variables need to be declared. It is good practice to be even more rigid than this and change your setting to Option Strict. Doing so forces you to declare all of your variables as a specific data type. While this may seem like extra work, it really is the way you should be doing things anyway. If you choose not to, your code will be less than optimal as all undeclared variables will become Object types. Most implicit conversions will still work, but you will probably be better off and safer if you explicitly declare all of your variables to the types you want them to be.
LET and SET Are No Longer Supported
Objects can be assigned to one another directly like this:
MyObj1 = MyObj2. You no longer need to use the SET or LET statements. If you use these statements, they must be removed.
Using Parentheses with Method Calls
In ASP, you could freely call methods on objects without using parentheses, as shown below:
Sub WriteData() Response.Write "This is data" End Sub WriteData
In ASP.NET, you must use parentheses with all of your calls, even for methods that do not take any parameters. Writing your code, as in the example below, allows it to function correctly in both ASP and ASP.NET.
Sub WriteData() Response.Write("This is data") End Sub Call WriteData()
ByVal Is Now the Default
In Visual Basic, all parameter arguments were, by default, passed by reference or ByRef. In Visual Basic .NET, this has changed so that all arguments are now passed by value or ByVal by default. If you still wish to have "ByRef" behavior, you must explicitly use the ByRef keyword in front of your parameters as follows:
Sub MyByRefSub (ByRef Value) Value = 53; End Sub
This is an area where you really need to be careful. When you are moving your code over to ASP.NET, I suggest double and triple checking each parameter used in your method calls to ensure that this change is what you really want. I suspect you will need to change some of them.
No More Default Properties
The concept of default properties no longer exists in Visual Basic .NET. What this means is that if you have ASP code that relies on a default property that was provided by one of your objects, you will need to change this to explicitly reference the desired property, as shown in the following code:
'ASP Syntax (Implicit retrieval of Column Value property) Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open("TestDB") Set RS = Conn.Execute("Select * from Products") Response.Write RS("Name") 'ASP.NET Syntax (Explicit retrieval of Column Value property) Conn = Server.CreateObject("ADODB.Connection") Conn.Open("TestDB") RS = Conn.Execute("Select * from Products") Response.Write (RS("Name").Value)
Changes in Data Types
In Visual Basic .NET,
Integer values are now 32 bits and
Long types have become 64 bits.
Problems may arise when invoking methods on COM objects from ASP.NET or calling Microsoft® Win32® API calls inside your custom Visual Basic components. Pay special attention to the actual data types required to ensure you are passing in or casting your values correctly.
Structured Exception Handling
Although the familiar On Error Resume Next and On Error Goto error handling techniques are still allowed in Visual Basic .NET, they are not the best way to do things anymore. Visual Basic now has full-blown structured exception handing using the Try, Catch, and Finally keywords. If possible, you should move to this new model for error handling as it allows for a more powerful and consistent mechanism in dealing with your application errors.
With the introduction of the .NET Framework and ASP.NET, COM really has not been changed at all. This does not mean, however, that you do not need to worry about COM objects and how they behave when you are using them from ASP.NET. There are a couple of fundamental things you need to be aware of.
Threading Model Changes
The ASP.NET threading model is the Multiple Threaded Apartment (MTA). What this means is that components that you are using that were created for the Single Threaded Apartment (STA) will no longer perform or function reliably without taking some extra precautions in ASP.NET. This includes, but is not limited to, all COM components that have been created using Visual Basic 6.0 and earlier versions.
You will be glad to hear that you can still use these STA components without having to change any code. What you need to do is include the compatibility attribute aspcompat=true in a
<%@Page> tag on the ASP.NET page. For example,
<%@Page aspcompat=true Language=VB%>. Using this attribute will force your page to execute in STA mode, thus ensuring your component will continue to function correctly. If you attempt to use an STA component without specifying this tag, the run time will throw an exception.
Setting this attribute to true will also allow your page to call COM+ 1.0 components that require access to the unmanaged ASP built-in objects. These are accessible via the ObjectContext object.
If you set this tag to true, your performance will degrade slightly. I suggest doing this only if you absolutely need to.
Early Binding Versus Late Binding
In ASP, all calls to COM objects occur through the IDispatch interface. This is known as "late binding" because calls to the actual objects are handled indirectly via IDispatch at run time. In ASP.NET, you can continue to invoke your components in this fashion if you like.
Dim Obj As Object Obj = Server.CreateObject("ProgID") Obj.MyMethodCall
This works but it is not the preferred manner to access your components. With ASP.NET, you can now take advantage of early binding and create your objects directly as follows:
Dim Obj As New MyObject MyObject.MyMethodCall()
Early binding allows you to interact with your components in a type-safe manner. In order to take advantage of early binding with your COM components, you need to add a reference in your project in much the same way that you add a COM reference to a Visual Basic 6.0 project. Assuming that you are using Visual Studio .NET, a managed proxy object is created behind the scenes, on top of your COM component, giving you the impression you are dealing directly with your COM component as a .NET component.
At this point you may wonder about performance. There is definitely some overhead involved when using COM interoperability as you now have an extra layer introduced because of the proxy object. In most cases, however, this will not be a factor because the amount of actual CPU instructions for the interoperation to occur is still substantially less than that required by your indirect IDispatch calls. You will be gaining more than you will lose. The ideal situation, of course, is to use newly created, managed objects, but we know that this will not always be possible immediately because of our investments in COM components over the years.
OnStartPage and OnEndPage Methods
One area that needs some additional consideration involves the use of the legacy OnStartPage and OnEndPage methods. If you rely on these methods to access ASP intrinsic objects, you will need to use the ASPCOMPAT directive and use Server.CreateObject to create your component in an early-bound fashion, as shown below:
Dim Obj As MyObj Obj = Server.CreateObject(MyObj) Obj.MyMethodCall()
Notice that instead of using the "ProgID," we have used the actual type in an early-bound manner. In order for this to work, you will need to add a reference to your COM component in your Visual Studio project so that the early-bound wrapper class is created for you. This should be the only case where you must continue to use Server.CreateObject.
Table 2 is a summary of what you need to do to continue to use your COM components as efficiently as possible.
Table 2. ASP.NET Settings for Legacy COM Objects
|COM Component Type/Method||ASP.NET Setting/Procedures|
|Custom STA (Visual Basic Components or other components marked as "Apartment")||Use ASPCOMPAT, use early binding|
|Custom MTA (ATL or custom COM components marked as "Both" or "Free")||Do not use ASPCOMPAT, use early binding|
|Intrinsic Objects (accessed via ObjectContext)||Use ASPCOMPAT, use early binding|
|OnStartPage, OnEndPage||Use ASPCOMPAT, use Server.CreateObject(Type)|
These same settings apply whether or not your components are deployed in COM+.
In ASP, all Web application configuration information is stored in the system registry and the IIS Metabase. This makes it quite difficult to view or modify settings because often the correct administration tools are not even installed on your server. ASP.NET introduces a whole new configuration model based on simple, human readable XML files. Each ASP.NET application has its own Web.Config file that lives in its main application directory. It is here that you control the custom configuration, behavior, and security of your Web application.
If you are like I was, you will be tempted to go to the Internet Services Manager snap-in to inspect and change the settings for your ASP.NET application. Understand, however, that we now have two totally separate configuration models. With the exception of some security settings, for the most part all other settings made using the IIS administration tool are ignored by ASP.NET applications. You need to place your configuration settings in the Web.Config file.
Application configuration with .NET is an article in itself and I will not detail it here. Table 3 shows some of the more interesting configuration sections you can set in your file. Keep in mind that there are many more.
Table 3. Sample Web.Config Settings
|Configures custom application settings.|
|Configures ASP.NET authentication support.|
|Identifies page-specific configuration settings.|
|Configures the ASP.NET process model settings on IIS systems.|
|Specifies session state options.|
There are classes available in the .NET Base Class Libraries that simplify programmatic access to these settings.
If your application uses the Session or Application intrinsic object to store state information, you can continue to use these in ASP.NET without any problems. As an added benefit, you now have a couple of more options for your state storage location.
State Management Options
In ASP.NET, you have additional options for your state storage model that will finally allow you to go beyond a single Web server and support state management across a Web farm.
You configure your state management options in the
<sessionState> section of your web.config file as follows:
<sessionState mode="Inproc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;user id=sa;password=" cookieless="false" timeout="20" />
The mode attribute specifies where you would like to store your state information. Your options are Inproc, StateServer, SqlServer, or Off.
Table 4. Session State Storage Information
|Inproc||Session state is stored locally on this server (ASP style).|
|StateServer||Session state is stored in a state service process located remotely or potentially locally.|
|SqlServer||Session state is stored in a SQL Server database.|
|Off||Session state is disabled.|
StateConnectionString and sqlConnectionString obviously come into factor if you use one of these other options. You can only use one storage option per application.
Storing COM Components
One thing to keep in mind is that if you rely on storing references to your legacy COM components in the Session or Application object, you cannot use the new state storage mechanisms (StateServer or SqlServer) within your application. You will need to use Inproc. This is due, in part, for the need of an object to be self-serializable in .NET terms, something that COM components obviously cannot do. New, managed components you create, on the other hand, can do this relatively easily and thus can use the new state storage models.
As far as performance goes, nothing comes for free, of course. One can safely assume that in most cases, Inproc will continue to be the best performer, followed by StateServer and then SqlServer. You should perform you own tests with your application to ensure the option you select will meet your performance goals.
Sharing State Between ASP and ASP.NET
Another important thing to consider is that although your application can contain both ASP and ASP.NET pages, you cannot share state variables stored in the intrinsic Session or Application objects. You either need to duplicate this information in both systems or come up with a custom solution until your application is fully migrated. The bottom line is that if you have made little use of the Session and Application objects, you should be in good shape. If, on the other hand, you use these objects extensively, you will need to proceed with caution and perhaps come up with a custom short-term solution to sharing your state.
Security is another area that requires a great deal of focus. Here is a brief overview of the ASP.NET security system. Consult the ASP.NET security documentation for a more thorough investigation.
ASP.NET security is primarily driven from settings in the security sections of your web.config file. ASP.NET works in concert with IIS to provide a complete security model for your application. IIS security settings are some of the few application settings that will actually carry over and be applied to your ASP.NET application in a similar manner to that in ASP. There are, of course, many additional enhancements.
For authentication, ASP.NET supports the different options shown in Table 5.
Table 5. ASP.NET Authentication Options
|Windows||ASP.NET uses Windows authentication.|
|Forms||Cookie-based, custom login forms.|
|Passport||External Microsoft provided Passport Service.|
|None||No authentication is performed.|
These are the same options you have in ASP, with the exception of the new Passport authentication option. As an example, the following configuration section enables Windows-based authentication for an application:
<configuration> <system.web> <authentication mode="Windows"/> </system.web> </configuration>
Once your users have been authenticated, you can focus on authorizing what resources you would like them to have access to. The following sample shows access being granted to "jkieley" and "jstegman," while everyone else is denied access.
<authorization> <allow users="NORTHAMERICA\jkieley, REDMOND\jstegman"/> <deny users="*"/> </authorization>
As a refresher, impersonation refers to the process whereby an object executes code under the identity of the entity on whose behalf it is performing. In ASP, impersonation will allow your code to run on the behalf of an authenticated user. Alternately, your users can run anonymously under a special identity. By default, ASP.NET does not do per-request impersonation. This is different from ASP. If you rely on this capability, you will need to enable this in your web.config file as follows:
<identity> <impersonation enable = "true"/> </identity>
Another key area you may need to focus on for your migration efforts is that of data access. With the introduction of ADO .NET, you now have a powerful new way to get at your data. Since data access is a large topic in itself, it goes beyond the scope of this article. For the most part, you can continue to use ADO as you have in the past, but I highly recommend taking a look at ADO .NET as a means to improve your data access methods within your ASP.NET application.
Now that you have been exposed to most of the issues you are likely to encounter, you may be wondering what things you can do today to be better prepared for them when you finally move to ASP.NET. Quite a few things can be done that will make the process smoother. Many of these suggestions will be beneficial to your ASP code even if you do not move to ASP.NET until sometime in the future.
Use Option Explicit
This has always been a good idea but still not everyone uses it. By enforcing variables to be declared in ASP by using Option Explicit, you will at least have a handle of where everything is defined and how your variables are being used. Once you move to ASP.NET, I suggest using Option Strict. Option Explicit will be the default in Visual Basic .NET but by using the more enforcing Option Strict, you will ensure all of your variables are declared as the correct data type. Doing this definitely requires a bit of extra work but, in the long run, you will discover that is was well worth it.
Avoid Using Default Properties
As we discussed, default properties are no longer allowed. Accessing your properties explicitly isn't really that hard to do anyway. It will make your code more readable and also save you time in porting in the future.
Use Parentheses and the Call Keyword
Use parentheses and Call statements wherever possible, as detailed earlier in this article. In ASP.NET you will be forced to use parentheses. Using the Call statement today will help you add a bit of discipline that will better prepare you for the future.
Avoid Nested Include Files
This may be easier said than done but, if possible, you should avoid nesting your include files. To clarify what I mean by this, you should try to eliminate any areas where you have include files that include other include files. What tends to happen over time is that your code ends up relying on a global variable that is defined in an include file somewhere else, and you are getting access to it only because you have included another file that includes the one you really need.
When you migrate to ASP.NET, you will most likely be moving your global variables and routines into class libraries, in which case, it is much easier to do if you have a clear picture of where you are getting access to everything. You may end up having to move things around and change some routines' names that were duplicated in multiple files.
Organize Utility Functions into Single Files
One strategy used in the migration process is to migrate all of the utility functions and code contained in your server-side include files into Visual Basic or C# class libraries. This allows you to finally put all of the code where it belongs—in objects, as opposed to multiple-interpreted ASP files. By organizing your code ahead of time, you will be saving yourself time in the future. Ideally, you should be able to group your sub-routines together in logical files thus allowing you to easily create a set of VB or C# classes. These are the functions that probably should have been in COM objects in the first place.
If you have a bunch of global variables or constants mixed in server-side include files, consider placing all of them in a single file, as well. Once you move to ASP.NET, you can then easily create a class that will house your global or constant data. This will make for a much cleaner and more maintainable system.
Remove Code from Content as much as Possible
This is another thing that is easier said than done but, if at all possible, you should separate your code from HTML content. Clean up functions that mix code and script throughout a function body. Doing so puts you in a much better position to leverage code-behind as this is the ideal model under ASP.NET anyway.
Do Not Declare Functions Inside <% %> Blocks
This is not supported in ASP.NET. You should be declaring your functions inside
<script> blocks. See the Structural Changes section earlier in this article for an example of this technique.
Avoid Render Functions
As discussed earlier, you should avoid using "render functions." If you can change or prepare your code now, you should be using Response.Write blocks when constructing these types of functions.
Explicitly Free Resources (Call Close Methods)
Make sure you explicitly call any close() or cleanup methods that exist on the objects and resources you may be using. We all know how forgiving Visual Basic and VBScript are when it comes to cleanup. Normally, they are pretty good at cleaning things up immediately but, as we move to .NET and the garbage-collected world, one cannot be sure exactly when objects will be cleaned up. If you can cleanup and release your resource explicitly, you should.
Avoid Mixing Languages
If possible, you should avoid intermixing server-side VBScript and JScript in the same page. In general, this is a poor programming practice anyway. This is also a migration issue for ASP.NET in that it requires only one inline
<% %> language per page because of the new compilation model. You can continue to emit client-side script in the same manner as you are used to.
As you have seen, there are a quite a few things you need to be aware of before moving your application to ASP.NET but most of the changes I have outlined should be relatively easy for you to implement.
If you have a large site, you will be amazed when you are finished with this process at the amount of dead code, inefficiencies, and outright bugs you came across and fixed. Additionally, you will be able to take advantage of the many powerful new features added to ASP.NET and the .NET platform in general.
Jim Kieley is a software development engineer at Microsoft. Since the inception of .NET, Jim has worked closely with the Visual Studio team and an early-adopter customer to create ASP.NET and the .NET Frameworks applications. Jim can be reached at firstname.lastname@example.org.