F# mobile development with WebSharper

Developing mobile applications is a tricky business; having the right orientation and technical foundation to start makes all the difference. Given the multitude of technology alternatives, mobile developers are increasingly realizing it is no longer feasible to specialize in one given platform. Traditional, native platforms (iOS, Android, Windows Phone 7, Windows Mobile, etc.) are unnecessarily complex and are pinned to a software stack that requires a steep learning curve and many tricks to work around their inherent ties to their non-web foundation. If developing for native platforms weren’t enough of a drive-away force, their tightly controlled application deployment and sales channels make things even worse.

Luckily, there are at least two main ways out of the native platform trap. One way is using more familiar programming languages and development environments and translating to native code (typically done for iOS development, with solutions like MonoTouch). To some degree, this relies on learning similarly complex APIs and having to deal with the quirks of fitting the native device capabilities over those APIs to perform the mapping correctly.

Another way out is web-based mobile applications. They eliminate the need for platform-specific technologies with their crippled development environments, and put your applications on a foundation based on common web standards such as HTML5, CSS3 and JavaScript, greatly simplifying cross-platform expansion. One thing we have learned from the web is it can’t and shouldn’t be contained: the capabilities and services in it must be consumable from whatever device you are using. You can expect future mobile platform versions and operating systems will further blur the traditional boundary between “native” and “web” applications.

Currently, developing cross-platform web-based mobile applications with solutions like PhoneGap, Rhomobile, or AppMobi relies on exposing native device functionality through JavaScript APIs and rendering your web applications written against those APIs through a native shell application. This should sound like an attractive proposition, but demands you develop your applications in JavaScript. DSL-based alternatives and a good discussion are available in the state of the art in mobile web application development article on InfoQ.

WebSharper

WebSharper aims to solve several of the above problems. First, it enables you to develop your entire web or mobile application in F# enjoying its concise syntax and powerful functional constructs, cutting most of the code you have been used to writing. Second, it gives you a rich set of abstractions and eDSL syntax for common web-related chores, such as composing HTML, defining web forms, managing required resources, handling URLs safely, and many others. What makes it especially well-suited to larger, enterprise-grade application development is these abstractions are strongly typed: for instance, constructing web forms yielding data values of the wrong type, or trying to add form validation to the wrong input control will yield compile-time errors, again greatly reducing development time.

Sitelets – composing websites

WebSharper 2.0 introduced sitelets, implementing type-safe, first-class website values. A sitelet is defined over a union “action” type that encompasses all pages/content in the site it represents, and contains a router and a controller to map URL requests back and forth between actions and actual content.

(Click on the image to enlarge it)

Figure 1: Sample website from the WebSharper Visual Studio template

Here is a simple Action type, taken from the sample sitelet application template, which comes with your WebSharper installer, defining the small sample website in Figure 1:

/// Actions that correspond to the different pages in the site.type Action =
| Home
| Contact
| Protected
| Login of option<Action>
| Logout
| Echo of string

Content can be arbitrary, you can return any file, or XML or HTML content, depending on what purpose your sitelet serves, such as RESTful services. You can manually construct your router and controller if you need fine-grained control over your URL space, or have them inferred automatically from your action type, or both by combining smaller sitelets using either strategy.

Sitelets also come with a type-safe templating language based on XML markup with special placeholders. These files (ending with .template.xml) are automatically converted to F# code and included in your build when you add them to your WebSharper Visual Studio solution.

Consider the following template markup in Skin.template.xml, again from the sample sitelet application template:

This creates a Templates.Skin module in the default namespace, available for composing markup snippets into the placeholders. Consider the following function that takes the title and the main content of a page and constructs a page value using the generated template function:

Here, main is a function yielding a list of XML/HTML elements, similar to the menu computed in the inner menu function. Also, note how the context object can map the various Action shapes to safe URLs (the pipe |> operator is used to send an argument to a function, e.g. x |> f is equivalent to f(x)).

You can define all kinds of tiny abstractions to make your application code more concise. Here is a link operator (=>) to create a hyperlink:

With the above sitelet, all you need is to annotate it as a sitelet and, voila, your site can be served from an ASP.NET-based web container (you get the necessary Web.Config changes in the WebSharper Visual Studio template):

/// Expose the main sitelet so it can be served./// This needs an IWebsite type and an assembly level annotation.type SampleWebsite() =
interface IWebsite<SampleSite.Action> withmember this.Sitelet = EntireSite
member this.Actions = []

[<assembly: WebsiteAttribute(typeof<SampleWebsite>)>]do ()

Formlets – composing first-class type-safe forms

Formlets, a recent formalism from academia, have been an integral part of WebSharper, one of the first frameworks to implement them. Formlets represent first-class, type-safe, composable data forms, much different from the less strictly-typed approaches you may have been using with ASP.NET or other web frameworks. The WebSharper implementation also includes dependent formlets, where one part of the formlet depends on another such as on a dropdown box with multiple options or values entered in an input box; and flowlets, a custom layout that renders each formlet step in a formlet computation expression, a monadic construct in F#, in a wizard-like sequence.

Here is a simple input formlet returning a string value with various enhancements applied incrementally:

Formlets can be mapped to return values of any type, for instance a percentage input control might return float values between 0 and 100, or a combo box might yield one of the shapes of a discriminated union (with or without tagged values). You can compose formlets into larger formlets in various ways. The simplest way is using the Formlet.Yield function, which wraps a value of any type into a formlet of that type, in combination with the <*> operator that composes two (or via subsequent calls multiple) formlets:

The result when embedded in a sitelet page is in Figure 2. Note the styling is provided by a dependent CSS resource automatically added to your page when you reference formlet code (actually, when you call Enhance.WithFormContainer). WebSharper’s sophisticated dependency tracking collects dependent resources for a given page automatically as they are served. This is very convenient and saves a great deal of time and effort when using various WebSharper extensions to third-party JavaScript libraries, essentially eliminating the need to manually track what needs to be included in a page.

Figure 2: A simple formlet with validation and various enhancements

The [<JavaScript>] annotation in the above formlet example directs WebSharper to translate this code block to JavaScript. The validators each control is enhanced with are part of the WebSharper formlet library and they provide client-side validation, so Validator.IsEmail will make sure only valid email addresses are entered before the formlet reaches an accepting state. You can also make calls to your own user-defined functions, or provide additional validation by further enhancing the formlet at hand. If a function is annotated with [<Rpc>] and is called from client-side code, WebSharper outputs code to perform an RPC call and handles the passing of values between the client and the server side automatically. You can work with arbitrarily complex F# values, such as nested lists, maps, sets, or sequences seamlessly without having to worry about how they are mapped. This makes programming client and server-side code uniform and greatly reduces development time. In fact, you typically develop client and server code in the same F# file, organized into different modules under the same namespace.

You can use a number of WebSharper patterns for developing client-server applications, we usually recommend working with sitelets and formlets and give various coding guidelines for maximizing your efficiency, but you may develop hybrid applications as well with a significant ASP.NET code base, or enhance your existing ASP.NET applications with WebSharper-based functionality.

Building form abstractions for your needs

Occasionally, you may need to step outside the boundaries of the standard WebSharper formlet library to implement the forms (or the entire UI) for your application. For instance, you may want to render your formlets using different input controls and simple CSS overrides are no longer sufficient to get the look and feel you desire. Other times, you would like to reuse existing JavaScript control libraries such as Ext JS, YUI, or jQuery UI to give a more elaborate look and feel. WebSharper comes with a large number of extensions to various third-party libraries including these, and some extensions come with a formlet abstraction as well.

Here is a short example utilizing the Formlets for jQuery Mobile extension, using the Formlet.Do computation expression with a flowlet layout, and the familiar Formlet.Yield composition to weave together a 2-step login sequence:

You can compose this login sequence into HTML markup, using the necessary jQuery Mobile attributes (which you can nicely abstract away with a few more lines of code), that you can then add to your sitelet page:

Once you tune the mobile configuration file in your WebSharper mobile project to produce an Android package (you can also choose Windows Phone 7) and install it on your phone you get what’s depicted in Figure 3.

Figure 3: jQuery Mobile formlets running on Android

Using the WebSharper mobile APIs and third-party map controls

Formlets or sitelets greatly simplify your web and mobile development, and give you robust, type-safe, and composable abstractions to model parts of your application. Another fundamental WebSharper abstraction are pagelets, the building blocks of formlets. Pagelets represent first-class, composable client-side markup and behavior. A WebSharper pagelet is compatible with ASP.NET controls and can be embedded directly into ASP.NET markup as well.

Here is an example of a pagelet that implements a map control depicted in Figure 4:

open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Bing
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.JQuery
open IntelliFactory.WebSharper.Mobile

// Sets the label to be the address of the current location Rest.RequestLocationByPoint(<<your-bingmaps-key>>, loc.Lat, loc.Long, ["Address"],fun result ->let locInfo = result.ResourceSets.[0].Resources.[0] label.Text <- "You are currently at " + JavaScript.Get "name" locInfo)

Figure 4: A Bing Map control and address bar showing your current location

This control uses the WebSharper mobile APIs to get the current GPS location. The IntelliFactory.WebSharper.Mobile namespace contains further utilities to interact with the underlying mobile device, including fetching accelerometer data, accessing the camera capabilities, or displaying native alert messages. Future versions of the WebSharper mobile API will also contain platform-specific extensions such as Bluetooth communication capabilities, etc.

Conclusion

If you haven’t used X-to-JavaScript tools to help you write web and mobile applications, you may wonder why there are so many of them and what makes people want to use them. WebSharper is a robust web development framework for F# and is in active use in a number of enterprise applications. It solves many of the web and mobile development issues you typically encounter and offers among others safe URLs; automatic resource tracking; and type-safe, composable abstractions for client-side markup and functionality; declarative-style web forms with client-side validation; and website values.

The WebSharper 2.3.28+ updates and the subsequent 2.4 release contain Visual Studio templates for mobile web development, and you can quickly try out and experiment with the two examples in this article using those templates. You can also download the sources here and here, including the final Android packages.

About the Author

Adam Granicz is a long-time F# insider and key community member, and the co-author of three F# books, including Expert F# 2.0 with Don Syme, the designer of the language. His company IntelliFactory specializes in consulting on the most demanding F# projects; shaping the future of the development of F# web, mobile and cloud applications; and developing WebSharper, the premiere web development framework for F#. You can reach him at granicz.adam {at} intellifactory.com, follow him on Twitter, or track him on FPish, the functional programming paradise.

Is your profile up-to-date? Please take a moment to review and update.

Email Address

Note: If updating/changing your email, a validation request will be sent

Company name:

Keep current company name

Update Company name to:

Company role:

Keep current company role

Update company role to:

Company size:

Keep current company Size

Update company size to:

Country/Zone:

Keep current country/zone

Update country/zone to:

State/Province/Region:

Keep current state/province/region

Update state/province/region to:

Subscribe to our newsletter?

Subscribe to our industry email notices?

You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.

We notice you're using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.