What you feel if you meet your favourite actor? Feeling is wonderful right? Now, add the your actress in the mixture. Have you said WOW??? How about director? Still heart is beating?!? How about having dinner with them? Nothing can be better than that.

I am having kinda same feeling. It is nothing new that Nancy is dancing quite comfortable with F#. And thanks to Daniel Mohl we are also having templates to get started with Nancy and F#.

Now, I was doing some experiments around it. It was quite good. But how about running it on Owin. hmmm, it works flow less. Nothing more on code side other than few lines here and there. Then I found few projects running SignalR with F#.

I knowing Nancy from a long time. But SignalR, I don’t know anything about it. The only thing I know is that, it is super awesome.

So, first task is to run Nancy on Owin.

Here are simple steps. Using template create a asp.net host with razor project. remove asp.net host and add Owin host using nuget package manager.

Now we need to add startup file.

type Startup() = 
    member x.Configuration(app : Owin.IAppBuilder) =  app.UseNancy() |> ignore
       

[<Microsoft.Owin.OwinStartup(typeof<Startup>)>]
do ()

And add simple Nancy code. The regular one. Nothing fancy.

There is bootstrap class

type Bootstrapper() =
    inherit DefaultNancyBootstrapper()
    override x.ApplicationStartup(container:TinyIoCContainer, pipelines:IPipelines) = 
        StaticConfiguration.DisableErrorTraces <- false
        base.ApplicationStartup(container,pipelines)
        ignore()

this is needed to trace the error if anything is there at nancy end.

And our index module

type IndexModule() as x =
    inherit NancyModule()
    do x.Get.["/"] <- fun _ -> box x.View.["Index"]

Pretty lame right. But it works.

Now, add Signalr asp.net host nuget package to project. As startup file is already there; no need to create one more. Just minor modification will do.

type Startup() = 
    member x.Configuration(app : Owin.IAppBuilder) =  app.MapSignalR().UseNancy() |> ignore

That MapSignalR thing is additionally added. I have just followed Hello World example of real time world. Create a chat application. So, here is the hub to broadcast the message to all users.

type ChatHub() as this = 
    inherit Hub()
    member x.send (name : string, msg : string) = this.Clients.All?broadcastMessage (name, msg) |> ignore

Now, copy paste code for html part. Here is code snippet. There is no need to go into detail as of now for JavaScript part.

<div>
    <p>Here is singnal R working great with Nancy</p>
    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion"></ul>
    </div>

</div>
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="Scripts/jquery-1.6.4.min.js"></script>
<!--Reference the SignalR library. -->
<script src="Scripts/jquery.signalR-2.0.2.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="signalr/hubs"></script>
<!--Add script to update the page and send messages.-->
<script type="text/javascript">
    $(function () {
        // Declare a proxy to reference the hub.
        var chat = $.connection.chatHub;
        // Create a function that the hub can call to broadcast messages.
        chat.client.broadcastMessage = function (name, msg) {
            // Html encode display name and message.

            var encodedName = $('<div />').text(name).html();
            var encodedMsg = $('<div />').text(msg).html();
            // Add the message to the page.
            $('#discussion').append('<li><strong>' + encodedName
                + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
        };
        // Get the user name and store it to prepend to messages.
        $('#displayname').val(prompt('Enter your name:', ''));
        // Set initial focus to message input box.
        $('#message').focus();
        // Start the connection.
        $.connection.hub.start().done(function () {
            $('#sendmessage').click(function () {
                // Call the Send method on the hub.
                chat.server.send($('#displayname').val(), $('#message').val());
                // Clear text box and reset focus for next comment.
                $('#message').val('').focus();
            });
        });
    });
</script>

Now, there is one “?” thing before broadcastMessage function. That is where dynamic method is getting called. F# do not support dynamic by default but there are many work around available. I personally prefer Fsharp.dynamic library. It is better than other code snippets I found over other sites. But that is all personal choice how one like to handle dynamic functions.

So, it is done. Hit F5 and you are ready to go.

What is fun of working with Web if I can’t publish it. But for now with F# web templates it is not possible. And that is known issue. So, if I like to publish it on cloud like azure I need to give git hooks. That is easiest thing I can think off. But road is still not that smooth.

Deployment will break with some weird error. I followed Mark’s article to make it work.

Needed to add below lines to .fsproj file after its own import tags.

<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" 
        Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets" 
        Condition="true" />

And things are working like anything. No, issues at all.

Nancy |> Razor |> SignalR |> Azure |> F# |> lots of love.

Please give it a shot. If it break somewhere let me know will try to solve it. Any suggestion to make things even better and streamlined are always welcome.

UPDATE: Here is my github repo with updated code. Project created with web express 2013. Also it is deployed over azure.