Exploring .NET Universal Windows Platform on Windows

This is the third and last in our series of blog posts around Windows desktop technologies. After exploring Electron and React Native for Windows, we decided to spend time investigating Microsoft native technology: .NET Universal Windows Platform.

During our investigation on React Native for Windows we were able to wrap our Web backend code into a library usable from any UWP app.

We want to share our experience and our evaluation of the technology, considering that this was done a few months ago and that technology evolves a lot in time.

What is Universal Windows Platform

Universal Windows Platform, also known as UWP, is the leading-edge platform for Windows 10 applications and games, targeting desktop, Xbox, and Hololens. It provides a modern API both for frontend (Fluent Design) and for OS (WinRT). It is the biggest refactoring Microsoft has worked on since winapi, so since Windows 95.

It is designed with security at its core, and with the will to give control back to the user. Each UWP app declares a list of features it requires, known as capabilities, and it’s up to the user to accept or deny such capabilities.

The native technologies used to develop UWP apps are Xaml and C#.

What is Xaml?

Extensible Application Markup Language (XAML) is the language used to define UWP app’s user interface. It can be entered manually, or created using the Visual Studio design tools. It is a XML-like descriptive language, with a powerful binding system to call C# code. A .xaml file has a .xaml.cs code-behind file which contains the logic. Together, the XAML and code-behind make a complete class. Microsoft documentation provides a detailed XAML overview.

Creating the first UWP app

VisualStudio introduced UWP app projects back in 2015. To create a new UWP app project, start by installing “Universal Windows Platform development” using Visual Studio installer.

Once the needed SDK is installed, create a new “Blank App (Universal Windows)” project.

The solution created by this template contains the minimal file set to build and deploy a basic UWP application:

  • Assets contains a set of logo images, used in Start Menu, Store Logo, task bar and task manager.
  • Package.appxmanifest is a xml file containing the description of a project, such as the display name, logos and required capabilities
  • <Project>_TemporaryKey.pfx is the self-signed certificate, used to test the app before it is submitted to the store. When building the app VisualStudio will generate an installable certificate associated to this one, that can be added to the trusted loal certificates to side-load the UWP app without using the Store.
  • App.xaml and App.xaml.cs
    • App.xaml is where resources that are used across the app are declared.
    • App.xaml.cs is the code-behind file for App.xam. It is the entry point for your app. This is where activation and suspension of the app are handled.
  • MainPage.xaml is where the UI of the app is defined.

Handling asynchronous communication with the backend

During our React Native investigation we decided to use our web extension backend, developed in TypeScript. To be able to execute it, we needed a JavaScript engine context where the JavaScript code could run, and it needed to implement common web/nodejs API such as promises, asynchrounous functionalities as setTimeout and setInterval, console logs, file system, and more. All of these are not defined in the ES6 standard, and therefore they are not implemented by JavaScript engines such as Microsoft Chakra or Chrome V8.

As a first iteration we used a Node.js process running along the UWP app. After verifing the feasability of this solution, we looked for a safer implementation.

Electron project uses Node.js compiled into a library, and they shared a great build guide in this blog post. We decided to not use Node.js as a library because it wasn’t possible to build it into a UWP library, and to use a Win32 library would have required extra capabilities that we wanted to prevent using.

Inspired by React Native Windows and ChakraBridge we developed a custom JavaScript engine based on Chakra, Microsoft JavaScript ES6 engine. The main advantage is that Chakra is available in all Windows 10, so no need to install further dependencies, and that can be customized by providing additional features not implemented by the ES6 standard, such as HTTP requests, timers and file system. At the end of this, we were able to run our web extension in a dedicated thread, that can communicate with a generic frontend through a two way asynchronous event-based channel. Our JavaScript engine is called Bijou.js, and is opensourced on Dashlane’s github (MIT license).

When exploring .Net, we were able to reuse this JavaScript engine that was initially developed during our investigation of React Native. The custom React Native module encapsulating the backend and exposing methods and events to JavaScript became a standard C# class exposing public methods and events.

Backend Class

// Declare a custom event data class for backend messages.
public MessageFromBackendReceivedEventArgs : EventArgs
{
    public JToken Message { get; set; }
}
 
public class Backend
{  
    ...
     
    public void SendMessageToBackend(JToken message)
    {
        // send message to the backend
    }
 
    public delegate void MessageFromBackendReceivedEventHandler(object sender, MessageFromBackendReceivedEventArgs e);
    public event MessageFromBackendReceivedEventHandler MessageFromBackendReceived;
 
    private void OnMessageFromBackend(JToken message)
    {
        // notify backend sent a message
        MessageFromBackendReceived?.Invoke(message);
    }
 
    ...
}

Our web-based backend uses JSON to format messages distributed between modules. With React Native we could import data model npm module and use it to deserialize messages into data objects and display them with the power of JavaScript Json.Parse.

In .Net world, we had to convert TypeScript data models into C# ones, and we could use the power of Newtonsoft JsonSerializer Populate to deserializes JSON messages into C# objects.

Parsing Json to C# objects

public class DataModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}
 
public class ViewModel
{
    private Backend _backend = new Backend();
    private DataModel _data = new DataModel();
 
    public ViewModel()
    {
        _backend.MessageFromBackendReceived += OnMessageFromBackend;
    }
 
    // Incoming message will match the DataModel property ids.
    // For example:
    // '{ "Id":1, "Name":"Hello" }'
    private void OnMessageFromBackend(object sender, MessageFromBackendReceivedEventArgs args)
    {
        // Create a JReader from the Json message.
        using (var jsonReader = args.Message.CreateReader()) {
            // Create a Json serializer.
            var serializer = JsonSerializer.Create(new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
            // aAdd a KeyedListMergeConverter to the serializer.
            serializer.Converters.Add(new KeyedListMergeConverter(serializer.ContractResolver));
            // Populate C# DataModel.
            serializer.Populate(jsonReader, _data);
        }
    }
}

Conclusion: React Native vs .NET UWP

While exploring React Native and .NET UWP, we found both languages are fun and straightforward to work with. Since our team was originally working with C++, C# looked like a smaller technology jump, but some of us were happy to move to a technology closer to web.

.NET UWP has the advantage of being built with Microsoft Fluent Design, providing modern and adaptive user interfaces. Beautiful features like navigation animations and acrylic textures can be achieved in few lines of code, and most of UWP controls enable them by default.

On the performance side, we evaluated both test apps loading a big test account, containing more than 1000 credentials.

React Native.NET UWP
TIME==================
Time to load login window~1s~0.6 s
Time to login
Time to show main window~2s~2.5 s
CPU==================
Logout00
Login00
On scroll~25%~7%
MEMORY==================
Logout~84 MB~66MB
Login~300 MB~150MB
Minimized00

Here .NET UWP was clearly performing better than React Native for Windows.

Wrapping up on our desktop technologies investigation, given our priorities of performance and user experience, .NET UWP is as of today the best solution, coming with the cost of a .NET development team. If performance is not a priority, Electron is a good solution to bring your web app to desktop.

    Paola Ducolin

    Staff Engineer at Dashlane

    Read More