comment
WebSharper 4.2 released
It is finally here! Today we are releasing WebSharper 4.2.
The main highlight of this release is the support for .NET Standard 2.0 and ASP.NET Core.
New features also make getting started with WebSharper easier than ever:
* With dotnet
templates, creating a new C# or F# WebSharper project is now done in a single command line.
1 2 3
``` dotnet new websharper-spa -lang f# ```
- WebSharper configuration for a project is now stored in a simple JSON file.

Installing
You can install or update the templates to create WebSharper projects via the following means:
in Visual Studio 2017, from the downloads page.
for the
dotnet
command line, by typing the following command (see below for more details:1
dotnet new -i WebSharper.Templates
You can also add WebSharper to an existing project. Simply add the NuGet package WebSharper.FSharp
or WebSharper.CSharp
(depending on your language of choice) and add a wsconfig.json file.
Now, let's see the changes that are coming in this release.
.NET Standard and .NET Core
WebSharper's built-in libraries, as well as the entire library of standard extensions, are now available for .NET Standard 2.0. This means that you can now run WebSharper applications on .NET Core 2.0 on Windows, OS X and Linux.
There are a small number of differences between the .NET Framework 4.6.1 and .NET Standard 2.0 versions of the WebSharper libraries, related to the fact that System.Web
is exclusive to .NET Framework:
WebSharper.Web.RpcModule
andWebSharper.Sitelets.HttpModule
are only available for .NET Framework.WebSharper.Web.Control
inherits fromSystem.Web.UI.Control
in .NET Framework, and fromSystem.Object
in .NET Standard.WebSharper.Core.Resources.HtmlTextWriter
inherits fromSystem.Web.UI.HtmlTextWriter
in .NET Framework, and fromSystem.IO.TextWriter
in .NET Standard.WebSharper.Sitelets.IHostedWebsite
, which builds a sitelet from aSystem.Web.HttpApplication
, is only available in .NET Framework.
ASP.NET Core support
WebSharper Client-Server applications can now be hosted on ASP.NET Core thanks to WebSharper.AspNetCore. It is a simple interface that is very easy to connect:
1 2 3 4 5 6 7 8 9
// Your WebSharper website module Site = let Main = // ... // Serve the WebSharper website type Startup() = member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment) = app.UseStaticFiles() .UseWebSharper(env, Site.Main)
WebSharper uses runtime configuration for things such as overriding the URL of dependent resources. WebSharper.AspNetCore provides this configuration from the standard runtime configuration system for ASP.NET Core, Microsoft.Extensions.Configuration
:
1 2 3 4 5 6 7 8 9 10 11 12
member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment) = // Create the configuration object... let config = ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json") .Build() app.UseAuthentication() .UseStaticFiles() // ... and pass it to WebSharper. .UseWebSharper(env, Site.Main, config.GetSection("websharper"))
You can then pass WebSharper configuration in appSettings.json
:
1 2 3 4 5
{ "websharper": { "WebSharper.JQuery.Resources.JQuery": "https://code.jquery.com/jquery-3.2.1.min.js" } }
WebSharper authentication also uses the standard methods:
1 2 3 4 5 6 7 8 9 10 11
// Configure user authentication... member this.ConfigureServices(services: IServiceCollection) = services.AddAuthentication("WebSharper") .AddCookie("WebSharper", fun options -> ()) |> ignore member this.Configure(app: IApplicationBuilder, env: IHostingEnvironment) = // ... and use it in the application. app.UseAuthentication() .UseStaticFiles() .UseWebSharper(env, Site.Main)
dotnet
project templates
To easily create new .NET Standard and ASP.NET Core WebSharper projects, we created templates for the dotnet new
command. You can install these templates with the following command:
1
dotnet new -i WebSharper.Templates
Once this is done, you can create a WebSharper project with one of the following commands (adding -lang f#
or -lang c#
to choose the language, with c#
being the default):
dotnet new websharper-web
This creates a Client-Server ASP.NET Core web project.dotnet new websharper-spa
This creates a Single-Page Application project. It is hosted in an ASP.NET Core project, so that you can quickly run it as well as serve RPCs to your SPA.dotnet new websharper-lib
This creates a simple WebSharper-compiled library.dotnet new websharper-html
This creates a static generated website.
wsconfig.json
WebSharper compilation can now be configured using a JSON file called wsconfig.json
located next to your project file. Its content overrides the corresponding properties set in your .*proj
file. Here is an example:
1 2 3 4 5 6
{ "project": "bundle", "dce": false, "outputDir": "scripts/", "warnOnly": true }
Read the full documentation about wsconfig.json.
The F# tooling extension for Visual Studio Code, Ionide, provides code completion for wsconfig.json.
Other changes
Updated FSharp.Compiler.Service to version 20.0.1, which makes compilation faster.
Support C# 7.2 language features: reference semantics with value types, non-trailing named arguments.
A new compilation mode,
bundleOnly
, allows faster compilation of SPA projects by skipping some parts of the C# or F# compilation that are unnecessary if you don't reference this project from other .NET projects. Use it by setting"project": "bundleOnly"
in wsconfig.json, or<WebSharperProject>BundleOnly</WebSharperProject>
in your .*proj file if you are not using wsconfig.json.- WebSharper.UI enhancements:
View.WithInit init view
creates a View that immediately returns a given initial valueinit
if the inputview
is still awaiting.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
```fsharp module Server = [<Rpc>] let Greet (x: string) = async { return "Hello, " + x } [<JavaScript>] module Client = let userInput = Var.Create "world" let vDoubled = userInput.View |> View.MapAsync Server.Greet |> View.WithInit "Deciding how to greet you..." ``` Similarly, `View.WithInitOption view` immediately returns `None` if the input `view` is still awaiting, then returns `Some` once `view` has a value.
Attr.DynamicClass
's API was inconsistent with otherAttr.*
functions: it was a generic function taking aView<'T>
and a mapping function'T -> bool
, rather than directly aView<bool>
. It is now deprecated, and the newAttr.DynamicClassPred
has the more standard behavior.1 2 3 4 5 6 7 8 9 10 11 12 13
Additionally, the new `Attr.ClassPred` is equivalent to `DynamicClassPred` but takes its argument as a `bool` rather than a `View<bool>` and is reactive when using `.V`. It is now the recommended way to create a class that is reactively set or unset. ```fsharp let currentPage = Var.Create "home" // Obsolete version: let hideIfHome() = Attr.DynamicClass "hidden" currentPage.View (fun x -> x = "home") // New recommended version: let hideIfHome() = Attr.ClassPred "hidden" (currentPage.V = "home") ```
Happy coding!