ASP.NET Core app with WebSharper
To use WebSharper features in an ASP.NET Core web application,
you will need the packages WebSharper
, WebSharper.FSharp
and WebSharper.AspNetCore
.
The easiest way to get started is to use one of the templates.
WebSharper can be enabled and configured in the Configure
method, and uses a few services configured in the ConfigureService
method. Here is a recommended default setup:
type Startup() =
member this.ConfigureServices(services: IServiceCollection) =
services.AddSitelet(mySitelet)
.AddAuthentication("WebSharper")
.AddCookie("WebSharper")
|> ignore
member this.Configure(app: IApplicationBuilder) =
app.UseAuthentication()
.UseWebSharper()
.UseStaticFiles()
|> ignore
Configure
setup
UseWebSharper()
By having open WebSharper.AspNetCore
, the UseWebSharper
extension method is available for IApplicationBuilder
. It installs the middlewares for WebSharper runtime.
For a basic setup, simply call UseWebSharper()
:
type Startup() =
member this.Configure(app: IApplicationBuilder) =
app.UseWebSharper()
|> ignore
You can also configure WebSharper by passing a builder function. For example:
type Startup() =
member this.Configure(app: IApplicationBuilder) =
app.UseWebSharper(fun builder ->
builder
.Sitelet(mySitelet)
.UseRemoting(false)
|> ignore)
|> ignore
The following methods are available for the builder:
builder.UseSitelets(?u: bool)
tells WebSharper whether to serve sitelets; the default is true.If this is true, then either
builder.Sitelet()
orservices.AddSitelet()
must be called to declare the sitelet to serve; otherwise, a runtime error is thrown.builder.UseRemoting(?u: bool)
tells WebSharper whether to serve remote functions; the default is true.builder.Sitelet(s: Sitelet<'EndPoint>)
tells WebSharper to serve the given sitelet. This will be ignored ifUseSitelets(false)
is called. Note that it is advised to pass the sitelet as a service rather than through the builder; see Sitelets for more details.builder.Config(c: IConfiguration)
tells WebSharper to use this appSettings configuration. By default, WebSharper uses thewebsharper
subsection of the host configuration.builder.Logger(l: ILogger)
tells WebSharper to use this logger for its internal messages. By default, WebSharper uses an injectedILogger<WebSharperOptions>
.builder.BinDir(d: string)
tells WebSharper to look for assemblies with WebSharper metadata in this directory. By default, it uses the directory where WebSharper.AspNetCore.dll is located.builder.AuthenticationScheme(s: string)
tells WebSharper to use the given authentication scheme forWeb.Context.UserSession
. See Authentication for more details.
UseStaticFiles()
If you have any client-side code, then it will need access to compiled JavaScript files, which the WebSharper middleware does not provide. So you need to add the default static files provider:
app.UseWebSharper()
.UseStaticFiles()
Note that UseStaticFiles()
should be called after UseWebSharper()
. This way, WebSharper
sitelets and remoting have a chance to handle requests even if they also happen to match a static file.
UseAuthentication()
If you wish to use Web.Context.UserSession
, then you need to call app.UseAuthentication()
, and to configure its services.
app.UseAuthentication()
.UseWebSharper()
.UseStaticFiles()
Note that UseAuthentication()
should be called before UseWebSharper()
. This way, Authentication
can parse session information from the request that WebSharper
can then use.
ConfigureServices
setup
WebSharper uses ASP.NET Core's dependency injection for a number of services.
Sitelets
The recommended way to tell WebSharper which sitelet to serve is to use services.AddSitelet()
. There are several variants:
AddSitelet(s: Sitelet<'EndPoint>)
simply uses the given Sitelet value.type Startup() = member this.ConfigureServices(services: IServiceCollection) = services.AddSitelet(mySitelet)
AddSitelet<'T when 'T :> ISiteletService>()
uses a Sitelet created through dependency injection. In F#, the best way to create a Sitelet service is by implementing the abstract classSiteletService<'EndPoint>
.type MyWebsite() = inherit SiteletService<MyEndPoint>() let sitelet = Application.MultiPage(fun ctx endpoint -> Content.Text "Hello, world!" ) override this.Sitelet = sitelet type Startup() = member this.ConfigureServices(services: IServiceCollection) = services.AddSitelet<MyWebsite>()
The type
MyWebsite
can now use injected services:type MyWebsite(logger: ILogger<MyWebsite>) = inherit SiteletService<MyEndPoint>() let sitelet = Application.MultiPage(fun ctx endpoint -> logger.LogInformation("Serving a sitelet page!") Content.Text "Hello, world!" ) override this.Sitelet = sitelet
Remoting
To use simple module-based remoting, there is nothing to add: as long as there is no UseRemoting(false)
in your call to UseWebSharper()
, remote module functions will be served.
WebSharper.AspNetCore additionally provides a way to inject a remoting handler (see Server-side customization here) with dependencies. For this, simply register your handler using services.AddWebSharperRemoting<_>()
. This call replaces the call to WebSharper.Core.Remoting.AddHandler
that would otherwise be needed.
// Rpc handler:
type MyRpc(logger: ILogger<MyRpc>) =
[<Remote>]
member this.MyMethod() =
logger.LogInformation("MyMethod was called")
// Registering:
type Startup() =
member this.ConfigureServices(services: IServiceCollection) =
services.AddWebSharperRemoting<MyRpc>()
|> ignore
If you have an abstract remoting handler, you can register an implementation using AddWebSharperRemoting<_, _>()
.
// Abstract Rpc handler:
[<AbstractClass>]
type MyRpc() =
[<Remote>]
abstract MyMethod : unit -> unit
// Implementation of the Rpc handler:
type MyRpcImpl(logger: ILogger<MyRpc>) =
inherit MyRpc()
override this.MyMethod() =
logger.LogInformation("MyMethod was called")
// Registering:
type Startup() =
member this.ConfigureServices(services: IServiceCollection) =
services.AddWebSharperRemoting<MyRpc, MyRpcImpl>()
|> ignore
Authentication
To use WebSharper's user sessions, add this to your ConfigureServices
method:
type Startup() =
member this.ConfigureServices(services: IServiceCollection) =
services
.AddAuthentication("WebSharper")
.AddCookie("WebSharper")
|> ignore
and also app.UseAuthentication()
to Configure
.
If you configured a different authentication scheme in UseWebSharper()
, then you need to use that same scheme name here instead of "WebSharper"
.