1. Introduction
In this Example we will create a Single-Call Remoting class which will live on the Server. ‘Dotnet Remoting’ is a client and server based distributed object technology. Here, we will build two applications. One is a Remote Server which hosts Single-Call Remote, and another one is a Client. First, we will complete the Server Application and then proceed with the client.
2. About this Single-Call Remote Server and Client Example
We will create the server as a console application. This console application will host our Single-Call Remote object on the server. The client will make a call to the public member functions exposed by that remote object.
The client is a windows form application, which will get access to the remote hosted objects and uses it. Below is the screenshot of the client application.

Dotnet Remoting – Client Application
When we click the Get Details button, the client makes a call to the remote server console application. The server will give the Customer Id, Customer Name, Last Deposit and Last Withdraw to the client. We will learn other remoting notions when we move along. First, we will go ahead and start with our Remote server console application.
3. Create Single-Call Remote Server Application
Follow the below steps to create a C-Sharp Console Application.
- Create a new console application and name it as ‘ConServer’.
- Right click the ConServer Project and choose Add Reference.
- From the dialog displayed, Select ‘System.Runtime.Remoting’ from the .net tab and click the OK button. This step provides access to the dot net remoting API.
- Next, add a class named LastTrans to the Project. And then add one more class and name it as RemCustomer.
Explanation
First, We created a console application project and then got access to the dot net remoting assemblies. Then we added classes to the project. The ‘RemoteObject’ instance is the one which we will keep in the Server’s memory. And at run-time, we will create LastTrans object on the Server and send it to the client through the RemoteObject instance which lives in the Server’s memory.
We will turn our LastTrans object as Bit Stream and send it to the Client Console Application. In the Client side, we will recreate the actual LastTrans object from the Bit Stream. The process of transforming an object to Bit Stream format is known as Object Serialization.
By this time, the Visual Studio created all the basic code required for the remoting. Now we can write the code for the Single-Call Remoting Server.
4. LastTrans as Serializable Class
1) First, we locate the LastTrans Class created by the IDE and Mark it as ‘Serializable’ by adding the
serializable
attribute before the Class. Also, we will make this Class as public. Now, we can use it as a Remote Class. Below is the code for it:
1 2 3 4 |
//RemoteServer_018: Make the Class Serializable [Serializable()] public class LastTrans { |
2) Next, we add below private variable to our class.
1 2 3 4 |
//RemoteServer_011: Private field for the Newly //added class private int LastDeposit; private int LastWithdraw; |
3) In the constructor, we initialize the above declared private variables. Note, here we hard-coded the values. In real world, it will be queried from the database to get the latest result. Below is the code:
1 2 3 4 5 6 7 8 9 |
//RemoteServer_012: Constructor for Last Transactions. //At present we will Default it to some constant value public LastTrans() { //Hard Coded here. In real world make a query to //the Database to get the latest information. LastDeposit = 68800; LastWithdraw = 12000; } |
4) Next, we add functions to return these private variables. The client uses these functions to get the Last Deposit amount and Last Withdrawal amount.
1 2 3 4 5 6 7 8 9 10 11 12 |
//RemoteServer_013: Get the Last Transaction amount public int GetLastDeposit() { Console.WriteLine("Last deposit Queried..."); return LastDeposit; } public int GetLastWithdraw() { Console.WriteLine("Last Withdrawl amount Queried..."); return LastWithdraw; } |
The ‘Console.WriteLine’ function which we wrote above prints nothing on the console window of the Remote Server. This is because, when a client makes a call, the object will be serialized as Bit Streams before shipping to the client machine. The client makes an object from this stream and function call on the object gets executed on the client machine.
5. The Single-Call Remoting RemCustomer Class
1) First, we will Include the below-specified namespace before implementing RemCustomer class.
1 2 |
//Remote_003: Include the Namespace using System.Runtime; |
2) In the following sections, we will make this RemCustomer Class to act as the Single-Call Remote Object. To make any IDE created object as Remote Server compatible, (Refer step 4 in Section 3) locate the Class and derive it from the ‘
MarshalByRefObject
‘. OK. Why we need that derivation? Because, we are planning to keep this object in Server’s Remote Pool. Remote Pool is a memory area in the Server where all the distributed Remote Object lives. Below is the second step of the code:
1 2 3 |
//RemoteServer_004: Make the class Remotable by inheritance. public class RemCustomer : System.MarshalByRefObject { |
3) Next, we declare the data members for this class. Note, our Remote Object will serve the client through standard and user-defined data types. User-defined type in our case is the LastTrans which we already saw in the previous section. Also recall, we marked it as serializable.
1 2 3 4 5 6 |
//RemoteServer_005: Feilds on the remote Class private string CustName; private int CustId; //RemoteServer_014: Instance for LastTrans declared private LastTrans trans; |
4) The constructor will initialize the members which we declared in the previous step. Constructor is below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
//RemoteServer_006: Constructor for the Remote Object public RemCustomer() { CustName = "Ram Gopal"; CustId = 1235; Console.WriteLine( "Instance of Remote object Created..."); //RemoteServer_015: Instance for LastTrans created trans = new LastTrans(); Console.WriteLine( "Instance of Last Transaction object created. "); } |
5) We declared all the data members as private. The below member functions with public scope will help the client for accessing these private members. Below is the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//RemoteServer_007: Get the Customer id public int Get_id() { Console.WriteLine("Customer Id requested..."); return CustId; } //RemoteServer_008: Get the Customer Name public string Get_Name() { Console.WriteLine("Customer Name requested..."); return CustName; } //RemoteServer_017: Instance for LastTrans declared public LastTrans GetLastTrans() { Console.WriteLine("Transaction object requested..."); return trans; } |
Now our Remote class also ready to serve the windows form-based client which we will write soon. Note, the
MarshalByrefObject
states that this
RemCustomer
will live on the server and a reference to it will be sent to the client. The client calls this reference as a ‘Proxy’. We will move to our last step of registering the RemCustomer as Single-Call Remote Object with ‘Net Remoting Pool’.
6. Hosting RemCustomer as Single-Call Remoting Object
6.1 Import Remoting Assemblies
First, we need to import required Remoting Assemblies to our code. To do that, locate the static void main, which is the program entry point for the console application. In the file’s top (program.cs if you had not changed the file name) we will include the Remoting Assemblies as shown below:
1 2 3 4 5 |
//RemoteServer_001: Required Assemblies using System.Runtime; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; |
6.2 Single-Call Remoting Server Channel and Port
Next, we create a ‘TCP Channel’ with a Port Number 13340 and register it in the server machine. The client application will use this port to communicate with the Remote Object. Below code creates a TCP Communication Channel and registers that with the server machine in which the server application will run.
1 2 3 4 5 |
//RemoteServer_002: Create a communication channel //(Server) and register it TcpServerChannel SrvrChnl = new TcpServerChannel(13340); ChannelServices.RegisterChannel(SrvrChnl, false); |
6.3 Register RemCustomer as Single-Call Remoting Object
Once the communication method is specified and registered with Server, we must register our Remote Object also on the Server machine. We use the remoting API ‘
RegisterWellKnownServiceType
’ to do that. The first parameter passed to the function specifies the object type being registered. The second one gives a unique name for the registered object. In our case, for simplicity, we keep the registration name same as the class name. But, one can also use a different name. The Client should use the same name when they ask for the Proxy of the Remote Object. The third parameter says how the Server should activate the Remote Object. In this example, we are using the ‘Single Call’ activation. This means for each Client call an object will be created and maintained in the remote pool. We will see more about it after writing our Client Application.
1 2 3 4 5 6 |
//RemoteServer_009: Register the Remote Class so //that the Object can go and sit on the Remote pool RemotingConfiguration.RegisterWellKnownServiceType( typeof(ConServer.RemCustomer), "RemCustomer", WellKnownObjectMode.SingleCall); |
6.4 Run the Remote Server
The server is ready. We can break the execution using the
ReadKey
method so that the server will be kept in the running state.
1 2 3 4 5 |
//RemoteServer_010: Halt the server so that //Remote client can access the object Console.WriteLine("Server is Running..."); Console.WriteLine("Press Any key to halt the Server"); Console.ReadKey(); |
We can run the server now. But there is nobody to consume the registered remote object on our server. We will now move on creating the Client. Below is the screenshot of server in the running state:

Remote Server in Running State
Note: Even though the server is running, C# will not create the object in the Remote Pool as the activation method is a Single-Call. For each client call, a separate instance of the RemCustomer will be created and kept in the Remote Pool. We will see it after writing the client.
7. The RemClient Project
We already know our client is a Windows Form Application. Follow the steps below to create the client application that uses the Remote Object hosted by our Remote Server. Make sure the Console Server project which was created in Section 3 is still in the open state.
- Click on File|Add|New Project.
- Select Visual C# in the project Types and Select Windows Application from the available template.
- Name the project as RemClient and click the OK button.
- Design the form by referring the first screenshot. Download the attached project for reference and set the properties by referring it. ConServer.sln will open both the projects. In your case, this solution will be created now as you are adding one more project. A solution file is a combination two or more projects.
- Add reference for Remoting assembly as we did in the server step 3.
- Once the form is designed, double click the Button Control to get the Click Event handler for it.
- Right click the RemClient Project and select add reference. Go to the project tab and select ConServer Project.
In the above steps, we created a windows application and designed the form. Then, we added a reference to the Dot net’s Remoting assembly and ConServer project.
8. Remote Client Implementation
8.1 Assemblies Required
First, we should include the below specified Name Spaces on top of the form‘s file. The code is below:
1 2 3 4 5 |
//RemoteClient_001: Include the required namespace using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using ConServer; |
8.2 Getting Client Proxy for RemCustomer Remote Object
Now, we will implement the click event handler. The button click will invoke the public functions exposed by the RemCustomer Remote Object. Make sure the RemCustomer Class on our Server Application is public. The first step is to get the Proxy for the Remote Object hosted by the Console Application on the Server. One can run the server on the Local or Remote machine. In both cases, we need a Proxy for the RemCustomer in the client machine. Below is the code for doing that:
1 2 3 4 5 |
//RemoteClient_002: Get the remote object on the server RemCustomer remoteCust = (RemCustomer)Activator.GetObject( typeof(RemCustomer), "tcp://localhost:13340/RemCustomer"); |
8.2.1 Resolving RemCustomer Reference
In the first argument of ‘
Activator.GetObject
’, we pointed out what object we are looking for. In our case, it is the actual object type which is RemCustomer. The ConServer project reference we added is just to deal with this RemCustomer type. But, in the interface style, we need not reference the server project. We require just an interface type on both server and client. If the client builds the application to invoke the third-party remote server object, then the server developers normally give the interface implemented by RemCustomer. By doing that the server piece of implementation not exposed to the client developers. In our case, let us assume the same party develops both server and the client.
8.2.2 Resolving the Machine to Contact
The Second parameter has three parts on it. The first one is the machine name. As the Client and Server applications are on the same machine, we kept localhost instead of specifying the machine name or IP Address. If the Server application is running on a different machine say; RemoteMC22 then the localhost in the string should be replaced by the machine name.
8.2.3 Resolving the Communication Port of Single-Call Remoting Server
The Client Application now knows which machine it need to connect for the RemCustomer Proxy. But the Server may have a lot of networks communication, right? It may be an Oracle Server or Sql2005 Server or even a JBoss Web Server. How does the Server distinguish the incoming request? It does through the Port Numbers. Therefore, we registered the Server with a Port Number 13340. This Port on TCP communication is called ‘Dedicated Port’. Our Application Server registered the Port 13340 saying “This Port is in use like 80 for HTTP”. Our client application by specifying this port number next to the machine name, sets up the communication for a connection request.
8.2.4 Resolving Single-Call Remote Object
The Remote Pool can have one or more registered objects. So, the client should resolve this situation by specifying the registered name of the remote object. Now we can have a look at Section 6 point 3. Finally, we performed a type cast and stored the proxy in the
remoteCust
proxy reference.
8.2.5 Summary of Activator.GetObject
- First, a machine name in the network needs to be resolved.
- A Port Number specifying which specific Application on the Server needs to be contacted.
- The registered name specifies a single object type upon several registered remote objects. In our case, we registered only one against the name RemCustomer.
8.3 Proxy Objects – Not Real
Once the Proxy to the Remote Object is with us, we make a call to the functions through that Proxy. Note, Proxy just shows that the object is with you, but it is not. It transmits all the calls to the server to get the result. Below is the code, which uses the Proxy Object to make a call to the public functions exposed by the Remote object, ‘
remCutomer
’.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//RemoteClient_003: Get Customer Id and Name exposed by //the remote object itself int id = remoteCust.Get_id(); string name = remoteCust.Get_Name(); //RemoteClient_004: Get Some other object from the //server through the remote object. Note the object //should be serializable. LastTrans trans = remoteCust.GetLastTrans(); int lastdeposit = trans.GetLastDeposit(); int lastwithdraw = trans.GetLastWithdraw(); //RemoteClient_005: Display the information retrieved txtCustId.Text = id.ToString(); txtCustName.Text = name; txtLastDeposit.Text = lastdeposit.ToString(); txtLastWithdraw.Text = lastwithdraw.ToString(); btnInvokeRemote.Enabled = false; |
The picture below explains how the application will work.

How Single Call Server Activated Object Works
9. Testing the Example
To test it on the same machine, follow the steps below:
- Right click the solution and Click rebuild all.
- Now navigate to both the generated Executable using windows explore.
- Run the Console Server and leave it in running state.
- Run the Windows Client Application.
- Click the button on the Windows application and Observe the result on the Client Window as well as Server’s Console Window.
To Test it on different machine, Place the Server project on the different machine. Keep the client on your machine. Search for localhost in the client project and replace it with your machine name or IP Address and then build it. Run the Server first and then the client.
Below is the screenshot taken when both the applications are running in the same machine.

Running instance of Remoting Single-Call Server And Client
Source Code: Download From Chrome
Categories: Remoting
Tags: C# Activator GetObject, C# RegisterChannel, C# RegisterWellKnownServiceType, C# Single-Call Remoting, MarshalByRefObject