Integrating a .NET Application

Our .NET Finsemble Library allows you to integrate custom .NET applications into Finsemble. It hosts native client versions of the Router Client, Linker Client, and the Drag and Drop Client. Other client API functionality is available via remote procedure calls (RPC). The library also contains a user control that allows you to give WPF applications Finsemble's window management features and appearance. The minimum Finsemble version required is 2.3.

Our Finsemble .NET Seed Repository contains three sample .NET projects:

  • The WPFExample project contains a Finsemble-aware .NET application that has the WPF Window Title Bar user control, accepts drag and drop from Finsemble, and communicates over linker channels.
  • The AuthenticationExample project contains an example of authenticating with a .NET application.
  • The WindowlessExample project contains an example of how to work with a .NET application without a window: for example, to allow it to function as a service within Finsemble, which can communicate over the Router.

Adding a Finsemble-aware .NET application to the config

Finsemble-aware .NET applications are specified with a windowType of "FinsembleNativeWindow".

You can use either an alias for a downloaded asset or a full path similar to assimilated windows.

Initializing a Finsemble-aware application

When a Finsemble-aware application is launched by Finsemble, several command line parameters are sent to the application. Those include:

  • finsembleWindowName
  • componentType
  • uuid
  • top
  • left
  • width
  • height
  • openfinVersion

These are required when you create the Finsemble object:

var FSBL = new Finsemble(args, this); //send arguments and the window to Finsemble
FSBL.Connect();
FSBL.Connected += Finsemble_Connected;

The application window InitializeComponent() is called after connecting to Finsemble:

private void Finsemble_Connected(object sender, EventArgs e)
{
    Application.Current.Dispatcher.Invoke((Action)delegate // Main thread
    {
        // Initialize this window and show it.
        InitializeComponent();
        FinsembleHeader.setBridge(FSBL); // The FinsembleHeader component requires a connected Finsemble object to function.
        this.Show();
    });
}

Handling shutdown

To handle closing an .NET component cleanly, finsemble.dll provides a HandleClose method:

FSBL.HandleClose((action) =>
{
    //Handle things here that need to happen before close.
    //When done, call action().
    action();
});

Here is how to handle closing with user interaction:

private Action callOnClose;
private void Finsemble_Connected(object sender, EventArgs e)
{
    Application.Current.Dispatcher.Invoke((Action)delegate // Main thread
    {
        // Initialize this window and show it.
        InitializeComponent();
        FinsembleHeader.setBridge(FSBL); // The FinsembleHeader component requires a connected Finsemble object to function.
        FSBL.HandleClose((action) =>
        {
            callOnClose = action;
        });
        this.Show();
    });
}

private void Function_That_Gets_Called_On_User_Action(object sender, EventArgs e)
{
    callOnClose()
}

Note that the maximum time allowed for a component to close is two seconds less than the shutdownTimeout config option. So if shutdownTimeout is set to ten seconds, the component must close in less than eight seconds or it will be killed. If you are planning on user interaction, please increase the value of shutdownTimeout appropriately.


Native Finsemble Clients

Using the .NET Linker

Publish

Publish a piece of data. The data will be published to all channels that the component is linked to. Foreign components that are linked to those channels will receive the data if they have subscribed to this data type. They can then use that data to synchronize their internal state. See "Subscribe" below. You can publish to specific channels by specifying a channels array in the parameters.

Subscribe

Registers a client for a specific data type that is sent to a channel.

FSBL.LinkerClient.Subscribe("symbol", (sender, event) => {
    var symbol = event.response["data"];
});

Unsubscribe

Remove all listeners for the specified data type.

FSBL.LinkerClient.Unsubscribe("symbol", (s, e) => { });

LinkToChannel

Add a component to a Linker channel programmatically. Components will begin receiving any new contexts published to this channel but will not receive the currently established context.

FSBL.LinkerClient.LinkToChannel("group1", null, (s, e) => { });

UnlinkFromChannel

Unlinks a component from a Linker channel programmatically.

FSBL.LinkerClient.UnlinkFromChannel("group1", null, (s, e) => { });

Using .NET Drag and Drop

Emitters

To show the drag and drop icon in the Window Title Bar (see "WPF Window Title Bar" below), you must create an emitter. Here is the code from our sample application that shares a "symbol" object that contains the text from a TextBox called "DataToSend".

FSBL.DragAndDropClient.SetEmitters(new List<KeyValuePair<string, DragAndDropClient.emitter>>()
{
    new KeyValuePair<string, DragAndDropClient.emitter>("symbol", () =>
    {
        return new JObject
        {
            ["symbol"] = DataToSend.Text,
            ["description"] = "Symbol " + DataToSend.Text
        };
    })
});

Receivers

To allow data from Finsemble to be dropped onto your application, you must create receivers. Here is the code from our sample application that receives a "symbol" object and sets that as the text of the "DataToSend" TextBox.

FSBL.DragAndDropClient.AddReceivers(new List<KeyValuePair<string, EventHandler<FinsembleEventArgs>>>()
{
    new KeyValuePair<string, EventHandler<FinsembleEventArgs>>("symbol", (s, args) =>
    {
        var data = args.response["data"]?["symbol"]?["symbol"];
        if(data != null)
        {
            Application.Current.Dispatcher.Invoke((Action)delegate //main thread
            {
            DataToSend.Text = data.ToString();
            });
        };
    })
});

Scrim

When data to be shared in Finsemble is dragged, a scrim is displayed on top of all components denoting whether or not the component can receive that data. You must create a control (generally a label) that occupies the entire space of the component, sits on top of all other controls, and is hidden. This is the control that will accept the dragged data from other components. Here is how to provide this control to Finsemble:

// Assuming the control is called Scrim
FSBL.DragAndDropClient.SetScrim(Scrim);

Using the .NET Router Client

The .NET Router Client is very similar to the JavaScript client with a few exceptions:

  • RouterClient.Subscribe: This does not return a subscribeID.
  • RouterClient.Unsubscribe: This takes the same parameters as subscribe above.

Only the following API Calls are currently supported:

  • Transmit
  • AddListener
  • RemoveListener
  • Subscribe
  • Unsubscribe
  • Query
  • AddResponder
  • RemoveResponder

Available Finsemble API endpoints via RPC

Here is the list of Finsemble API endpoints currently supported by the .NET Finsemble Library. Refer to the documentation of each endpoint in our API documentation:

Launcher Client

  • showWindow
  • spawn

Config Client

  • getValue

Logger

  • error
  • warn
  • log
  • info
  • debug
  • verbose
  • Logger API: All logs will be sent to Finsemble regardless of settings in the Central Logger.

To use these endpoints, use the RPC function. For example:

// Definition:
RPC(string endpoint, List<JToken> arguments, RPCCallBack callback)

The RPC call takes three parameters. The first one is the API endpoint. The second is a list of all the arguments to the API call that are specified in the JavaScript API documentation—except the callback or eventHandler. The third parameter is the callback or eventHandler.


WPF Window Title Bar

The WPF Window Title Bar user control provides Finsemble's built-in window management functionality to WPF components. By using this user control, .NET windows can participate in snapping and docking. Additionally, the WPF Window Title Bar allows the .NET component to link with other Finsemble components or utilize drag and drop data sharing.

Styling the Window Title Bar

You can change the background and button hover colors using the functions below. All the buttons are styled identically except the "close" button and the docked state background of the "docking" button.

// FinsembleHeader is the name of the WPFWindowTitleBar Control

//Set title bar background colors
FinsembleHeader.SetActiveBackground(new SolidColorBrush(Colors.Red));
FinsembleHeader.SetInactiveBackground(new SolidColorBrush(Colors.DarkRed));

//Set button backgrounds on hover
FinsembleHeader.SetButtonHoverBackground(new SolidColorBrush(Colors.Purple));
FinsembleHeader.SetInactiveButtonHoverBackground(new SolidColorBrush(Colors.Yellow));
FinsembleHeader.SetCloseButtonHoverBackground(new SolidColorBrush(Colors.SeaShell));
FinsembleHeader.SetInactiveCloseButtonHoverBackground(new SolidColorBrush(Colors.BurlyWood));

//Set docking button background when docked
FinsembleHeader.SetDockingButtonDockedBackground(new SolidColorBrush(Colors.BlanchedAlmond));

//Set text colors
FinsembleHeader.SetTitleForeground(new SolidColorBrush(Colors.LightGoldenrodYellow));
FinsembleHeader.SetButtonForeground(new SolidColorBrush(Colors.LightSalmon));

//Set Fonts for title and buttons.
//Use null for fontFamily, fontStyle and fontWeight to not change. Use 0 for fontSize to not change.
FinsembleHeader.SetTitleFont(fontFamily, fontSize, fontStyle, fontWeight);
FinsembleHeader.SetButtonFont(fontFamily, fontSize, fontStyle, fontWeight);

Authenticating with a .NET application

The main window of the AuthenticationExample application needs to be initialized the same way as a regular .NET Finsemble-aware window as described above. However, this authentication window cannot use the WPF Window Title Bar because the services are not available until authenticated. Once the user is authenticated, you need to call PublishAuthorization:

FSBL.RPC("AuthenticationClient.publishAuthorization", new JArray { username, credentials});

Getting user credentials

If your .NET app requires credentials from Finsemble, you can call GetCurrentCredentials:

FSBL.RPC("AuthenticationClient.getCurrentCredentials", new List<JObject>(), (err, credentials) => {
});

Using a .NET application as a service

The .NET Finsemble Library also allows .NET applications that do not display a window to interoperate with other components via the RPC Service and the Router. This allows for the integration of a .NET application as a service within Finsemble. An example of such an integration is provided in the WindowlessExample project.

Microservices created from .NET applications currently need to be added to the Finsemble component configuration and will always be started after all other services have been initialized. To add a .NET service (i.e., windowless component) to Finsemble, add it to the components.json file as normal and ensure that you set:

  • window.windowType to "FinsembleNativeWindow"
  • a window.name field to help you identify the component in the central logger
  • window.autoShow to false as no window should be displayed
  • window.addToWorkspace to false to disable any state capture and lifecycle events
  • component.spawnOnStartup to true to ensure that the component is auto-started
  • foreign.components["App Launcher"].launchableByUser to false to stop the component appearing in the launcher menu.

The component may be launched using a path or alias and can be passed arguments in the same way as any other .NET component.

For example:

"WindowlessExample": {
    "window": {
        "id": "Windowless",
        "name": "winlessSeed",
        "windowType": "FinsembleNativeWindow",
        "alias": "windowlessExample",
        "arguments": "arg1 arg2 arg3",
        "autoShow": false,
        "addToWorkspace": false
    },
    "component": {
        "spawnOnStartup": true
    },
    "foreign": {
        "components": {
            "App Launcher": {
                "launchableByUser": false
            }
        }
    }
}

check   The .NET Library contains several methods to integrate an app with Finsemble and calls to many Finsemble APIs via remote procedure calls.
 


Further reading

For information about authentication, check out the Authentication tutorial.

For information on making native applications into Finsemble components, read the Assimilation tutorial.

Understanding how the Linker Client and Drag and Drop Client work is important for understanding this tutorial.