WebReference.com - Part 3 of Chapter 6: Professional C# Web Services, from Wrox Press Ltd (4/5)

To page 1To page 2To page 3current pageTo page 5
[previous] [next]

Professional C# Web Services

Sending MBR Objects to the Server

Sending marshal-by-value objects from the client to the server is very similar to sending them in the other direction, but what about sending a remotable object to the server? How does the server come back to the client?

Instead of showing the derivation of MarshalByRefObject in this picture, I've introduced a stereotype <<remotable>> to make it easier to read. We can see <<remotable>> as indicating inheritance from MarshalByRefObject. The MBR class B will be instantiated from the client, and passed with the method SetB() to the remote object MyRemoteObject. The remote object will use the object that was instantiated on the client across the network:

sending MBR objects to the server

Let's add two methods to the remote object class in the file MyRemoteObject.cs. With the method SetB() the client can pass a remotable object of type B to the server. The method SetB() accepts an object of class B. In the last section we created class B so that it derives from MarshalByRefObject, so the object will not be copied but a proxy will be created instead. The method SetB() stores the reference to the proxy of B in the field b. The method UseB() uses the field b to call the property Data and passes the value returned to the client.

public class MyRemoteObject : System.MarshalByRefObject
{
   public MyRemoteObject()
   {
      Console.WriteLine("MyRemoteObject Constructor called");
   }
   private B b;
   public void SetB(B b)
   {
      Console.WriteLine("SetB called");
      this.b = b;
   }
   public int UseB()
   {
      Console.WriteLine("UseB called");
      return b.Data;
   }
// ...

One important thing to note here is that the class MyRemoteObject now has state. Using this class as a well-known object would result in b being set to null with every method call, so UseB() wouldn't work. This remote object class can only be used in client-activated object configurations.

The client can be changed to call the remote object. In the client code, we create a new instance of the class B and initialize it with the value 44. While obj is instantiated remotely with the new operator, b is created locally because the class B is not listed in the client configuration file, but the class MyRemoteObject is. Accessing the Data property merely performs a local call:

// SimpleClient.cs
class SimpleClient
{
   static void Main(string[] args)
   {
      RemotingConfiguration.Configure("SimpleClient.exe.config");
      MyRemoteObject obj = new MyRemoteObject(333);
      obj.Hello();
      B b = new B(44);
      // This is a local call!
      int b1 = b.Data;

When calling SetB() with MyRemoteObject, we pass a reference to b to the server. Because B is derived from MarshalByRefObject a reference can be passed. Next we call the UseB() method where this reference is used within the server. The remote object will try to access the object that is running in the client process:

      // Pass a reference to the object running in the client
      // to the server
      obj.SetB(b);
      // Use the object in the client from the server
      b1 = obj.UseB();

To run this application we have to use a bi-directional channel. Because the client application now has to act both as a client to call methods in the remote object, and as a server where the instance b is invoked from the server, we must use the TcpChannel that can do both. If we use the wrong channel, the result will be a RemotingException with the following error message:

The remoting proxy has no channel sinks which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server.

Be sure to specify a reference to the channel tcp in both the client and server configuration files as we did earlier instead of tcp client and tcp server.

Running the server and client application, we get this output in the client:

client output

The first time we see the output of the B.Data is when we access this property locally. The second output we see is when a method of the object running in the client is invoked from the server by calling obj.UseB() in the client application.


To page 1To page 2To page 3current pageTo page 5
[previous] [next]

Created: March 26, 2002
Revised: March 26, 2002


URL: http://webreference.com/programming/csharp/webservices/chap6/3/4.html