Sunday, March 24, 2013

Simple.Web and F#

I have become increasingly more interested in F# and hope, someday, to transition over from C# to F# in my day-to-day work. (More on that later.)

I have also become increasingly more interested in Simple.Web by Mark Rendle and hope, someday, to transition over from ASP.NET MVC to Simple.Web in my day-to-day work. (More on that later, as well.)

Given both my fondness of F# and Simple.Web, I decided to try to marry the two. I created the normal ASP.NET Empty Project and added the Simple.Web.Aspnet NuGet package along with the Simple.Web.Razor NuGet package. Then I created a handlers project (F# Class Library), referenced it from the first project, and added the same NuGet package. I created a simple handler for the site's index in the first project.

namespace SimpleTest.Web

open Simple.Web

[<UriTemplate("/")>]
type Class1() =
    interface IGet with
        member this.Get() = Status.OK

I also added a Razor page to handle my get request and then hit F5 to fire it up. Since it was so simple, I was expecting to see my fake homepage and see my little test succeed. Wrong.

Instead, I am greeted with a yellow screen of death telling me "Object reference not set to an instance of an object." Hmmm...

I created the same class in C# and everything worked fine. I was beginning to wonder if this was going to work out at all. Well, after some fiddling, I got it to work. Why it works, I am not really sure about. (I'm far from completely comfortable in F#, let alone an expert.) All I had to do was add a member function that mirrored my interface version of Get().

namespace SimpleTest.Web

open Simple.Web

[<UriTemplate("/")>]
type Class1() =
    member this.Get() = Status.OK

    interface IGet with
        member this.Get() = Status.OK

Of course that means I can just return the result of the member function from the interface implementation. But, that got me to thinking. I decided, in the interface implementation, to throw a NotImplementedException:

namespace SimpleTest.Web

open System
open Simple.Web

[<UriTemplate("/")>]
type Class1() =
    member this.Get() = Status.OK

    interface IGet with
        member this.Get() = raise(new NotImplementedException())

To my amusement, it still loaded my page. I understand that to access an interface-defined method in F# you have to explicitly cast the instance to the interface you're targeting. I just did not know that applied across the language boundaries as well when doing whatever magic Simple.Web is doing to find the applicable method.

Time to hunt that down next.

No comments:

Post a Comment