By Loïc Denuzière on Saturday, May 23, 2015 — 0 comments

WebSharper 3.1 published Core team

It's barely been a month since we released WebSharper 3.0, and we are now at it again with the release of WebSharper 3.1. Without further ado, here are the main highlights.

ASP.NET MVC support

WebSharper has supported including client-side controls in ASPX pages since version 1.0, and running sitelets alongside ASP.NET since version 2.0. With version 3.1 and WebSharper.AspNetMvc, WebSharper now has extended support for running together with ASP.NET MVC in the following scenarios:

  • Including WebSharper client-side controls in pages that use the Razor view engine. Here is an example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    @{
        // Create a web control
        var myControl = WebSharper.AspNetMvc.ScriptManager.Register(new MyWebSharperControl())
    }
    <!DOCTYPE html>
    <html>
      <head>
        <title>Testing WebSharper with ASP.NET MVC!</title>
        <!-- Render the needed css and script tags -->
        @WebSharper.AspNetMvc.ScriptManager.Head()
      </head>
      <body>
        <h1>Here is my control:</h1>
        <!-- Render the control -->
        @myControl
      </body>
    </html>

    Remoting is also supported, you can simply call server-side [<Rpc>]-annotated functions from MyWebSharperControl.

  • Running WebSharper sitelets alongside ASP.NET MVC, serving pages and APIs from both. You can decide which one takes priority when their URL spaces overlap.

See the WebSharper ASP.NET documentation page to learn how to integrate WebSharper.AspNetMvc into an ASP.NET MVC application.

Lightweight syntax to embed client-side elements in sitelets markup

Until now, in order to include client-side generated markup (whether using Html.Client or UI.Next) inside Html.Server markup, you had to create a new class inheriting from Web.Control and override its Body property. There is now a much easier syntax that you can use thanks to the ClientSide function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[<JavaScript>]
module Client =
    open WebSharper.Html.Client

    let myContent text1 text2 = I [Text (text1 + "; " + text2)]

module Server =
    open WebSharper.Html.Server
    
    // Old Web.Control style:

    type MyControl(text1, text2) =
        inherit Web.Control()
        [<JavaScript>]
        override this.Body = Client.myContent text1 text2 :> _
        
    let OldBody =
        let t = "a local variable"
        Div [ new MyControl(t, "a literal") ]

    // New ClientSide style:

    let Body =
        let t = "a local variable"
        Div [ ClientSide <@ Client.myContent t "a literal" @> ]

Unlike the presence of a quotation suggests, this doesn't run any F#-to-JavaScript compilation at runtime. The quotation is only here to allow looking up the fully qualified name of the function you are calling (Client.myContent in the above example) and inlining it in the resulting page, alongside its JSON-serialized arguments.

You can read more about ClientSide in the documentation.

Sitelets routing enhancements

WebSharper 3.1 includes several enhancements to sitelets routing.

Wildcard paths

You can add the [<Wildcard>] attribute to an action union case to make its last argument match the remainder of the path. This argument must be of type list, array, or string.

1
2
3
4
5
6
7
8
type Action =
    | [<Wildcard>] Articles of pageId: int * tags: list<string>
    | [<Wildcard>] Articles2 of tags: string[]
    | [<Wildcard>] GetFile of path: string

// GET /Articles/12/fsharp/websharper   -->   Articles(12, ["fsharp";"websharper"])
// GET /Articles2                       -->   Articles2 [||]
// Get /GetFile/Content/css/main.css    -->   GetFile "Content/css/main.css"

Multiple actions with the same prefix

You can now create an action with several cases that parse the same prefix (ie. have the same [<CompiledName>]) on the same method. They will be tried in the order in which they are declared, until one of them matches. This is very convenient for REST-style URLs where additional information can be added with additional URL fragments.

1
2
3
4
5
6
7
8
type Action =
    | [<Method "GET"; CompiledName "blog">] ListBlogEntries
    | [<Method "GET"; CompiledName "blog">] BlogEntry of id: int
    | [<Method "GET"; CompiledName "blog">] BlogEntryWithSlug of id: int * slug: string

// GET /blog                               -->   ListBlogEntries
// GET /blog/123                           -->   BlogEntry 123
// GET /blog/123/websharper-31-published   -->   BlogEntryWithSlug(12, "websharper-31-published")

Parsing form post data

Web forms using method="post" send their data in the request body with a format determined by enctype (generally either application/x-www-form-urlencoded or multipart/form-data). This data is available in the sitelet context as Request.Post. It is now also possible to directly parse it in the action using [<FormData>]. This attribute is used in a similar way as [<Query>].

1
2
3
4
5
6
7
8
type Action =
    | [<Method "POST"; FormData("firstName","lastName")>]
        Register of firstName: string; lastName: string

// POST /Register
// Content-Type: application/x-www-form-urlencoded
//
// firstName=Loic&lastName=Denuziere                 --> Register("Loic", "Denuziere")

Disposable enumerators

Perviously WebSharper translation didn't dispose enumerator objects used internally in for ... in loops. Also, enumerators created by Seq module functions didn't dispose the wrapped enumerators. These all now follow semantics of their .NET counterparts.

The future

As you can see, we are now committing to a higher turn-around of WebSharper releases. Among enhancements you can expect in the future, we will be adding proxies for the new library functions as soon as F# 4.0 hits the shelves.

We are also preparing a service to try WebSharper F#-to-JavaScript compilation online. You will be able to experiment with F#-based web applications quicker and more easily than ever!

We cannot wait to make this available for you to try. In the meantime, happy coding!

By Loïc Denuzière on Thursday, May 21, 2015 — 0 comments

CloudSharper 0.9.31 published Core team

This release of CloudSharper 0.9.31.0 brings it on par with WebSharper 3.1. CloudSharper itself uses WebSharper 3.1, and the web project templates are also updated to reference WebSharper 3.1.6.

You can of course still use CloudSharper to work on WebSharper 3.0 projects, but we nevertheless recommend that you update your projects to WebSharper 3.1.

Happy coding!

By Adam Granicz on Friday, May 15, 2015 — 1 comment

Deploying WebSharper apps to Azure via GitHub Core team

More and more .NET developers come to appreciate functional programming, and this is really good news for F#. A couple weeks ago Scott Hanselman ran a short article on running Suave.io apps as Azure web apps deployed via GitHub. His setup was the following:

  1. You configure your Azure web app to be sourced from a GitHub repository. This sets up a GitHub hook that notifies Azure on every commit.
  2. Your suave.io app consists of an F# script (site\webserver.fsx) inside an empty ASP.NET project with a web.config.
  3. On a commit, Azure executes a deployment script (deploy.cmd via .deployment) found in your project.
  4. This script uses Paket to restore FAKE and Suave, and uses FAKE to execute an F# script (build.fsx) by passing it to fsi.exe shipped with FAKE.
  5. This FAKE script can optionally execute various build tasks, if necessary, to build a site - in Scott's example it was just used as a placeholder script.
  6. Finally, the web app is copied to the right folder in your Azure web app.
  7. When starting, the app executes a "setup" step, configured as an <httpPlatform> directive. This in turn uses FAKE to execute site\webserver.fsx, which starts Suave.io and listens on a given port that is then mapped to the standard HTTP port.

This sequence is more complicated than it needs to be because it has to work around the lack of the F# tools and core libraries when setting up a new Azure web app deployment. Since Scott's article, I filed a ticket to bundle the F# compiler and tools in a Nuget, and thanks to Don Syme and Steffen Forkmann, that Nuget was out within a couple days.

Armed with that, we quickly put together a similar deployment setup for WebSharper client-server apps (other types of WebSharper apps are equally possible.) This has the obvious advantage that:

  • It uses WebSharper, so you can add client-side (e.g. JavaScript) functionality as well and write it in F#.
  • It produces an ASP.NET app that serves fine in Azure without the need to run a separate server process like Suave.io (although you can also create OWIN-based self-hosted WebSharper applications and run them as in Scott's scenario.)
  • It no longer needs FAKE to compile F# apps or run F# scripts.

Loic blogged the technical details in his WebSharper: From Zero to an Azure-deployed Web Application article, using a WebSharper implementation/clone of the "2048" game. I also put together a simpler template that you can use for client-server applications, and it's available in...

this GitHub repository

The template uses Paket instead of Nuget, and you can build your project with build.cmd (you will need curl installed and on your path). Run build.cmd before opening in Visual Studio as well.

You can also get started quickly by clicking here:

There is a single main.fs file, and it contains both the server and the client functionality:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
namespace MyApplication

open WebSharper
open WebSharper.Sitelets

type Action =
    | [<CompiledName "">] Home
    | [<CompiledName "about">] About

module Server =
    [<Rpc>]
    let DoSomething input =
        let R (s: string) = System.String(List.ofSeq s |> List.rev |> Array.ofList)
        async {
            return R input
        }

[<JavaScript>]
module Client =
    open WebSharper.Html.Client

    let Main () =
        let input = Input [Attr.Value ""]
        let output = H1 []
        Div [
            input
            Button [Text "Send"]
            |>! OnClick (fun _ _ ->
                async {
                    let! data = Server.DoSomething input.Value
                    output.Text <- data
                }
                |> Async.Start
            )
            HR []
            H4 [Class "text-muted"] -- Text "The server responded:"
            Div [Class "jumbotron"] -< [output]
        ]

open WebSharper.Html.Server

module Skin =
    open System.Web

    type Page =
        {
            Title : string
            Menubar : Element list
            Body : Element list
        }

    let MainTemplate =
        Content.Template<Page>("~/Main.html")
            .With("title", fun x -> x.Title)
            .With("menubar", fun x -> x.Menubar)
            .With("body", fun x -> x.Body)

    let Menubar (ctx: Context<Action>) action =
        let ( => ) text act =
            LI [if action = act then yield Class "active"] -< [
                A [HRef (ctx.Link act)] -< [Text text]
            ]
        [
            LI ["Home" => Action.Home]
            LI ["About" => Action.About]
        ]

    let WithTemplate action title body : Content<Action> =
        Content.WithTemplate MainTemplate <| fun ctx ->
            {
                Title = title
                Menubar = Menubar ctx action
                Body = body ctx
            }

module Site =
    module Pages =
        let Home =
            Skin.WithTemplate Action.Home "Home" <| fun ctx ->
                [
                    H1 [Text "Say Hi to Azure"]
                    Div [ClientSide <@ Client.Main() @>]
                ]

        let About =
            Skin.WithTemplate Action.About "About" <| fun ctx ->
                [
                    H1 [Text "About"]
                    P [Text "This is a template WebSharper client-server application
                             that you can easily deploy to Azure from source control."]
                ]

    let Main =
        Sitelet.Infer (function
            | Action.Home -> Pages.Home
            | Action.About -> Pages.About
        )

[<Sealed>]
type Website() =
    interface IWebsite<Action> with
        member this.Sitelet = Site.Main
        member this.Actions = [Action.Home; Action.About]

[<assembly: Website(typeof<Website>)>]
do ()

This uses basic WebSharper templating and a master main.html template and implements a two page sitelet application:

You can run it directly here.

Happy coding!

By Loïc Denuzière on Tuesday, May 12, 2015 — 0 comments

WebSharper: From Zero to an Azure-deployed Web Application Core team

We are often asked what the deployment story is like for WebSharper applications. Our usual reply has long been that WebSharper applications follow standard formats, in particular:

  • Client-Server Web Applications are simply ASP.NET applications, and can be deployed using usual methods such as publishing from Visual Studio or using Azure's git integration;
  • HTML Applications are composed of static files located in $(WebSharperHtmlDirectory) (which is bin/html by default) and can be deployed from there using the method of your choice.
  • Single-Page Applications are also composed of static files, index.html and the Content folder, so the same methods apply.

However there can be some caveats, in particular with regards to running the F# compiler and referencing FSharp.Core.dll in build-and-deploy environments.

Fortunately, the recently released NuGet package FSharp.Compiler.Tools combined with the excellent package manager Paket now provide a nice and streamlined development and deployment experience for git-hosted, Azure-deployed applications.

This article presents the build and deployment setup for a reimplementation of the popular game 2048, available on GitHub. To try it out, simply click the button "Deploy to Azure" and follow the instructions.

The project

This particular project was created as a Single-Page Application; this project type was chosen because the application runs on a single page and is only composed of client-side code. The solution, 2048.sln, contains a single project located at Game2048/Game2048.fsproj.

If you want to recreate this setup, you can create a Single-Page Application from Visual Studio or Xamarin Studio / MonoDevelop with the WebSharper extension installed. This deployment setup will also work if you create a Client-Server Application or an HTML Application instead. For Self-Hosted Client-Server Applications, you will additionally need to set up an HttpPlatformHandler to run the generated executable, similarly to Scott Hanselman's Suave setup.

Paket

For package management, the project uses Paket. It offers many advantages over traditional NuGet, which you can read about here.

Note that paket restore is run in the build script before running MSBuild. Indeed, since we will be importing several .targets files that come from packages, the packages must be restored before running MSBuild or opening the project in an IDE. So for your first build after cloning the 2048 project, you can either run the full build.cmd, or if you only want to restore the packages, you can run:

1
.paket/paket.bootstrapper.exe && .paket/paket.exe restore

If you want to reproduce this setup for your own project as created in the previous section, here are the steps:

  • Remove the WebSharper NuGet package from the project and delete the file <your_project_name>/packages.config if it exists.

  • Download paket.bootstrapper.exe and paket.targets from here into the folder .paket.

  • To ensure that you build with the right package versions after a git pull, add the following to <your_project_name>.fsproj:

    1
    
    <Import Project="..\.paket\paket.targets" />
  • Run the following commands:

    1
    2
    3
    4
    5
    6
    
    # Download paket.exe:
    .paket/bootstrapper.exe
    # Initialize paket.dependencies:
    .paket/paket.exe init
    # Install the WebSharper package into your project:
    .paket/paket.exe add nuget WebSharper project <your_project_name>
  • The files paket.dependencies, paket.lock and <your_project_name>/paket.references must be committed.

The F# Compiler

Since fsc is not available on Azure, we retrieve it from NuGet. We reference the package FSharp.Compiler.Tools which contains the compiler toolchain. By importing tools/Microsoft.FSharp.targets from this package in our project file, we instruct MSBuild to use the F# compiler from the package. This means that even when building locally, fsc from the package will be used. This ensures consistency between local and deployment builds.

If you want to apply this change to your own project, here are the steps:

  • Install the F# compiler package:

    1
    
    .paket/paket.exe add nuget FSharp.Compiler.Tools
  • Use it in your project: in <your_project_name>.fsproj:
    • Remove any references to Microsoft.FSharp.targets and FSharp.Core.dll. In a Visual Studio-created project, this means removing this whole block:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      <!-- F# targets -->
      <Choose>
        <When Condition="'$(VisualStudioVersion)' == '11.0'">
          <PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
            <FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
          </PropertyGroup>
        </When>
        <Otherwise>
          <PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
            <FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
          </PropertyGroup>
        </Otherwise>
      </Choose>
      <Import Project="$(FSharpTargetsPath)" />
    • and add this line instead:

      1
      
        <Import Project="..\packages\FSharp.Compiler.Tools\tools\Microsoft.FSharp.targets" />

You now have a project that should build and run fine locally. Try it out!

2048 Screenshot

Azure Deployment

Now, on to the deployment setup itself. We will be using a custom build script, so we need to tell so in the .deployment file:

1
2
[config]
command = build.cmd

The build.cmd script itself is in three parts:

  1. Package restore: we retrieve paket.exe if it hasn't already been retrieved, and run it to restore packages.

    1
    2
    3
    4
    5
    
    if not exist .paket\paket.exe (
      .paket\paket.bootstrapper.exe
    )
    
    .paket\paket.exe restore
  2. Build: Azure conveniently points the environment variable MSBUILD_PATH to the path to MSBuild.exe; in order to be also able to run this script locally, we check for it and set it to the standard installation location if it doesn't exist. Then, we run it.

    1
    2
    3
    4
    5
    
    if "%MSBUILD_PATH%" == "" (
      set MSBUILD_PATH="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe"
    )
    
    %MSBUILD_PATH% /p:Configuration=Release
  3. Deploy: Deploying the application simply consists in copying the application files to the Azure-provided DEPLOYMENT_TARGET folder. The actual file in the 2048 repository is a bit more complex than necessary for Azure because it is also used on AppVeyor to deploy the application to github-pages. But a simple implementation can just copy all files and subdirectories from the project directory to DEPLOYMENT_TARGET:

    1
    2
    3
    
    if not "%DEPLOYMENT_TARGET%" == "" (
      xcopy /y /e <your_project_name> "%DEPLOYMENT_TARGET%"
    )

As a recap, here is the full build.cmd with some extra error management:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@ECHO OFF
setlocal

echo ====== Restoring packages... ======

if not exist .paket\paket.exe (
  .paket\paket.bootstrapper.exe
)

.paket\paket.exe restore

if not %ERRORLEVEL% == 0 (
  echo ====== Failed to restore packages. ======
  exit 1
)

echo ====== Building... ======

if "%MSBUILD_PATH%" == "" (
  set MSBUILD_PATH="%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe"
)

%MSBUILD_PATH% /p:Configuration=Release

if not %ERRORLEVEL% == 0 (
  echo ====== Build failed. ======
  exit 1
)

if not "%DEPLOYMENT_TARGET%" == "" (
  echo ====== Deploying... ======
  xcopy /y /e <your_project_name> "%DEPLOYMENT_TARGET%"
)

echo ====== Done. ======

And there you have it! A WebSharper application easily deployed to Azure with a simple configuration and consistent build setup between local and deployed.

Note that this particular example is a Single-Page Application, but the same setup can be used for Client-Server Applications and HTML Applications. For the latter, make sure to copy the WebSharperHtmlDirectory (<your_project_name>/bin/html by default) in the final step rather than the project folder itself.

Thanks to Steffen Forkmann and Don Syme for their quick response on creating the FSharp.Compiler.Tools NuGet package, and to Scott Hanselman for his Suave Azure deployment tutorial which has been of great help to create this one despite the fairly different final setup.

Happy coding!

By Loïc Denuzière on Wednesday, May 6, 2015 — 0 comments

WebSharper 3.0.59 released Core team

This is the first minor release since WebSharper 3.0 went live. Here is the change log:

  • The types Web.IContext and Sitelets.Context<_> have a new member Environment : IDictionary<string, obj>. This property is used to pass host-specific data to sitelets and Rpc functions. Currently, this dictionary contains:
    • When running as an ASP.NET module (eg. Client-Server Application project template), "HttpContext" contains System.Web.HttpContext.Current.
    • When running on OWIN (eg. Self-Hosted Client-Server Application project template), "OwinContext" contains the current IOwinContext.

      Thanks to Catalin Bocirnea for this contribution on this!

  • Added a Sitelets.Content creation helper: Content.FromAsync : Async<Content<'T>> -> Content<'T>

  • Fixed #391: Sitelet.Infer would incorrectly match URLs longer than prescribed, for example a union case such as:

    1
    
    | Article of id: int

    would not only accept urls such as:

    1
    
    /Article/123

    but also urls with any extraneous fragments afterwards:

    1
    
    /Article/123/something-extra

    Now it only accepts urls with the following formats:

    1
    2
    
    /Article/123
    /Article/123/

As always, WebSharper 3.0.59 is available on NuGet, and the installers for Visual Studio and Xamarin Studio / MonoDevelop are available on the official website and on the respective update channels.

Happy coding!

By Adam Granicz on Tuesday, April 28, 2015 — 0 comments

WebSharper site enhancements Core team

The recent WebSharper 3 release also saw a number of enhancements to the WebSharper website, including a major reorganization to its content. In this post, I will summarize these, in particular:

  1. Developer pages have moved under For Developers, whose main page now points to the core documentation, along with a brief description of the product stack. These pages also got a submenu where you can navigate, among others, to:

    For-Developers submenu

    a. Tutorials - that highlight various technical topics for WebSharper developers.

    b. Videos - a list of getting started/tutorial videos (not yet available) and a selected list of recorded conference talks (more to follow).

    c. Extensions - start here to learn about available extensions and how to work with JavaScript libraries.

    d. Books - a list of books with WebSharper content.

  2. Insider Program and Support are in the Premium section, along with other services (more on these in a subsequent blog).

    For-Subscribers submenu

    Companies and individuals with support plans can submit tickets here, and view their available subscriptions. Be sure to use your subscriber login and not your regular user account (and see below about accounts) when accessing these pages. You can be logged in with both at any time, if you need to, as well.

  3. The Forums got a bit of a facelift, and filtering (All/Forum/Core/Extension) to select between all entries including GitHub tickets, forum content only, WebSharper GitHub tickets, and GitHub tickets from the public extensions (including UI.Next - however, not all are fed into the forums yet).

Wait! Two kinds of logins? What are these about?

  1. Ordinary user accounts are primarily for posting in the Forums, and you can now use a number of new login providers (GitHub and Facebook, in addition to those before) to register and/or log in:

    Login providers

    We continue to add new login providers, our next target is Azure logins.

  2. Subscriber logins are created when you subscribe to the WebSharper Insider Program or to any dedicated support plan.

    Subscriber logins

What's coming?

  1. Getting Started videos - 2-5 minute clips showing you how to get started with WebSharper.
  2. More recorded talks added to the Videos page.
  3. A simplified login/registration flow with more login providers (Azure, etc.)
  4. A comprehensive guide to developing mobile applications with WebSharper.
  5. More walkthrough tutorials, including reactive applications with UI.Next, adding OAuth to your applications, deploying to Azure via GitHub, etc.

Happy coding!

By Frank Joppe on Sunday, April 19, 2015 — 0 comments

Websharper Grid: Paste from Excel Community

The nice thing about Websharper is that you’re released from writing Javascript. As a pet project I was wondering how much effort it would take to write a simple DataGrid in which you can paste clipboard data, which you copied earlier from MS-Excel. If you want to write something ambitious like a project planning tool, then such a paste function could be useful.So what does excel put on the clipboard if select a rectangle of cells and copy it? In the Desktop world one would deal with the D [...[...]
>> Read the full article on fjoppe.weebly.com
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!