Using the Remote - Containers extension

Develop with Refinitiv WebSocket API Docker Image with C# in VS Code

Wasin Waeosri
Developer Advocate Developer Advocate

Introduction

Last Update: July 2023

Visual Studio Code (or just VS Code) is a free source code editor developed and maintained by Microsoft. This cross-platform editor rapidly gained popularity with developers as it is fast and lightweight, supports a variety of programming languages with IntelliSense (a feature that has originated with VS Code’s older sibling, Visual Studio IDE), and enables complete development operations like debugging, task running, and version control.

VS Code provides numerous extensions that add features and expand development workflows like the remote development that lets developers use a container, remote machine, or the Windows Subsystem for Linux (WSL) as a full-featured development environment with the Remote Development Extension Pack.

As part of the Remote Development Extension Pack, the Remote - Containers extension lets developers use a Docker container as an immutable/sandbox development environment. It allows the developers to open any folder inside (or mounted into) a container and take advantage of Visual Studio Code's full feature set (IntelliSense, code navigation, debugging, etc) as a local-quality development experience. This feature is called devcontainer or dev container.

mage from VS Code - Developing inside a Container page.

The previous Develop with Refinitiv Real-Time SDK Docker Image in VS Code article demonstrates how to use Refinitiv Real-Time SDK Java/C++ Docker Images devcontainer with VS Code Remote - Containers extension. This part 2 article shows how to set up a .NET devcontainer with the Remote - Containers extension to for the Refinitiv Real-Time Optimized (RTO) C# WebSocket examples using a Dockerfile. This Dockerfile is built on top of the refinitivapis/websocket_api Docker Image and developers can run the RTO C# WebSocket examples codes directly in VS Code.

Update: The refinitivapis/websocket_api Docker Image has been updated to the current version of WebSocket API GitHub repository. All C# example projects have been update to .NET 6.0.

Refinitiv WebSocket API Introduction

As part of the Refinitiv Real-Time SDK, the Websocket API for Pricing Streaming and Real-Time Service (aka Websocket API) provides a connection to Refinitiv Real-Time via a standard WebSocket protocol and JSON message format. Developers can use multiple client technology standards such as Python, JavaScript, .Net, etc. to establish WebSocket connections to Refinitiv Real-Time Distribution Systems (RTDS), or Refinitiv Real-Time - Optimized (RTO - cloud solution) available via Refinitiv Data Platform (RDP).

The WebSocket API examples source code for various programming languages is available on GitHub. If developers are new to the Refinitiv Real-Time, they can use the refinitivapis/websocket_api Docker Image to learn the WebSocket API and RTO connection flows quickly. This Docker image contains all WebSocket API Examples, the Python runtime, and dependencies required to run the Python WebSocket examples. You can check my colleague's Introduction to the refinitivapis/websocket_api Docker Image article for step-by-step guidance on how to deploy and run the RTSDK Docker images via the Docker command line.

If you are using the Refinitiv Real-Time SDK C/C++ or Java, there are the following Docker images that contain the latest version SDK too.

Prerequisite

This devcontainer example requires the following dependencies software and libraries.

  1. Visual Studio Code editor.
  2. Docker Desktop/Engine application.
  3. VS Code - Remote Development extension pack
  4. Access to the Refinitiv Refinitiv Data Platform and Refinitiv Real-Time - Optimized. (for the RTO example only)
  5. Internet connection.

I highly recommend following System requirements and Installation sections to set up your environment.

Please contact your Refinitiv representative to help you to access the RTO account and services. You can find more detail regarding the RDP and RTO access credentials set up from the Getting Started for Machine ID section of the Getting Start with Refinitiv Data Platform article.

RTO C# devcontainer Detail

A devcontainer.json file

The main configuration file that tells VS Code how to access (or create) a devcontainer with a well-defined tool and runtime stack is named the devcontainer.json file. The dev container configuration is either located under .devcontainer/devcontainer.json or stored in a file named .devcontainer.json file (note the dot-prefix) in the root of the project.

Note: Make sure to commit a .devcontainer folder to your version control system.

Let me explain these configurations:

    	
            

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:

// https://github.com/microsoft/vscode-dev-containers/tree/v0.202.5/containers/

{

    "name": "WebSocket_dotNet",

    "build": {"dockerfile": "Dockerfile"},

    "runArgs": [

        "--env-file=.devcontainer/.env.devcontainer"

    ],

    "customizations": {

        "vscode": {

            "extensions": ["ms-dotnettools.csharp"],

            "settings": {

                "omnisharp.useModernNet": false,

                "omnisharp.sdkPath": "/usr/bin/dotnet"

            }

        }

      },

    "workspaceFolder": "/opt/refinitiv/websocket-api/Applications/Examples/RDP/CSharp",

    "mounts": [

        "source=${localWorkspaceFolder}/.vscode,target=${containerWorkspaceFolder}/.vscode,type=bind,consistency=cached",

        "source=${localWorkspaceFolder}/shareFolder,target=${containerWorkspaceFolder}/shareFolder,type=bind,consistency=cached"

    ],

    "shutdownAction":"stopContainer"

}

The detail of the configurations above are:

  • name: A display name for the container.
  • build: The location of a Dockerfile that defines the contents of the container.
  • runArgs: An array of Docker CLI arguments that VS Code uses when running the container. I am setting the --env-file option that sets the container's environment variables via a file named .env.devcontainer.
  • customizations.vscode.extensions: Specify VS Code extension IDs that will be installed inside the container. I am setting the C# extension for Visual Studio Code here.
  • customizations.vscode.settings: Adds default settings.json values into a container/machine specific settings file. I am setting the C# extension configurations here.
  • workspaceFolder: Sets the default path that VS Code should open when connecting to the container. This devcontainer sets the default path to /opt/refinitiv/websocket-api/Applications/Examples/RDP/CSharp which is the RTO C# examples location in the container.
  • mounts: Add mount points to the container when created for sharing files between the host and devcontainer. I am mounting the .vscode folder for the C# running/debugging configurations and the shareFolder to share files between host and devcontainer.
  • shutdownAction: set the VS Code stops the container when the editor window is closed/shut down.

The development container is not limited to Docker Images or a Dockerfile, it supports Docker Compose too. You can build your image(s) to match your development requirements, and then share Dockerfile and/or docker-compose.yml inside a .devcontainer folder (with a devcontainer.json file) with your colleagues to help them to set up the same development environment.

Please find more details about all devcontainer.json configuration parameters on the VS Code - devcontainer.json reference page.

A Dockerfile

The refinitivapis/websocket_api Docker Image has the Python runtime and dependencies pre-installed for the Python WebSocket examples. However, it is based on the Linux OS Image, so we can build a new Docker image on top of it and install compilers, SDKs, or runtime for the other WebSocket examples.

A Dockerfile for the RTO C# WebSocket examples is as follows:

    	
            

# Pulling Image from https://hub.docker.com/r/refinitivapis/websocket_api

FROM refinitivapis/websocket_api:latest

LABEL maintainer="Developer Advocate"

ARG dotnet_version="6.0"

 

# Install updates, dotnet-sdk and tools for VS Code devcontainer.

RUN yum update -y \

 && yum -y install dotnet-sdk-${dotnet_version} wget tar.x86_64 which \

 # Clean up unnecessary files to reduce Image size

 && yum clean all

# Set work directory to be RDP/CSharp

 

WORKDIR /opt/refinitiv/websocket-api/Applications/Examples/RDP/CSharp

 

# Set Docker to start bash

CMD /bin/bash

The above Dockerfile instructions do the following tasks.

  1. Pull refinitivapis/websocket_api as the Base Image with the FROM instruction.
  2. Install .NET SDK and runtime to the Image (As of July 2023: The RTO C# examples support .NET version 6.0)..
  3. Install additional packages for VS Code and the Remote - Containers extension.
  4. Set a new working directory to /opt/refinitiv/websocket-api/Applications/Examples/RDP/CSharp folder with the WORKDIR instruction.

Please note that you can build and run this Dockerfile with the Docker engine CLI too.

An Environment Variables file

According to the methodology 3rd factor of the Twelve-Factor App methodology, it is a good practice to keep configuration information and credentials as environment variables, then inject them into the application on runtime.

I am keeping the RTO credentials (both V1 and V2 Authentication) in a file named .env.devcontainer file under the .devcontainer folder as follows:

    	
            

#V 1

RTO_USERNAME=<Version 1 RTO Machine-ID>

RTO_PASSWORD=<Version 1 RTO Password>

RTO_CLIENTID=<Version 1 RTO AppKey>

#V 2

RTO_CLIENTID=<Version 2 Client-ID>

RTO_CLIENTSECRET=<Version 2 Client-Secret>

Please note that the environment variable file above contains the V1 and V2 Authentication. If you have only V1 or V2, please change the file based on your preference.

Then, we set this .env.devcontainer file to Docker on runtime with the devcontainer.json's "runArgs": ["--env-file=.devcontainer/.env.devcontainer"] configuration. Once the devcontainer creation is successful, developers can access RTO credentials via the following methods:

  • In a container's bash: via the $<variable name> syntax like $RTO_USERNAME (V1) or $RTO_CLIENTID (V2)
  • In VS Code launch.json: via the {env:<variable name>}* syntax like *env:<variablename>∗syntaxlike∗{env:RTO_USERNAME} (V1) or ${env:RTO_CLIENTID} (V2)

Caution

You should not share this .env.devcontainer file to your peers or commit/push it to the version control. You should add the file to the .gitignore file to avoid adding it to version control or public repository accidentally.

You can create a .env.devcontainer.example file as a template for environment variables file sharing. The file has the same parameters' keys as a .env.devcontainer file but without sensitive values.

Launch and Tasks Configurations files

VS Code has built-in debugging support for various programming languages. Developers can configure and save their debugging setup detail in a lunch configuration file named launch.json located in a .vscode folder of the workspace (project root folder).

To set a devcontainer to run and debug the MarketPriceRdpGwServiceDiscoveryExample application with the .NET Core runtime, I am setting a launch.json configuration as follows:

    	
            

{

    "version": "0.2.0",

    "configurations": [

 

        {

            // Use IntelliSense to find out which attributes exist for C# debugging

            // Use hover for the description of the existing attributes

            // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md

            "name": ".NET Core Launch (console)",

            "type": "coreclr",

            "request": "launch",

            "preLaunchTask": "build",

            // If you have changed target frameworks, make sure to update the program path.

            "program": "${workspaceFolder}/MarketPriceRdpGwClientCredAuthExample/bin/Debug/net6.0/MarketPriceRdpGwClientCredAuthExample_NET6.0.dll",

            //V1

            //"args": ["--user","${env:RTO_USERNAME}","--password","${env:RTO_PASSWORD}","--clientid","${env:RTO_CLIENTID}","--ric","/EUR="],

            //V2

            "args": ["--clientid","${env:RTO_CLIENTID}","--clientsecret","${env:RTO_CLIENTSECRET}","--ric","/EUR="],

            "cwd": "${workspaceFolder}/MarketPriceRdpGwClientCredAuthExample",

            // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console

            "console": "internalConsole",

            "stopAtEntry": false

        },

        {

            "name": ".NET Core Attach",

            "type": "coreclr",

            "request": "attach"

        }

    ]

}

Please noticed that the args attribute has been set to map a container environment variable to the example application parameters. This setting makes VS Code automatic passes the RTO credentials in a devcontainer's environment variables to the MarketPriceRdpGwServiceDiscoveryExample command line options. Developers do not need to manual paste their credentials in a devcontainer anymore.

Developers can save their building, packaging, testing, or deploying steps in a tasks configuration file named tasks.json located in a .vscode folder of the workspace (project root folder). A tasks.json file for automatic builds of the RTO C# WebSocket CSharpRdpGwExamples_NET6.0.sln solution with the following configurations:

    	
            

{

    "version": "2.0.0",

    "tasks": [

        {

            "label": "build",

            "command": "dotnet",

            "type": "process",

            "args": [

                "build",

                "${workspaceFolder}/CSharpRdpGwExamples_NET6.0.sln",

                "/property:GenerateFullPaths=true",

                "/consoleloggerparameters:NoSummary"

            ],

            "problemMatcher": "$msCompile"

        },

        ....

    ]

}

We mount this .vscode folder to a Docker Container with the devcontainer.json's "mounts": ["source={localWorkspaceFolder}/.vscode,target=localWorkspaceFolder/.vscode,target={containerWorkspaceFolder}/.vscode,type=bind,consistency=cached"] configuration. Once the devcontainer creation is successful, developers can start run and debug RTO C# Websocket examples session in VS Code directly.

Please find more detail about VS Code Debugging and Tasks configurations from the following resources:

Running the Development Container

Docker Desktop/engine should be running before the next step.

You can connect to the container and start developing within it by selecting the Remote-Containers: Reopen in Container command from the VS Code Command Palette (F1).

Alternatively, the VS Code can detect whether there is a folder containing a Dev container configuration file, and then asks you if you want to reopen the folder in a container.

Next, the VS Code window (instance) reloads and builds a Docker image from a Dockerfile, then starts a devcontainer. Please note that if the image is already built, the process will be faster.

There may be a message “There are unresolved dependencies. Please execute the restore command to continue” At this point. This message is generated from VS Code C# extension. Please click the Restore button.

Once this build completes, VS Code automatically connects to the container at the path we set to the workspaceFolder property which is the /opt/refinitiv/websocket-api/Applications/Examples/RDP/CSharp folder. You can check the VS Code Remote connection status from the button left toolbar.

If you click this toolbar, VS Code shows the Container Remote connection menu options at the top of the editor.

To close the remote connection, choose the "Close Remote Connection" from the drop-down menu.

Running the MarketPrice RDP Service Discovery Example

This devcontainer already has the C# extension built-in and VS Code's launch.json and tasks.json configurations files, developers can run the MarketPrice RDP Service Discovery Example (MarketPriceRdpGwServiceDiscoveryExample) by pressing the F5 button or selecting Run then Start Debugging option from VS Code menu.

VS Code automatic runs the MarketPriceRdpGwServiceDiscoveryExample application with the RTO credentials, and --ric command-line options set in a launch.json file. All RTO credentials are available in the container environment variables, so developers do not need to manually set them. Developers can change the RIC code or add other options in the args attribute of a launch.json file. Please find more detail about other options in the solution readme file.

Please find more detail about other options in the solution readme file.

Alternatively, developers can run the example in bash manually via the following steps (I am demonstrating with the V2 Authentication):

    	
            

$>dotnet build CSharpRdpGwExamples_NET6.0.sln

 

$>cd MarketPriceRdpGwClientCredAuthExample/bin/Debug/net6.0/

 

$>dotnet MarketPriceRdpGwClientCredAuthExample_NET6.0.dll --clientid $RTO_CLIENTID --clientsecret $RTO_CLIENTSECRET --ric <RIC Code>

How to run the Examples

The first step is to unzip or download the example project folder from the GitHub repository into a directory of your choice, then follow the steps below.

1. Go to the project's .devcontainer folder and create a file name .env.devcontainer with the following content.

    	
            

  # V1

    RTO_USERNAME=<Version 1 RTO Machine-ID>

    RTO_PASSWORD=<Version 1 RTO Password>

    RTO_CLIENTID=<Version 1 RTO AppKey>

    # V2

    RTO_CLIENTID=<Version 2 Client-ID>

    RTO_CLIENTSECRET=<Version 2 Client-Secret>

Please note that the environment variable file above contains the V1 and V2 Authentication. If you have only V1 or V2, please change the file based on your preference.

2. Start a Docker desktop or Docker engine on your machine.

3. Open the project folder in the VS Code editor

4. Install the VS Code - Remote Development extension pack.

5. Open the VS Code Command Palette with the F1 key, and then select the Remote-Containers: Reopen in Container command.

Now VS Code is ready to run the RTO C# WebSocket devcontainer.

Bonus: Running the WebSocket Python examples

This C# devcontainer is based on the refinitivapis/websocket_api Docker Image, so developers can run the Python WebSocket examples too.

The steps to run the RTO Python WebSocket example are as follows:

    	
            

$>cd /opt/refinitiv/websocket-api/Applications/Examples/RDP/python

 

$>python market_price_rdpgw_service_discovery.py --clientid $RTO_CLIENTID --clientsecret $RTO_CLIENTSECRET --ric <RIC Code>

Troubleshooting

Question: I do not have the RTO credentials.

Answer: Please contact your Refinitiv representative to help you to access the RTO account and services.

Question: When I select the Remote-Containers: Reopen in Container command, VS Code returns an error with Docker returned an error. Make Sure the Docker daemon is running. message.

Answer: Please install and start a Docker desktop or Docker engine on your machine.

Question: When I select the Remote-Containers: Reopen in Container command, VS Code returns an error with Docker returned an error. Make Sure the Docker daemon is running. message.

Answer: Please install and start a Docker desktop or Docker engine on your machine.

Question: VS Code throws an error with the An error occurred setting up the container message.

Answer: Please choose the Open devcontainer.json Locally option. Delete Docker container and images (named vsc-XXX), check the error log file, and restart the process.

Question: VS Code throws an error and the log show *docker: open .devcontainer/.env.devcontainer: The system cannot find... message.

Answer: This error message means you do not have a .dev.devcontainer environment variables file in the .devcontainer folder. Please create it using the template from a .dev.devcontainer.example file.

Conclusion and Next Steps

Docker is an open containerization platform for developing, testing, deploying, and running any software application. It helps developers create a consistent development environment (aka devcontainer) without manually maintaining dependencies and toolsets for the project. The VS Code Remote - Containers let developers develop applications with a devcontainer using VS Code full-featured sets such as debugging and various extensions. This devcontainer is easy to set up and share among the project team.

This example project is just a brief introduction to the Remote - Containers extension. Developers can work with Docker Compose to build a customized Docker image that matches the development requirements, debugging, install various VS Code extensions to use in the Dev Container (via the GUI or configuration file), clone Docker container from Git repositoryattach the VS Code to a running containerport forwarding, and much more. I highly recommend you check the following VS Code resources for more details:

The refinitivapis/websocket_api Docker Image is a good starting point for developers who are new to the WebSocket API. Developers can use the Docker Image with the Remote - Containers extensions to set up a development environment, and run the Python WebSocket examples. Developers who are using other programming languages can install more compilers/runtime to run the WebSocket examples based on their preferred technology too.

References

For further details, please review the following resources:

For any questions related to this project or the WebSocket API page, please use the Developer Community Q&A Forum.

GitHub

Refinitiv-API-Samples/Article.WebSocketAPI.CSharp.DevContainer.RTO