TP

ASP.NET web applications in F#

More recent article available

This article is no longer up-to-date. Although the techniques described in the article might still work (with a lot of adjustments to the newer version of F#), it is now recommended to use a different approach. Note that CodeDOM provider is now a part of F# Power Pack. For more recent information see:

CodeDOM and providers

CodeDOM (Code Document Object Model) is set of objects (located in System.CodeDom namespace) that can be used for representing logical structure of .NET source code. For example you can use CodeTypeDeclaration class to represent class declaration or CodeAssignStatement to represent assignment in the body of method. CodeDom is language independent and CodeDOM structure can be translated to source code in specified language using code generator (class that implements ICodeGenerator namespace). The CodeDOM structure can be also compiled to assembly using code compiler (implementation of ICodeCompiler interface). Microsoft provides several code providers with .NET Framework (for C#, VB.Net, JScript and C++), but you can add your own by by implementing previously mentioned interfaces.

In the .NET Framework, CodeDOM is used for automatic code generation. For example when you add web reference to your project, the wrapper class that calls web service is generated using CodeDom. Some more examples are typed dataset (generated from XSD files) and generator for data layer in the upcoming LINQ project, but the most interesting use for CodeDOM for me is in ASP.NET 2.0.

Typical ASP.NET web page consists of several aspx/ascx files and associated code behind files written in one of the .NET languages. When building web page, ASP.NET uses CodeDOM for building aspx/ascx files. It parses these files and generates according CodeDOM structure. For example <asp:Button id="btn" runat="server" /> declaration is translated to declaration of btn member and code that assigns new instance of Button object to this member. This generated structure is compiled to .NET assemblies using code compiler and the web page is ready to use. If you use any in-line code in ASP.NET page, it is included in the CodeDOM structure as literal, which means that if the generated CodeDOM is compiled using C# code compiler, it can contain literals only in C# language (because you can't mix languages in one source file).

ASP.NET and F#

In ASP.NET 1.1 you could compile code behind files using different compiler than the rest of the page (source generated from aspx/ascx). This method is used by ASP.NET in F# demo by Robert Pickering [1]. The more complex approach that is available in ASP.NET 2 is to write CodeDomProvider implementation for F#. This makes it possible to write F# in-line code in web pages and this method allows you to fully benefit of ASP.NET compilation model (for example you can use Publish Web Site command in Visual Studio).

FSharpCodeProvider & AspNetFsharpCodeProvider

I wanted to implement CodeDomProvider for the F# language, for the reasons mentioned above. Currently, I'm presenting version of provider that is able to compile ASP.NET pages quite well, however I implemented only features required by ASP.NET, so the provider is not complete. There are also some problems that has to be handled specially (for example, F# doesn't support partial classes), so apart from standard provider (FsharpCodeProvider), I also implemented AspNetFsharpCodeProvider that contains several 'hacks' for ASP.NET.

How to use it?

Important: For correct functionality of F# CodeDOM compiler, you have to modify your system variable PATH to include 'bin' directory of your F# installation folder. This is because, code compiler uses fsc.exe for compilation and there is no simple way for finding where the F# is installed.

The most simple way to start creating ASP.NET web sites in F# is to use VS.NET project template that you can find in the downloads section. Using this template, you can create web page that is already configured to use F# language. After installation, select File - New - WebSite.. and in the dialog select language 'Visual C#' (it is not possible to add another language AFAIK) and than select 'F# WebSite' template.

If you want to configure ASP.NET web site to use F# code provider manually, you have to do the following steps. First modify the web.config file to include the following elements in the compilation section:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true">
      <compilers>
        <compiler language="F#;f#;fs;fsharp" extension=".fs" 
          type="EeekSoft.FSharp.CodeDom.AspNetFSharpCodeProvider, fscodeprovider"/>
      </compilers>
    </compilation>
  </system.web>
</configuration>

This adds reference to the assembly that contains the AspNetFShaprCodeProvider class and it configures ASP.NET to use F# code generator for aspx files which Language attribute is set to "F#". When this is done, you can add F# page by adding aspx and code behind fs files. In the Page directive, set the Language attribute to "F#" and define the code behind class in the fs file.

The following example shows code behind class for simple web page (that contains one button with ID set to btnOk):

namespace FSharpWeb

open System;;
open System.Web.UI.WebControls;;

// Code behind class declaration
type Default = class inherit System.Web.UI.Page as base
  // Declaration of button control
  val mutable btnOk : Button;
  // All fields must be initialized in constructor
  new() = { btnOk = null; }
  // Set text of button in onload
  override this.OnLoad (e) =
    btnOk.Text <- "Hello world!";
    base.OnLoad (e);
end;;

There is still one little difference when compared with C#, which is that it is required to manually declare all controls (with ID) that are on the page (btnOk in this example). This is because F# doesn't (currently) support partial classes and so the partial class with control declarations that is generated by ASP.NET is dropped by the CodeDOM provider. The rest is very similar to how you develop ASP.NET pages in other languages; you can see more examples if you download attached example application. More information regarding object oriented programming in F# can be found in F# manual available at F# homepage [3].

Other CodeDom provider notes

As I mentioned earlier, the CodeDOM generator I created is still very limited and it is tested only with ASP.NET. You can find list of not implemented features in the release notes (see downloads). In the future, I'd like to extend it to support generating code for accessing web services too (code is generated using wsdl tool). If you have any interesting idea, how it could be used or if you have any other comments, ideas, bug fixes, etc., please let me know (at tomas@tomasp.net).

Downloads & links

Published: Sunday, 13 August 2006, 9:06 PM
Author: Tomas Petricek
Typos: Send me a pull request!
Tags: web, f#