Using FSharp with OrchardCMS

Using FSharp with OrchardCMS




This post describes how to use FSharp and Orchard together. If you want to know why to use FSharp, here you can find a lot of reasons ( 


In this post you won't learn how to use FSharp or Orchard, it only will show you how to use them together without changing anything in the core of Orchard.



Configuring the environment


The first thing that we have to do is to download the source of the latest stable Orchard version (at this moment 1.7.2) []. We just have to unzip the file and open the sln file with Visual Studio. If we run it now, Orchard should launch its pretty simple configuration page. Just fill the form (choose the SQLCompact database and the Default recipe). 


When Orchard shows the HomePage just go back to Visual Studio and add a FSharpLibrary project to the solution. Call it FSharpModule. The location of the project should be on src/Orchard.Web/Modules.


Now is time to configure our project to work with Orchard, go to the Properties of the project and on Build->Output path choose Orchard.Web/bin directory. This way Orchard will rediscover your module and its dependencies (such as FSharp.Core) each time that you compile it. Note that Dynamic Compilation is not working and every time that you have to change your Module you have to compile it again, but since the assembly is on Orchard.Web/Bin directory, Orchard will notice that something changed and it will pick the assembly again. 


We also have to change the .NET target framework to 4.0. and the FSharp target runtime to 3.0. The next step is to create the Module.txt file. It should look something like this:


Name: FSharpModule

AntiForgery: enabled

Author: Juan M Gómez


Version: 1.7.2

OrchardVersion: 1.7.2

Description: This is a sample of module in fsharp



The file is mandatory, Orchard will explore the Modules subfolders looking for that file in each module. The next step is to add the references:













We also have to add the nuget package FSharp.Dynamic. We will need it to play nicely with Dynamic objects.


Disabling "Edit and continue" on Orchard.Web->options->web is also helpful to prevent restarting iis every time that you want to stop the debugger. 


Hello World Orchard


Next step is to write the code, I'm writing it on Library1.fs. This is a simple controller with a simple model.


namespace FSharpModule
open System.Web.Mvc
open Orchard.Themes

type Salute() =
member this.SayHello = "Hello from Fsharp"

type FSharpController() =
inherit Controller()       
member this.Index() =            


By marking the controller with the Themed attribute orchard will inject our View to the current theme. If we don't use it, our plain view will be displayed.


For creating our views, since FSharp projects don't support directories by default, you can copy->paste the View folder from another module to the directory and it will be created on Modules/FSharpModule/Views which is where orchard will look for Views. But I recommend to create the file structure outside of VisualStudio (By the way you can also create the Index view on the View directory of your theme). So, on the View directory you must have the web.config file and the Index.cshtml file





Now it's time to activate it, compile the library and go back to the browser (or run orchard again if you closed it), you will see our module on /admin -> Modules -> feature. Activate it. The next step is to navigate to the url of our controller, since each module in orchard can be regarded as a mvc area, you have to put the module name on the url, in our case: ~/ModuleFSharp/FSharp . Notice that you can change that route by implementing IRouteProvider, but that's out of the scope of this post.


So here it is:




A simple ContentPart


Now it’s time to truly integrate FSharp with Orchard by creating a ContentPart and a ContentItem. I'm going to base this example on the MapPart tutorial from the Orchard documentation (


I will start by creating the Model, to keep the post as simple as possible I will do everything on the same file, except the Models which have to be placed under the FSharpModule.Models namespace, because Orchard will look into it to discover Records. Be aware that in FSharp the order of the files matters, so our Models file should be before our Library1 file.


We should add these namespaces to our Models file


namespace FSharpModule.Models
open Orchard.ContentManagement
open Orchard.ContentManagement.Records
open System.ComponentModel.DataAnnotations

An for the Library.1fs file


namespace FSharpModule
open System.Web.Mvc
open Orchard.Themes
open Orchard.ContentManagement
open Orchard.ContentManagement.Records
open System.ComponentModel.DataAnnotations
open Orchard.ContentManagement.Handlers
open Orchard.Data
open Orchard.ContentManagement.Drivers
open EkonBenefits.FSharp.Dynamic
open Orchard.Data.Migration
open Orchard.ContentManagement.MetaData
open Orchard.ContentManagement.MetaData.Builders
open Orchard.Core.Contents.Extensions
open System.Data
open FSharpModule.Models

Notice that this is not the way of organizing the code in fsharp, it is just to keep it as short as possible.



So we're going to start with our model, in our Models.fs file we're going to write our MapRecord:


type DVA = DefaultValueAttribute

type MapRecord() =
inherit ContentPartRecord()
false)>] valmutableprivate lat : double
false)>] valmutableprivate lon : double

abstract Latitude : double with get,set
override this.Latitude with get() =
and set(v) = <- v

abstract Longitude : double with get,set
override this.Longitude with get() = this.lon
and set(v) = this.lon <- v     

This can be a bit painful, since implementing a virtual property with back fields in FSharp, it generates fields in runtime (see here for an example the NHibernate proxy validation will fail. So we have to tell NHibernate that we don't want to use the proxy validator, we can do it just implementing ISessionConfigurationEvents, back on Library1.fs


type SessionConfiguration() =
interface ISessionConfigurationEvents with
        member this.Created(cfg,defaultModel) =
fun c->c.Properties.Add("use_proxy_validator", "false") |>ignore)|>ignore
member this.Building(cfg) =
member this.Prepared(cfg) =
member this.Finished(cfg) =
member this.ComputingHash(hash) =



In our Models.fs again, MapPart


type MapPart() =
inherit ContentPart<MapRecord>()
member this.Latitude
with get() = base.Record.Latitude
and set(v) = base.Record.Latitude <- v
member this.Longitude
with get() = base.Record.Longitude
and set(v) = base.Record.Longitude <- v


Notice the beauty of the type inference on the properties, we don’t have to tell FSharp that the properties are double. 


Now it’s time to make the Handler, so go back to Library.fs. 

It will be needed to tell Orchard how to store the content.


type MapHandler(repository:IRepository<MapRecord>) =
inherit ContentHandler()
base.Filters.Add(StorageFilter.For(repository)) |> ignore



The next step is to do our Driver, Orchard uses drivers to create the template which will render the Display (for the front-end) and Editors (dashboard) methods. For each content item Orchard will iterate over its parts composing the view. This process is dynamic heavy, this is why we installed the FSharp.Dynamic library from nuget.



type MapDriver() =
inherit ContentPartDriver<MapPart>()
override this.Prefix with get() = "MapPart"
    override this.Display(part,displayType,shapeHelper) =            
"Parts_Map",fun()-> shapeHelper?Parts_Map(part))
        :> DriverResult
    override this.Editor(part,shapeHelper) =     
let editor = shapeHelper?EditorTemplate()      
        editor?TemplateName <-
        editor?Model <- part
        editor?Prefix <- this.Prefix         
"Parts_Map_Edit",fun()->editor):> DriverResult
    override this.Editor(part,updater,shapeHelper) =
null,null) |> ignore




Since there is no way to use Named Parameters dynamically on FSharp, we have to add the parameter to the shape in each line. Not a big deal.


Now it’s time to do our migration, the migration is where our scheme is defined. 


We're going to go a bit further and do a Widget with our MapPart. So this is the Migration file:


type Migration() =
inherit DataMigrationImpl()
member this.Create()=               
"MapRecord",fun table->
fun t->t.Column<double>("Longitude")
"MapPart",fun cfg->
"MapWidget",fun cfg->
fun t->t.WithPart("CommonPart").WithSetting("Stereotype","Widget")



If we start the site again, you will see that the database is modified with our MapRecord table and the rest of values of our Migration.



Adding the Views


We should create the following file structure under Modules/FSharpModule/Views




The Parts/Map.cshtml file:


<img alt="Location" border="1" src="
" />

The Editor/Parts/Map.cshtml file


@model FSharpModule.Models.MapPart

    <legend>Map Fields</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Latitude)
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Latitude)
        @Html.ValidationMessageFor(model => model.Latitude)

    <div class="editor-label">
        @Html.LabelFor(model => model.Longitude)
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Longitude)
        @Html.ValidationMessageFor(model => model.Longitude)




Now we just have to tell Orchard where our mappart should be placed inside of our ContentItem, so we just add a new file called and to put the following code:


  <Place Parts_Map="Content:10"/>
  <Place Parts_Map_Edit="Content:7.5"/>


Now it’s time to test that everything works as expected. Start the site again and go to admin->widget->content->add->Map Widget , fill the fields and save it. Navigate to the home and you should see the map there.







And that’s all. 


You can download the source here: