Click here to Skip to main content
15,911,711 members
Articles / Programming Languages / C#
Article

Multiple Views on Different Computers with a Single Model on Server

Rate me:
Please Sign up or sign in to vote.
3.88/5 (9 votes)
30 Jul 2007CPOL2 min read 31.1K   339   20   1
Implements Multiple Clients with different views connected with a single server remotely. Server has a single centralized model database. All views are updated asynchronously if the model is updated from any client or server itself.
Screenshot - ServerClients.jpg

Introduction

This article is a merger of MVC architecture and .NET remoting using HTTP and TCP channel. The server is nothing but an executable that acts as a container of controller, model and local view. Individual views are running with their discrete on local or remote computers and they have proxies of remote server controller and model.

How It Works

Screenshot - ClientServerMVC.jpg

Activating the server will create the local view, controller and model objects. It registers controller and model objects for remote purposes. The server starts listening on HTTP and TCP ports. In this code sample, all port numbers are hard coded that can be modified to make it dynamic. Server side controller and model proxies will be marshaled to client on specific channel with specific formatters using special IConnect object. IConnect is something that acts as a connector between client and server. Client activates IConnect object in the server and takes the proxy object of controller and model through IConnect.

Client-Server Communication

When the client starts, it tries to connect to the server and activates the IConnect object at server. IConnect is a singleton type object and if multiple clients try to connect, it will pass the same object proxy to each client. Once IConnect object proxies are marshalled to server, the client can access proxies of the controller and model by calling properties (get-set) of IConnect.

All the UI events either from server or from client go to the controller on the server. The controller on the server updates the model if required. Once the model is updated, it updates all the views (server + clients views) using delegates. If any client is not registered with a delegate, it will not receive broadcast update messages from the model.

Lease time and server client disconnectivities are not covered in this article. If the user wants, he can derive InitializeLifetimeService() of MarshalByRefObject class and can modify lease time.

All Clients are statically programmed to connect to localhost server in this sample code. The user can modify localhost with remote IP address and the code will work fine.

Using the Code

The following is the server boot up routine that:

  1. Registers channels (HTTP and TCP)
  2. Registers remote objects (Connect, Controller and Model)
  3. Displays local UI
C#
//Server register for TCP channel
BinaryClientFormatterSinkProvider clientProvider = null;
BinaryServerFormatterSinkProvider serverProvider = 
new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = 
System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
IDictionary props = new Hashtable();
props["port"] = 3870;
props["typeFilterLevel"] = TypeFilterLevel.Full;
TcpChannel tcpChannel = new TcpChannel(
                props, clientProvider, serverProvider);
ChannelServices.RegisterChannel(tcpChannel);
//Server register HTTP channel 
props.Clear();
props = new Hashtable();
props["port"] = 3970;
props["typeFilterLevel"] = TypeFilterLevel.Full;

SoapClientFormatterSinkProvider scl = null;
SoapServerFormatterSinkProvider ssr = new SoapServerFormatterSinkProvider();
ssr.TypeFilterLevel = TypeFilterLevel.Full;                                 
HttpChannel httpChannel = new HttpChannel(props, scl, ssr);
ChannelServices.RegisterChannel(httpChannel);          

RemotingConfiguration.RegisterWellKnownServiceType(
           typeof(windowConnect),
           "Window Connect", WellKnownObjectMode.Singleton);

RemotingConfiguration.RegisterWellKnownServiceType(
           typeof(windowController),
           "Window Controller", WellKnownObjectMode.Singleton);


RemotingConfiguration.RegisterWellKnownServiceType(
           typeof(windowModel),
           "Window Model", WellKnownObjectMode.Singleton);

wndController = new windowController();
theForm1 = new Form1();            
theForm1.WindowController = wndController;

theForm1.WindowModel = wndModel;
theForm1.UpdateFromServer();
Application.Run(theForm1);

Following is the client activation code that:

  1. Registers channel (HTTP or TCP)
  2. Registers own view
  3. Activates IConnect object
  4. Accesses proxy of controller and model remotely
C#
BinaryClientFormatterSinkProvider clientProvider = null;
BinaryServerFormatterSinkProvider serverProvider = 
	new BinaryServerFormatterSinkProvider();
serverProvider.TypeFilterLevel = 
	System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;

//register for TCP channel
IDictionary props = new Hashtable();
props["port"] = 0;
props["typeFilterLevel"] = TypeFilterLevel.Full;
TcpChannel tcpChannel = new TcpChannel(
props, clientProvider, serverProvider);
ChannelServices.RegisterChannel(tcpChannel);
            
//client registers himself
RemotingConfiguration.RegisterWellKnownServiceType(
	typeof(IView),
	"Window View", WellKnownObjectMode.Singleton);
Form1 theForm = new Form1();

IConnect windowConnect;
try //unable to connect to server
{
	windowConnect = (IConnect)Activator.GetObject(typeof(IConnect), 
	"tcp://localhost:3870/Window Connect");
	windowConnect.RegisterView(theForm);
	theForm.WindowController = windowConnect.ProxyController;
	theForm.WindowModel = windowConnect.ProxyModel;
}
catch (Exception e)
{
	MessageBox.Show("Server not running. Link cannot be established");
	return;
} 

The following code is used by both client and server programs. It contains the base classes of view, controller, model and connect.

C#
namespace MVCInterface
{
   public delegate void updateRadius();
   public class IView:System.Windows.Forms.Form
    {       
    public updateRadius updateRadiusEvent;
    }
    public abstract class IController:MarshalByRefObject
    {       
        public abstract void AnotherRadiusChange(int radius);             
    }

    public abstract class IModel:MarshalByRefObject
    {
        private int radius=12;
        public int Radius
        {
            get { return radius; }
            set { radius = value; }
        }

       public abstract void RadiusChange(int radius);
    }
    public abstract class IConnect:MarshalByRefObject
    {
        public abstract void RegisterView(IView proxyView);
        private IController _proxyController=null;

        public IController ProxyController
        {
            get { return _proxyController; }
            set { _proxyController = value; }
        }
        private IModel _proxyModel=null;
        public IModel ProxyModel
        {
            get { return _proxyModel; }
            set { _proxyModel = value; }
        }   
    }
} 

Points of Interest

I learned a lot about .NET remoting and MVC architecture with the implementation of this article.

History

  • 30th July, 2007: Initial post

About Myself

Screenshot - 23194745.jpg

Hi I am Vikas working on Microsoft technologies for last 2.5 yrs. Currently working with Tektronix,India as a Senior software Engineer. I have worked in Bharat Electronics, India also for 2 yrs.

mailme@maan_vikas@rediffmail.com

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
Vikas Maan is a software developer for last 4 years working on windows platform with multiple programming languages mainly VC++, C#.net etc.

Comments and Discussions

 
GeneralHi Pin
[Neno]20-May-08 4:22
[Neno]20-May-08 4:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.