.NET Remoting provides a way for application in different machines/domains to communicate with each other. To make an object remotable that should be inherited by MarshalByRefObject.
There are two types of activation modes an MBR object is classified to
Server Activated objects
Server Activated objects SAO’s are those remote objects whose lifetime is directly controlled by the server.
Single call activation Mode (object per call)
In the single call activation mode an object is instantiated for the sole purpose of responding to just one client request. After the request is fulfilled the .NET Remoting Framework deletes the object and reclaims the memory.
Singleton Activation Mode
In the Singleton activation mode at most (Minimum) there will be one instance of the remote object regardless of the no. Of clients accessing it.
Client Activated objects
Client Activated objects are those remote objects whose Lifetime is directly Controlled by the client.
FIRST WAY - To create Remoting application
Now lets prepare sample Remoting application
Files to be placed on Remote Server
#. Create a class file with following code
myObj.cs
using System;
using System.Runtime.Remoting;
namespace ACD
{
public class myObj : MarshalByRefObject
{
public string returnSomething()
{
return "<h1><font color=''red''>First Namespace</font></h1>" +
"<br /> server name: " + System.Environment.MachineName;
}
}
}
#. Compile this .cs file by csc command using Visual Studio.NET command prompt.
csc /t:library /out:myObj.dll myObj.cs
this will create myObj.dll file.
#. Create a web.config file with the following contents
Web.config
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown mode="Singleton" type="ACD.myObj, myObj"
objectUri="myObj.soap" />
</service>
</application>
</system.runtime.remoting>
</configuration>
Here type ="ACD.myObj, myObj" is the full type name, followed by the assembly name.
Suppose we have to use more than one assembly then add one more <wellknown> tag. Eg.
<wellknown mode="Singleton" type="ACD.myObj, myObj"
objectUri="myObj.soap" />
<wellknown mode="Singleton" type="ACD.First.myObjAnother, myObjectDLL" objectUri=" myObjAnother.soap" />
To use two assembly myObj, myObjAnother from the remote machine we need to write two <wellknown> tags in the web.config file instead of one tag.
Here ACD.First is the namespace, myObjAnother is the class name, myObjectDLL is the name of the assembly or .dll file. The objectUri value will be the nameOfClass.soap or .rem
On the Remote Server:
1) Create a directory called “myRemoteObject”. Create a Bin directory beneath it.
2) Create a new IIS virtual Directory called myIISObj that points to the myRemoteObject directory.
3) Place your compiled versions of myObj.dll in the myRemoteObject \Bin directory
4) Place the Web.Config file in the myRemoteObject directory.
Files to be placed on the Client machine
First way (Not recommended)
#. Create a client.config file which will tell the CLR how to access the remote object.
Client.config
<configuration>
<system.runtime.remoting>
<application name="Client">
<client url="http://andy2k/myIISObj">
<wellknown type="ACD.myObj, myObj"
url="http://172.21.14.21/myIISObj/myObj.soap"/>
</client>
<channels>
<channel ref="http" />
</channels>
</application>
</system.runtime.remoting>
</configuration>
If we are using more than one assembly from the remote server, place more <wellknown> server tag as you have placed in the web.config file like.
<wellknown type="ACD.myObj, myObj"
url="http://172.21.14.21/myIISObj/myObj.soap"/>
<wellknown type="ACD.First.myObjAnother, myObjectDLL" url="http://172.21.14.21/myIISObj/myObjectDLL.soap"/>
Here the IP address is the address of your remote server and myIISObj is the virtual directory you had created on the server.
#. Now in the client code, simply create the object as usual but first of all load the client config file.
try
{
RemotingConfiguration.Configure("client.config");
}
catch{}
//instantiate the remote object on the server
//(this is really just a proxy object here)
ACD.myObj anObj = new ACD.myObj();
Here RemotingConfiguration.Configure is in the try block, because once the configuration of the remote object is loaded and set, next time it will give error as you had already set the client.
Please note that the .dll you have put on the remote server should also be referenced on the local development machine, so that it wouldn’t give error at the time of running the application. If that .dll is not referenced, the application will complain about the namespace not found or so.
SECOND WAY - To create Remoting Application
1. Create interface for all the classes you have to use (create separate class library project for all the interfaces).
2. Create class file and inherit with MarshalByRefObject and their corresponding Interfaces too (create separate class library for the business object) . Eg. public class User : MarshalByRefObject, IMyObj
3. Compile both projects (above two), you will have to give reference to the interfaces .dll in the class library project.
4. Put class library .dll with the interface .dll on the remote server bin folder.
5. In the client application, reference interface .dll so that the application will run successfully or remote objects behavior is identified in the application. This will ease in coding.
In place of above code (instantiation with new keyword in the first way) use the following code.
Note: In this way there is no need of client.config file.
String str = string.Empty;
IMyObj thisO = (IMyObj) Activator.GetObject(typeof(IMyObj), "http://172.21.14.21/ACD_BusinessLogic/RemotingObjects.soap");
str = thisO.returnSomething();
Response.Write(str);
So total class code, interface code and the application code will be like this
Class code (myObj.cs)
using System;
using System.Runtime.Remoting;
namespace ACD
{
public class myObj : MarshalByRefObject, IMyObj
{
public string returnSomething()
{
return "<h1><font color=''red''>First Namespace with Interface</font></h1>Checked on 05th October 2006" +
"<br /> server name: " + System.Environment.MachineName + "<hr /><hr />";
}
}
}
Interface code(IMyObj.cs)
using System;
/// <summary>
/// Summary description for Class1
/// </summary>
public interface IMyObj
{
string returnSomething();
}
Client side application code
IMyObj thisO = (IMyObj) Activator.GetObject(typeof(IMyObj), "http://172.21.14.21/ACD_BusinessLogic/myObj.soap");
str = thisO.returnSomething();
thisO = null;
(here ACD_BusinessLogic is the virtual directory on the remote machine. myObj.soap is the objectUri value of the config file. returnSomething is the method that return string value.)
Issues at the time of development
#. If you are not sure that the application you are running is getting executed on the remote server try to put the following method and call them in your application, it will give the name of the computer where the object is being executed.
Public string getCompName()
{
return System.Environment.MachineName;
}
#. If sometimes, the object or assembly is being executed from your local machine try restarting the IIS of your local machine (it is possible only when you are opting for the first way of doing Remoting). Also confirm the application by stopping the IIS of the remote server and running the application, if the application is giving error (something like connection is closed…. ) then its confirmed that the object is being created on the remote machine and you have successfully setup Remoting. Now start the remote server’s IIS again and enjoys REMOTING.
#. Sometimes the following error occurs
System.NullReferenceException: Object reference not set to an instance of an object. at
System.Runtime.Remoting.MetadataServices.RealSchemaType.Resolve(StringBuilder sb) at
To overcome this error keep class and interface in different namespace.
Config file when more than one assembly need to be used from the remote machine
Sample configuration files
For Server web.config file
<system.runtime.remoting>
<application>
<channels>
<channel ref="http" >
<serverProviders>
<provider ref="wsdl" />
<formatter ref="soap" typeFilterLevel="Full" />
<formatter ref="binary" typeFilterLevel="Full" />
</serverProviders>
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channel>
</channels>
<service>
<wellknown
mode="SingleCall" objectUri="CustomerMaster.rem"
type="SupportLib.CustomerMaster,SupportLib"/>
</service>
<service>
<wellknown
mode="SingleCall" objectUri="BuyerMaster.rem"
type="SupportLib.BuyerMaster,SupportLib"/>
</service>
</application>
</system.runtime.remoting>
For client config file
<system.runtime.remoting>
<application>
<channels>
<channel ref="http">
<clientProviders>
<formatter ref="binary" />
</clientProviders>
</channel>
</channels>
<client>
<wellknown
url="http://bigg:80/dashboardserver/BuyerMaster.rem"
type="SupportLib.BuyerMaster,SupportLib"
/>
</client>
<client>
<wellknown
url="http://bigg:80/dashboardserver/CustomerMaster.rem"
type="SupportLib.CustomerMaster,SupportLib"
/>
</client >
</application>
</system.runtime.remoting>