Sample Server - Sending data to the client

Remoting SDK has a feature called 'server-sent events'. It allows client applications to subscribe for notifications sent from the server.

In this simple Chat sample such notifications will be used to relay chat messages to clients.

First step is to define the events interface.

Add a new Interface to the server app project as

using RemObjects.SDK; 
 
namespace ChatServer 
{ 
    [EventSink] 
    public interface IChatEvents : IROEventSink 
    { 
        void MessageReceived(string sender, string message);
    }
} 

That's it. There is no need to provide implementation of this interface as it will be auto-generated by the server bootstrapper at runtime.

Server-sent event interfaces have several obvious limitations:

  • They cannot contain properties or events
  • All interface methods should have a void return type

Both limitations are aimed at keeping the code clean. First one means that all members of the interface should clearly describe that it is an operation of sending out some data. Second one means that there is no code that will listen to the methods result.

Events data is sent out in asynchronous manner, i.e the user code just puts the event data to a queue and doesn't wait until all clients receive that data.

Second step is to subsctibe/unsubscribe client app to the events.

Open the LoginService code and add there code:

using System; 
using RemObjects.SDK; 
using RemObjects.SDK.Server; 
 
namespace ChatServer 
{ 
    [Service] 
    public class LoginService : RemObjects.SDK.Server.Service 
    { 
        [ServiceMethod] 
        public bool LogIn([StreamAs(StreamingFormat.Utf8String)]string loginEx) 
        { 
            try 
            { 
                SemicolonSeparatedString login = new SemicolonSeparatedString(loginEx); 
                 
                if (string.IsNullOrEmpty(login["User ID"]) || (login["User ID"] != login["Password"])) 
                { 
                    this.DestroySession(); 
                    return false; 
                } 
                 
                this.Session["User ID"] = login["User ID"]; 
                this.Session["Login Time"] = DateTime.UtcNow; 
                 
                this.SubscribeClientEventSink(typeof(IChatEvents)); // This line was added 
                 
                return true; 
            } 
            catch (Exception) 
            { 
                this.DestroySession(); 
                throw; 
            } 
        } 
             
        [ServiceMethod] 
        public void LogOut() 
        { 
            this.UnsubscribeClientEventSink(); // This line was added 
             
            this.DestroySession(); 
        } 
    } 
} 

So the event management code is actually just a simple calls to corresponding methods performed during log in/log out process.

Third step is to actually send out the event data.

Add the ChatService code and modify it as follows:

using RemObjects.SDK.Server; 
 
namespace ChatServer 
{ 
    [Service] 
    [ServiceRequiresLogin] 
    public class ChatService : Service 
    { 
        [ServiceMethod] 
        public void SendMessage(string message) 
        { 
            this.GetEventSink<IChatEvents>().MessageReceived((string)this.Session["User ID"], message); 
        } 
    } 
} 

Again the code is quite simple:

The internal Remoting SDK infrastructure is queried for the server-sent events interface implementation object and then a method of this object is called.

The GetEventSink method has several overloads that allow to filter recipients of the event data. For example for private chat message it would be wise to limit the recipients list with just one recipient.

ChatServer code can be downloaded here.

Start the ChatServer and move to the next section to implement handlers for the server-sent events.