Running CodeBehind ASP.NET CSharp Projects on Mono by Charlie Calvert
Rating: Ratings: 25 Rate it
Abstract: This article explains how to take a default ASP.NET CodeBehind project of the type created in Visual Studio.net and run it under Mono on Linux or Windows.
Copyright (c) 2004 by Charlie Calvert
This article explains how to get a standard CodeBehind ASP.NET program up and running under Mono on Linux or Windows.
Mono is an open source implementation of Microsoft's .NET technology. It is very much a work in progress, and so having the latest version is important. The Mono team is going through the Microsoft .NET standard, implementing each class and each method, one at a time, as fast as they can. With each build, many ASP.NET standard functions are added to Mono.
If you are interested in Mono development on Linux, you should read my article on installing the latest Mono code. Getting the latest build is important if you want to have the widest possible range of code available to you when you run your ASP.NET applications on Linux.
The Default Visual Studio 2003 or C#Builder ASP.NET Project
When you enter Visual Studio or C#Builder, and create a default ASP.NET Web Application, you end up with four key files:
The first file, WebForm1.aspx, contains standard HTML code slightly modified to support the ASP.NET standard. If that were the only file in your project, then you would be in good shape, since either Mono's or Microsoft's tools would automatically compile it for you. The other files, however, are CSharp files that need to be compiled manually. It is the compilation of these files that I believe needlessly discourages some Mono developers.
The actual compilation of the files can be accomplished at the command line with a single call to the Mono CSharp compiler (mcs). The short file found in Listing 1 is a Linux script that will perform the compilation. The same command will work in a Windows batch file, but minus the first line which references the Linux bash script engine. Note that the call to mcs, the Linux compiler, could all be on one line. The code shown here will compile and run cleanly on Linux as is, but you might want to place it all on one line in Windows. I have broken the call to mcs into three lines with the backslash character in order to make it more readable. You can remove the backslash character and put the command all on one line.
Listing 1: A simple script for compiling an ASP.NET program created in Visual Studio.
#! /bin/bash
mcs /t:library /out:WebApplication1.dll
-r:System.Web -r:System.Data -r:System.Drawing
AssemblyInfo.cs WebForm1.aspx.cs Global.asax.cs
On the first line of the call to mcs, the first argument (/t:library) tells the compiler that you want to create a library. In Mono, libraries have a DLL extension whether they are run on Windows or on Linux. The second argument states that you want to create a library called WebApplication1.dll. After the compilation is complete, you should copy this file to a directory called bin, which should be manually created one level further from the root of the file system. The end result is that WebForm1.aspx will be one level closer to the root than WebApplication1.dll:
/home/charlie/src/WebForm1.aspx
/home/charlie/src/bin/WebApplication1.dll
The second line of the call to mcs in Listing 1 specifies links to the libraries that are needed to complete the compilation. A default Visual Studio 2003 project depends on System.Web.dll, System.Data.dll and System.Drawing.dll. By including these references in the script, the Mono CSharp compiler knows to resolve the calls to these system libraries.
The third line in the call to mcs lists the three CSharp source files that you are generated by a default Visual Studio project. All three files will be compiled and the resulting binary code will be stored in WebApplication1.dll.
After executing this call to mcs, on either Linux or Windows, you will end up with WebApplication1.dll. On my system, the file is 4608 bytes in size. As explained earlier, I copied this file to a directory called bin, which is located one level further from the root of the file system than WebForm1.aspx.
After compiling your ASP.NET project, you will want to run it. On Linux, this is a fairly straight forward process. I will describe the necessary steps in the next two sections of this article. The first section is on Linux, the second on Windows.
Running Your ASP.NET Project in Linux
Mono comes with a special Web Server called xsp.exe. Starting the server is very simple. On my system, I simply type mono /usr/bin/xsp.exe at the shell prompt. The output from the command looks like this:
[charlie@rohan MonoCodeBehind]$ mono
/usr/bin/xsp.exe Listening on port: 8080
Listening on address: 0.0.0.0
Root directory: /home/charlie/src/csharp/WebApps/MonoCodeBehind
Hit Return to stop the server.
By default, the server will start on port 8080. This means that you do not have to shut down Apache, if you happen to have it running. Apache is, of course ,running on port 80. For now, you want the root directory to be the directory in which you have stored your source files. In particular, it should be where WebForm1.aspx is stored. xsp provides options for changing the root directory or the port. You can see all the options by typing mono /usr/bin/xsp.exe --help:
xsp.exe [--root rootdir] [--applications APPS] [--virtual virtualdir]
[--port N] [--address addr]
--port N: n is the tcp port to listen on.
Default value: 8080
AppSettings key name: MonoServerPort
--address addr: addr is the ip address to listen on.
Default value: 0.0.0.0
AppSettings key name: MonoServerAddress
--root rootdir: the server changes to this directory before
anything else.
Default value: current directory.
AppSettings key name: MonoServerRootDir
--applications APPS: a comma separated list of virtual directory and
real directory for all the applications we want to manage
with this server. The virtual and real dirs. are separated
by a colon.
Samples: /:.
the virtual / is mapped to the current directory.
/blog:../myblog
the virtual /blog is mapped to ../myblog
/:.,/blog:../myblog
Two applications like the above ones are handled.
Default value: /:.
AppSettings key name: MonoApplications
--nonstop: don't stop the server by pressing enter. Must be used
when the server has no controlling terminal.
--version: displays version information and exits.
You can now start Mozilla, and type in the following URL: http://localhost:8080/WebForm1.aspx. Note that you have effectively made the directory in which you stored WebForm1.aspx your root directory for the Web Server. As a result, the URL is very straightforward.
At this stage, you should see your ASP.NET program in your browser, as shown in Figure 1. Please note that I have modified the default project slightly to include a button and a text field.
![AspDotNet01.jpg](http://bdn.borland.com/article/images/32057/AspDotNet01.jpg)
Figure 1: A simple ASP.NET program running in the Mozilla browser on RedHat Linux 9.0 with all the latest updates from the RedHat Network and the Red Carpet mono channel.
Besides the XSP WebBrowser described in this article, there is also a module add on to Apache that has been created by the Mono project. Discussion of that tool will be reserved for a later article.Running Your ASP.NET Project in Windows
There is no special preparation that you need do to run your project on Windows. If you have Microsoft's IIS server installed on your system, then all you need to do is set up a virtual directory, copy your files into it, and aim your browser at your copy of WebForm1.aspx.
When setting up your project, remember to place WebApplication1.dll in a subdirectory one level further from the root of the file system than the directory that holds WebForm1.aspx.
If WebForm1.aspx is in a virtual directory called MyWebForm, then you should point your web browser at the following URL: http://localhost/MyWebForm/WebForm1.aspx. The result should look very much like what is shown in Figure 1. Note that I modified the default VS or C#Builder project slightly to contain a text field and a button so that you can see that the project actually does something.
To set up a virtual directory in IIS, run the snap-in administration tool for IIS (c:\windows\System32\inetsrv\inetmgr.exe). Right click on the Default Web Site and choose New | Virtual Directory to run a wizard. After completing the wizard, select the directory you created, right click to bring up its properties, and use the Application Setting to create an Application Name. The execute permissions for the directory can be left at Scripts only.
The Source
This article has been about how to get a default ASP.NET project up and running in Mono. However, I think it is important to show you the actual source files, even if I don't explain them in any detail. That way you can check your source code against the code I created in order to confirm that you are following all the steps correctly.
As you may have noticed in the screen shot, I did modify the default project slightly by adding a button and text field, and code to respond to clicks on the button by placing the word "Sam" in the text field. This modifies the default project just enough so you can sense something has been accomplished, without muddying the waters by adding complex code not germane to the topic of this article.
The files needed in this project are shown in Listings 2 - 5.
Listing 2: The WebForm1.aspx file.
<%@ Page language="c#"
Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false"
Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Button id="Button1"
style="Z-INDEX: 101;
LEFT: 144px;
POSITION: absolute;
TOP: 64px"
runat="server"
Text="Button">
</asp:Button>
<asp:TextBox id="TextBox1"
style="Z-INDEX: 102;
LEFT: 256px;
POSITION: absolute;
TOP: 72px"
runat="server">
</asp:TextBox>
</form>
</body>
</HTML>
Listing 3: The WebForm1.aspx.cs file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace WebApplication1
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.TextBox TextBox1;
protected System.Web.UI.WebControls.Button Button1;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Button1_Click(object sender, System.EventArgs e)
{
TextBox1.Text = "Neither fire nor wind, birth nor death can erase our good deeds.";
}
}
}
Listing 4: The Global.asax.cs file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.SessionState;
namespace WebApplication1
{
/// <summary>
/// Summary description for Global.
/// </summary>
public class Global : System.Web.HttpApplication
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
public Global()
{
InitializeComponent();
}
protected void Application_Start(Object sender, EventArgs e)
{
}
protected void Session_Start(Object sender, EventArgs e)
{
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
}
protected void Application_EndRequest(Object sender, EventArgs e)
{
}
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
}
protected void Application_Error(Object sender, EventArgs e)
{
}
protected void Session_End(Object sender, EventArgs e)
{
}
protected void Application_End(Object sender, EventArgs e)
{
}
#region Web Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
}
#endregion
}
}
Listing 5: The AssemblyInfo.cs file.
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the "project output directory". The location of the project output
// directory is dependent on whether you are working with a local or web project.
// For local projects, the project output directory is defined as
// <Project Directory>obj<Configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("....mykey.snk")]
// For web projects, the project output directory is defined as
// %HOMEPATH%VSWebCache<Machine Name><Project Directory>obj<Configuration>.
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
Summary
In this article you have seen how to compile a default Visual Studio or C#Builder CodeBehind ASP.NET project under Mono. It turns out not to be a difficult task, so long as you understand the steps involved. The key points to remember are that you need to use mcs to compile the CSharp source files in your project, and that you should place resulting DLL in a directory called bin that is one level further from the root than the directory where your source is stored.