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
:development
declares that this is a development environment (as opposed to eg.staging
orproduction
). It is used, among other things, to determine whichappSettings
file to use (see below).- If you're running Linux:
LD_LIBRARY_PATH
:<workspace folder>/packages/System.Data.SQLite.Core/runtimes/linux-x64/lib/netstandard2.0
allows 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.0
allows 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.fs
contains the core data model types and functionality.- The
EndPoint
type defines the set of HTTP endpoints served by the application, andRouter
can create URLs fromEndPoint
values and vice-versa; - The
Link
andUser
modules define the model for stored links and users, respectively. Each defines a set of immutable data types and related pure functions.
- The
Client.fs
contains the Model-View-Update client-side implementation of the "My links" page. Learn more about MVU- The
Model
module defines the state of the client-side page in terms of immutable data types. It also defines aMessage
type which lists all the possible events that can happen on this page. - The
View
module defines how to display the page based on this state. It uses adispatch
function to sendMessage
s when something needs to happen. - The
Update
module defines what must happen when aMessage
isdispatch
ed. This means modifying the state and/or triggering impure actions such as calling the server. - Finally the
MyLinks
function puts all these together and returns a value that can be directly included in a page.
- The
Database.fs
contains the database interaction code.-
Sql
instantiates SQLProvider to connect to the SQLite database, which is stored in the filesystem asdb/urlshortener.db
. -
Context
encapsulates the database context. It is declared as an ASP.NET Core service (seeConfigureServices
inStartup.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
CreateLink
orGetAllUserLinks
.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
Db
is added toWeb.Context
to easily retrieve a databaseContext
from either a remote function or a sitelet content.
-
Authentication.fs
contains the definition for the Facebook OAuth provider. It usesWebSharper.OAuth
.Remoting.fs
contains 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.fs
contains the server side code for rendering the application's various endpoints.- Most pages use HTML templating to define their content.
MainTemplate
parsesMain.html
and extracts HTML snippets, marked with thews-template
attribute; F# code can then put these snippets together as needed. This also happens at run time, so editingMain.html
does 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
Sitelet
defines the site to serve. It unites together the handler fromFacebookProvider
with anApplication.MultiPage
that returns content based on the endpoint.
- Most pages use HTML templating to define their content.
Startup.fs
creates 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.fsproj
tells 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 here
similarly 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!