SocketXClient.Blazor
1.0.1.10618
dotnet add package SocketXClient.Blazor --version 1.0.1.10618
NuGet\Install-Package SocketXClient.Blazor -Version 1.0.1.10618
<PackageReference Include="SocketXClient.Blazor" Version="1.0.1.10618" />
<PackageVersion Include="SocketXClient.Blazor" Version="1.0.1.10618" />
<PackageReference Include="SocketXClient.Blazor" />
paket add SocketXClient.Blazor --version 1.0.1.10618
#r "nuget: SocketXClient.Blazor, 1.0.1.10618"
#:package SocketXClient.Blazor@1.0.1.10618
#addin nuget:?package=SocketXClient.Blazor&version=1.0.1.10618
#tool nuget:?package=SocketXClient.Blazor&version=1.0.1.10618
SocketX Blazor Client
Introduction
Microsoft .Net provides a ClientWebSocket class for managing the Client side
of a WebSocket connection. This is a concise class that exposes the methods
and properties that the WebSocket specification calls for.
Eclypses has created a SocketXClient class that introduces the Eclypses MTE technology
into the WebSocket protocol to protect all traffic that is transmitted between a Sender and a
Receiver.
It is a wrapper on the .Net ClientWebSocket and the method usage is similar.
This document describes the usage of the SocketXClient in a Blazor application.
Application Configuration
There are a few application configuration items that your client application must include for the SocketXClient to be used. These should be supplied in your application IConfiguration object which could be populated from an appsettings.json file, an Environment Variable, the Command Line or a custom configuration class that you may have created.
These items include:
- LICENSED_COMPANY -- The company name that your MTE Library is licensed to:
My Company Inc. - LICENSE_KEY -- Your license key:
abcDEF123+/HIJklm
NOTE: These items are root level items, they are not imbedded in an appsettings section
Example appsettings.json:
{
// SocketX configuration settings
"LICENSED_COMPANY": "My Company Inc.",
"LICENSE_KEY": "abcDEF123+/HIJklm",
// Application configuration settings
"AppSettings" : {
"AppVariable": "Log this",
"AnotherAppVariable": "Log this as well"
}
}
The Methods Involved
There are several methods that are required to handle protected WebSocket traffic.
- Constructor This creates a SocketXClient.
- ConnectAsync This handles the initial connection from a client to a server.
- SendAsync This handles sending a message to a remote endpoint.
- ReceiveAsync This handles receiving messages from a remote endpoint.
- CloseAsync This closes a WebSocket connection and disposes of all resources.
Constructor
This creates an instance of the SocketXClient. Its signature varies slightly from the .Net ClientWebSocket. See an example class below,
using SocketXClient.Blazor;
using Microsoft.JSInterop;
using System.Net.WebSockets;
/// <summary>
/// This is an example class that uses the SocketXClient
/// to send protected messages to the SocketXServer service and eventually
/// to your WebSocket service.
/// </summary>
public MyBlazorClass
{
private readonly IConfiguration _config;
private readonly IJSRuntime _jsRunTime;
private readonly ILogger<MyClass> _logger;
private SocketXClient _myWebSocket;
/// <summary>
/// Initializes a new instance of the <see cref="MyBlazorClass"/> class.
/// </summary>
/// <param name="config">The configuration instance used to retrieve application settings.</param>
/// <param name="jsRuntime">The JavaScript runtime instance used to invoke JavaScript functions from .NET.</param>
/// <param name="loggr">The standard .Net ILogger for this class.</param>
public MyBlazorClass(IConfiguration config, IJSRuntime jsRuntime, ILogger<MyClass> logger)
{
_config = config;
_jsRuntime = jsRuntime;
_logger = logger;
//
// Note the additional parameters required for the SocketXClient.
// The application configuration must include the properties described above.
// The java script runtime is required to utilize the MTE WASM module.
//
_myWebSocket = new SocketXClient(_config, _jsRuntime);
}
}
ConnectAsync
This establishes the channel between an originating application (a Blazor Web Page) and a destination application (a WebSocket service).
Once you have created a SocketXClient you must connect to the WebSocket service. That is done using the ConnectAsync method as shown in this example:
/// <summary>
/// Starts a protected conversation with my WebSocket service via the SocketXServer service.
/// </summary>
/// <param name="baseAddress">The address of the paired SocketXServer service .</param>
/// <param name="ct">The CancellationToken to monitor this connection.</param>
public async Task StartMyConversation(string baseAddress, CancellationToken ct)
{
//
// The base address must be the SocketXServer service with any optional
// path that myService needs to do the initial upgrade. So for instance
// if my SocketXServer service is listening at wss://socketxserver.cloud.com
// and that proxies to wss://mycompany.cloud.com/api/ws then the base
// address must be wss://socketxserver.cloud.com/api/ws.
// The extra path is captured and appended by the SocketXServer service
// when it establishes the connection to your service.
//
Uri theUri = new Uri(baseAddress);
await _myWebSocket.ConnectAsync(theUri, ct);
if (_myWebSocket.State == WebSocketState.Open)
{
_logger.LogInformation($"WebSocket connection established to {theUri}");
//
// Start the listening loop since we are now connected.
//
StartListeningToTheSocket();
}
}
SendAsync
Your application can now send messages to the protected channel as demonstrated below:
/// <summary>
/// Sends a protected message to my WebSocket service via the SocketXServer service.
/// </summary>
/// <param name="message">The text message to send to my WebSocket service.</param>
/// <returns>Completed Task.</returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task SendMyMessageAsync(string? message, CancellationToken ct)
{
if (_myWebSocket is null || _myWebSocket.State != WebSocketState.Open)
{
throw new InvalidOperationException("WebSocket is not connected.");
}
try
{
byte[] messageBytes = JsonSerializer.SerializeToUtf8Bytes(message);
await _myWebSocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, endOfMessage: true, ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while sending a text message via WebSocket.");
throw;
}
}
/// <summary>
/// Sends a protected message to my WebSocket service via the SocketXServer service.
/// </summary>
/// <param name="message">The binary message to send to my WebSocket service.</param>
/// <returns>Completed Task.</returns>
/// <exception cref="InvalidOperationException"></exception>
public async Task SendMyMessageAsync(byte[]? message, CancellationToken ct)
{
if (_myWebSocket is null || _myWebSocket.State != WebSocketState.Open)
{
throw new InvalidOperationException("WebSocket is not connected.");
}
try
{
await _myWebSocket.SendAsync(new ArraySegment<byte>(message), WebSocketMessageType.Binary, endOfMessage: true, ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while sending a binary message via WebSocket.");
throw;
}
}
ReceiveAsync
Your application can now receive protected messages from the protected channel as shown below:
//
// Note: cts is a CancellationTokenSource so that we can cancel it
// if the received message is requesting a Close.
// Note: Be sure to check a received frame to ensure it is an EndOfMessage
// otherwise accumulate the bytes prior to processing.
//
try
{
//
// This loop will run until the socket is closed or a cancellation is requested.
//
while (!cts.Token.IsCancellationRequested && _myWebSocket.State == WebSocketState.Open)
{
//
// This memory stream accumulates the received frames until EndOfMessage is true.
//
using (MemoryStream ms = new MemoryStream())
{
var buffer = new byte[1024 * 4];
//
// Receive a frame from the SocketXServer service - it is protected by
// Eclypses MTE, but the SocketXClient reveals the bytes that
// your upstream service originally sent.
//
var result = await _myWebSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cts.Token);
//
// If we received a CloseMessage, close the SocketXClient.
//
if (result.MessageType == WebSocketMessageType.Close)
{
await _myWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", cts.Token);
_logger.LogInformation("WebSocket connection closed.");
cts.Cancel();
break;
}
//
// Capture the revealed bytes into our accumulator MemoryStream.
//
ms.Write(buffer, 0, result.Count);
if (result.EndOfMessage)
{
//
// Process the received message as needed
//
byte[] messageBytes = ms.ToArray();
await ProcessTheReceivedMessage(messageBytes, result, cts);
}
}
}
}
catch (OperationCanceledException)
{
_logger.LogInformation("WebSocket listening loop was cancelled.");
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while managing the WebSocket listening loop.");
cts.Cancel();
}
finally
{
// Ensure the task completion source is set to avoid deadlocks
if (!cts.IsCancellationRequested)
{
cts.Cancel();
}
}
CloseAsync
When you need to close the connection from your Blazor client such as your application issues a logoff, issue the CloseAsync command as shown below:
public async Task DisconnectAsync(CancellationToken ct)
{
try
{
//
// This sends a Close request to the SocketXClient so that it gracefully shuts down.
// and then disposes of the actual .Net ClientWebSocket.
//
await _myWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "User logged out", ct);
}
catch (Exception ex)
{
throw;
}
}
Configuration
Since the SocketXServer service acts as a proxy between your front end application and your web socket service, there is some configuration required to ensure communication channels correctly converse.
Example Setup
Your front end application (without the SocketXServer service) requires an initial connection request to upgrade to a WebSocket. For sake of example, consider the following:
- https://myfrontend.mydomain.com is your front end (Blazor application).
- wss://myapplication.mydomain.com is your web socket service that handles all web socket traffic for your application.
- https://mysocketxserver.cloud.com is your SocketXServer service that protects and proxies between the two.
The front end service (https://myfrontend.mydomain.com) must have a configuration setting (probably in appsettings.json) to point to the SocketXServer service such as:
"AppSettings": {
"SocketXServerUrl": "wss://mysocketxserver.cloud.com/api/ws"// The url to connect to for the WS Upgrade request when using MTE
}
You should then retrieve that setting (AppSettings:SocketXServerUrl) and use that as the baseAddress in your ConnectAsync method (see above).
The SocketXServer service (mysocketxserver.cloud.com) contains the configuration to actually find your web socket service (wss://myapplication.mydomain.com).
This is handled by a mapping entry in the configuration for the SocketXServer service. The configuration for SocketXServer must have that entry in its configuration file to properly proxy messages to your service.
See the documentation for your SocketXServer for the specific details.
Using Http traffic in your application
If you also have Http traffic in your application that you need to protect you must also use the Eclypses MteRelay service to protect that traffic.
For instance, your application may require standard authorization and authentication to be established prior to allowing a WebSocket channel to be established.
Since the SocketXServer protects WebSocket communication, you must use the MteRelay service to
protect the Http requests and replies.
This is NOT a requirement, however, many front end applications require both protocols. This section describes
the configuration in your front end application needed to establish protection for the Http traffic.
Consider the following services that you have running:
- https://myfrontend.mydomain.com is your front end (Web application).
- https://myapplication.mydomain.com handles your Http traffic as well as your WebSocket traffic.
- https://mymterelay.cloud.com is your MteRelay service that protects and proxies http traffic between the two.
Your front-end application requires the following settings in your appsettings.json file:
{
"mteRelay": {
"Endpoints": [
{
"HttpClientRelayName": "API1",
"RelayIdentifier": "API1",
"MteRelayUrl": "https://mymterelay.cloud.com", // This is the url to your mte relay server.
}
],
"ShouldProtectUrl": true, // If true the route to your API will be protected by MTE.
"HeaderDisposition": "EncodeAllHeaders" //EncodeAllHeaders, EncodeNoHeaders, EncodeListOfHeaders (include pipe delimited HeadersToEncode)
}
}
Your MteRelay service must have the address of your upstream service that becomes the ultimate destination for your Http traffic.
This setting may be in your appsettings.json file or may be supplied via an Environment variable.
{
"APP_SETTINGS": {
"PERSONA" : "MRS",
"UPSTREAM" : "https://myapplication.mydomain.com" // The same upstream service is handling http and ws traffic.
}
}
Conclusion
The SocketXClient is a functional equivalent to the .Net ClientWebSocket with one minor exception.
The constructor requires an IConfiguration object to retrieve values from your configuration and it
requires an IJSRuntime object to invoke the WASM methods that are the actual Eclypses MTE library.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- Microsoft.AspNetCore.Components.Web (>= 9.0.9)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.9)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.9)
- Microsoft.Extensions.Logging (>= 9.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.1.10618 | 219 | 11/25/2025 |