Hosting the ASP.NET runtime in your own application


Applies to:
  • ASP.NET runtime
Summary: In this second article you will learn how to create an application that enables running an ASP.NET application from a cd-rom.

Download the sample code for this article at the author's website.

Introduction

In the previous part of this article I explained how easy it is to host the ASP.NET runtime in your own application. We created an ASP.NET runtime host and 2 clients using that host: a Windows Forms client (a simple browser in fact) and a command-line tool (console application). Now, we want to do even more: what about hosting an ASP.NET website on read-only media (for example a cd-rom)? It would be great to redistribute our ASP.NET application on a cd-rom since we would have a far more powerful platform for our application (in comparison with a set of static HTML pages).

To do this, we can't simply use an application as we wrote in the first part of the article. One of the problems there was linking between pages and performing postbacks to the 'server', which didn't exist in fact. Today we're going to create (to be honest, we'll reuse) a light-weight web server and redistribute this on a cd-rom.

Allow me to tell a short story before we kick off. I'm moderator on the ASP.NET forums and one of the questions which is posted very regularly out there in the 'Getting started' forum is the next one: "Why do I need to run a web server to see the results of an .aspx page?'. This is in fact a typical question for a beginner and the reply on such a question is always the same: "since ASPX pages are processed server-side", etc. When you've finished developing the application presented in this article, things will be even more confusing... Can you imagine the reaction of an ASP.NET beginner which has posted the question I mentioned earlier on the forum and has got the answer that a web server is needed? Yes, I know I can. So, to summarize, this article is certainly not intended for beginning (ASP.NET) developers.


Application design

To start, I'm going to have a look at the design of the application. Since .aspx pages require processing by a web server (or at least by the ASP.NET runtime as mentioned in the previous part of the article), it's not possible to request an .aspx file that is stored locally on the machine using a web browser. When using static HTML pages, it is very easy to create a cd-rom that contains a browsable website. So, I'll create an application that can be stored on the cd-rom and will be launched when the cd-rom is inserted.

That application won't host the ASP.NET runtime the way I did before in the first part of this article. Why? I've answered that question already in the previous article: there are problems with postbacks and linking of pages. Our application will launch the Cassini web server instead so that we can access our application via the HTTP protocol itself, which will avoid all the problems we mentioned earlier.
The entire solution will exist of:
  • An autorun.ini file to launch the application when the cd-rom is inserted
  • The Cassini web server, which can be reused entirely
  • A launcher application
  • Dynamic configuration data. By modifying the configuration you'll be able to setup the folder of the ASP.NET application, the home page and the action to be executed when the server has started

The Cassini web server

Okay, I already said we'll be 'recycling' the code of the Cassini web server. To get started, I'll explain briefly what the Cassini web server is and how it works. The Cassini web server is a lightweight, free and open-source project written in C# by the ASP.NET Team and was developed as a solution for users what want to kick of with ASP.NET but don't have IIS on their machines, which is the case on Windows XP Home clients for example. Users of the ASP.NET Web Matrix will have used the Cassini web server probably since it's integrated in this tool to run and test ASP.NET applications written in ASP.NET Web Matrix. As you can see in the next image, a web server is launched when the F5 key is pressed inside the ASP.NET Web Matrix to run the application:


Although it's called the "ASP.NET Web Matrix Server" over here, it's actually the Cassini web server being launched.


The first you should do to develop the sample discussed in this article, is to download the Cassini source code from the ASP.NET website at http://www.asp.net/Projects/Cassini/Download/Default.aspx?tabindex=0&tabid=1. Download the bits of the "Cassini Sample Web Server".
If you've read the previous part of this article you'll recognize the System.Web.Hosting namespace in the short description of the 'tool'.

Okay, let's download the file (only 217 KB) and launch the installer, which will copy the source code files to the specified location (by default C:\Cassini). When the installed has finished its work, the readme.txt file will be displayed in Notepad containing the instructions about how to run the web server.
The entire solution consists of only 8 code files in C#. I'll start to explain what the functions of those files are:
  • AssemblyInfo.cs contains the information about the assembly generated by the compiler. The most important line in this file is this one:

    [assembly: AssemblyKeyFile("Cassini.snk")]

    This line of code is needed to install the Cassini assembly in the GAC. As I've explained in the introduction and in the first part of this article, we'll need to 'change' this in our solution to eliminate the need for the web server to be installed in the GAC.
  • ByteParser.cs is the source code file of a small helper-class, the ByteParser, that's used to convert a byte array to a set of lines in an efficient way. This is needed because requests to the server are sent in a byte array format and need to be converted to a format with more manipulation capabilities.
  • ByteString.cs works together with the previous class file to create a string-like type based on a byte array which was sent to the server during the HTTP request.
  • Connection.cs is needed to handle HTTP connections on our web server. To do so, it uses the System.Net namespace to create a socket to listen to incoming requests. Beside this, it's responsible to create the response headers and to send response itself, the processing of a request (using the Request class, see further), the content type header, ...
  • Host.cs has the same functionality (although more complex) than our Host.cs file in the first part of this article. It hosts the ASP.NET runtime and extends the MarshalByRefObject. To do this, the same technique is used as the one I showed you in the previous part of the article. The other task of this Host class is to listen on the configured port for incoming requests and to accept the requests and send those to a new Connection object (see the previous bullet). This class is used to start, stop and restart the web server.
  • Messages.cs provides the functionality to display messages in an HTML format to the client, for example when a resource isn't found (404), when the access is denied (403), etc. It's used to display the directory content of a folder as well.
  • Request.cs contains the Request class that's inherited from SimpleWorkerRequest. Remember the first part of the article where I used the SimpleWorkerRequest to execute the ASP.NET request to the .aspx page. One instance of this class is made for every request to the server and passed to the HttpRuntime. The class is response for the processing of the entire request, including the headers (read, parse, etc) and the content posted to the server. Other code sends the status code back to the client, gets the query string for the HttpRuntime and other information needed by the ASP.NET runtime (for example, the MapPath method is written in this class as well).

    Note: the Process method in this class determines whether the request is a local request or not. If you ever want to create a web server with more functionality based on this code, you'll need to change this method to accept remote requests as well. To do this, locate this piece of code and remove it:

    // Limit to local requests only
    if (!_conn.IsLocal)
    {
      _conn.WriteErrorAndClose(403);
      return;
    }

  • Server.cs is the only class file which contains a public class (all other files contain internal classes). The Server class is used to start the entire web server using the configuration passed in to the application (physical path, virtual path and the port to listen on). When ASP.NET is not configured correctly on the machine, the class will configure ASP.NET properly before the web server is launched.This file contains the 'famous line of code' used to create an ApplicationHost object:

    _host = (Host)ApplicationHost.CreateApplicationHost(typeof(Host), _virtualPath,
      _physicalPath);
There are some other files contained in the installation file as well:
  • Cassini.snk – the strong key used to register the Cassini assembly in the GAC on the machine. It can be regenerated using the sn.exe tool of the .NET Framework:

    sn.exe -k Cassini.snk

  • CassiniWebServerMain.cs which contains the Windows Forms application to start and stop the Cassini web server.
  • CassiniWebServer.ico, the icon for the Cassini web server (used to display the server in the system tray when it's running).
  • Build.bat to build the complete web server and to register it in the GAC.

For more info you can read the included readme.txt file.

Once the Cassini source is compiled, the server can be launched using the CassiniWebServer.exe executable as follows using 3 parameters:

CassiniWebServer.exe <physical path> <port> <virtual path>

Creating the Cassini light project in Visual Studio .NET

The first step in the development process of the "cd-rom ASP.NET application host" is the creation of a new Visual Studio .NET project containing the Cassini source.

Remark: It's important to note that the Cassini solution (as well as other ASP.NET Source Projects) comes with a little EULA in the EULA.rtf file. This license agreement allows us to extend the Cassini project as we'll be doing in this article.

Enough about the theory, let's move on to the exciting work. Start Visual Studio .NET and create a new Class Library project in C# and give it the name 'CassiniLight':


Why CassiniLight? The answer is very simple: it doesn't require to be hosted in the GAC. In fact we'll just need to copy the source of Cassini to our project without any modifications.

Tip: If you want to create a cd-rom launcher application with a maximum customization for your company, you can edit the Messages.cs file to have a custom look-and-feel for the messages displayed by our web server.

Now copy the original source files of the Cassini project to the solution (except for the AssemblyInfo.cs since no strong name would be needed anymore). In every file, you should change the namespace to be CassiniLight:

namespace CassiniLight

When this job is completed, add a reference to the System.Web.dll assembly in the Solution Explorer:


Finally the solution should look like this:


This should compile without build errors.

The Launcher application itself

Okay, our web server is ready now (special thanks to the ASP.NET team of course). Add a new Windows Application project in C# to the solution and call it 'Launcher':


Set the new project to be the startup project for the solution. Then add a reference to the CassiniLight project using the Solution Explorer again:


Delete the Form1.cs file from the solution and add a new windows form called 'Start.cs'. In the source, add a reference to the CassiniLight namespace:
using CassiniLight;

Next, add an entry point for the application using this piece of code:
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
  Application.Run(new Start());
}

What we'll do in the code of the Start.cs form is this:
  • Look for a free port on the computer to start the web server on.
  • Read the configuration of the launcher application to find the root folder for the ASP.NET application stored on the cd-rom.
  • Start the web server on the free port and host the specified application in it.
  • Launch a browser (self-written and later Internet Explorer).
Step 1: Design the form

First of all, let's design the form for the Start.cs file. The form will be used to display a simple message on the screen when the application is launching.

Set the FormBorderStyle to none and resize the form to a format of 376 x 64 pixels. The StartPosition property should be changed to CenterScreen as well. Now, add a label to the form with the name lblTitle and dock it to the top border of the form (Dock = Top). Set Navy as the ForeColor and 'Sans Serif, 12 pt, Bold' for the Font property. Change the Text of the label to 'Please wait while the application is launching'. Finally, set the TextAlign property to MiddleCenter. Add another label to the form, called lblAction. ForeColor should be Maroon now, the Font 'Sans Serif, 10 pt, Bold' and the Text 'Initializing...'. Set the TextAlign property to MiddleCenter again and finally dock the label to the bottom of the form using Dock = Bottom. Last but not least, add a Timer control to the form called timer with the default properties (not enabled, 100 ms interval).

The form should look like this now:


Step 2: The first piece of code

Go to the code of the windows form and add this piece of code to the event handler for the Start_Load event. It will enable the timer when the form is loaded:

timer.Enabled = true;

We're using the timer over here to start the other tasks mentioned before (look for a free port etc). Although you can do the same using a threading application, I'm using a timer to start the task to keep things simple in this demo.

Back in the Design mode for the form, double click the timer control to add an event handler for the Tick event of the timer.
Step 3: Look for a free port on the computer

In the timer_Tick event handler method, add this first code snippet:
timer.Enabled = false;

lblAction.Text = "Searching free port...";
this.Refresh();

int port = FindPort();
if (port < 0) //Should never happen
  return;

This fragment relies on the FindPort method which we still need to write. The FindPort method looks like this:
private int FindPort()
{
  for (int i = 49000; i < 49151; i++)
    if (PortIsFree(i))
      return i;
  return -1;
}

In this method the code performs a search operation to find a free port in the range 49000 – 49150. Normally, all those ports are not used, so in 99,999% percent of the cases the first port should be free. If a port is found, the port number is returned. If not, -1 is returned but this should never happen. In this piece of code there's an unknown method as well, i.e. PortIsFree:
private bool PortIsFree(int port)
{
  TcpClient client = new TcpClient();
  try
  {
    client.Connect("localhost",port);
    return false;
  }
  catch
  {
    return true;
  }
}

To run this piece of code, you'll need to import another namespace on top of the class:
using System.Net.Sockets;

The implementation of the method is very simple: it tries to connect to the localhost on the specified port. If it fails, the port is free, otherwise it's being used by another service.
Step 4: Start the CassiniLight server

Once we've found a free port, we can start the Cassini web server on that port to host our application. At the bottom of the timer_Tick event handler method, add this code:
lblAction.Text = "Starting server...";
this.Refresh();

string dir = Directory.GetCurrentDirectory();
string root = ConfigurationSettings.AppSettings["root"];
string path = (dir.EndsWith("\\") ? dir : dir + "\\") + root;

srv = new Server(port,"/",path);
srv.Start();

To get this to work properly a few other namespace imports are needed:
using System.IO;
using System.Configuration;

as well as an app.config file. In the Solution Explorer, add a 'Application configuration file' to the solution and modify it as follows:
<appSettings>
  <!--
  Root folder to the ASP.NET application (relative to launcher.exe)
  -->
  <add key="root" value="webdir" />
</appSettings>

This setting will allow the developer of a cd-rom to specify the location on the cd-rom where the application is stored. In this case, we'll test our Launcher application with an ASP.NET application inside the webdir subfolder.

Finally, in the timer_Tick event handler, the Cassini web server is launched on the free port and with the correct application folder. The virtual path is set to the default "/" value.
Step 5: Launching our browser window

In this last step, we're going to create a simple browser window to show the ASP.NET application. Start with adding this piece of code at the bottom of the timer_Tick event handler in the Start.cs file:
lblAction.Text = "Ready";
this.Refresh();

this.Hide();
new Browser(srv).Show();

The Browser class is another windows form in the Launcher solution which will be created right now. In the Solution Explorer, add a new windows form to the solution and call it 'Browser.cs'.
Step 6: Creating the simple browser form

First of all, import this namespace in the Browser.cs code:
using CassiniLight;

and add this private attribute to the class:
private Server srv;

The next task is to change the constructor of the Browser class by changing the constructor of the class like this:
public Browser(Server srv)
{
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent();

  this.srv = srv;}

Now, let's design the form itself. Go back to the design of the Browser.cs file, right-click the toolbox and add the 'Microsoft Web Browser' control as we did in the first part of this article:


To continue, drag and drop the Microsoft Web Browser control from the Toolbox on the form and rename it to 'internetExplorer'. Set the Dock property of the browser control to Fill. Finally, we still need to change the WindowState property of the form itself to Maximized.

Now, add this code snippet to the Browser_Load event handler method:
this.Text = ConfigurationSettings.AppSettings["title"];

string home = ConfigurationSettings.AppSettings["home"];
int port = srv.Port;
string url = String.Format("http://localhost:{0}/{1}", port, home);
object o = null;
internetExplorer.Navigate(url,ref o, ref o, ref o, ref o);

This code navigates to the server which was launched in the Start.cs form earlier. As you can see, two additional values are read from the configuration data (app.config), one for the title of the browser window and one for the homepage which should be opened:
<!--
Title
titlebar text for the custom browser
-->
<add key="title" value="Our test site" />

<!--
Home
startpage of the ASP.NET application (in the 'root' folder)
-->
<add key="home" value="default.aspx" />

Note: Cassini supports default file names as well. By default these are set to default.aspx, default.htm and default.html. You can edit these in the Request.cs class in the private (string array) variable s_defaultFilenames.

Finally, add another event handler for the Closed event of the Browser.cs form and add this code:
srv.Stop();
Application.Exit();

This will stop the Cassini web server and exit the application.
Step 7: First testing

It's compile-time: compile the solution in Visual Studio .NET. This should complete without a single error... and it does over here. I hope you're that lucky as well. The next thing we should do is make an ASP.NET application available in the 'webdir' folder we have specified in the configuration file. In the previous part of the article, I created a simple .aspx page with an asp:Calendar control in it. Let's resume the results:
  • The calendar was rendered correctly
  • But the postback functionality didn't work
Let's create this page again and test whether the postback functionally of the calendar control works in our new solution.

Go to the Windows Explorer and open the bin\Debug subfolder of the Launcher solution. Create a subfolder with the name 'webdir':


Open notepad and type this piece of code:
<form runat="server">
  <asp:Calendar id="cal" runat="server" />
</form>

Save the file in the webdir folder as default.aspx and go back to Visual Studio .NET. Launch the application with that well-known F5 key... The application will look for a free port, an try to start the Cassini web server. However, it will crash with this error message:


The reason is the CassiniLight isn't registered in the GAC. But we don't want to do so. In the previous part of the article I presented the solution for this problem: create a bin folder and put the missing assembly in there. Let's take a look how to do this in our case...

Create a new subfolder in the bin\Debug\webdir subfolder of the Launcher solution directory, called 'bin'. So, the result is: bin\Debug\webdir\bin. Copy the CassiniLight.dll and CassiniLight.pdb files from the bin\Debug folder to the bin\Debug\webdir\bin folder.

Okay, go back to Visual Studio .NET now and restart the debugger with F5. Now, the server is launched correctly and this page is displayed in our simple browser:


When you click on a date, data is posted back to the server and the result looks as it should look:


Exciting, isn't it?
Step 8: Advanced testing

This calendar demo is great but probably you like to see a complete (and more complex) application being hosted in our webdir folder? Okay, let's do it! Go back to the ASP.NET community website website and go to the Starter Kits tab. For example, download the Community Starter Kit.

Remark: The starter kits provide full-functional web sites written in ASP.NET with the source code and Visual Studio .NET projects available as well.

When you've downloaded the starter kit, install it on your machine. This setup will require IIS since the starter kits are developed to be hosted in IIS. However, we can do better using our tool! The community starter kit needs a SQL Server (or MSDE) database as well. Just install everything by following the instructions of the setup. Finally, the starter kit will be launched in Internet Explorer on http://localhost/communitystarterkit and it will look like this:


Of course, this is still hosted in IIS itself.

Important: Since the portal starter kit requires a SQL Server database it's not possible to host this on a cd-rom without installing the database locally first. You could however connect to a SQL Server on-line. If you want to create a cd-rom application with database functionality you'll probably use a read-only database (for example when you want to distribute a catalogue of a bookshop) stored in an Access database on the cd-rom. This will be possible in this solution and won't have any performance drawbacks since the database will only have one connection (it's only being used by one user at a time).

Time to try this in our application! Go to the Windows Explorer and locate the folder containing the Community Starter Kit application on your machine. In my case, this is C:\Program Files\ASP.NET Starter Kits\ASP.NET Community Starter Kit (CSVS)\CommunityStarterKit but if you can't find it, you can go to the IIS Management MMC and look for the 'communitystarterkit' virtual folder.Copy the complete content of this folder (including all subfolders) to the webdir folder of our application (overwrite the existing default.aspx demo page).Don't forget to check the existence of the CassiniLight files in the bin subfolder of the webdir folder! If everything is on the right place, go back to Visual Studio .NET and launch the application again.

Indeed, the result is exactly what I wanted to see (that is, exactly the same as the result in Internet Explorer for the request to the local IIS machine where the starter kit was hosted as well):


But I'm still not happy with the solution... The web server launched very fast once the free port was found, that's not the problem. The problem is the compilation of the ASP.NET pages on the first-time request. I'll try to fix this a little further. Another thing is I want to use Internet Explorer to view the application as well.

Solving the problems

How can we solve the 'first-time request compilation problem'? I would like to suggest this solution: once the launcher application has started the Cassini web server on the machine, we can perform a first-time request behind the scenes to get the ASP.NET runtime to 'JIT' compile the application. If this is done, the browser is displayed which will result in a much faster response time.

But I can already guess your comment... Although this will increase the speed of the browser it will make the launcher slower. This is definitely true but I shouldn't be a real problem. For example, you can play a little video when the cd-rom is started (by changing the Start.cs form to play a video). For promotional cd-roms this shouldn't be a problem at all!

Let's dive into the code... Go to the app.config file again and add this new configuration key:
<!--
Optimize
true - No first time request
false - First time request
-->
<add key="optimize" value="true" />

We'll use this key to determine whether an optimization (by doing a first time request) is needed or not. Now, jump to the start.cs code file and locate this piece of code
srv = new Server(port,"/",path);
srv.Start();

lblAction.Text = "Ready";
this.Refresh();

Between the second and third line, add this code snippet:
string home = ConfigurationSettings.AppSettings["home"];
string url = String.Format("http://localhost:{0}/{1}",port,home);

bool optimize = bool.Parse(ConfigurationSettings.AppSettings["optimize"]);
if (optimize)
  PerformInitialRequest(url);

This will read the configuration settings and if the optimization is required the PerformInitialRequest method is called, which is listed here:
private void PerformInitialRequest(string url)
{
  lblAction.Text = "Performing initial request...";
  this.Refresh();

  WebClient client = new WebClient();
  client.OpenRead(url);
}

This requires this additional namespace import:
using System.Net;

When you launch the application again, a first time request is made which take a while but the default.aspx page is returned to the client much faster when the browser is displayed:


Launch Internet Explorer

A custom browser is fine, it actually is Internet Explorer hosted in our own application. But a lot of people like the real Internet Explorer browser more. In this paragraph we're going to take a look at how we can do this.

First of all, we should extend the application configuration file again by adding this setting:
<!--
Action
0 - Custom browser
1 - Internet Explorer
-->
<add key="action" value="1" />

Now, go back to the Start.cs file (code view) and locate this line of code:
new Browser(srv).Show();

Replace it by:
int action = int.Parse(ConfigurationSettings.AppSettings["action"]);
if (action == 0)
  new Browser(srv).Show();
else if (action == 1)
  StartIE(url);
else
  Stop();

As you can see in the code, the '0-action' will cause the custom browser to be launched, where the '1-action' will invoke the StartIE method which will launch Internet Explorer. In all other cases (that's invalid configuration), the server is stopped and the application is exited using this method:
private void Stop()
{
  srv.Stop();
  Application.Exit();
}

Take a look at the StartIE method:
private void StartIE(string url)
{
  Process process = new Process();
  process.EnableRaisingEvents = true;
  process.StartInfo.FileName = "iexplore.exe";
  process.StartInfo.Arguments = url;
  process.Exited += new EventHandler(process_Exited);
  process.Start();
}

Again, another namespace import is needed:
using System.Diagnostics;

This piece of code may look a little strange but I'll explain. Common questions could be: "Why do we need a process with an Exited event han0064ler?" and "Why can't we just start Internet Explorer and quit the application?". The answer is simple in fact: we need to wait till Internet Explorer has been closed by the user before we can stop the Cassini web server that's running inside our application.

Remark: I love Visual Studio .NET 2003... And those images show why:





Finally, let's take a look at the process_Exited event handler:
private void process_Exited(object sender, EventArgs e)
{
  Stop();
}

In this code, the Cassini server is stopped and the application is exited using the Stop method we wrote earlier.

Stiil need another test! Press F5 again and take a look at what happens now... Internet Explorer is launched indeed and here's the result:


Looks magic at the first sight but it isn't... As you can see in the Address field in the browser, the port 49000 was used to start the Cassini web server on. Don't close the browser window but take a look at the status of the debugger in Visual Studio .NET. As you can see it's still running:


Now, close the Internet Explorer window and the debugger will stop. This proves that our event handler for the process_Exited event works properly.

Finally, make a Release compile of the complete solution. Note that you'll need top copy the webdir folder to the Release folder to test the release version of the Launcher application.

Burning the cd-rom

The application is ready. In this last paragraph I’ll explain how to create a cd-rom that hosts an ASP.NET web application.
Step 1: Folder structure

I suggest this basic folder structure:
Cd-rom root
  |-- Autorun.ini (see step 3)
  |-- Launcher.exe
  |-- Launcher.exe.config (see step 2)
  |-- CassiniLight.dll
  |-- Webdir
  |   |-- Files of the ASP.NET application
  |   |-- bin
  |   |   |-- assemblies of the ASP.NET application
  |   |   |   |-- CassiniLight.dll

Step 2: Configuration

The complete Launcher.exe.config file (in the solution called app.config) should look like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!--
    Root
    folder to the ASP.NET application (relative to launcher.exe)
    -->
    <add key="root" value="webdir" />

    <!--
    Title
    titlebar text for the custom browser
    -->
    <add key="title" value="Our test site" />

    <!--
    Home
    startpage of the ASP.NET application (in the 'root' folder)
    -->
    <add key="home" value="default.aspx" />

    <!--
    Optimize
    true - No first time request
    false - First time request
    -->
    <add key="optimize" value="true" />

    <!--
    Action
    0 - Custom browser
    1 - Internet Explorer
    -->
    <add key="action" value="1" />
  </appSettings>
</configuration>

Step 3: Autorun.ini

Last but not least, it’s nice to have a cd-rom with AutoPlay functionality. To do this, create an autorun.ini file in the root of the cd-rom containing:
[autorun]
OPEN=launcher.exe
ICON=myicon.ico

As you can see, you can specify an icon for the cd-rom as well.

Remark: Since this is a C# application the users of the cd-rom will need to have the .NET Framework installed on their pc (redistributable or SDK).

Wrap up

Possible implementations

  • A host for simple ASP websites (can run off-line!)
  • Demo sites for the .NET technology (how about a host for the QuickStart tutorials or the Starter Kits of ASP.NET)
  • Client-side interface for a back-end service (a web service consumer, a SQL client, etc)
  • Catalogues for shops, ... (read-only database)
Drawbacks

  • .NET Framework needed on the client
  • No support for SQL Server or MSDE, although you can solve this by launching an installer application first which creates a MSDE instance on the client and executes some .sql scripts
Extensible

  • Add video playback during start up (initial request)
  • Other ideas are always welcome

About the author

Although being a student Informatics, Bart De Smet is already actively developing applications with the .NET Framework since the first beta. His interests are rather broad: going from C# and Visual Basic .NET development and the internet (ASP.NET, Web Services, .NET Remoting) over systems administration (Windows 2000, Windows XP and Windows Server 2003, Active Directory, Exchange Server 2003) to .NET Enterprise Servers (SQL Server, BizTalk). Bart is also responsible for the maintenance of the network of the "College" in Zottegem (Windows Server 2003) and is actively involved in the Belgian .NET community.

In 2001 he built the first site using .NET Passport in Belgium. Recently Bart became a Top 25 Poster and moderator of the official ASP.NET Forums. Bart is also a regular speaker about ASP.NET and Windows Server 2003 on AAL and he also takes care of several workshops.You can contact him at info@bartdesmet.net or on his website http://www.bartdesmet.net

Since October 2003, Bart was also appointed as ASP.NET MVP (Most Valuable Professional) by Microsoft.