Thursday, May 27, 2010

Getting Started with WebSharper Platform 2010

A little while ago a cool new product was brought to my attention that allows client-based web development in F#.  The name of this product is WebSharper Platform 2010.  In this post, I will show a simple example for getting started with WebSharper Platform 2010.

Overview of this Example: 
The following code is a slimmed down and slightly modified version of the example provided in the default WebSharper-1.0 template.  Additionally, this example saves the information captured on the form to a CouchDB database.  Note: To run this example, you will need to download and install the WebSharper Platform 2010 Standard - Version 1.0.28 - Public Release (Instructions can be found at http://www.intellifactory.com/products/wsp/GettingStarted.aspx).  Additionally, in order for the registration information to be saved to the CouchDB database, CouchDB must be running on the default port (5984) of the local machine and a database named registration must exist.

Setting up the Form:
Our basic form is setup with the help of the Formlets library ("a library for type-safe web form combinators" - http://www.intellifactory.com/docs/websharper.pdf). The JavaScript attribute informs the WebSharper compiler that the function should be translated from F# to JavaScript.
    [<JavaScript>]
    let RegistrationForm : Formlet<RegistrationInformation> =
        Formlet.Yield (fun firstName lastName email -> 
                           {FirstName = firstName; 
                            LastName = lastName; Email = email})
        <*> input "First Name" "Please enter your first name"
        <*> input "Last Name" "Please enter your last name"
        <*> inputEmail "Email" "Please enter a valid email address"
Creating the Form Validation:
You probably noticed the input and inputEmail function calls in the form setup. These functions create the form elements with appropriate validation.  The code is as follows:
    [<JavaScript>]
    let input (label: string) (error: string) = 
        Controls.Input ""
        |> Validator.IsNotEmpty error
        |> Enhance.WithValidationIcon
        |> Enhance.WithTextLabel label

    [<JavaScript>]
    let inputEmail (label: string) (error: string) = 
        Controls.Input ""
        |> Validator.IsEmail error
        |> Enhance.WithValidationIcon
        |> Enhance.WithTextLabel label
Adding the Flow:
In this simple example, the user completes the three fields and clicks submit. The information is then saved to couch and the user is redirected to a summary page. That sequence is setup with the following code:
    [<JavaScript>]
    let RegistrationSequence =
        let registrationForm =
            RegistrationForm
            |> Enhance.WithSubmitAndResetButtons
            |> Enhance.WithCustomFormContainer {
                Enhance.FormContainerConfiguration.Default with
                    Header = 
                        "Enter the following information to register:" 
                        |> Enhance.FormPart.Text 
                        |> Some
                }
        let completeRegistration registrationInformation () =
            SaveRegistrationToCouch registrationInformation
            FieldSet [
                Legend [Text "Registration summary"]
                P ["Hi " + registrationInformation.FirstName + " " + 
                    registrationInformation.LastName + "!" |> Text]
                P ["You are now registered." |> Text]]
        let flow =
            Flowlet.Do {
                let! initialForm = registrationForm
                return! Formlet.OfElement (completeRegistration initialForm)
            }
        Div [H1 [Text "Register today!"]] -< [flow.BuildForm()]

Saving the Information to CouchDB: 
The final piece of code that I will show from this example is the server side method that is called from the client to save the information to CouchDB. In the RegistrationSequence function, we saw a call to a function named SaveRegistrationToCouch. This function looks like this:
    [<Rpc>]
    let SaveRegistrationToCouch (registrationInformation:RegistrationInformation) =
        JsonConvert.SerializeObject registrationInformation
        |> FSharpCouch.CreateDocument couchDBUrl 
        |> ignore
As you can see, all it takes for us to expose a server-side method is to add the Rpc attribute to that function.

Viewing the Result:
The result is a nice little registration sequence that contains client-side validation.  An example of the initial form with all completed information is below:

Conclusion:
This example shows how easy it is to throw together a simple registration form with WebSharper Platform 2010. We've only touched the surface on the capabilities of this platform.  You can find out more by visiting the Intellifactory web site.  You can find the full solution at http://github.com/dmohl/WebSharper-Example.

Sunday, May 23, 2010

A Simple Inversion of Control (IoC) Container in F#

In this post I will show how to build a simple Inversion of Control (IoC) container in F#.  If you are new to IoC containers I would recommend getting acquainted by reading http://martinfowler.com/articles/injection.html and http://msdn.microsoft.com/en-us/library/aa973811.aspx.

The Code:
namespace FSharpIoC

open System
open System.Collections.Generic
open System.Reflection

module FSharpIoCModule = 
    let rec Resolve requestedType (typeContainer:Dictionary<Type,Type>) =
        let newType = typeContainer.[requestedType]
        let constructors = newType.GetConstructors() 
                           |> Array.sortBy (fun c -> c.GetParameters().Length) 
                           |> Array.rev
        let theConstructor = constructors.[0]
        match theConstructor.GetParameters() with
        | cstorParams when cstorParams.Length = 0 -> Activator.CreateInstance(newType)
        | cstorParams -> cstorParams 
                         |> Seq.map(fun (paramInfo:ParameterInfo) -> 
                                (Resolve paramInfo.ParameterType typeContainer)) 
                         |> Seq.toArray 
                         |> theConstructor.Invoke

type Container =
    val typeContainer : Dictionary<Type, Type>
    new () = {typeContainer = new Dictionary<Type, Type>()}
    member x.Register<'a,'b> () =        
        x.typeContainer.Add(typeof<'a>, typeof<'b>)
    member x.Resolve(requestedType) =
        FSharpIoCModule.Resolve requestedType x.typeContainer
    member x.Resolve<'a> () =
        FSharpIoCModule.Resolve typeof<'a> x.typeContainer :?> 'a
Using Our IoC Container From F#:

The code below is not exactly a "real world" example, but it does show how our IoC container could be used in an F# application:
module FSharpIoCExample

open System
open FSharpIoC

type Person =
    { FirstName : string
      LastName : string}

type IPersonFactory =
    abstract CreatePerson : unit -> Person

type PersonFactory() = 
    interface IPersonFactory with
        member x.CreatePerson () = 
            {FirstName = "TestFirst"; LastName = "TestLast"}

type PersonService = 
    val personFactory : IPersonFactory
    new (personFactory) = {personFactory = personFactory}
    member x.GetPerson () = 
        x.personFactory.CreatePerson()

let iocContainer = new Container()
do iocContainer.Register<IPersonFactory, PersonFactory>()
do iocContainer.Register<PersonService, PersonService>()
let personService = iocContainer.Resolve<PersonService>()
let person = personService.GetPerson()
do Console.WriteLine("The person's name is {0} {1}", person.FirstName, person.LastName)
do Console.ReadLine()
Using Our IoC Container From C#:

Here is the same example in C#:
using System;
using FSharpIoC;

namespace CSharpIoCExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var iocContainer = new Container();
            iocContainer.Register<IPersonFactory, PersonFactory>();
            iocContainer.Register<PersonService, PersonService>();
            var personService = iocContainer.Resolve<PersonService>();
            var person = personService.GetPerson();
            Console.WriteLine("The person's name is {0} {1}", person.FirstName, person.LastName);
            Console.ReadLine();
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public interface IPersonFactory
    {
        Person CreatePerson();
    }

    public class PersonFactory : IPersonFactory
    {
        public Person CreatePerson()
        {
            return new Person { FirstName = "TestFirst", LastName = "TestLast" };
        }
    }

    public class PersonService
    {
        protected readonly IPersonFactory _personFactory;
        public PersonService(IPersonFactory personFactory)
        {
            _personFactory = personFactory;
        }

        public Person GetPerson()
        {
            return _personFactory.CreatePerson();
        }
    }
}
Conclusion

As you can see, it doesn't take much to build a slim featured IoC container in F#. You can find the full source at http://github.com/dmohl/FSharpIoC.

Thursday, May 20, 2010

Creating an F# Solution Template for Visual Studio 2010

The title of this post is misleading because you can't actually create a VS2010 solution template (to my knowledge at least).  However, you can create a multi-project template and when I first went looking for how to do this, a search for "how to create a VS2010 solution template" was the first thing that came to mind (apparently many others have done this as well).  Hopefully, this post will make it easier for others to find the information for which they are searching.

In my last post, I provided an F# ASP.NET MVC 2 Web Application template that provides the same functionality as the out of the box C# ASP.NET MVC 2 Web Application template.  In this post, I will show how that template was created.  The full solution including all *.vstemplate and *.vscontent files can be found at http://github.com/dmohl/FSharpMVC2Starter.

Creating the *.vstemplate File for Each Project:


The first step in creating a multi-project template is to create a *.vstemplate file for each of the projects that you wish to include.  This can be accomplished using the export template wizard in visual studio (view the steps on the MSDN web site) or by manually creating the template (view the steps on the MSDN website).

This is what my *.vstemplate file looks like for the FSharpMVC2.Controllers project:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <Name>FSharpMVC2.Controllers</Name>
    <Description>MVC Controllers in F#</Description>
    <ProjectType>FSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>FSharpMVC2.Controllers</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <Project TargetFileName="FSharpMVC2.Controllers.fsproj" File="FSharpMVC2.Controllers.fsproj" ReplaceParameters="true">
      <ProjectItem ReplaceParameters="false" TargetFileName="HomeController.fs">HomeController.fs</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="AccountController.fs">AccountController.fs</ProjectItem>
    </Project>
  </TemplateContent>
</VSTemplate>
The ProjectType element value of "FSharp" specifies that this is an F# template.

Creating the Root *.vstemplate File:

Once the *.vstemplate files have been created, it's time to create a root *.vstemplate.  This looks very similar to the project level *.vstemplate files; however, it references each project level *.vstemplate file rather than the specific project level source/content files.

My root level *.vstemplate file looks like this:
<VSTemplate Version="2.0.0" Type="ProjectGroup"
    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
    <TemplateData>
        <Name>F# ASP.NET MVC2 Web Application</Name>
        <Description>F# ASP.NET MVC2 Web Application</Description>
        <Icon>__TemplateIcon.ico</Icon>
        <ProjectType>FSharp</ProjectType>
    </TemplateData>
    <TemplateContent>
        <ProjectCollection>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Controllers">
                src\FSharpMVC2.Controllers\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Models">
                src\FSharpMVC2.Models\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Core">
                src\FSharpMVC2.Core\MyTemplate.vstemplate
            </ProjectTemplateLink>
            <ProjectTemplateLink ProjectName="FSharpMVC2.Web">
                src\FSharpMVC2.Web\MyTemplate.vstemplate
            </ProjectTemplateLink>
        </ProjectCollection>
    </TemplateContent>
</VSTemplate>
Once again, the ProjectType element value of "FSharp" indicates that this is an F# template.

Compresssing the Files:

Once all of the *.vstemplate files are created, it is time to compress all files that are to be included in the template.  To do this, select all the desired items including the root *.vstemplate file, then right-click and choose Send To/Compressed (zipped) Folder.  This will create a single *.zip file.

Creating the Template Installer:

We are now ready to create our template installer.  This involves the creation of one last XML file named *.vscontent.  My FSharpMVC2Template.vscontent file looks like this:
<VSContent xmlns="http://schemas.microsoft.com/developer/vscontent/2005">
    <Content>
        <FileName>FSharpMVC2Template.zip</FileName>
        <DisplayName>F# ASP.NET MVC2 Web Application</DisplayName>
        <Description>F# ASP.NET MVC2 Web Application</Description>
        <FileContentType>VSTemplate</FileContentType>
        <ContentVersion>1.0</ContentVersion>
        <Attributes>
            <Attribute name="ProjectType" value="Visual Web Developer"/>
            <Attribute name="ProjectSubType" value=""/>
            <Attribute name="TemplateType" value="Project"/>
        </Attributes>
    </Content>
</VSContent>
Note: Make sure that the FileName element value matches the name of the compressed file that you made during the "Compressing the Files" step.

Once the *.vscontent file has been created, select it, and the previously created zip file, and compress them into a single zip file. Change the extension of this file to .vsi and you're ready for a test run.

Sunday, May 16, 2010

F# and the Standard ASP.NET MVC 2 Web Application Template

Tomas Petricek recently provided a great blog post on creating MVC web applications in F#.  I thought it might be nice to also have a template that replicates the functionality of the standard C# ASP.NET MVC 2 Web Application template. The primary aspects of this template that differ from Tomas's include custom validators, authentication and membership services, and several jQuery plugins that are recommended and frequently used by Elijah Manor.

Here are a few examples of some of the code differences.

Custom Validators:
namespace FSharpMVC2.Web.Models
open System
open System.ComponentModel.DataAnnotations
open System.ComponentModel
open System.Globalization
open System.Web.Security

[<AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)>]
[<Sealed>] 
type PropertiesMustMatchAttribute = 
    inherit ValidationAttribute 
        val typeId : obj
        val mutable originalProperty : string
        val mutable confirmProperty : string
        new (originalProperty, confirmProperty) = 
            {inherit ValidationAttribute("'{0}' and '{1}' do not match."); originalProperty = originalProperty; 
             confirmProperty = confirmProperty; typeId = new Object()} 
        member x.OriginalProperty with get() = x.originalProperty and set(value) = x.originalProperty <- value
        member x.ConfirmProperty with get() = x.confirmProperty and set(value) = x.confirmProperty <- value
        override x.TypeId with get() = x.typeId
        override x.FormatErrorMessage name =
            String.Format(CultureInfo.CurrentUICulture, x.ErrorMessageString, x.OriginalProperty, x.ConfirmProperty)
        override x.IsValid value =
            let properties = TypeDescriptor.GetProperties value
            let originalValue = properties.Find(x.OriginalProperty, true).GetValue(value)
            let confirmValue = properties.Find(x.ConfirmProperty, true).GetValue(value)
            Object.Equals(originalValue, confirmValue)

[<AttributeUsage(AttributeTargets.Field ||| AttributeTargets.Property, AllowMultiple = false, Inherited = true)>]
[<Sealed>] 
type ValidatePasswordLengthAttribute = 
    val minCharacters : int
    new () = {inherit ValidationAttribute("'{0}' must be at least {1} characters long."); 
                minCharacters = Membership.Provider.MinRequiredPasswordLength} 
    inherit ValidationAttribute 
        override x.FormatErrorMessage name =
            String.Format(CultureInfo.CurrentUICulture, x.ErrorMessageString, name, x.minCharacters)
        override x.IsValid value =
            let valueAsString = value :?> string
            (valueAsString <> null && valueAsString.Length >= x.minCharacters)
Authentication and Membership Services:
namespace FSharpMVC2.Web.Models

open System
open System.Web.Security

module InputValidation =
    let Validate stringValue errorMessage =
        match String.IsNullOrEmpty(stringValue) with
        | true -> failwith(errorMessage)
        | _ -> do "" |> ignore

type IMembershipService = interface
    abstract MinPasswordLength : int with get
    abstract ValidateUser : string*string -> bool
    abstract CreateUser : string*string*string -> MembershipCreateStatus
    abstract ChangePassword : string*string*string -> bool
end    

type AccountMembershipService =
    val provider : MembershipProvider
    new () = AccountMembershipService(Membership.Provider)
    new (provider) = {provider = provider}
    interface IMembershipService with 
        member x.MinPasswordLength with get() = x.provider.MinRequiredPasswordLength
        member x.ValidateUser (userName, password) =
            InputValidation.Validate userName "Username cannot be null or empty."
            InputValidation.Validate password "Password cannot be null or empty."
            x.provider.ValidateUser(userName, password)
        member x.CreateUser (userName, password, email) =
            InputValidation.Validate userName "Username cannot be null or empty."
            InputValidation.Validate password "Password cannot be null or empty."
            InputValidation.Validate email "Email cannot be null or empty."
            let (_, status) = x.provider.CreateUser(userName, password, email, null, null, true, null)
            status
        member x.ChangePassword(userName, oldPassword, newPassword) =
            InputValidation.Validate userName "Username cannot be null or empty."
            InputValidation.Validate oldPassword "OldPassword cannot be null or empty."
            InputValidation.Validate newPassword "NewPassword cannot be null or empty."            
            try
                let currentUser = x.provider.GetUser(userName, true)
                currentUser.ChangePassword(oldPassword, newPassword)
            with 
            | :? ArgumentException -> false
            | :? MembershipPasswordException -> false

type IFormsAuthenticationService =
    abstract SignIn : string*bool -> unit
    abstract SignOut : unit -> unit

type FormsAuthenticationService() =
    interface IFormsAuthenticationService with
        member x.SignIn(userName, createPersistentCookie) =
            InputValidation.Validate userName "Username cannot be null or empty"
            do FormsAuthentication.SetAuthCookie(userName, createPersistentCookie)
        member x.SignOut () =
            do FormsAuthentication.SignOut()
You can download the template installer by clicking here.  The full solution can be found at http://github.com/dmohl/FSharpMVC2Starter.  (Note: The full solution includes a few things that are not included in the template such as a sample test project for the home controller.)

Wednesday, May 5, 2010

Integrating F# and Erlang Using OTP.NET

Recently, I ran across a post that talked about a .NET library named OTP.NET.  OTP.NET is a port of a Java library named JInterface that allows a .NET application to act as an Erlang node.  OTP.NET hasn't been updated in a while and the API is a bit clunky, but the provided functionality is very cool.  Note: A forked version of OTP.NET that has been migrated to VS2010 can be found at http://github.com/dmohl/OTP.NET-2010.

I decided to give OTP.NET a test drive by adding a simple command-line interface to an Erlang project that I have been playing with called Querly.

Querly is a simple query engine that allows T-SQL style queries against a CouchDB database.  You can read more about Querly in the following posts:

- Querly - A Query Engine for CouchDB
- Setting Up Querly
- Getting Started with Querly: A Simple CouchDB Query Engine

Getting Setup


To make this work, we first need to do the following:

1. Setup Querly by following the instructions provided in the blog post entitled Setting Up Querly.
2. If you want to load up a database for testing, follow the instructions provided in the blog post entitled Getting Started with Querly: A Simple CouchDB Query Engine.
3. Make sure that RabbitMQ and CouchDB are running.
4. Launch Querly by navigating to the Querly directory and running a command such as:
"C:\Program Files\erl5.7.5\bin\werl.exe" -sname querly -setcookie supersecretcookie -pa ./ebin -pa ./src
5. Finally, in the Erlang interactive shell, run the following command:
querly:start().

If everything worked as expected, you should see something like this:

Building the F# Application

Now that we have the Erlang application up and running, it's time to put together the F# code that will allow us to join the Erlang node cluster and interact with Querly.  Note: You'll need to replace the value assigned to peerNode with the name of your querly node. The full solution can be found at http://github.com/dmohl/Ferly.
module Ferly

open System
open Otp

Console.Write ":>"  
let mutable input = Console.ReadLine()  

let erlangCookie = "supersecretcookie"
let peerNode = "querly@dmohl-PC" // Replace with querly node name

let connection =
    let cNode = new OtpSelf("querlyclientnode", erlangCookie)
    let sNode = new OtpPeer(peerNode)
    cNode.connect(sNode)

let RemoteCall (sql:string) = 
    let arguments = [|new Erlang.String(sql)|] : Erlang.Object[]
    do connection.sendRPC("querly_client", "sql_query", arguments) 
    connection.receiveRPC().ToString()

while input <> "quit" do 
    Console.Write(RemoteCall input)
    Console.Write "\n\n:>"   
    input <- Console.ReadLine()


We should now be able to run the F# application and write queries against a couch database.  An example of the running application after a few processed queries is shown below:


Wrapping Up


We have only touched the surface of the functionality provided by OTP.NET.  Hopefully this post has shown how OTP.NET can be used to quickly integrate F# with Erlang.  Unfortunately, there is not a lot of documentation out there for OTP.NET, so if you want to learn more, your best bet is to pull down the code and start thumbing through it.  Happy polyglot programming!


Sunday, May 2, 2010

Getting Started with Querly: A Simple CouchDB Query Engine

About a month ago, I introduced a simple project that allows limited T-SQL style queries against a CouchDB database.  The codename for that project is Querly.  Today, I'm going to talk a little about what you need to get started with Querly.

The other posts can be found in the following locations:

- Querly - A Query Engine for CouchDB  
- Setting Up Querly

Loading Up A Test Database

To get started with Querly, make sure that you have followed the instructions outlined in Setting Up Querly.  If all the tests run, you are ready to get started with Querly.  Press [Enter] to get back to the Erlang prompt.  In order to load up a database with several documents that we can play with, type  querly_load_tests:load_10000_people(). and press [Enter] (Note: This will take a little while to finish).

Writing Our First Query

Once the "person" database is loaded, we can start Querly and begin writing simple queries.

To start querly, type querly:start().

Here are a few samples of queries that can now be run (Note: The first query may take a few seconds as the documents are being loaded into an ETS table):

querly_client:sql_query("select * from person where Idno = 1").
querly_client:sql_query("select * from person where FirstName = TestFirst2").
querly_client:sql_query("select * from person where Dob= 08/28/1977 and FirstName = TestFirst3").

Querying Other Databases

In order to write T-SQL style queries against a database, a record must be defined in the src/record_definitions.hrl file.  An example for the person table is as follows:

-record(person, {'Idno', 'FirstName', 'LastName', 'Dob', 'Ssn'}). 
-define(personFields, record_info(fields, person)).

This definition makes it possible to use specific field names in the TSQL style queries.

Limitations

There are a number of known limitations in this simple query engine. 

The most notable limitations are as follows:

- The T-SQL style query functionality is limited to simple "where" clauses.  
- A record must be predefined in order to query a database.

Conclusion

Querly allows simple T-SQL style queries against a CouchDB database.  While Querly has a number of known limitations, it hopefully serves as a simple PoC and/or starting point for a CouchDB query engine.