Skip to content

A starter desktop app which uses HTML and F# for the UI and F# .NET for the API.

License

Notifications You must be signed in to change notification settings

kspeakman/FSharpHtmlDesktopApp

Repository files navigation

F# HTML Desktop app

This sample app demonstrates a desktop app using HTML/CSS/F# for the UI and F# .NET for the back end. All hosted in WPF.

How does it work?

The UI is a webpack-built JS app just like you would expect. It uses F# and Elmish for a functional (as in functional programming) UI. The F# code gets transpiled to JS and uses React for DOM rendering.

The "backend" API is an F# library. In this starter app, the backend is very simple. So there is nothing interesting to demonstrate yet.

A messaging library is shared between the front and back. It defines all the requests and responses that can pass between them.

The host application is WPF. WinForms would work too. Either way there is not much to it. The only control is the WebView2 control. And about 40 lines of wiring code.

For communication between the JS front and .NET back, I used WebView2's string-based messaging. Each side gets some functions to send/receive messages. Types from the messaging library are converted to JSON strings for transport.

What does it look like?

Right now it mainly demos the front-to-back communication. So it is not much to look at.

image

TODO polish up the starter UI

Install pre-requisites

You'll need to install the following pre-requisites in order to build SAFE applications

  • The .NET SDK 5 or higher.
  • npm package manager.
  • Node LTS.
  • See the WebView2 installation instructions below.

WebView2 install - Fixed Version Runtime

This solution uses the Fixed Version Runtime. This means the WebView2 runtime binaries are distributed as part of the app. The binaries are not included in the git repo for size and licensing reasons.

These same instructions can be used later to update the version of the runtime.

For more information about Evergreen vs Fixed Version Runtimes, see the WpfHost README and the WebView2 Distribution documentation.

When you see curly braces like {version}, it is representing the kind of text that should be there.

  • Download the WebView2 Fixed Version Runtime.
    • The file should be named similar to Microsoft.WebView2.FixedVersionRuntime.{version}.{arch}.cab.
  • Extract the cab file with expand: expand {cab file} -F:* .\.
  • Move the extracted folder into the WpfHost folder.
    • The folder name can be shortened. But it should contain "WebView2" to be ignored by git.
  • Modify WpfHost.csproj to match the folder name.
    <ItemGroup>
      <Content Include="{WebView2 folder}\**\*.*">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
    • This ensures the WebView2 runtime will be included in the built app.
  • Change the MainWindow.xaml.cs file to reference the exact WebView2 folder name.
              webView.CreationProperties =
                  new CoreWebView2CreationProperties
                  {
                      BrowserExecutableFolder = "{WebView2 folder}"
                  };

TODO

  • script installation to project
  • code the Init method to find the WebView2 runtime folder

Starting the application

Start the HTML UI, then the host.

Start the HTML UI

Open a powershell or command line in the solution folder. Then run:

dotnet tool restore
npm install
npm run start

Start the WPF host

  • In VS2019 Solution Explorer, locate src/WpfHost project
  • Right-click the WpfHost project and Set as Startup Project
  • Press F5

Browser Dev tools

In Debug mode you can right-click somewhere inside the WPF window to bring up the Edge context menu. Click Inspect. This will open the Edge (Chromium) dev tools in another window.

In Release mode this is disabled.

Packaging the HTML UI

The built web app can be included in the WPF project. Or it can be independently deployed to a web server.

Build it:

npm run build

To WPF content

This option will bundle the HTML UI with the WPF app. It will be included as "Content" in the WPF project.

To make this work smoothly, map a virtual host name to a local folder name. Then the Source can be set to the virtual host name. Otherwise it would be necessary to use a local file path, which are usually blocked by browsers.

await webView.EnsureCoreWebView2Async();

// must be after webView is "ensured"
webView.CoreWebView2.SetVirtualHostNameToFolderMapping(
                    "app.ui", "UI",
                    Microsoft.Web.WebView2.Core.CoreWebView2HostResourceAccessKind.Allow);
webView.Source = new Uri("https://app.ui");

TODO

  • add UI folder to project as Content
  • script deployment to UI folder

To local web server

Copy the built assets from the deploy/public folder to your web server. Then set the Source to the web server deploy location.

Security

Reference documentation

Untested

Ideas

  • prevent the user from navigating off your app in WebView2 by handling NavigationStarting and FrameNavigationStarting events
  • block external scripts/assets using CSP (part of UI app)
    • include assets in UI build instead of pulling from CDN

Acknowledgements

This project is adapted from the SAFE template.

About

A starter desktop app which uses HTML and F# for the UI and F# .NET for the API.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published