Using .NET Remoting with XPO

XPO Team Blog
20 April 2006

In my recent post XPO is good for distributed applications I explained the basics of support for distributed applications in XPO 6.1. This post is going to show how .NET Remoting can be used to make the interface IDataStore available remotely – of course the same approaches can be used to publish ICacheToCacheCommunicationCore instead, if the caching structure is to be used.

The server setup

The setup for a Remoting server can be extremely simple:

  IDataStore dataStore = new DataStoreLogger(new InMemoryDataStore(new DataSet( ),
    AutoCreateOption.SchemaOnly), Console.Out);

  int port = 8880;
  ChannelServices.RegisterChannel(new TcpChannel(port), false);  
  MarshalByRefObject serverObject = (MarshalByRefObject) dataStore;
  RemotingServices.Marshal(serverObject, "DataSetServer");

 Note that in this example, a combination of the DataStoreLogger and the InMemoryDataStore classes is used to implement the server-side data store. This makes for a good test setup, but in a real-world application you would most probably want to replace that with creation code for a more useful data store, like SQL Server:

  IDataStore dataStore = XpoDefault.GetConnectionProvider(
    MSSqlConnectionProvider.GetConnectionString("server", "database"),
    AutoCreateOption.DatabaseAndSchema);
  ...

All data store implementations in XPO implement the interface IDataStore, and all are derived from MarshalByRefObject – the latter is very important to be able to marshal the object as the sample shows, which is why the explicit cast in the sample code makes sure that the given class has the correct ancestor. 

Instantiation

In the sample above, the object in question is being marshalled as a singleton pre-existing instance. This is a good thing if you want to marshal an existing class (that you didn’t create yourself) and the creation logic is somewhat complicated – and of course if you want to use singleton objects server-side. If you want to use a server-activated object (SOA) as a singleton instead, you’d have to create a class that can be instantiated with a default constructor, and make that available as a well-known service type. And you have to override the standard lease time to make sure the object isn’t disposed after a few minutes.

  public class MyDataStore : DataStoreLogger {
    public MyDataStore( ) : base(
      new InMemoryDataStore(new DataSet(), AutoCreateOption.SchemaOnly), Console.Out) { }

    public override object InitializeLifetimeService( ) {
      // make sure the object is never discarded
      return null;
    }
  }

  ...

  // instead of the RemotingServices.Marshal( ... ) call:
  RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(MyDataStore), "DataSetServer", WellKnownObjectMode.Singleton);

Combinations of these approaches are also possible, or per-client instantiation – the point is, XPO doesn’t really have anything to do with this, you can use standard features of .NET Remoting as you see fit.

The client

Assuming we have a server-side singleton that can be directly accessed, like in the samples given above, the client-side code is extremely simple:

  IDataStore dataStore = (IDataStore) Activator.GetObject(typeof(IDataStore),
    "tcp://localhost:8880/DataSetServer");
  XpoDefault.DataLayer = new SimpleDataLayer(dataStore);

The client simply fetches a reference to the data store that the server is publishing (assuming in the sample that the server is running on the same system, but of course “localhost” could be replaced by any other computer name or address) and creates a data layer in the normal way. As usual, all sessions that are now created will use the data layer referenced by XpoDefault.DataLayer by default, effectively accessing the server-side data store through the Remoting connection.

Channels and deployment

In the samples above we have been using the TCP channel all the time. Out of the box, .NET Remoting also includes an HTTP channel and (in .NET 2) an IPC channel for local communication. The IPC channel is not very important here due to its restricted use (which is not to say that it doesn’t work nicely when remoting across AppDomain boundaries), but the HTTP channel is definitely very interesting, because it allows .NET Remoting services to be deployed in IIS. This is in no way XPO specific, I just thought it might be worth mentioning, to show how flexibly .NET Remoting solutions can be deployed.

Creating and registering an HTTP channel is just as easy as the TCP channel in the examples. The HTTP channel uses SOAP formatting by default – it might be a good idea to use binary formatting instead for performance reasons, but be aware that firewalls may sometimes be configured to perform special filtering on SOAP traffic, so binary formatting may not be an option.

This is how you would add an HTTP channel with a binary formatter on the server side:

  Dictionary props = new Dictionary( );
  props["port"] = "8880";
  HttpChannel channel = new HttpChannel(props, null, 
    new BinaryServerFormatterSinkProvider( ));
  ChannelServices.RegisterChannel(channel, false);

And this is the code to add the channel on the client side, and to get the published interface via HTTP:

  ChannelServices.RegisterChannel(
    new HttpChannel(null, new BinaryClientFormatterSinkProvider(), null), false);
  IDataStore dataStore = (IDataStore) Activator.GetObject(typeof(IDataStore),
    "http://localhost:8880/DataSetServer");
  ...

I’m not going to go into the details of deploying to IIS here. There’s a pretty good description available on MSDN: Hosting Remote Objects in Internet Information Services (IIS)

Links

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
Tags
No Comments

Please login or register to post comments.