Migrating from ColdFusion to ASP.NET
Microsoft Visual Basic® .NET
Summary: Learn how to migrate from ColdFusion to ASP.NET. A comparison of ColdFusion MX and ASP.NET as well as common task scenarios for each application development framework are included. (25 printed pages)
Comparing Common Tasks
Any migration begins with a solid understanding of how the capabilities of the source system map to the capabilities of the target system. Is there any functionality missing in the target system that might require the purchase of third-party components? What new capabilities might the target system provide? In this paper, we compare the capabilities of Macromedia's ColdFusion MX and Microsoft® ASP.NET Web application development frameworks and then examine how some common tasks are performed in each environment. By understanding the similarities and differences in these platforms, ColdFusion developers can begin to transform their expertise in ColdFusion Markup Language (CFML) into an understanding of ASP.NET development.
The most fundamental of all architectural differences between ColdFusion MX and ASP.NET is the underlying framework that each is based upon. ColdFusion MX is Java-based, running on top of Macromedia's JRun server. It also supports a number of other industry-standard J2EE application servers. At runtime, all CFML pages are parsed and converted into Java source code, then compiled into Java bytecode before being executed. After the initial compilation, the cached bytecode for a page is re-executed without the need for further parsing or compilation.
ASP.NET is based on Microsoft's .NET Framework. At runtime, all ASP.NET pages are parsed and converted into source code for a .NET-compatible language (usually Microsoft Visual Basic® .NET or C#) and then compiled into Microsoft Intermediate Language (MSIL), a processor-independent bytecode with many similarities to Java bytecode. This MSIL is then further just-in-time compiled into native machine code before being executed. After the initial compilation, the cached native machine code for a page is re-executed without the need for further parsing or compilation.
Although the low-level frameworks underlying each system cannot be ignored, the most striking differences between ColdFusion MX and ASP.NET that many Web developers will notice occur at a much higher level—in the development and page execution models. While the details vary, ColdFusion follows the same development and page execution model as that of classic ASP, PHP, JSP, and other similar Web-scripting languages. Specifically, code is embedded in HTML markup, and as a given page executes from top to bottom, the output of the code's execution takes the place of the embedded code in the resulting HTML document. This development model is easy to grasp, but it does have a number of drawbacks. Chief among these is the lack of separation between application logic and presentation markup. Mixing code and presentation makes the code harder to read, which increases the time and effort involved in maintenance, and creates significant challenges for non-programming graphic designers who need to modify a page. Over the years, ColdFusion has introduced several ways to mitigate this lack of separation, including custom tags, and others—but the fundamental model remains.
ASP.NET, however, makes a very distinct break from the traditional model of Web application development. Rather than being linear and page-oriented, ASP.NET code is strongly typed, object oriented and event based. Basically, ASP.NET development is a blending of traditional Web development and traditional fat-client GUI development. Page elements are represented on the server-side by objects, each with its own properties, methods and events. An example is a page that posts back to itself and inserts some information from a form into a database. In ColdFusion, you might write some code to check for the existence of a form variable corresponding to the name of the HTML submit button to see if the page is loading for the first time, or as the result of a form submission. Then you would read the various form variables, validate them, and perform a database insert. If one or more form variables failed validation, you would need to write more code to display an error message to the user and to preserve the values the user has already entered. In ASP.NET, you simply bind a function to the
event of a
server control. Within this function, some code will read the Text property of the various form fields, represented on the server-side with
objects. By the time the button's
event has fired, form field validation has already been performed by any validation controls on the page, which also take care of displaying any necessary error messages to the user. Each individual
takes care of preserving its own contents in the event users need to edit one or more of their entries.
For more information about ASP.NET's page framework, please see Introducing Web Forms.
Table 1 presents a comparison of some of the prominent features in ColdFusion MX and ASP.NET.
Table 1. Comparing the Features of ColdFusion MX and ASP.NET
|Coding Language||Has two related coding languages: CFML and CFScript. Most developers use a mix of CFML and CFScript.||Supports more than 25 languages, but the 2 that are most-commonly used are Visual Basic .NET and C#. Most developers pick one language but can consume components written in any of the other supported languages.|
|Compiled Application Logic||Supported, dynamically compiled.||Supported, in both dynamically-compiled and precompiled modes.|
|Full-Page Output Caching||Supported, caches different versions of the page based on all URL parameters.||Supported, caches different versions of the page based on one or more URL parameters, browser type, a custom function or any combination.|
|Partial-Page Output Caching||No built-in support.||Built-in support through use of User Controls. Data and other objects can be cached with sophisticated expiration rules using the Cache API.|
|Database Access||Supports Type III and Type IV JDBC drivers, as well as ODBC via a JDBC-ODBC bridge.||Supports OLE-DB and ODBC directly, as well as including native drivers for MS SQL Server and Oracle.|
|Database Output||Formatted output using looping with the CFOUTPUT or CFLOOP tags.||Templated databinding to server-side controls for ease of development, or manual looping if that is preferred.|
|External Components||Supports CORBA objects, Java and EJB object, and JSP tag libraries, as well as special extension tags written in C++ or Java. COM is supported, but from most reports is rather unreliable in the current release.||Very good support for native C libraries and COM objects, as well as assemblies written in any .NET-compliant language, including Managed C++. No built-in support for CORBA objects or Java classes.|
|XML/XSLT||Basic XML DOM and XSLT transformation is supported in an intuitive fashion, but there is little to no access to advanced features such as XML namespaces, XSD validation, and XSLT parameters. Lightweight stream-oriented parsing of large XML documents (such as SAX) is not supported.||Comprehensive and easy-to-use support is provided for XML DOM, XSLT, validation, and lightweight stream-oriented parsing of XML documents.|
|XML Web Services||The current release supports publishing and consuming Web services with a beta version of Apache Axis. Publishing and consuming Web services are very easy, but there are some known compatibility issues that may be corrected by an update that uses Apache Axis 1.0. Another major limitation is that asynchronous calls to Web services, and the creation of Web services that can be called asynchronously are not supported.||The current release provides extensive and flexible standards-compliant support and makes it extremely easy to both publish and consume Web services. Asynchronous calls to Web services, and the creation of Web services that can be called asynchronously are supported with ASP.NET.|
|Session State||Cookie-based, in-memory single-server session state, or cookie-based persistent "client state" using a database back-end. Cookieless sessions are supported but can require moderate-to-extensive modification of existing code in order to take advantage of them.||Cookie-based or cookieless session state, using a single-server in-memory store, a centralized state server, or a database back-end. In addition, the extensible architecture allows for custom session-state modules to replace the built-in options. Cookieless sessions require only a configuration change to enable.|
|Built-In Functionality||ColdFusion MX has built-in functions to cover many common tasks that a Web-based application may need to perform. It can also access Java class libraries with some extra work.||ASP.NET has direct access to the entirety of the .NET Framework class libraries, which encompass a vast amount of functionality. This functionality is comparable to Java, but far more than is natively exposed in ColdFusion.|
|Regular Expressions||Supports a mostly-Perl-5-compatible regular expression syntax, but has only partial Unicode support.||Supports Perl-5-compatible regular expressions, with additional features such as right-to-left matching, precompiled expressions, named groups, full Unicode support. Also allows the user to specify a function to be called during a regular expression replace operation.|
|Error Handling||Supports structured error handling, raising custom errors, and specifying custom error pages for different types of unrecoverable errors.||Supports structured exception handling (with the addition of a "finally" block for code that executes regardless of whether or not an error occurs), raising custom exceptions, and specifying custom error pages for different types of unrecoverable errors.|
|Charting||Includes support for generating a variety of basic charts in JPG, PNG, or Flash format.||No built-in support, although third-party components are available.|
|Image Manipulation||No built-in support, although third-party components are available.||Includes extensive image creation and manipulation facilities.|
|Code Re-Use||Custom tags, user-defined functions, ColdFusion Components, and included files.||User Controls, Server Controls, custom classes, and included files.|
|Threading||No support, aside from the fact that simultaneous page requests happen in separate threads.||Fully supported. Not only do simultaneous page requests happen in separate threads, but also each page can (if needed) spawn its own threads to perform simultaneous or asynchronous work.|
|Full-Text Search||Includes a stripped-down version of the Verity search engine and allows access to a full-featured Verity K2 server. Can use any full-text search features provided by a database vendor, and other search engines can be accessed through their respective COM or Java API's.||Does not include a built-in search engine but can access MS Index Server for full-text searching of files. Can use any built-in full-text search features provided by a database vendor. The Verity K2 server can be accessed through its provided COM and .NET API's, and other search engines can be accessed through their respective COM or .NET API's.|
|Data Caching||Allows for time-based caching of database query results. Other types of data can be explicitly stored in application or session variables, but expiration and concurrency locking must be handled manually.||Includes an extensive cache API that allows nearly any type of data (including database query results) to be stored, with expiration based upon time, usage, or dependency upon a file or another cached item. Also allows for a user-defined function to be called when a given item is removed from the cache.|
|Internationalization||Supports Unicode strings and various character encodings and includes a variety of functions for converting numbers, currency, and dates to a locale-specific format. Some functions are culture-aware, and others are not. No built-in support for dynamically localizing an application into a specific language or culture.||Supports Unicode strings and various character encodings. Date, number, and currency functions are all culture-aware and alter their output depending on what the current culture is set to (rather than requiring different functions to be called). Support for using resource files to dynamically localize an application is included.|
|SMTP, HTTP, FTP, POP3||Supported, although CFMAIL is generally viewed as rather unreliable.||SMTP support depends upon the Internet Information Services (IIS) SMTP Service. HTTP has very good support. FTP and POP3 are not supported in .NET, but free and commercial third-party components are available for this functionality.|
|Web Server Support||Supports IIS, Sun ONE, Netscape IPlanet, and Apache.||Supports IIS and Covalent's commercial version of Apache 2.0.|
|Operating System Support||Supports Windows, Linux, Solaris, and HP-UX.||Currently supports Microsoft Windows® 2000, Windows XP, and the forthcoming Windows Server 2003.|
Custom Tags vs. User Controls
Two features that bear a strong resemblance to one another are ColdFusion's custom tags and ASP.NET's user controls. Although superficially similar, there are some important differences to be aware of. Like custom tags, user controls are implemented as separate files that are built much like the pages that host them (the files have a slightly different extension, ascx instead of aspx). And similar to ColdFusion's custom tags, user controls are placed into a page using "custom tags" in the HTML markup. User controls can send HTML output to the browser, but unlike custom tags, user controls are typically not used for anything other than sending output to the browser. Also unlike custom tags, user controls are full-fledged objects with their own properties and methods. In that sense, they are closer to ColdFusion Components than custom tags.
User controls can encapsulate other controls and respond to the encapsulated controls' events. This capability allows for the creation of self-contained units of functionality, such as a log-in control that contains two
controls and a
and handles the button's click event, validating the username and password entered by the user. In this way, user controls can participate in the entire page lifecycle. Their methods can be called at any time while the various parts of the page are running, rather than having one routine executed only when the tag is encountered during processing (as with ColdFusion's custom tags).
For more information about user controls, please see Web Forms User Controls.
ColdFusion Components vs. Classes
Newly introduced in ColdFusion MX, ColdFusion Components (CFCs) represent the first real step for ColdFusion towards the encapsulation, flexibility and maintenance benefits of a true object-oriented system. CFCs can have multiple instances running at one time on a single page, with each instance containing its own data and each able to have its methods called to manipulate this instance data. ColdFusion Components support a limited amount of access control on methods and a limited form of inheritance. CFCs are not, however, truly object-oriented. They lack constructors, interfaces, protected members, method overloading and other trappings of a true object-oriented system.
If you're suffering from object-oriented buzzword overload, don't worry. All you need to know to get started is that most CFCs can be translated to classes in whatever ASP.NET-compatible programming language you happen to be using. However, while you can get by in ASP.NET with very little object-oriented knowledge, object-oriented concepts truly are one of the most powerful and productive techniques you could spend your time studying. You can find an introduction to the main areas of object-oriented programming (from a Visual Basic point of view) in Object-Oriented Programming in Visual Basic.
User-Defined Functions vs. Class Methods
User-defined functions in ColdFusion are a means of creating your own custom functions. These functions are not attached to any particular object, but rather are pseudo-objects in their own right, which can be stored in a number (but not all) of ColdFusion's built-in variable scopes or called directly in the context in which they were created.
There is no direct equivalent of user-defined functions in .NET, as .NET is an object-oriented framework and global functions are always attached to any object. The closest equivalent would be
static (in C#) or
Shared (in Visual Basic) methods. These methods are attached to a class, as all methods are, but they are attached globally to the class itself rather than to any instance of the class. For this reason, static/Shared
methods can be called with ClassName.MethodName(), rather than needing to create an instance of the class and calling the method on that instance. These methods can be useful for utility functions that do not require any data other than what is passed to them when they are called.
XML Web Services
Both ColdFusion MX and ASP.NET provide support for XML Web Services, and both frameworks go to great lengths to make the creation and consumption of Web services an easy task. ColdFusion does so through an extension to ColdFusion Components that allows one or more methods of a CFC to be published as a Web service. When publishing a Web service, ColdFusion takes care of reading the CFC metadata and automatically generating a Web Services Description Language (WSDL) file that programmatically describes the service to consumers. When consuming a Web service, ColdFusion will read the service's WSDL file, and provide relatively transparent access to the methods described therein.
Similarly, you create a Web service in ASP.NET by making a file with the extension "asmx," and using attributes to mark which methods in the file should be exposed as Web service methods. The ASP.NET Framework takes care of generating a WSDL file from the Web service metadata. When consuming a Web service, the .NET Framework will take care of reading the service's WSDL file and automatically generating proxy classes that allow you to treat the remote services as if they were local objects. If additional control is needed, the proxy classes can be modified or even written by hand, if necessary.
As of this writing, ColdFusion's Web service implementation is based upon a beta version of Apache Axis, an open-source Web services framework. This beta version has some known incompatibilities with other frameworks, which can make interoperation with disparate sources (a fundamental tenet of XML Web Services) problematic. A forthcoming update to ColdFusion MX should upgrade its Axis support to version 1.0 and improve interoperability, but even then some issues will remain. ColdFusion does such a good job of hiding the underlying Simple Object Access Protocol (SOAP) implementation, that it can actually hinder interoperability. For example, ColdFusion provides no means of reading or writing to SOAP headers during a request, so a Web service that takes full advantage of the SOAP specification by requiring that authentication information be sent in a SOAP header, or requiring that the body be encrypted, simply will not work with ColdFusion. In addition, there is no indication when (or, indeed, if) ColdFusion will support emerging Web service standards, such as those covered in the recently-released Web Services Enhancements for Microsoft .NET, which includes support for the WS-Security, WS-Routing, WS-Attachments and DIME specifications.
Another significant limitation to the ColdFusion Web services implementation is the lack of support for asynchronous Web service calls. The ability to call Web services asynchronously allows application developers to make a Web service call and perform additional work (i.e. not "block") while waiting for the Web service to return. The capability to call Web Services asynchronously from an application, and the capability to create Web services that can be called asynchronously is critical to many application development scenarios. ASP.NET supports both.
ASP.NET includes a large number of pre-built Server Controls that vastly simplify working with form-based Web applications. Some of these controls have analogs in ColdFusion's
cfform and related tags, but the ASP.NET controls are for the most part significantly more powerful and flexible. ColdFusion includes
cfform, cfinput, cftextinput and cfselect
(which handle basic form elements and validation), as well as
cfgrid, cftree and cfslider
(providing a grid with inline editing, a tree control and a slider control, respectively; all three of which are implemented as client-side Java applets).
Another rich control included in ASP.NET is the
DataGrid. At its most basic, this control is generally used for displaying the results of a database query in an HTML table in the browser. However, with only a few extra lines of code, the DataGrid supports paging through large sets of data, sorting on columns, and inline editing of data, all without requiring any client-side downloads or special capabilities. Other built-in controls include the
Calendar, which draws a dynamic calendar on the page, allowing the user to intuitively select a date; the
AdRotator, which allows for easy and configurable displaying of ad banners on a page; and the
control, which provides an easy and intuitive way of performing XSLT transformations of XML Data to produce content.
Numerous free and commercial third-party server controls are becoming available for ASP.NET. Microsoft also supplies a set of additional controls that include
TreeView, TabStrip, and Toolbar
Comparing Common Tasks
The following sections provide comparisons of how to accomplish some common programming tasks in ColdFusion, and in one of the most-common ASP.NET languages, Visual Basic .NET.
The typical way of outputting data in ColdFusion is with the
Extensible Stylesheet Language Transformations
ut tag, or with
in CFScript. The closest analogue to this in ASP.NET is the
method, or the
construct, which is simply shorthand for
Response.Write(). Table 2 shows basic syntax for writing a value to the page.
Table 2. Basic Output
|CFML||Visual Basic .NET|
<cfoutput> The current date is: #Now()# </cfoutput>
The current date is: <% Response.Write(DateTime.Now) %> Or: The current date is: <%= DateTime.Now %>
However, these methods for sending output to the browser exist primarily for backwards compatibility with classic ASP. ASP.NET's new control-based, event-oriented model allows for data to be output to the browser by simply setting properties on server controls. This technique allows for clean separation of layout and code and can make maintenance easier, requiring significantly less code in complex situations.
<script language="VB" runat="server"> Sub Page_Load(sender As Object, e As EventArgs) TheDate.Text = DateTime.Now End Sub </script> The current date is: <asp:Label id="TheDate" runat="server"/>
This example declares a server-side
Label control, and during the page's
Load event, sets the
property of the label to the current date and time. The HTML output of this code is identical to the other two versions, except that the
Label control renders itself as a
span tag containing whatever was set as the label's text.
ColdFusion allows you to insert server-side comments in a page, and anything within those comment indicators will be removed from the page and not sent to the browser. Server-side code in a comment block will not be executed. In addition, CFScript Extensible Stylesheet Language Transformations (XSLT) has its own comment syntax: a double-slash (//) at the beginning of a line will comment out the entire line.
ASP.NET has equivalents for both types of comments. A comment block in an aspx page will not be sent to the browser, and any server code contained in that block will not be executed. In addition, each .NET language has its own comment syntax for writing comments within a block of code. In Visual Basic, a single apostrophe (') at the beginning of a line will comment out the entire line. Table 3 shows server-side comments in each environment.
Table 3. Server-Side Comments
<!--- This is a comment. --->
<%-- This is a comment. --%>
The two main groups of conditional processing tags in ColdFusion are
cfswitch/cfcase/cfdefaultcase. Visual Basic .NET has equivalent constructs with fairly similar syntax. Table 4 provides a comparison of equivalent conditional logic in CFML and Visual Basic .NET.
Table 4. Basic Conditional Logic
|CFML||Visual Basic .NET|
<cfif x GT y OR x EQ z> <!--- do something ---> <cfelseif x LT m AND x GT r> <!--- do something else ---> <cfelse> <!--- do a third thing ---> </cfif>
If x > y OrElse x = z Then ' do something ElseIf x < m AndAlso x > r Then ' do something else Else ' do a third thing End If
It should be noted here that Visual Basic .NET has
operators as does ColdFusion. However, they behave slightly differently than the ColdFusion versions. The
operators in ColdFusion are short-circuiting operators. If the statement on the left side of the operator fails its test, the statement on the right side of the operator will not be executed. This allows statements such as the following example, which first checks for the existence of a variable called "x", and then checks the value of one of its properties. If the existence test fails, the second part of the statement will not be executed.
<cfif IsDefined("x") AND x.SomeProperty EQ true>
In Visual Basic .NET, the
operators are not short-circuited; all statements will be executed regardless of the result of the earlier statements. This behavior can be a critical difference. Consider the following code that is seemingly equivalent to the last statement:
If Not x Is Nothing And x.SomeProperty = True
Although this code seems identical, it will actually generate an error in the case where
Nothing. Because all statements are evaluated, Visual Basic will try to read the property of a non-existent object. In order to get short-circuiting behavior equivalent to that in ColdFusion, you must use the
OrElse operators, which are newly introduced in Visual Basic. NET.
Visual Basic .NET will attempt to coerce integer and other values into Boolean values if they are used directly in an If statement (0 becomes false; anything else becomes true), just as ColdFusion does. However, if Visual Basic's
If statements will accept only true Booleans. Shortcuts such as
"If y Then"
become impossible and must be replaced by
"If y > 0 Then"
because the greater-than operator returns an actual
False value. In general, the restrictions imposed by Option Strict are viewed as a good thing, because they force programmers to be more explicit about their intentions, reducing the chance of causing a difficult-to-diagnose bug.
When you test a single expression for multiple values, the
cfswitch statement can be both easier to read and better performing than multiple
statements. The same holds true in Visual Basic. NET, through the
statement. Table 5 shows a comparison of ColdFusion's
cfswitch statement and Visual Basic's
Select Case statement.
Table 5. A Comparison of cfswitch and Select Case
|CFML||Visual Basic. NET|
<cfset num = 4> <cfset description = ""> <cfswitch expression="#num#"> <cfcase value="1,2,3,4,5"> <cfset description = "Between 1 and 5"> </cfcase> <cfcase value="6,7,8"> <cfset description = "Between 6 and 8"> </cfcase> <cfcase value="9,10"> <cfset description = "Greater than 8"> </cfcase> <cfdefaultcase> <cfset description = "Not between 1 and 10"> </cfcase> </cfswitch>
With the exception of using
cfoutput to write a query result set to the browser, virtually all looping in CFML is accomplished with the
cfloop tag. Visual Basic (along with most other .NET languages) has different language elements for different types of looping rather than a single language element with different attributes. Table 6 shows a basic index loop in each language.
Table 6. Index Loop
|CFML||Visual Basic. NET|
<cfset sum = 0> <cfloop index="counter" from="1" to="100" step="5"> <cfset sum = sum + counter> </cfloop>
Dim sum As Integer = 0 Dim counter As Integer For counter = 1 To 100 Step 5 sum += counter Next
In Visual Basic, this type of loop is known as a For…Next loop. In this example, the += operator is used as shorthand for "sum = sum + counter." A cfloop can be broken out of with the cfbreak statement. A For…Next loop can be broken out of with the Exit For statement.
A conditional loop iterates over a set of instructions as long as a condition evaluates to true. Table 7 shows an example of a basic conditional loop in each language.
Table 7. Conditional Loop
|CFML||Visual Basic. NET|
In Visual Basic, this type of loop is known as a
Do. . .Loop
statement, or a while loop. The
Do. . .Loop
statement, however, has some additional capabilities not directly available in a
cfloop conditional loop. It includes the ability to loop until a condition is true, rather than while a condition is true:
Do Until counter > 10 counter += 1 Loop
The code inside either a conditional cfloop or a Do…Loop statement will not be executed at all if the loop condition is not met when the statement is first processed. However, unlike
Do. . .Loop
statement can be reversed, so that the code inside the loop is always executed at least once, and then more times if conditions warrant.
Do counter += 1 Loop While counter < 11
This construct is not as commonly used as a normal loop but can be useful in certain situations.
ColdFusion can use cfloop to iterate over every item in a collection or structure. This functionality is covered natively by each language supported by ASP.NET. In Visual Basic .NET, the equivalent is the
For Each. . .Next
statement. Table 8 shows an example of looping over a collection in each language.
Table 8. Looping Over a Collection
|CFML||Visual Basic. NET|
<cfloop collection="#myStruct#" item="key"> <cfoutput> #key# = #myStruct[key]# </cfoutput> </cfloop>
For Each key In myHashTable.Keys Response.Write(key + " = " + myHashTable[key]) Next
Looping over a query with
has no direct analogue in any ASP.NET language. The reason is that database query results are not treated as a special type of object. Typically database queries are returned from ADO.NET as
can be traversed with either a
For. . .Next
loop or a
For Each. . .Next
loop, while an
can be traversed with a
Do While. . .Next
loop. However, in many cases it is not necessary to manually loop over a set of query results at all. Both the
can be bound directly to an ASP.NET server control, such as the
DataGrid, which will take care of extracting data from the result set and formatting it for you.
Setting and Retrieving Session Variables
Session variables in ASP.NET are at their most basic level very similar to ColdFusion's session variables. They are cookie-based, expire after a configurable span of inactivity, and can store nearly any type of object. There are, however, some important differences that should be noted. Perhaps most significantly for ColdFusion developers, reads and writes to ASP.NET session variables seldom need to be locked. Unless there's a strong possibility that a page that writes to a session variable and a page that reads from the same session variable could be called simultaneously from the same client, there is no need to slow your application by locking every single session variable access. Other differences include cookieless sessions and out-of-process or database-based session storage, all available through simple configuration file changes.
The last important difference is that when a value is retrieved from the ASP.NET session object, it is returned as the generic
type, which can hold any type of data. This value must be converted back to its original underlying type before it can be used. Table 9 shows some examples of session variable usage.
Table 9. Session Variable Usage
|CFML||Visual Basic. NET|
<cfset Session.Today = Now()> <cfset today = Session.Today> <cfoutput>#today#</cfoutput>
The .NET framework includes support for structured exception handling very similar to ColdFusion's
tags, with the notable addition of a
block, which allows for code to be executed regardless of whether an error occurred in the
block. This can be very useful for performing clean-up operations. Table 10 shows a comparison of error handling in each language.
Table 10. Structured Exception Handling
|CFML||Visual Basic. NET|
<cftry> <!--- code that might cause an error here ---> <cfcatch type="exceptiontype"> <!--- code to handle the error ---> </cfcatch> <!--- Optional: More cfcatch blocks ---> </cftry>
It is worth noting that a
block can have either one or more
blocks, or a
block, or both. In other words, in situations in which you know that there is no way to correct for an error, but you still need to clean up some objects regardless of whether an error occurs or not, you can use a
Try. . .Finally
block with no Catch
ColdFusion arrays support any data type, dynamically resize themselves, and are multi-dimensional only in the sense that they support nested arrays-of-arrays. Arrays in the .NET framework (and by extension, Visual Basic. NET and other languages) are more restrictive in some areas, less in others, and perform better in nearly all areas.
Visual Basic. NET arrays must be declared as holding a specific type of data when they are created. If the type specified is
(the generic type underlying every object type in .NET), then the array can hold any type of data, but values must be converted to their original type when they are retrieved from the array. This restriction is generally viewed as a good thing, as the compiler is able to make some significant performance optimizations in cases in which it knows exactly what type of data an array can hold. In addition, it prevents the programmer from accidentally adding a string to an array of dates, potentially causing a hard-to-find error later when the array is read.
Visual Basic. NET arrays can be either nested arrays-of-arrays (or jagged arrays), as in ColdFusion, or true multi-dimensional arrays. Arrays in Visual Basic. NET do not automatically resize themselves as in ColdFusion; you must explicitly resize the array with the
statement. However, if a resizable array is needed, it is often advisable to use the System.Collections.ArrayList object, which does dynamically resize as needed and can give significantly better performance than
One final difference to note is that unlike in ColdFusion, assigning an array to a new variable does not implicitly make a copy of that array. Rather, it makes a copy of the reference to the same array; changes to the new variable will affect the original array. In order to make a copy of an array, you can use the
method attached to any array object, or the global
For more detailed information about declaring and manipulating arrays in Visual Basic. NET, see the language reference.
Structures and Other Collections
object is quite extensively used in many ColdFusion applications. In fact, it forms the basis of most of the variable scopes in ColdFusion, such as
Form, URL, Session, Request, CGI
and so on. The equivalent in any ASP.NET language is the System.Collections.Hashtable object. The System.Collections namespace also contains many other more specialized collection objects that can be useful in various situations.
The .NET framework provides extensive support for regular expressions. The syntax supported is slightly different from that supported by ColdFusion, and .NET provides some additional capabilities not present in the current version of ColdFusion. Some of the capabilities include full Unicode support, pre-compiled expressions, and the ability to specify a custom function to be called during a regular expression replace operation. For more information about .NET's regular expression support, see .NET Framework Regular Expressions.
Built-in support for sending SMTP is included in ASP.NET, but has some external dependencies. Specifically, the IIS SMTP service must be installed because the built-in mail objects depend on the CDONTS objects included with the service. Table 11 shows the minimum code required to send an email in each language.
Table 11. Sending Email
|CFML||Visual Basic. NET|
<cfmail to="firstname.lastname@example.org" from="email@example.com" subject="Test Message"> This is a test message. </cfmail>
Dim myMail As MailMessage = New MailMessage() myMail.From = "firstname.lastname@example.org" myMail.To = "email@example.com" myMail.Subect = "Test Message" myMail.Body = "This is a test message." SmtpMail.Send(myMail)
Date/Time Manipulation and Formatting
ColdFusion date-time variables can range from the year 100 Common Era (CE) to the year 9999, with a minimum resolution of one second. ColdFusion includes an extensive set of functions that can operate on date-time variables to manipulate them and extract the various components (year, month, hour).
objects in .NET can range from the year 1 CE to the year 9999, with a minimum resolution of 100 nanoseconds (one "tick"). Functionality for manipulating DateTime
objects and extracting the various components is attached directly to the DateTime
objects themselves, as Table 12 shows.
Table 12. Date Manipulation
|CFML||Visual Basic. NET|
<cfset today = Now()> <cfset thisYear = Year(today)> <cfset thisMonthName = MonthAsString(Month(today))> <cfset nextMonth = DateAdd("m", 1, today)> <cfset difference = DateDiff("d", today, nextMonth)> <cfset dateString = DateFormat(today, "full")>
Dim today As DateTime = DateTime.Now Dim thisYear As Integer = today.Year Dim thisMonthName As String = today.ToString("MMMM") Dim nextMonth As DateTime = today.AddMonths(1) Dim difference As Long = DateDiff("d", today, nextMonth) Dim dateString As String = today.ToString("F")
One important difference to note is that, the equivalent of the
function is the
method of the
DateTime object. Passing in a format string tells the
object how to format the resulting string. For information about what format strings can be used, refer to Date and Time Format Strings.
Setting and Retrieving Cookies
Cookie support is fairly standard across any Web scripting language, and ASP.NET is no exception. Table 13 shows an example of writing and then reading a cookie in each language.
Table 13. Setting and Retrieving Cookies
|CFML||Visual Basic. NET|
<cfcookie name="LastVisit" value="#Now()#" expires = "#DateAdd('d', 10, Now())#"> .. <cfoutput>#Cookie.LastVisit#</cfoutput>
Dim myCookie As HttpCookie = New HttpCookie("LastVisit") Dim now as DateTime = DateTime.Now myCookie.Value = now.ToString() myCookie.Expires = now.AddDays(10) Response.Cookies.Add(myCookie) .. Response.Write(Request.Cookies ["LastVisit"].Value)
One additional feature that ASP.NET has that is not present in ColdFusion is the ability to store multiple name/value pairs in a single cookie. You can perform the same operation in ColdFusion, but the code must be written manually, while ASP.NET provides convenient properties and methods on the
object to do this for you.
Querying a Database
Database access in .NET is accomplished through the hierarchy of objects collectively known as ADO.NET. A full exploration of ADO.NET is beyond the scope of this paper, so we'll just touch on the most important points. The actual execution of a database query is accomplished with a set of connection, command, parameter and data-adapter objects. There are multiple versions of each of these objects, depending on the type of database being accessed. For example, there is a set for databases with OLE-DB drivers (such as Microsoft Access), as well as a set for databases that have ODBC drivers but lack OLE-DB drivers. There are also specialized data providers for both Oracle and Microsoft SQL Server™ that are optimized to provide high-performance access to each of those specific databases. The examples in this section will use the SQL Server objects, as that is one of the most-commonly-used databases with ASP.NET. The SQL Server objects are located in the System.Data.SqlClient namespace.
In ColdFusion, ad-hoc SQL queries are typically executed with the
tag. Although variables can be inserted directly into the SQL statement with this tag, doing so is not recommended, as this technique is vulnerable to SQL injection attacks, as well as invalid characters invalidating the entire SQL statement. In addition, inserting variables directly into the SQL statement prevents the database server from caching the query execution plan, forcing it to parse the statement anew every time it is executed, which can hurt performance. ColdFusion accounted for this issue by introducing the
tag that works with the
tag to allow for parameterized queries, which can still be built dynamically, but suffer from none of the disadvantages just mentioned. ADO.NET supports both types of queries, but like ColdFusion, parameterized queries are preferred over queries with variables embedded in the SQL statement. Table 14 shows an example of executing a parameterized query in each language.
Table 14. Executing Parameterized Queries
|CFML||Visual Basic. NET|
<cfset sales_cutoff = 1000> <cfquery name="topSellers " datasource="datasource_name"> SELECT title_id, title, ytd_sales FROM titles WHERE ytd_sales >= <cfqueryparam value="#sales_cutoff#" CFSQLType="CF_SQL_INTEGER"> ORDER BY ytd_sales DESC </cfquery>
Dim sales_cutoff As Integer = 1000 Dim myConnection As SqlConnection = New SqlConnection ("connection_string") Dim myCommand As SqlCommand = myConnection.CreateCommand() myCommand.CommandText = "SELECT title_id, title, ytd_sales FROM titles WHERE ytd_sales >= @sales ORDER BY ytd_sales DESC" myCommand.Parameters.Add("@sales", SqlDbType.Int).Value = sales_cutoff Dim SqlDataAdapter myAdapter = New SqlDataAdapter(myCommand) Dim topSellers As DataSet = New DataSet() myAdapter.Fill(topSellers, "titles")
The results of an ADO.NET database query are typically returned in either a
is an in-memory data store that resembles ColdFusion's
object in that it is a copy of the data returned by the database and doesn't require an active connection to the database while it is being used. The
object is specific to the data provider in use (SqlDataReader,
OleDbDataReader, etc.) and represents a live connection to the database that returns data as it's received from the database server. For this reason, the data-reader is read-only, and you cannot navigate backwards through it, but read performance is typically better than that of a
DataSet. You must be careful, however, not to tie up the underlying database connection for longer than necessary when using a data-reader.
ColdFusion uses the
cfstoredproc, cfprocparam, and cfprocresult
tags to execute stored procedures against a database server. In ADO.NET, the code to execute a stored procedure is identical to the code needed to execute a parameterized query, except that you set the
to the name of the stored procedure to be executed. If we were to imagine a stored procedure equivalent to the query above, the code to call it might look something like the example in Table 15.
Table 15. Calling a Stored Procedure
|CFML||Visual Basic. NET|
<cfset sales_cutoff = 1000> <cfstoredproc procedure="GetTopSellers" datasource="datasource_name"> <cfprocparam type="in " value="#sales_cutoff#" CFSQLType="CF_SQL_INTEGER"> <cfprocresult name="topSellers "> </cfstoredproc>
Although ADO.NET requires slightly more code to do things than ColdFusion does, the benefit lies in greatly increased flexibility and control. For cases in which this additional flexibility is not needed, Microsoft has provided the Data Access Application Block, which encapsulates many common data-access tasks. The result is that you can accomplish the same thing in significantly fewer lines of code, and in fact for many tasks, only a single line of code is required when using this tool.
Outputting Query Data
The typical way to output query data in ColdFusion is to loop over the query results by using
cfoutput, embedding each row of the data columns directly into some HTML markup. Although this same approach is supported in ASP.NET, many people prefer ASP.NET's powerful and easy-to-use support for databinding. When using databinding, all you need to do is assign some query results to the
property of a data-aware server control (such as the
DataGrid), optionally provide some additional formatting information for each column, and call the
method. The server control will take care of the rest. Many data-aware server controls will provide additional functionality, such as support for paging or in-line editing of the data being displayed. As an example, let's output the query results we got in the previous section, as Table 16 shows.
Table 16. Outputting Query Results
|CFML||Visual Basic. NET|
<table> <tr> <th>title_id</th> <th>title</th> <th>ytd_sales</th> </tr> <cfoutput query="topSellers "> <tr> <td>#title_id#</td> <td>#title#</td> <td>#ytd_sales#</td> </tr> </cfoutput>
In page load event:
myDataGrid.DataSource = topSellers myDataGrid.DataBind()
For more information and examples, please refer to Data Binding Server Controls.
Data Caching and Page Caching
Caching frequently-accessed data can dramatically improve the response time of a site, as the page processing doesn't need to wait on a database query. Caching the HTML generated by a page request can improve response time even more, as the cached page doesn't need to be processed at all. Both ColdFusion and ASP.NET provide support for both caching strategies; however, ASP.NET's support is quite a bit more powerful and flexible than that provided by ColdFusion.
Database query results can be cached in ColdFusion by using the
attributes of the
tag. The results of a stored procedure call with
can't be cached with an equivalent mechanism. It's possible to call a stored procedure with
by using a slightly slower provider-specific syntax. Cached queries are differentiated based on the full text of the SQL statement used (along with the other
attributes) and are removed from memory after the specified span of time has elapsed, or when an administrator-defined limit on the number of cached queries is exceeded. Other types of data (arrays, structures, the parsed contents of an XML file) can't be cached in this manner; they must be stored in Application variables where they remain until the ColdFusion service is restarted or they are explicitly removed.
ASP.NET provides a single caching mechanism for any type of data (DataSets, arrays, Hashtables, the parsed contents of XML files) exposed through the
object. This object allows for time-based expiration from the cache, as is the case with ColdFusion's query caching, and it adds the ability to expire items based on usage, dependencies, or memory pressure. An example of usage-based expiration might be a cached object that is set to expire from the cache 20 minutes after the last time it is accessed. If this object is accessed every 10 minutes, it will never expire from the cache. On the other hand, if it is not accessed for a long period of time, it will be dropped from the cache to free up memory for more frequently-used items. An example of dependency-based expiration might be some data that is loaded from an XML file. The data can be inserted into the cache with a dependency on the XML file, so that if the XML file ever changes (invalidating the cached data), the loaded data is dropped from the cache immediately.
Cache items can also have dependencies on other cache items. The final method of cache expiration—memory pressure—simply means that the Cache object itself will actively monitor the amount of memory available in the system and the amount of memory taken up by the items it contains. If the available memory in the system gets too low, the
object will start removing the least recently accessed items in the cache until it has freed up enough memory to keep the system running smoothly. This process allows ASP.NET to avoid a hard limit on the number of cached items, as ColdFusion has for cached queries. For more information, see the documentation for the
Caching the HTML output of a page request is accomplished in ColdFusion with the
tag. Pages can be cached on either the client or the server or both, for a specified span of time, and a different version of each page is cached for each distinct set of URL parameters passed to that page. If the page in question generates different HTML depending on the capabilities of the browser requesting the page, or different text depending on the preferred language of the current user, ColdFusion's page caching scheme can't be used. The reason is that it would return the HTML tailored for the first browser to request the page to all browsers, or the language preferred by the first user to request the page to all users.
The HTML output of a page request can be cached in ASP.NET with the
directive. This directive allows the page to be cached on either the client or the server, or both, for a specified span of time. Different versions of the page can be cached based on a combination of many criteria, including one or more specific URL parameters, the browser type and major version requesting the page, one or more HTTP headers (roughly equivalent to ColdFusion's CGI variables), or the output of a custom function that uses whatever criteria you code it to use. This flexibility allows ASP.NET's page caching to be used in many situations in which ColdFusion's page caching falls down.
In addition to full-page caching, ASP.NET also includes support for partial-page caching. The HTML output by a custom user control can be cached based on most of the same criteria supported by full-page caching, with the addition of allowing different versions of a control's output to be cached for different values of one or more of that control's properties.
For more information about ASP.NET's output caching, see Caching ASP.NET Pages.
Server-Side HTTP Requests
Making an HTTP request from the server can be done with the cfhttp tag in ColdFusion, and with the
object in ASP.NET, as Table 17 shows.
Table 17. HTTP Requests
|CFML||Visual Basic. NET|
<cfhttp url="http://www.macromedia .com/" method="GET"> </cfhttp> <cfoutput>#HTMLCodeFormat(CFHTT P.FileContent)#</cfoutput>
Dim myWebClient As System.Net.WebClient myWebClient = New System.Net.WebClient() Dim buffer As Byte() buffer = myWebClient.DownloadData ("http://www.microsoft.com/") Dim content As String content = System.Text.Encoding .UTF8.GetString(buffer) Response.Write(Server.HtmlEncode (content))
XML Parsing and Manipulation
Built-in support for parsing and manipulating generic XML is new in ColdFusion MX, and although it is very easy to use, certain advanced capabilities are lacking. For example, ColdFusion MX lacks support for XML namespaces, XML Schema Definition (XSD) validation, using parameters in XSLT transformations, and reading and writing large XML documents without loading the entire document into memory.
The .NET framework has extremely comprehensive support for XML and related technologies, and full coverage of this support is beyond the scope of this paper. A good starting place would be Employing XML in the .NET Framework.
A migration from ColdFusion to ASP.NET can be as simple or as complex as it needs to be. Your migration could be a straightforward port of existing functionality or a complete rewrite that takes full advantage of ASP.NET's advanced features. Nearly every feature present in ColdFusion has an equivalent in ASP.NET, which facilitates a straight port that requires very little effort beyond basic syntax translation. However, if time constraints allow, a re-examination of the application's architecture (in light of ASP.NET's unique capabilities), can lead to a significant improvement in the application's performance, scalability and functionality.