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.
- refinitivapis/realtimesdk_c: This docker image contains the latest version of the RTSDK C/C++ libraries and examples.
- refinitivapis/realtimesdk_java: This docker image contains the latest version of the RTSDK Java libraries and examples.
Prerequisite
This devcontainer example requires the following dependencies software and libraries.
- Visual Studio Code editor.
- Docker Desktop/Engine application.
- VS Code - Remote Development extension pack
- Access to the Refinitiv Refinitiv Data Platform and Refinitiv Real-Time - Optimized. (for the RTO example only)
- 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.
- Pull refinitivapis/websocket_api as the Base Image with the FROM instruction.
- Install .NET SDK and runtime to the Image (As of July 2023: The RTO C# examples support .NET version 6.0)..
- Install additional packages for VS Code and the Remote - Containers extension.
- 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:
- VS Code: Debugging User Guide.
- VS Code: Integrate with External Tools via Tasks.
- Configuring launch.json for C# debugging.
- Console (terminal) window setting.
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 repository, attach the VS Code to a running container, port forwarding, and much more. I highly recommend you check the following VS Code resources for more details:
- Developing inside a Container
- Remote development in Containers tutorial
- Create a development container
- devcontainer.json reference
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:
- WebSocket API on the Refinitiv Developer Community website.
- Refinitiv Real-Time & Distribution Family page page.
- Changes to Customer Access and Identity Management: Refinitiv Real-Time - Optimized
- Websocket API Quick Start page.
- Developer Article: 10 important things you need to know before you write an Enterprise Real Time application article.
- Introduction to the refinitivapis/websocket_api Docker Image article.
- Develop with Refinitiv Real-Time SDK Docker Image in VS Code article.
- Introduction to the refinitivapis/realtimesdk_c Docker Image article.
- Introduction to the refinitivapis/realtimesdk_java Docker Image article.
- Coding & Testing Linux Applications on Windows using WSL and VS Code article.
- VS Code: Developing inside a Container page.
- VS Code: Remote development in Containers tutorial page.
- VS Code: Create a development container page.
- VS Code: devcontainer.json reference page.
- VS Code: Create a development container: Dockerfile page.
- VS Code: Debugging and Task Variables reference page.
- VS Code: Remote Development: Environment variables reference page.
- Try Out Development Containers: .NET Core page.
- Docker run reference page.
- Dockerfile reference page.
- Setting up a VS Code Dev Container blog post.
- Hands-On with VSCode & "Dev Containers" blog post.
- Development Acceleration Through VS Code Remote Containers: An Introduction blog post.
- Secure and immutable development environments with Dev Containers blog post.
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