By Adam Granicz on Friday, April 17, 2015 — 0 comments

CloudSharper 0.9.30 with WebSharper 3 templates Core team

To match yesterdays's official WebSharper 3 release, we are following up with a CloudSharper update, version 0.9.30. Most importantly, this release comes with updated WebSharper 3 project templates and the new UI.Next project template to make it easy to try out WebSharper 3 online.

Other changes and enhancements in this release are:

  • #601: Trigger auto completion on more key presses
  • #604: Add command for opening a file in Document/Split view
  • #602: Load blog entries with ajax for faster display of dashboard
  • #609: Interactive WebSharper compilation fails to reference assembly that is referenced but not loaded

Next, we will be adding various WebSharper 3 sample applications (highlighting WinJS, PhoneJS, TODOMvc, and various other more complex applications) on the CloudSharper website, along with a comprehensive site update as part of our efforts to ramp up to the upcoming 1.0 release, so keep an eye on the site and on this blog.

Happy coding!

By András Jankó on Thursday, April 16, 2015 — 1 comment

WebSharper 3.0 released Core team

Finally!

Changes since the last release candidate

  • Added DateTimeFormatAttribute for specifying date formatting for JSON REST APIs. See documentation

  • Macro and code generation API have been simplified. See documentation.

  • Content.Redirect has been renamed to Content.RedirectPermanent.

  • Improved source mapping. Now source map files contain the original sources, no separate hosting is necessary. See documentation.

  • Some proxy revisions for performance.

  • Improved TypeScript declaration ouput, but it is still considered an experimental feature. See documentation.

Bug fixes

  • #374: WebSharper.JavaScript.X now throws a ClientSideOnly exception when called from .NET code.

  • #375: FuncWithArgs constructor fails when called with a function that does not take a tuple. (If you want to create a JavaScript function that takes a variable number of arguments, use the FuncWithRest type.)

  • #376: Exception "This stream does not support seek operations" in OWIN project.

  • #378: Added basic CSSOM features to Dom.Element.

  • #379: Union types containing records get translated to the wrong representation when returned from RPC.

  • #381: Html projects do not output source maps or TypeScript declaration.

Happy coding!

By Adam Granicz on Saturday, March 28, 2015 — 0 comments

WebSharper forum enhancements Core team

In recent weeks we had been busy with a series of enhancements to the WebSharper website and some underlying FPish services.

These include, among others:

  1. Editing and marking-as-answer for forum entries. We took this opportunity to catch up on markdown support and use that as the main input format instead of the custom FPish markup (which has been obsoleted since then), and pushed that change through displaying on FPish properly as well. Editing directly on the WebSharper website makes it more convenient to respond to forum entries or tidying up your past comments if necessary.

    Editing and marking-as-answer on forum entries

    These features are enabled for your own content only. We at times edit/enhance forum topics and their comments by hand, as well. We ask that you submit content 1) without typos, 2) format your code blocks appropriately (setting the language on blocks and quoting identifiers inlined in paragraphs), and 3) use proper markdown for bullet or numbered lists and other elements. If unsure, consult the markdown reference by clicking the Help button in the editor.

  2. Feeding Github tickets into the forums. This makes it easier to track tickets and shows what's happening in the main repository. The underlying machinery feeds GitHub updates into FPish topics (hidden from the other content), allowing us to do interesting analytics on this growing content in FPish. You can't comment on these forum entries directly, so just follow the GitHub icon to the original ticket.

    GitHub issues are now fed into the WebSharper forums

    We are planning to integrate GitHub tickets from extension repositories as well in the near future, starting with UI.Next and the other open source extensions.

  3. Fixing authentication with FPish, so it doesn't expire after a minute. You may have noticed an annoying flickering of the Login menu and the posting controls earlier when commenting or adding new forum topics on the WebSharper website. This turned out was due to a bug in how FPish handled Oauth sessions and is now fixed. To circumvent the issue earlier, we had to code the interaction controls with a timer to renew authentication tokens with FPish every minute, causing a short visual flickering. This is now fixed.

More work is underway. In particular, we are streamlining how commenting works and doing a facelift to the forums in the next round of releases. This is in preparation of rolling out a support surface for WebSharper support customers where they can file tickets and track progress of various items more easily, etc. This has traditionally lived on FPish, but is now being reimplemented and moved to the WebSharper website to provide a more consistent and streamlined experience.

Overall, we hope you will find the new forums better, and will take the time to use it to find answers to your WebSharper and related questions. Happy coding!

By Loïc Denuzière on Wednesday, March 18, 2015 — 0 comments

WebSharper 3.0 RC released Core team

Today we just pushed out our release candidate for WebSharper 3.0. This means that WebSharper 3.0 is now in feature freeze, and we will only be releasing bug fixes until the stable release of WebSharper. So if you were holding out on switching to 3.0 because of continuous breaking changes, now is the time to try it out!

WebSharper 3.0-rc1 is available for download right now.

We also made large enhancements to the online documentation; check out the sections on Sitelets, HTML combinators, WIG and UI.Next. More will be coming until the stable release.

Change log

Here is the list of changes:

  • Homogenize WebSharper.Html.Client, WebSharper.Html.Server and WebSharper.UI.Next.Html: the HTML combinators are now generated from a list of standard HTML tag names and attributes, to ensure consistency between the client and server libraries.

  • #337: Exception when building WebSharper itself in debug mode.

  • Html.Client:
    • Mouse and keyboard events have an Event field to access the underlying Dom.Event.
    • Add OnEvent to bind a custom event by name.

  • UI.Next:
    • Doc now implements WebSharper.Web.IControlBody. This means that it can be used directly as the Body of a Web.Control:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      type MyControl() =
          inherit Web.Control()
      
          [<JavaScript>]
          override this.Body =
              let rvText = Var.Create ""
              Doc.Concat [
                  Doc.Input rvText
                  Label [] [Doc.TextView rvText.View]
              ]
              :> _
  • JQuery:
    • Make the types of .on(), .off() and .one() more consistent with other event handlers such as .click(), passing the element and the event to the callback and returning the JQuery:

      1
      2
      3
      4
      
      JQuery.Of("#my-input")
          .On("paste", fun el ev ->
              JS.Alert ("Text pasted, value is now: " + JQuery.Of(el).Val()))
          .Ignore
    • Add Event.AsDomEvent.
    • Fix JQuery.GetJSON inline.

  • WebSharper.JavaScript:
    • More accurate Dom.Event class hierarchy.
    • #206: Add JS.Prompt().
    • #356: Move |>! from WebSharper.JavaScript to WebSharper, as it can be useful in some server-side scenarios.

  • Sitelets:
    • #327: Allow using all standard integer, float and decimal types in Sitelet.Infer.
    • #355: Fix Sitelet.Embed deadlock.
    • #357: In JSON deserialization, null can be used to represent None.
    • #363: Fix Template.LoadFrequency.WhenChanged.

  • Remoting:
    • #361: Show a warning when using a synchronous [<Rpc>] function.
    • #362: Throw an error when an [<Rpc>] function has a generic type.

  • WIG:
    • Removed access modifiers, as only public makes sense in a WIG definition anyway.
    • Deprecated Type.New(). It was mainly used for two purposes:
      • Self-reference: you can use TSelf instead.
      • Mutually recursive types: the recommended way is to name classes first and add members later:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        
        let Chicken' = Class "Chicken"
        let Egg =
            Class "Egg"
            |+> Instance [
                "hatch" => T<unit> ^-> Chicken'
            ]
        let Chicken =
            Chicken'
            |+> Instance [
                "lay" => T<unit> ^-> Egg
            ]
    • Added Pattern.RequiredFields, Pattern.OptionalFields and Pattern.ObsoleteFields to create configuration objects in a more compositional way:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      
      // Existing Pattern.Config:
      let MyConfig : Class =		     
          Pattern.Config "classname" {
              Required =        
              [		
                  "name", T<string>	
              ]
              Optional = 
              [		
                  "width", T<int>	
                  "height", T<int>	
              ]
          }
          
      // New API:
      let MyConfig : Class =
          Class "classname"
          |+> Pattern.RequiredFields [
              "name", T<string>
          ]
          |+> Pattern.OptionalFields [
              "width", T<int>
              "height", T<int>
          ]

Future plans

This release candidate means that the 3.0 stable will be coming soon. In fact, unless a big issue holds us up, we will be releasing WebSharper 3.0 as early as next week.

After that, here is a peek at what you can expect from future releases:

  • TypeScript declarations: we will be stabilizing the support for outputting .d.ts declarations for generated JavaScript modules, which was an experimental feature so far.
  • F# 4.0 support: as soon as F# 4.0 is finalized, we will provide proxies for the extended standard library.
  • Source mapping: we will improve the support for source maps, in particular reduce the need for many-to-many mapping which several browsers have trouble with.

Happy coding!

By Loïc Denuzière on Monday, March 2, 2015 — 0 comments

CloudSharper 0.9.29 released Core team

Here comes a new release of CloudSharper, with a bunch of bug fixes as well as the first steps of a big UI enhancement. We are updating CloudSharper to a clearer, slicker and more modern flat visual style.

In this first installment, the startup screen and the dashboard have been completely redesigned, and dialog windows are also restyled.

Other improvements

  • Autocomplete for F# now filters members.
  • WebSharper has been updated to 3.0.36-alpha, together with the online documentation.

Fixes

  • #594: Autocomplete should not trigger if there is no identifier before .
  • #595: An exception is raised when creating a new file
  • #596: FSI input uses UTF8 encoding now

Happy coding!

By Loïc Denuzière on Wednesday, February 25, 2015 — 3 comments

WebSharper 3.0-alpha for Xamarin Studio / MonoDevelop is now available! Core team

We have updated the WebSharper Xamarin Studio / MonoDevelop add-in for the latest WebSharper 3.0.36-alpha. It is now easier than ever to get started with WebSharper 3.0 on Mac or Linux!

Here is how to install it:

  • Open the add-in manager.

  • Make sure that you have the F# Language Binding installed.

  • In the Gallery, add a new repository with the following address:

    https://raw.githubusercontent.com/intellifactory/monodevelop.websharper/master/repository/

  • The WebSharper add-in is now available under the "Web Development" category. Select it and click "Install".

Voilà! The "New Project" and "New Solution" dialogs now have a new category for WebSharper. In this category you can find the same templates that are provided by the Visual Studio extension and CloudSharper, to quickly start new projects using WebSharper.

You can check the sources for the addin here.

Happy coding!

By András Jankó on Wednesday, February 25, 2015 — 3 comments

WebSharper-3.0.36-alpha released Core team

This release brings the last batch of breaking changes we have planned before 3.0 stable. The three bigger items we have left are updating/fixing TypeScript output, reviewing code mapping and adding more documentation.

Namespace changes

We have shortened namespace names by changing every occurence of IntelliFactory.WebSharper to WebSharper. This affects base package and all extensions. Also IntelliFactory.JavaScript is renamed to WebSharper.Core.JavaScript. DLLs are similarly renamed with the exception of IntelliFactory.WebSharper.dll which is now WebSharper.Main.dll.

WebSharper.Formlets in a separate package

The Formlets library is now contained in the NuGet package WebSharper.Formlets. Its dependency, IntelliFactory.Reactive is in another new package IntelliFactory.Reactive.

JSON Sitelets

You can now create REST APIs easily by using F# types. See previous announcement.

User Session in Sitelets and Rpc functions

Up until now, the module WebSharper.Sitelets.UserSession could be used to manage user login. Unfortunately, functions in this module have two major drawbacks:

  • They use ASP.NET-specific functionality, and therefore cannot be used with other hosts such as self-hosted OWIN.
  • They assume that they run on the same thread that is responding to the request. This assumption is unreasonable, especially when using functions such as Content.PageContentAsync.

For these reasons, the following changes are made:

  • The module WebSharper.Sitelets.UserSession is marked as obsolete.
  • The type Sitelets.Context<'T> now contains a field UserSession, which can be safely used in asynchronous sitelets. Note that unlike the old UserSession, its methods are asynchronous.
  • The new function WebSharper.Web.Remoting.GetContext() can be used in Rpc functions to retrieve a thread-safe user session manager. It must be called from the Rpc function's thread, but the resulting object can be used asynchronously. For example:
1
2
3
4
5
6
7
8
9
[<Rpc>]
let DoSomethingIfLoggedIn() =
    let ctx = Web.Remoting.GetContext()
    async {
        let! loggedIn = ctx.UserSession.GetLoggedInUser()
        match loggedIn with
        | None -> return "Error: not logged in"
        | Some username -> return! DoSomething username
    }
  • This functionality is implemented both in the built-in ASP.NET module and in WebSharper.Owin.

JavaScript interop

  • Previous .ToEcma() methods for converting a .NET type to its EcmaScript binding equivalent has been obsoleted. Renamed to .JS property.
  • Previous .ToDotNet() methods are now a .Self property on WebShaper.JavaScript. types.
  • JavaScript.Function is now a base class for all JavaScript.FuncWith... types (giving strong typing to JavaScript functions).
  • Methods on JavaScript.Function has been renamed to ApplyUnsafe, CallUnsafe, BindUnsafe to avoid overloading with the strongly-typed methods on descendant classes.

WebSharper Interface Generator

  • The generic helper for more than 4 type parameter is now GenericN n - fun typeParamList -> ...
  • Generic % can be used to add the same type parameters to a list of members.
  • Generic * can be used to add the same type parameters to a to a ClassMembers value (created by Instance [...] or Static [...]).
  • These generic helpers all add type parameters in addition to previously defined ones on the members returned by the inner function, instead of overwriting the generics list.
  • Type parameters are automatically renamed on library generation to avoid name clashes.

Other improvements

  • A compile warning is given when a tupled or curried lambda or variable with the same types are coerced to obj. This can help avoiding some mistakes, for example writing

    1
    
    New [ "compare" => fun (a, b) -> a - b ] 

    and passing it to JavaScript code expecting a function that takes two arguments. However, this is translated to a JavaScript function taking a single 2-element array argument. The former is the much more common scenario, so on this warning, change it to

    1
    
    New [ "compare" => FuncWithArgs(fun (a, b) -> a - b) ] 

    to pass the right function. Otherwise, you can use the Function.As static method to wrap the lambda and and get rid of the warning.

  • [<OptionalField>] attribute now can be used on class or record types. This makes all option valued fields of the type represented as present/missing JavaScript properties in the translation.

Fixes

  • #340: Generic methods of a generic type used wrong type parameters for generating the member. This could have affected some of our extensions.
By András Jankó on Wednesday, February 18, 2015 — 0 comments

CloudSharper 0.9.28 released Core team

This release fixes some issues introduced in last release, and improves tooltips and autocomplete.

Fixes

  • #588: Pressing Tab/Shift-Tab with a single cursor works now as in Visual Studio.
  • #589: Pressing . for autocomplete fixed, also works for (.
  • #587: Autocomplete works for .fsx files.
  • #591: Save in File menu and Ctrl+S fixed.

Happy coding!

By Loïc Denuzière on Friday, February 13, 2015 — 5 comments

Upcoming in WebSharper 3.0: serving REST APIs, easy as pie! Core team

WebSharper Sitelets are a wonderful way to build websites quickly and safely. They can automatically manage your URLs in a type-safe way, and generate HTML markup using simple F# combinators. In WebSharper 3.0, we are extending Sitelets with the capability to create REST APIs with unrivaled simplicity.

Requests

Just like you can currently type these lines in F#:

1
2
3
type Action =
	| [<CompiledName "listing">] Listing of pagenum: int
    | [<CompiledName "article">] Article of id: int * slug: string

to tell WebSharper that your site will be served on these URLs:

1
2
/listing/1
/article/135/upcoming-in-websharper-30

You can now also specify all the information necessary to serve a web API on a given HTTP method and with the given JSON body, simply by using a couple attributes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Action =
	| [<Method "GET"; CompiledName "article">]
    	GetArticle of id: int
    | [<Method "POST"; CompiledName "article"; Json "data">]
    	PostArticle of data: ArticleData

and ArticleData =
	{
    	author: string
        title: string
        tags: Set<string>
        summary: option<string>
        body: string
    }

The following requests are now accepted:

1
GET /article/135

1
2
3
4
5
6
7
8
9
POST /article

{
  "author": "loic.denuziere",
  "title": "Upcoming in WebSharper 3.0: serving REST APIs, easy as pie!",
  "tags": ["websharper", "fsharp"],
  "summary": "WebSharper 3.0 is coming with an (...)",
  "body": "WebSharper Sitelets are a wonderful way to (...)"
}

The JSON serialization provides all the niceties possible to be friendly with F# types:

  • F# records are represented as JSON objects;
  • list<'T>, 'T[] and Set<'T> are representad as JSON arrays;
  • Map<string, 'T> is represented as a flat JSON object;
  • F# fields of type option<'T> are represented as a JSON field that is present if Some or absent if None;
  • F# unions are represented as JSON objects using the union field names, and a separate named field to indicate the union case (the name of this field is specified in an attribute).

Responses

Of course, a REST API is not just parsing requests, but also writing responses. For this too, WebSharper 3.0 has you covered. A new function Content.JsonContent allows you to serve any F# value as JSON with zero hassle:

1
2
3
4
5
6
7
let mySite = Sitelet.Infer <| function
	| GetArticle id ->
    	Content.JsonContent <| fun ctx ->
        	{ author = "loic.denuziere"; (* ... *) }
    | PostArticle articleData ->
    	Content.JsonContent <| fun ctx ->
        	SaveArticle articleData

Want to see a full example? How about a full CRUD API serving an in-memory database of people information, with all interactions perfectly type-safe, in less than fifty lines?

Look for this new WebSharper 3.0 pre-release on NuGet early next week, or build it right now from source!

By Loïc Denuzière on Wednesday, February 11, 2015 — 0 comments

CloudSharper 0.9.27 released Core team

Here comes another release of CloudSharper! Version 0.9.27 comes with a number of enhancements:

  • It is now possible to write RPC functions in F# interactive. When you call an [<Rpc>]-annotated function from the client side, the arguments are serialized and sent through the WebSocket used by F# Interactive, passed to the function, and the response is sent back the same way.
    Here is an example where two separate widgets share a common server-side state:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    let serverSideCounter = ref 0
    
    [<Rpc>]
    let increment() =
        serverSideCounter := !serverSideCounter + 1
    
    [<Rpc>]
    let get() =
        async { return !serverSideCounter }
    
    let x =
        <@ Button [Text "Increment"]
            |>! OnClick (fun _ _ -> increment()) @>
    
    let y =
        <@ Button [Text "Get the current value"]
            |>! OnClick (fun button _ ->
                async {
                    let! value = get()
                    button.Text <- "The value is " + string value
                }
                |> Async.Start) @>
  • The first time experience is largely improved. When entering CloudSharper without a local component running, instead of a message that could easily be mistaken for an error, CloudSharper now displays a friendly screen with install instructions.
  • The project templates are updated to the latest WebSharper (3.0.26-alpha).

We are now planning a major rework of the dashboard screen which will contain a lot of cool new features, including GitHub integration and statistics about your workspaces. We can't wait to have them ready for you to enjoy!

Happy coding!