Migrating Classic ASP To ASP.NET Razor Web Pages Part One- Razor Syntax And Visual Basic

You have a classic ASP application that needs migrating to ASP.NET. You are comfortable working with classic ASP. but ASP.NET is fairly new to you. So what do you do? This article is the first in a series that looks at your options and proposes an approach to the migration that follows the path of least resistance.

The other articles in the series are

Classic ASP and ASP.NET are very different technologies, and until a few years ago, that difference really shone through the development model choices on offer: Web Forms and MVC. Web Forms was the first iteration of ASP.NET. It is as control-based event-driven development model that resonates most with Windows Forms developers. It offers a fairly steep learning curve for developers who are used to working with HTTP, HTML and CSS as most of these basic web development technologies are abstracted away behind event handlers, server controls and other platform-specific artefacts. MVC was introduced to provide developers with more control over the basic web technologies, as well as a separated architecture that lends itself very well to unit testing. It also brought its own learning curve which is also considered pretty steep by Microsoft.

A third model was introduced in 2011 - the Web Pages framework, which also saw the introduction of the Razor syntax. ASP.NET Web Pages is a page-centric development model just like classic ASP in that server-side logic and HTML markup co-exist in the same file which represents a page in a web site. Server-side code is separated from HTML, CSS and client-side code through the use of tokens. Server-sde code is written using C# or VB, the latter option being more familiar to classic ASP developers who are used to writing in VBScript. Although VBScript and VB are completely different languages, a lot of the syntax is identical, which makes migrating to ASP.NET Web Pages using VB a compelling option. This article will explore how code blocks migrate from classic ASP to Web Pages using Razor and VB. Future articles will look at data access and how to manage include files and other reusable code.

If you have decided to really bite the bullet and learn C# at the same time as moving across to ASP.NET, you can learn the basics of Razor syntax with C# at the official ASP.NET Web Pages tutorials.

To help with illustrating the migration, I am using the Classifieds sample from the code download that comes with Chapter 15 of Wrox' seminal ASP title: Beginning Active Server Pages 3.0 (ISBN: 978-0-7645-4363-0). I still have my copy of this fine book, and the code sample served as the inspiration for the sample site I built in my ASP.NET Web Pages book. One of the best features of the code in the download is that it is truly awful. Consequently, it serves beautifully to illustrate some of the challenges that can be faced in porting really old code across to the new platform.


The amount of work that you have to do up front depends largely on the reasons for your migration to ASP.NET. I'm going to take a 'just get it done' approach in this article, which will involve as little reworking of the original code as possible. The HTML will ony be altered where it has to be in order to work with the Razor parser.

You also have to think about the tools you will use for development. ASP.NET Web Pages can be authored in either Visual Studio or WebMatrix. WebMatrix is a free lightweight IDE which includes a number of template starter sites. At the moment, it only supports Web Pages up to version 2 (ASP.NET 4.0). It offers a limited set of development tools such as a code completion system and compile time checking. Visual Studio includes a free edition: Express for Web. It supports Web Pages 3 (ASP.NET 4.5) and includes a fuller range of tools such as debugging and stronger IntelliSense. It only offers one Razor Web Pages template which includes a fair amount of clutter. For that reason, you might want to start with the Empty Site template in WebMatrix and once it has been created, open that in Visual Studio. If you opt to start with Visual Studio, you can remove everything from the generated template site except the bin folder. Even then, there is probably a lot in the bin folder that you won't need. The shaded libraries below are optional:

Bin folder

If you start with the WebMatrix Empty Site option, you will need to delete the default.cshtml file that gets generated. Razor files end in either .cshtml or .vbhtml depending on the language used. It is possible to mix file types in a Razor Web Pages site, but you are going to work with VB only, so you need to create a default.vbhtml file (or index.vbhtml if your existing classic ASP site has an index.asp file).

Razor Syntax and Visual Basic

In classic ASP. code blocks are delimited using <% and %> tags. The default.asp file in the Wrox Classifieds site has only one code block at the top of the file:

<% Session.Abandon %>
<BASEFONT FACE="Comic Sans MS" COLOR="DarkBlue">

(I did mention that the code was awful, didn't I?)

Razor code blocks are delimited are opened with @Code and terminated with End Code. The equivalent lines in a Visual Basic Razor file are as follows:

End Code

<BASEFONT FACE="Comic Sans MS" COLOR="DarkBlue">

ASP objects such as Session, Request, Response etc are more or less identical in ASP.NET, so the code in the existing asp file can be copied and pasted into the ASP.NET Web Pages site with just the amendments to the code block markers detailed above, and the links in the HTML (not shown here) need to be updated to point to .vbhtml files instead of .asp files.

The next piece of code to migrate is the contents of Registration.asp. Mostly, this is just HTML, but there is a block of VBScript at the top of the page:

  If Request("Update") = "True" Then 
    Response.Write "<H1>Wrox Classifieds<BR> Update User Registration</H1>"
    Response.Write "<H1>Wrox Classifieds<BR> New User Registration</H1>"
  End If 

  If Request("Update") = "True" Then 
    Response.Write "Please change your registration information as listed below<P>"
    If Request("NotFound") = "True" Then 
      Response.Write "<I>We were unable to locate your information. " & _
                     "Please take the time to register again.</I><P>"
      Response.Write "<CENTER>(If you're already registered with us, " & _
                     "then click the 'Login' link below.)</CENTER><P>"
    End If 
    Response.Write "You only need to register with our system if you want to " & _ 
                   "bid on existing 'for-sale' items, or sell your own items " & _
                   "on these pages. <BR> " & _
                   "In order to use these services, please take a few minutes " & _
                   "to complete the form below. Once you have done that, " & _
                   "you will have full access to the system."
  End If 

Calls to Response.Write in classic ASP result in the output being rendered within the document where the call is positioned. It doesn't work like that in ASP.NET - Response.Write will result in the output being injected at the beginning of the document in all cases. Response.Write is simply not used in ASP.NET for that reason.

The first If... Then... block within the <CENTER> tags is re-written as follows:


    @If Request("Update") = "True" Then
        @<h1>Wrox Classifieds<br> Update User Registration</h1>
        @<h1>Wrox Classifieds<br> New User Registration</h1>
    End If


Selection and iteration key words, like If, For, For Each and so on, do not need @Code... End Code markers when they are used to determine what is rendered inline. You just need to prefix the opening line of the server code with an @ sign. Instead of using Response.Write to render markup, you place it within the selection statement and also prefix it with an @ sign. Note that prefixing the HTML markup with the @ sign is only necessary for VB. It is not needed when coding in C#. This point is an important one to bear in mind when looking for tutorials or sample code for Web Pages - the vast majority of which are in C#.

The next block of code poses some new problems. The Razor parsing engine requires HTML tags to be balanced when they are preceded by the @ character and are intended to be rendered to the browser. You can see this in the previous example where the opening <h1> tag is balanced by the closing </h1> tag. The block that still needs to be migrated has an opening <P> tag but no matching closing tags. This is legal for HTML 4.01 and under but confuses Razor, and won't validate for HTML5. So the opening <P> tag needs to be brought inside the code block and closed off:

@If Request("Update") = "True" Then

    @<p>Please change your registration information as listed below</p>
    @If Request("NotFound") = "True" Then

        @<p><i>We were unable to locate your information. Please take the time to register again.</i></p>
        @<p><center>(If you're already registered with us
                then click the 'Login' link below.)</center></p>
    End If
    @<text>You only need to register with our system if you want to
            bid on existing 'for-sale' items, or sell your own items
            on these pages.
    <br />
            In order to use these services, please take a few minutes
            to complete the form below. Once you have done that,
            you will have full access to the system.
            you will have full access to the system.</text>
End If

There is a block of text that isn't surrounded by HTML tags. Razor requires this to be denoted and separated form server-side code somehow, so it introduces the <text> tag. The tag itself is not rendered. It simply acts as a marker for Razor. An alternative, but messier option is to prefix each line of text with the @ sign followed by a colon:

@:You only need to register with our system if you want to
@:bid on existing 'for-sale' items, or sell your own items
@:on these pages.
@:<br />
@:In order to use these services, please take a few minutes
@:to complete the form below. Once you have done that,
@:you will have full access to the system.
@:you will have full access to the system.

This approach is better utilised for single lines of bare text.

The final change to this file involves the values that are applied to the various fields in the registration form. Here are a couple of examples:

    <TD WIDTH=20% ROWSPAN=11>&nbsp;</TD>
    <TD>E-Mail Address:</TD>
    <TD><INPUT TYPE="Text" NAME="email" VALUE="<%= Session("EMailAddress")%>"
    <TD>Given Name:</TD>
    <TD><INPUT TYPE="Text" NAME="GivenName" VALUE="<%= Session("GivenName")%>"

If you want to render variables or the result of expressions to the browser wth Razor, you simply prefix them with the @ sign:

    <TD WIDTH=20% ROWSPAN=11>&nbsp;</TD>
    <TD>E-Mail Address:</TD>
    <TD><INPUT TYPE="Text" NAME="email" VALUE="@Session("EMailAddress")"
    <TD>Given Name:</TD>
    <TD><INPUT TYPE="Text" NAME="GivenName" VALUE="@Session("GivenName")"

The existing login.asp page includes a couple of examples of inline expressions. Here's one of them that conditionally sets the action attribute of the form:

<FORM ACTION="CheckLogin.asp<% If Request("SecondTry")="True" Then 
                                 Response.Write "?SecondTry=True"
                               End If %>" METHOD="POST">

This can be replaced with the following:

<FORM ACTION="CheckLogin.vbhtml@(If(Request("SecondTry")="True", "?SecondTry=True", String.Empty))" METHOD="POST">

So far, three files have been migrated with minimum changes to the originals despite the strong urge I feel to tidy up the atrocious HTML - but the brief was to just get it done. A certain amount of tidying up can be achieved by pressing Ctrl + K, Ctrl + D. This will convert the HTML tags to lower case and ensure that all attribute values are surrounded by double quotes. It will also attempt to apply some indenting of nested elements. WebMatrix validates the document against HTML5 and produces an error list for you to work against should that be important to you.

All of the existing VBScript has converted over to VB with little to no changes required. But that is about to change as I look at Data Access in the next article in this series.

:In the meantime, you can download the original classic ASP site from here, and the migrated Web Pages version from here.


Date Posted:
Last Updated:
Posted by:
Total Views to date: 54853


- Byron Smith

An interesting and timely article. I'm an ASP/MSSQL Developer now learning ASP.NET and C#. I'm learning the Razor syntax, but we might wind up going full-blown Visual Studio at work since I use 2013 Express (Visual Basic) there and have active projects I have developed. Some of my interest in this is professional and some of it is personal (translation: if it's really cool and I can't find an excuse to use it at work, I'll be forced to tinker with it at home and make new digital toys for myself, LOL). Seriously, though, I would like to learn more about Razor anyway, especially subroutines (which I have seen implemented somewhere else on the web and forgot where, so I am about to do a Bing search on that next). I hope you will blog on that soon. I found your website from the forum on ASP.NET from your comment on the "@using System.Drawing" which was particularly interesting to me. Cheers!

- Mike


I will publish an article covering data access tomorrow and one that looks at functions, subs and other reusable code the following week.

- Dan H.

The image that's supposed to display below the words "The shaded libraries below are optional:" isn't showing. Just "[img]"


- Mike


The image has been restored :-)
Add your comment

If you have any comments to make about this article, please use this form to do so. Make sure that your comment relates specifically to the article above. More general comments can be posted through the form on the Contact page.

Please note, all comments are moderated, and I end up deleting quite a lot. The kind of things that will ensure your comment is deleted without ever seeing the light of day are as follows:

  • Requests to fix your code (post a question to forums.asp.net instead, please)
  • Gratuitous links to your own site or product
  • Anything abusive or libellous
  • Spam

I do not pass email addresses on to spammers, so a valid one will assist me in responding to you personally if required.

Recent Comments

Senad Mustafa 3/31/2015 8:57 AM
In response to ASP.NET MVC DropDownLists - Multiple Selection and Enum Support
Hi Mike, Thanks for the articles on dropdownlists. They are really great but I think you are one...

Black 3/28/2015 4:02 AM
In response to Displaying One-To-Many Relationships with Nested Repeaters
it's working. thank for the code...

Lorenzo 3/26/2015 8:21 AM
In response to iTextSharp - Introducing Tables
Hi Mike How can I add padding to all cells in the table? Kind Regards Lorenzo...

Satyabrata Mohapatra 3/25/2015 8:11 AM
In response to How To Send Email In ASP.NET MVC
Great article. Simple and up to the point....

Afzaal Ahmad Zeeshan 3/24/2015 8:17 PM
In response to How To Send Email In ASP.NET MVC
A great way to teach the MVC framework for sending the emails... Also, what I found helpful was the...

Jim H 3/24/2015 2:32 PM
In response to Migrating From Razor Web Pages To ASP.NET MVC 5 - Model Binding And Forms
Thank you. This helps....

wazz 3/22/2015 5:48 AM
In response to Posting Data With jQuery AJAX In ASP.NET Razor Web Pages
great info!!...

rael 3/21/2015 8:53 PM
In response to Getting the identity of the most recently added record
I spent hours trying to figure how to achieve this in C#. This article helped me. Thanks a lot...

Stephen 3/21/2015 8:48 PM
In response to Ajax with Classic ASP using jQuery
This was very helpful, thanks:)...

patrick voes 3/19/2015 10:19 AM
In response to iTextSharp - Introducing Tables
Thank you! very helpfull....