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

4.86 (7 votes)

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: 62302


- 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 :-)

- Mike

have you used any of the code converters to convert classic asp to c#? If so, which one do you recommends?

I have a large classic asp program that I want to convert to MVC using C#.

- Mike


I haven't tried any converters for migrating from Classic ASP to MVC. In fact, I'm not aware of any. Frankly, I can;t see how they can be that effective, if they exist. There would be no way to determine what code goes into the View, Controller or Model. If you wan't to migrate a classic ASP app to MVC, you have to rewrite it from scratch, in my opinion.

Recent Comments

Ghazanfar 30/01/2016 06:43
In response to Getting Started with ASP.NET MVC 5 using Visual Basic
Nice working. Please keep it up to convert csharp code into vb.net. Its very helpful for vb...

sara 29/01/2016 09:39
In response to Simple Login and Redirect for ASP.NET and Access
Hi there, I am trying to validate and check for inputs entered. When I don't enter any inputs and...

Martin Thatcher 28/01/2016 17:28
In response to MVC 5 with EF 6 in Visual Basic - Advanced Entity Framework Scenarios
A small typo I think. In the code section that begins Function Index(ByVal SelectedDepartment As As...

Suresh_thefame 28/01/2016 08:03
In response to Sessions and Shopping Carts

Andrey Kurdyumov 28/01/2016 05:47
In response to ASP.NET 5: Uploading files with ASP.NET MVC 6
@Lee IFormFile has OpenReadStream(): Stream method...

Alisa 27/01/2016 18:37
In response to A Better Way To Export Gridviews To Excel
Thanks for this example! I am also asking about the date fields having to be re-formatted when the a...

Dan Buckley 27/01/2016 00:47
In response to What ASP.NET Can And Cannot Do
New to all things programming, this was very helpful and clear. Please write more....

satyabrata 26/01/2016 16:16
In response to Request.Form Is Empty When Posting To ASPX Page
Thank you....

david sanchez 26/01/2016 09:51
In response to ASP.NET MVC 5 with EF 6 - Working With Files
Thanks! This line " <img src="~/images/@Model.FilePaths.First(f => f.FileType == alt="" />" an...

Bryon 25/01/2016 15:06
In response to Windows Authentication With ASP.NET Web Pages
Was hoping this would help solve the issues I'm having. Then I saw the dates and new it was too old....