Friday, January 28, 2011

WebSharper Sitelets Cont’d: Developing a Blog Service

The previous article might have left you with an erroneous impression that WebSharper sitelets only support a static set of URLs. This is not the case. In fact, the user-defined Action type can be an arbitrary data structure that maps to a URL. This comes particularly handy when designing a blogging website, since the set of blogs and their URLs is not statically bounded. Something like this would do:

Now you would need to write a router, which is roughly a bijection between Action values and URLs. A boring way to do so might look like this:

Writing routers by hand you get full control – you can inspect an Http.Request value when routing, and generate any URL when linking. However writing the above code is not much fun. If you do not particularly care for the exact URLs, there is a much shorter way to get there:

The Infer function inspects the Action type by reflection to derive a router automatically. It is smart enough to handle records, unions, most scalar types, lists, and options. In our case it derives the following mapping:

A smart thing to do would be to alter it just a little bit, for example by making ShowRecentBlogs available at the root. This can be done by combining a simple table router with the inferred router:

This is much better: 80% of the benefit with 20% of the work.

Now that URL routing is out of the way, you can finally get down to the blog service itself. I present the most interesting thing first, the controller:

The controller simply handles actions (Action values) and returns responses (Content values), no surprises here. Together with a router, the controller forms a sitelet, a self-contained website ready to go by itself or be embedded in a bigger application:

For the model in this example, you can use the simplest thing that can possibly work in a development environment, namely a static mutable variable (see the listing at the end of the article). Now, views are quite straightforward as well. The only thing of interest is the use of WebSharper Formlets (client-side form combinators) to build the UI for editing and creating the blogs. I build a simple control that renders the form and talks to the model directly over RPC, redirecting to the homepage when done:

Time to try it out:

And here is the complete code listing:

Friday, January 21, 2011

WebSharper sitelets: building a two-page website

Let me show the simplest possible self-contained example involving WebSharper sitelets that are coming with the 2.1 release. You define a website with two pages (and two actions):

Let us quickly mash up a template for the website using F#-embedded HTML combinators. A template is just a function taking the body and decorating it:

Two things to notice:

  1. F# lets you define your own syntax, and the example makes liberal use of that (=>).
  2. Instead of generating URLs by hand, you ask the context to create a link to the action. This ensures safety: renaming Home action makes the project stop compiling, and moving it to a different URL keeps the links correct.

Now, you define the sitelets:

HomePage and AboutUsPage are single-page sitelets, with a single URL and a single Action. They are combined into a website by the Sum operator.

Now, a little bit of administrative boilerplate:

And you are done! Let’s browse:

s2 s1

So far so good. The pages have the expected URLs and the menu links work.

The above could have been accomplished by any reasonable web framework. Let us push the limit and spice it up a bit now. Let us add a few lines of F# that will actually compile to JavaScript:

So there is a button that changes its title when clicked. AND there is a control. Now, this while the Button lives on the client-side completely (constructs DOM nodes, in fact), the Control executes a quantum leap: the constructor executes on the server, and the body on the client. But that means you can use the Control to glue the server and the client together. Let us update the AboutUs page:

That’s it. The user will now see a clickable, JavaScript-enabled, F#-implemented button, right where you expect it. No script tags to worry about, no dependency chasing, no “ondocumentready” worries, it just works:

s2

Below is the complete listing. As soon as the 2.1 release becomes public, you will able to enjoy running it yourself. Stay tuned!

Thursday, January 20, 2011

Can WebSharper beat ASP.NET MVC at the routing game?

At work we have been having a lot of fun designing WebSharper sitelets lately. A quick recap: WebSharper is our web development framework that is all about cross-compiling F# to neatly interoperating client-side JavaScript and server-side .NET assemblies - a GWT of sorts. Sitelets are the recently introduced server-side abstraction, the new kid on the block where the bully is of course the notorious ASP.NET MVC.

ASP.NET MVC operation is all about controllers and actions: a request comes in, is matched to a controller/action, and then gets handled. At first glance it appears that controllers are classes and actions are methods. But NO! By introducing something they consider an improvement, the MVC team decoupled actions from methods and insists now that both controllers and actions are strings:

http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx

If you now want to construct a link to a particular action in a view, you have to know it by its string name. And what if it changes? Bummer, the project compiles fine and then fails at runtime.

This is particularly sad given that they used to offer a safer way:

http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx 

While ASP.NET MVC fans wait for this feature to come back, we can do better with F#. The basic idea is that we model everything first-class: an action is just a value of a user-defined Action data type, and a controller is a value as well. Consider:

Now, a controller is simply a function of type Action –> Response. And a website? A website, or a sitelet, as we call it in WebSharper, is a controller coupled with a router, where a router is a bijection from locations to actions.

While the controller is fun to write, the router is not. One tedious way to write it is to write two F# functions, one pattern-matching a location and returning an Action, and the other doing the reverse. For actions that can be listed in a finite list, a less tedious is to write a table with a 1:1 correspondence between locations and actions. But the easiest is to automate it all:

This little function will automatically infer locations such as “/HomePage”, “/AboutUs”, “/Blog/123”... All the tedious work done, time to write the controller!

And how about safe links in the view? Nothing is easier:

And if anything happens to change, F# compiler will make sure the links are still correct.

Sitelets offer a lot more than this, such as easy embedding of F#-defined client-side (JavaScript) controls or the pre-generation of the static part of the web application as a set of HTML and resource files. But none of it can beat the fun of designing routing the functional way.