WebSharper is self-sufficient and can run as the single component of a web application, but it can also be integrated into an existing ASP.NET or ASP.NET MVC application. This integration is twofold:
-
Client-side WebSharper controls can be used within an ASPX or Razor page. This allows you to use C#/F#-compiled-to-JavaScript directly within an existing page, and take advantage of client-side generated markup with UI.Next and easy remote calls.
-
Full WebSharper sitelets can run alongside an ASP.NET application, sharing the same URL space, as well as the same server state, sessions, etc.
In any case, you need to add the following references to your ASP.NET web project:
-
Your WebSharper project;
-
FSharp.Core. You can find it under Assemblies / Extensions in Visual Studio's "Add Reference" dialog, or get it from NuGet if you prefer.
If you use F# 3.1 or more recent (most likely), then you also need to add a binding redirect to your
Web.config
:<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> <!-- For F# 3.1: <bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" /> --> <!-- For F# 4.0: --> <bindingRedirect oldVersion="0.0.0.0-4.4.0.0" newVersion="4.4.0.0" /> </dependentAssembly> ...
-
The WebSharper.AspNetMvc package, if you are using ASP.NET MVC and/or the Razor view engine.
Ordinary ASP.NET applications are heavily server-based: content is rendered on the server and sent to the client, and any client interaction typically involves a server roundtrip. This can be eased somewhat using Ajax techniques on the client, where content or data is retrieved from the server asynchronously. Such content then is integrated into the presentation layer (on the client) once it becomes available after the call.
WebSharper makes it even easier to communicate with the server by enabling clients to make RPC calls seamlessly, as easily as making a client-side call. Here is a snippet to illustrate this in both languages:
- Define a remote method and a client-side
Web.Control
in C#
public static class Server
{
[Remote]
public static Task<int[]> GetData()
{
return Task.FromResult(new[] { 1, 2, 3});
}
}
[Serializable]
public class SimpleClientServerControl : WebSharper.Web.Control
{
[JavaScript]
public override IControlBody Body
{
get
{
var model = new ListModel<int, int>(x => x);
// call the server-side asynchronously, insert response items to ListModel
Task.Run(async () =>
{
foreach (var n in await Server.GetData())
model.Add(n);
});
return ul(model.View.DocSeqCached((int x) => li("Value= ", x)));
}
}
}
- Define a remote method and a client-side
Web.Control
in F#
namespace WebSharperProject
open WebSharper
module Server =
[<Rpc>]
let GetData () = async { return [1; 2; 3] }
module Client =
open WebSharper.Html.Client
[<JavaScript>]
let Main () =
let ul = UL
// call the server-side asynchronously, insert response items to DOM
async {
let! data = Server.GetData ()
for i in data do
ul.Append(LI [Text ("Value= " + i)])
} |> Async.Start
ul
type SimpleClientServerControl() =
inherit Web.Control()
[<JavaScript>]
override this.Body = Client.Main () :> _
Here is how to integrate the above client-side control in your ASPX or Razor page.
The class Web.Control
used in the above snippet inherits from System.Web.UI.Control
, which means
that it can be included directly in an ASPX page. Here are the necessary steps:
-
Add declarations for your content to
Web.config
:<configuration> <system.web> <pages> <controls> <add tagPrefix="WebSharper" namespace="WebSharper.Web" assembly="WebSharper.Web"/> <add tagPrefix="ws" namespace="WebSharperProject" assembly="WebSharperProject"/> </controls> ...
-
The first entry makes the WebSharper ScriptManager available, and it should remain in
Web.Config
for all WebSharper ASPX-based applications. -
The second entry declares that there is a
WebSharperProject
assembly with a namespace with the same name. This is what the default WebSharper ASP.NET and other ASP.NET-based Visual Studio project templates write by default. If you change the name of your WebSharper assemblies, or the namespaces they contain, you should update this entry or add further entries to cover those namespaces.
-
-
In the
<head>
of your ASPX page (orSite.Master
if you use one), add the WebSharper ScriptManager:<head runat="server"> <WebSharper:ScriptManager runat="server" /> ...
This will include all the CSS and scripts needed by the controls on your page. Make sure that the
<head>
tag is markedrunat="server"
. -
Insert the control itself in your ASPX page:
<ws:SimpleClientServerControl runat="server" />
Even though it may seem that your WebSharper control runs on the server (as would be indicated by the
runat="server"
attribute in your ASPX markup), this is not the case. Instead, this server control embeds a placeholder in your host page, and the WebSharper ScriptManager control takes care of "bringing it to life" by populating it when your page loads on the client, also referencing any dependencies it may have to ensure correct behavior.
Razor integration is provided by WebSharper.AspNetMvc. Here are the necessary steps:
-
In your main razor layout, inside the head tag, add the following:
@WebSharper.AspNetMvc.ScriptManager.Head()
This will include all the CSS and scripts needed by the controls on your page.
-
To insert a control in a view, first create it at the top of the view:
@{ var myControl = WebSharper.AspNetMvc.ScriptManager.Register(new MyControl()); }
and then you can insert it in the view, eg:
<div> <h1>My control:</h1> @myControl </div>
It is important to create the control before the view starts rendering, or else
ScriptManager.Head()
will already have been rendered without this control's dependencies.
To enable WebSharper remoting, Web.Config
must contain the declaration for the WebSharper HTTP module. This module is responsible for all RPC communication and comes already configured in the WebSharper Visual Studio project templates for ASP.NET. You should see something like this:
-
For IIS 7.x+:
<configuration> <system.webServer> <modules> <add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web"/> </modules> ...
-
For IIS 6.x:
<configuration> <system.web> <httpModules> <add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web"/> </httpModules> ...
In addition, if you are using ASP.NET MVC, you need to add WebSharper to your filters configuration, located in App_Start/FilterConfig.cs
in a default ASP.NET MVC application:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new WebSharper.AspNetMvc.Filter());
}
If you want to take full advantage of WebSharper's server-side facilities, including type-safe URLs and composable websites, as part of an ASP.NET application, it is very easy to do so.
In order to integrate a WebSharper Sitelet into an existing ASP.NET application, you need to
reference your Sitelet project from the ASP.NET website project, and add the following code
to your Web.config
file:
-
For IIS 7.x, 8.x:
<configuration> <system.webServer> <modules> <add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web"/> <add name="WebSharper.Sitelets" type="WebSharper.Sitelets.HttpModule, WebSharper.Sitelets"/> </modules> ...
-
For IIS 6.x:
<configuration> <system.web> <httpModules> <add name="WebSharper.RemotingModule" type="WebSharper.Web.RpcModule, WebSharper.Web"/> <add name="WebSharper.Sitelets" type="WebSharper.Sitelets.HttpModule, WebSharper.Sitelets"/> </httpModules> ...
In addition, just like with remoting, if you are using ASP.NET MVC, you need to add WebSharper to your filters configuration, located in App_Start/FilterConfig.cs
in a default ASP.NET MVC application:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new WebSharper.AspNetMvc.Filter());
}
Note that you can specify which of ASP.NET MVC or WebSharper Sitelets' routing takes precedence in case their URL space overlaps. By default, WebSharper takes precedence.
filters.Add(new WebSharper.AspNetMvc.Filter { SiteletsOverrideMvc = false });
We generally advise against using WebSharper alongside ASP.NET for a new application, and recommend instead to simply run a WebSharper Sitelets application to contain the whole application. Nevertheless, the Visual Studio extension includes a template that facilitates creating an ASP.NET/Sitelets hybrid application. The "Sitelets Host Website" template is an ASP.NET Web application template that includes the facilities describe above to run alongside Sitelets. All you have to do is to include a reference to your Sitelets project in this web project, and you're good to go!