Monday, December 30, 2013

Simple.Web F# Helpers

If you're using the new Simple.Web F# project template and haven't used Simple.Web, here are some little helpers to get going.

Static Content

Using the current NuGet package for Simple.Web, one has to setup static content like so (comes with the template at the moment):

open Simple.Web

type StaticContentStartupTask() =
    interface IStartupTask with
        member __.Run(config, env) =
            let pf f = config.PublicFolders.Add(PublicFolder f) |> ignore
            ["/Scripts"; "/Content"; "/App"] |> List.iter pf

Unfortunately, the template currently leaves out one line of code to make this useful. Currently (I'm sorry I didn't add this, please forgive me!), you must add a line to the OwinStartupApp class.

type OwinAppSetup() =
    static member Setup(useMethod:UseAction) =
        let run x y = Application.Run(x, y)
        Application.LegacyStaticContentSupport <- true  // This is the line missing
        run |> useMethod.Invoke

Need to add the "Application.LegacyStaticContentSupport" line to tell Simple.Web (well, Fix, really) to use the static content. There will be an OWIN-specific way of doing this in a later release.

Public File Mappings

One of the cool things about Simple.Web is we can map a URI to a static HTML file very easily.

open System.Collections.Generic

type PublicFileMappingStartup() =
    interface IStartupTask with
        member __.Run(config, env) =
            let pf (ep, f) = config.PublicFileMappings.Add(KeyValuePair(ep, PublicFile f))
            [("/", "/Views/index.html");
             ("/account/login", "/Views/Account/login.html");
             ("/account/create", "/Views/Account/create.html")] |> List.iter pf

Overall I really like the F# syntax for setting these sorts of things up over C#. I think it maps cleanly and, at least to me, seems a lot lighter. The only portion that I can't seem to make more F#-ish is the StructureMap setup. If anybody has some tips, I'd love to hear them! I'd love something like:

open Simple.Web.StructureMap
type StructureMapStartup() =
    inherit StructureMapStartupBase()
    override __.Configure(config) =
        let register<'a, 'b>() = config.For<'a>().Use<'b>() |> ignore
        register()

Much Thanks

Much thanks must be given to Mark Rendle and his awesome design of Simple.Web. It has made web programming fun, again.

Friday, December 27, 2013

Simple.Web F# Project Template - Part 2

Much thanks to Daniel Mohl for his help in creating this project template. After some cleanup, the issues I ran into were cleared up and I was able to produce a functioning template.

After receiving Daniel's feedback (all in my Twitter feed), this was pretty easy:

  • Install Template Builder 1.0.3.22-beta or higher;
  • Change the Is-TemplateSubFolder value to "Simple.Web";
  • Make the Repository Id in the VSTemplate file match the Product Id in the manifest file;
  • Remove references to Packages.config from the fsproj and vstemplate files;
  • Make all nupkg files have a build action of "Content", and set "Include in VSIX" to true;
  • Set "ReplaceParameters" to "true" in the VSTemplate file for AssemblyInfo.fs.

So, here it is, my first Visual Studio extension, and project template: Simple.Web F#. Please let me know what you think or if you have any issues.

Tuesday, December 24, 2013

Simple.Web F# Project Template - Part 1

After working with the new ASP.NET F# community template with Simple.Web and some chatter on Twitter, I decided to put attempt to put together a Simple.Web F# project template. I wanted to write out the steps I took to get started to see if anybody can point out what I might be doing wrong or how I could probably do it better.

Since the community templates are based on SideWaffle, I started with a video made by Sayed Hashimi on how to create a SideWaffle project:

Based on the video, I created a new project based on the F# Web API project, removed almost all the NuGet packages, and added all of the Simple.Web packages needed for a new site. Next, I forked the GitHub repository, cloned it, and copied the Mvc5 folder into a new Simple.Web folder. I had to delete most of the stuff in the new solution that I copied over and added the extracted template items. (See the video.)

Finally, I cleaned up the project to ensure the right license was included, etc., and wound up at this state. (Update: and like an idiot, I deleted the branch in that link. The changes can still be seen, though, in the repo.) Unfortunately, after building the new solution and installing the VSIX (again, see the video), I can't see the new template in the File->New Project dialog box.

Any ideas? (Pull requests are welcomed!)

Update

With the help of Daniel Mohl, I was able to get this taken care of. Here's part 2.

Friday, December 20, 2013

Pure F# ASP.NET Web Applications and Simple.Web

So, there has been some awesome work done by Daniel Mohl on a pure F# project for ASP.NET. Unfortunately, I have been spoiled by Simple.Web and wondered if I could make the project work with it. It was not as hard as I thought it would be, at all. Fortunately, Mark Rendle and company have given us the Simple.Web.AspNet NuGet package which makes this trivial.

The biggest hurdle of it all is the NuGet package adds a C# file called OwinAppSetup.cs which sets up the OWIN bindings, on top of which Simple.Web runs. It is a really simple file, actually:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Simple.Web;

namespace FsWebApp
{
    using UseAction = Action<Func<IDictionary<string, object>, Func<IDictionary<string, object>, Task>, Task>>;

    public class OwinAppSetup
    {
        public static void Setup(UseAction use)
        {
            use(Application.Run);
        }
    }
}

Converting this to F# was fairly straight forward and is easily replaced with:

module OwinAppSetup

open System
open System.Collections.Generic
open System.Threading.Tasks
open Simple.Web

type UseAction = Action<Func<IDictionary<string, obj>, Func<IDictionary<string, obj>, Task>, Task>>

type OwinAppSetup() =
    static member Setup(useMethod:UseAction) =
        let run x y = Application.Run(x, y)
        run |> useMethod.Invoke

It is pretty much like the original version except that F#'s type system doesn't let us pass the run method into the UseMethod directly and call it like a method. Instead you have to manually call the Invoke method. (Easy stuff.) Other than deleting a few of the folders from the project template like the Models folder, everything runs perfectly. I also removed a few of the MVC/Web API specific assemblies from the project but that was all that was needed to get going.

Update

There is now some semblance of a Simple.Web F# project template available.