This project demonstrates how to use WebSharper to build the server side and client side of a web application.
It features:
- a server side using WebSharper sitelets hosted on ASP.NET Core;
- a SQLite database driven by SQLProvider, with schema migrations using Evolve;
- Facebook login using OAuth;
- a Model-View-Update client side page, using WebSharper remoting for server interaction;
- reactive DOM construction, using both HTML templates and F# HTML functions.
You can see it running on Azure here.
- The .NET Core SDK, version 2.1.401 or newer.
- On Windows: .NET Framework 4.6.1 (select it in Visual Studio installer, or download the Dev Pack here).
- On OSX or Linux: Mono 5.10 or newer.
The recommended way to develop on this project on all platforms is using Visual Studio Code with the following extensions:
- Ionide-fsharp for F# language support.
- C# (optionally) for the server side debugger.
To get running, start the "Run Build Task" command (Ctrl+Shift+B by default) and select the "watch" task. This starts a job that compiles the application, starts it at urls http://localhost:5000 and https://localhost:5001, and restarts this process when you save an F# file.
For the same effect from the command line, run dotnet watch run in the UrlShortener folder. Note that this needs the following environment variables set in the shell where you run it:
ASPNETCORE_ENVIRONMENT:developmentdeclares that this is a development environment (as opposed to eg.stagingorproduction). It is used, among other things, to determine whichappSettingsfile to use (see below).- If you're running Linux:
LD_LIBRARY_PATH:<workspace folder>/packages/System.Data.SQLite.Core/runtimes/linux-x64/lib/netstandard2.0allows the compiler and the application to find the required SQLite native library. - If you're running OSX:
LD_LIBRARY_PATH:<workspace folder>/packages/System.Data.SQLite.Core/runtimes/osx-x64/lib/netstandard2.0allows the compiler and the application to find the required SQLite native library.
The application demonstrates the use of OAuth login with Facebook. This means that you need a Facebook application set up to be able to log into the application. For this, you need to create a developer account on the Facebook developer console, then create an App and add Facebook Login to it.
UrlShortener retrieves the application credentials (app ID and app Secret, which you can retrieve on the Facebook console under Settings > Basic) from the application configuration. The simplest way to set it up is to create a file called appSettings.development.json in the UrlShortener directory with the following content:
{
"facebook": {
"clientId": "your app id here",
"clientSecret": "your app secret here"
}
}It is not recommended to add the above to the general appSettings.json: this file is committed to git, and you should never commit such credentials to source control under any circumstances.
The application's source code is structured as follows.
DataModel.fscontains the core data model types and functionality.- The
EndPointtype defines the set of HTTP endpoints served by the application, andRoutercan create URLs fromEndPointvalues and vice-versa; - The
LinkandUsermodules define the model for stored links and users, respectively. Each defines a set of immutable data types and related pure functions.
- The
Client.fscontains the Model-View-Update client-side implementation of the "My links" page. Learn more about MVU- The
Modelmodule defines the state of the client-side page in terms of immutable data types. It also defines aMessagetype which lists all the possible events that can happen on this page. - The
Viewmodule defines how to display the page based on this state. It uses adispatchfunction to sendMessages when something needs to happen. - The
Updatemodule defines what must happen when aMessageisdispatched. This means modifying the state and/or triggering impure actions such as calling the server. - Finally the
MyLinksfunction puts all these together and returns a value that can be directly included in a page.
- The
Database.fscontains the database interaction code.-
Sqlinstantiates SQLProvider to connect to the SQLite database, which is stored in the filesystem asdb/urlshortener.db. -
Contextencapsulates the database context. It is declared as an ASP.NET Core service (seeConfigureServicesinStartup.fs) in order to access the application settings and the logger through dependency injection. Learn more about ASP.NET Core dependency injectionIt contains methods for the various CRUD operations needed by the application, such as
CreateLinkorGetAllUserLinks.It also contains
Migrate(), which is called on application startup to apply any outstanding migrations to the database. The migration scripts are located underdb/migrations. -
Finally, an extension property
Dbis added toWeb.Contextto easily retrieve a databaseContextfrom either a remote function or a sitelet content.
-
Authentication.fscontains the definition for the Facebook OAuth provider. It usesWebSharper.OAuth.Remoting.fscontains server-side functions that are callable from the client side. They are basically wrappers for the corresponding database functions that additionally check for user authentication.Site.fscontains the server side code for rendering the application's various endpoints.- Most pages use HTML templating to define their content.
MainTemplateparsesMain.htmland extracts HTML snippets, marked with thews-templateattribute; F# code can then put these snippets together as needed. This also happens at run time, so editingMain.htmldoes not require a recompile. Learn more about WebSharper.UI templating Site, similarly toDatabase.Context, is declared as an ASP.NET Core service to gain access to dependency injection.- Its property
Siteletdefines the site to serve. It unites together the handler fromFacebookProviderwith anApplication.MultiPagethat returns content based on the endpoint.
- Most pages use HTML templating to define their content.
Startup.fscreates the ASP.NET Core application proper, registers WebSharper with it and runs database migrations on startup.
This application is easy to deploy as an Azure web app. Here are the steps:
- Create a Windows Web App on the Azure Portal.
- Under "Application settings", add the following application settings:
SCM_SCRIPT_GENERATOR_ARGS:--aspNetCore UrlShortener\UrlShortener.fsprojtells Azure where to find the application to run.facebook__clientId:your app id here(note the double underscore) sets the OAuth client id for the Facebook application. It is equivalent to the aboveappSettings.development.json.facebook__clientSecret:your app id heresimilarly sets the OAuth client secret.
- Under "Deployment options", set up the deployment method of your choice.
- "Local git" is a good option: it creates a git repository that you can simply push to and the application will be built and deployed. You will need to set up the git login/password under "Deployment credentials", and retrieve the git repository URL under "Deployment Center".
- Alternately, if you forked this repository on Github, the "Github" option will trigger a deployment every time you push there, without having to push to a separate repository.
Happy coding!



