WebSharper
By Adam Granicz on Thursday, November 13, 2014 — 2 comments

Self-hosted WebSharper application template availableCore team

A new Visual Studio template has been added to the latest Visual Studio installer called "Self-Hosted Client-Server Application," and you can use this template to build OWIN-based self-hosted applications that can be deployed via an .exe file and without requiring an installed web container (IIS, etc.) on the serving machine.

The following code shows embedding a given sitelet (Site.MainSitelet) into an OWIN container and starting it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module SelfHostedServer =

    open global.Owin
    open Microsoft.Owin.Hosting
    open Microsoft.Owin.StaticFiles
    open Microsoft.Owin.FileSystems
    open IntelliFactory.WebSharper.Owin

    [<EntryPoint>]
    let Main = function
        | [| rootDirectory; url |] ->
            use server = WebApp.Start(url, fun appB ->
                appB.UseStaticFiles(
                        StaticFileOptions(
                            FileSystem = PhysicalFileSystem(rootDirectory)))
                    .UseSitelet(rootDirectory, Site.MainSitelet)
                |> ignore)
            stdout.WriteLine("Serving {0}", url)
            stdin.ReadLine() |> ignore
            0
        | _ ->
            eprintfn "Usage: OWIN1 ROOT_DIRECTORY URL"
            1

The OWIN machinery to make this work has been released as a new WebSharper.Owin NuGet package as well. The new Visual Studio template contains this boilerplate code, takes care of fetching the dependent OWIN packages, and calls the generated OWIN container .exe with the right arguments to host your sitelets easily.

Work to add this new WebSharper project template to the MonoDevelop/Xamarin Studio integration is underway.

Let us know what you think and happy coding!

  • bananasareyellow

    Great. This is simpler than the previous WebSharper.WebApi version, and with UseCustomSitelet I can now control whether to serve .js (for debug) or .min.js (for release), which is good.

    The comments for UseCustomSitelet say:

    ... Allows a more customized setup than the previous methods, for example running a Sitelet whose code isn't located in the "bin" subfolder of the root folder ...

    I am using this code in an Azure 'worker role', and that means all the DLLs are in the 'webRoot' folder itself (rather than in a 'bin' subfolder, as would be the case with a 'web role'), so this comment caught my eye. But, unless I am missing a trick, the only way I could achieve this was to create another Create overload, which takes a 'binFolder':

    1
    2
    3
    4
    5
    
        type Options with
            static member Create (webRoot, binFolder) =
                let meta = M.Info.LoadFromBinDirectory binFolder
                Options.Create(meta)
                    .WithServerRootDirectory(webRoot)

    But this requires me to duplicate the code for LoadFromWebRoot (and DiscoverAssemblies), since these are not public. Is there a better way?

    Anyway, it all seems to work.

    Thank you.

    David.

    • loic.denuziere

      Indeed, this is an oversight in the public API; thanks for pointing it out! I will add methods and optional arguments to Options.Create and IAppBuilder extensions to address this. You can expect it to be released in the coming days.