Client JavaScript - XSockets/XSockets.NET-4.0 GitHub Wiki

##JavaScript To get the client just get the latest package from http://nuget.org/packages/xsockets.jsapi

The JavaScript API supports RPC, PUB/SUB and WebRTC.

###Client Setup The JavaScript client has no dependencies, just add the XSockets.latest.js to your page. You can get the latest package from http://nuget.org/packages/xsockets.jsapi

<script src="Scripts/XSockets.latest.min.js"></script>

###How to establish a connection To get a connection just pass in the endpoint to the server.

var conn = new XSockets.WebSocket('ws://localhost:4502',['chat']);

Note that the second parameter is an array of controllers to connect to. We only use one controller in this sample.

###How to configure the connection You have a few options when creating the connection, such as sub protocol, query strings and controllers.

####How to specify query string parameters You might wanna pass in query string parameters in the connection. This is done by setting the third parameter to key-value pairs of JSON-object.

var conn = new XSockets.WebSocket('ws://localhost:4502',['chat'],{username:'steve',age:35});

####How to specify controllers Since you can multiplex over several controllers on one connection you can specify the controllers to use when you create the connection. If you would like to connect to three controllers A, B and C you would do:

var conn = new XSockets.WebSocket('ws://localhost:4502',['a','b','c']);

The names of the controllers is not case sensitive so A is the same as a.

###RPC

####How to set properties on the server from the client Since we have state on all controllers in the connection and can take advantage of that we can store information server side and not send trivial things like a user name each time we want to communicate.

Server

A simple model for a chat

public class ChatModel
{
    public string UserName {get;set;}
    public string Text {get;set;}
}

A controller where we use state to only send in text since the username is known.

//using XSockets.Core.XSocket;
//using XSockets.Core.XSocket.Helpers;

public class Chat : XSocketController
{
    public string UserName {get;set;}
    public void ChatMessage(ChatModel message)
    {
        message.UserName = this.UserName;
        this.InvokeToAll(message,"chatmessage");
    }
}

Client

conn.controller('chat').setProperty('username','David');

####How to call server methods from the client

Server

A simple model for a chat

public class ChatModel
{
    public string UserName {get;set;}
    public string Text {get;set;}
}

A controller where we use state to only send in text since the user name is know. See How to set properties on the server from the client

//using XSockets.Core.XSocket;
//using XSockets.Core.XSocket.Helpers;

public class Chat : XSocketController
{
    public string UserName {get;set;}
    public void ChatMessage(ChatModel message)
    {
        message.UserName = this.UserName;
        this.InvokeToAll(message,"chatmessage");
    }
}

Client

Since we already have set the property of UserName on the server we only need to send the Text property

conn.controller('chat').invoke('chatmessage',{Text:'Calling chatmessage on server and passing a part of the complex object'});

####How to define methods on the client that the server can call To define a method that the server can call from a Controllerjust add a method to the controller in JavaScript. The parameters can be complex objects.

Method name has to be lowercase in the JavaScript API. For example:

this.Invoke('Hello from server','ChatMessage'); 

on the server will execute chatmessage on the client.

Client

var conn = new XSockets.WebSocket('ws://localhost:4502',['chat']);

conn.controller('chat').chatmessage = function(data){
    console.log(data.UserName + " - " + data.Text);
};

Server

A simple model for a chat

public class ChatModel
{
    public string UserName {get;set;}
    public string Text {get;set;}
}

A controller where we use state to only send in text since the user name is know. See How to set properties on the server from the client

//using XSockets.Core.XSocket;
//using XSockets.Core.XSocket.Helpers;

public class Chat : XSocketController
{
    public string UserName {get;set;}
    public void ChatMessage(ChatModel message)
    {
        message.UserName = this.UserName;
        this.InvokeToAll(message,"chatmessage");
    }
}

####How to call a server side method and wait for the result

Client

conn.controller('stockticker').invoke('getstocks').then(function(data){
    console.log(data);
});

Server

public IEnumerable<Stock> GetStocks()
{
    return _stockService.GetAll();
}

###PUB/SUB ####How to define subscription methods on the client that the server can publish to

conn.controller('chat').subscribe('chatmessage', function(data) {
    console.log(data);
});

#####How to subscribe one time If you only want to get a message once and then unsubscribe automatically you can use one

conn.controller('chat').one('chatmessage', function(data){
    console.log(data);
});

This will make sure that the client unsubscribe to the topic after getting the first message.

#####How to subscribe n times If you want to get a message 1 to n times and then unsubscribe automatically you can use many

conn.controller('chat').many('chatmessage', 3 function(data){
    console.log(data);
});

This will unsubscribe the chatmessage topic after getting 3 messages.

How to know when the subscription is ready

When you compare PUB/SUB with RPC an obvious disadvantage with PUB/SUB is that you do not know if the server has bound the subscription when you do a publish. Therefor you can pass in an additional function to get a callback from the server when the subscription is completed.

This works similar for all subscribe methods.

subscribe(topic, fn, cb);
one(topic, fn, cb);
many(topic, n, fn, cb);

where fn is called when a publish occurs and cb is the callback that confirms the subscription.

####How to publish to server methods from the client

Client

conn.controller("chat").publish("chatmessage",{Text: "Hello people!"});

Server

//using XSockets.Core.XSocket;
//using XSockets.Core.XSocket.Helpers;

//The server migth publish the message back to all clients subscribing
public void ChatMessage(ChatModel chatModel)
{
    this.PublishToAll(chatModel, "chatmessage");
}

###How to handle connection lifetime events The events on connection level provide information about the socket being opened/closed. The controllers has their own lifetime events.

OnConnected

conn.onconnected = function(){
    console.log('socket connected');
};

OnDisconnected

conn.ondisconnected = function(){
    console.log('socket disconnected');
};

###How to handle controller lifetime events The controller has nothing to do with the actual socket. These events tell you about the controllers you are using over your connection.

OnOpen Event

conn.controller("chat").onopen = function(ci){
    console.log('opened',ci);
};

OnClose Event

conn.controller("chat").onclose = function(ci){
    console.log('closed',ci);
};

Open a controller

As soon as you start to communicate over a new controller the OnOpen event will fire. You actually do not need to specify the controller in the connection. As long as the controller exists on the server the OnOpen event will fire.

Close a controller

To close as controller (not the actual connection/socket) you just call the Close method on the controller instance. This will fire the OnClose event on the controller.

conn.controller("chat").close();

###Binary data XSockets has supported binary messages for a long time, but in 4.0 we have made it even easier than before.

####How to handle binary data Lets say that we want to send binary data from the client to the server.

Clients

Client - JavaScript

// Create a simple Array buffer and fill it with "something"
var arrayBuffer = new ArrayBuffer(10);
// Send the binary data and metadata to XSockets
conn.controller("chat").invokeBinary("myfile",blob);

Server

//using XSockets.Core.Common.Socket.Event.Interface;
//using XSockets.Core.XSocket;

public void MyFile(IMessage message)
{
    var filecontent = Encoding.UTF8.GetString(message.Blob.ToArray());
}

####How to pass meta-data together with binary data If we want to attach metadata about the binary data that is easy to do. Just pass along the object representing the metadata and XSockets will let you extract that data on the server.

Client

Client - JavaScript

// Create a simple Array buffer and fill it with "something"
var arrayBuffer = new ArrayBuffer(10);
// Send the binary data and metadata to XSockets
conn.controller("chat").invokeBinary("myfile",blob,{Name:"xfile.txt"});

Server

//simple class for holding metadata about a file
public class FileInfo
{
    public string Name {get;set;}
}

//using XSockets.Core.Common.Socket.Event.Interface;
//using XSockets.Core.XSocket;
//using XSockets.Core.XSocket.Helpers;

public void MyFile(IMessage message)
{
    var filecontent = Encoding.UTF8.GetString(message.Blob.ToArray());
    var metadata = message.Extract<FileInfo>();
}

Just use Extract<T> to get back to metadata attached to the binary data.

###How to handle errors

conn.controller("chat").onerror = function(err){
    console.log(err);
};

Using In-Memory Storage

This feature lets you store any serializable object on the server by using simple methods on the client API's. This is useful when you need to store data between connections/pages for the client. You are responsible for cleaning up the memory your self since data written to the storage will remain there until you remove it or the server stops.

Note: You can set any serializable object as value in the storage

Setting data on the server

Set the generic type that you want to store (in this case string)

conn.controller('chat').storageSet('color','red');

Getting data from the server

conn.controller('chat').storageGet('color', function(data){console.log(data)});

Removing data on the server

conn.controller('chat').storageRemove('color');

Clear the storage

conn.controller('chat').storageClear();

⚠️ **GitHub.com Fallback** ⚠️