Mats Halfvares, the Content Studio Development Team

Introduction

The Content Studio server, that contains all the callable API:s that can be called to interact with Content Studio data, runs as a serviced application that must be reached via the .NET Remoting infrastructure. Remoting can be somewhat tricky to set up but once correctly configured, it is very convenient and highly reliable. If you are writing your application code in a Content Studio document, the Remoting is already set up correctly but in other applications ex. regular Windows or Console applications this must be done by the developer. This article describes two ways of doing this.

Channels

.NET Remoting is a way for two processes or application domains to communicate by sending serialized data between each other. For this purpose there must be a listenar (server) that accepts calls from a client through a dedicated channel. The channels available in .NET Remoting includes the Http and the Soap channels that are hosted in a Web server as well as the TCP channel and the IPC channel. The two latter is used by Content Studio and are secured, encryped and uses binary formatting when passing messages from and to each other. The TCP channel uses a TCP listener on a particular TCP port (9792) and is available on the same machine or between different trusted machines in the network. The IPC channel uses an underlying named pipe kernel object and is only accessible locally.

When you set up .NET Remoting for your application Content Studio must be installed on the development computer. In addition to this you need to set up a client channel that communicates with the listener that Content Studio server provides. You also need to specify which one of the Content Studio objects that should be accessed remotly. That includes all objects that make database calls or access the Web site's file system directly. Even though that is possible to use different channels for different objects it is wise to use the same channel for all of the objects, the only exception is the SessionManager object that must use the TCP channel. There is a bug (or a feature) in the IPC channel current implementation of .NET Remoting that tends to remember the first caller that created the client listener and since the SessionManager identifies the calling user by impersonating her this will cause identity problems under the IPC channel.

IMPORTANT
You must use the TCP channel when calling the SessionManager object, since the IPC channel has an identity spoofing problem in impersonation operations in the current implementation of the IPC channel.

Configuring your application

To configure an application for .NET remoting you typically add code in the constructor of your application or in the Main procedure if you are developing a console application. In this way you ensure that the configuration process is performed only once per instance of your program. If you try to reconfigure an application a RemotingException will occur. If you are building a class library (.DLL) you should put the configuration methods in the calling application rather than in the class library itself. Remember that a class library runs in the context of the calling process and any configuration code in the class library will affect the calling application directly.
For this reason there is no need to write code to configure .NET Remoting if your class library will be used from Content Studio but this is not true for any test application you use for debugging your code.

Using a configuration file

The instructions below assumes that you have Content Studio installed locally

Using a configuration file is quite straight forward and requires the following steps (the sample below assumes that you are doing a regular console application that communicates with Content Studio).

  • Create a new C# console application in Visual Studio 2005 (or later) and name it RemConfig.
  • Add a reference to the CSServer5.dll assembly. Event though that CSServer is installed in the GAC it might not be listed in among the .NET assemblies available in Visual Studio. In that case you can browse to the installed .DLL and is by default located in the Program Files/Teknikhuset/Content Studio 5.0/CSServer sub folder.
  • Add a new configuration file to your project and name it RemConfig.exe.config. In the properties window for the configuration, file you should set that Visual Studio should copy the file as a part of the building process since it must be located in the same folder as the resulting executable.
  • Download the content of the either the the IPC configuration file or the TCP configuration file depending on whether you prefer to use  the IPC or the TCP channel. You find a text version of these files in the links below in this section.
  • Paste the content of one of these files into your configuration file and save it.
  • Now you should be able to build an run your application.

In Program.cs class file, insert the following code that configures the .NET Remoting channels to use and makes a call into the CSApplication.SiteListStream() Content Studio API to fetch a list of registered sites in Content Studio.

C#
using System;
using System.Runtime.Remoting;
using ContentStudio;
namespace RemConfig
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //Configure the Remoting client channels by using the configuration file
                RemotingConfiguration.Configure("RemConfig.exe.config", true);
                //Get a list of all registered sites in Content Studio
                CSApplication csApp = new CSApplication();
                using (System.Xml.XmlReader xrd = System.Xml.XmlReader.Create(csApp.SiteListStream(true)))
                {
                    Console.WriteLine("Id\tName");
                    while(xrd.Read())
                    {
                        if (xrd.NodeType != System.Xml.XmlNodeType.Element)
                            continue;
                        if (xrd.Name == "cs_site")
                        {
                            Console.Write(xrd.GetAttribute("connectionid"));
                            Console.Write("\t");
                            Console.Write(xrd.GetAttribute("sitename"));
                            Console.WriteLine();
                        }
                    }
                    xrd.Close();
                }
            }
            catch (RemotingException rex)
            {
                Console.WriteLine("ERROR: There is a problem with your remoting configuration!");
                Console.WriteLine(rex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: There was problem with the call!");
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
    }
}
            
VB.NET
Imports System
Imports System.Runtime.Remoting
Imports ContentStudio

Class Program
    Public Shared Sub Main(args() As String)
        Try
            'Configure the Remoting client channels by using the configuration file
            RemotingConfiguration.Configure("RemConfig.exe.config", True)
            'Get a list of all registered sites in Content Studio
            Dim csApp As New CSApplication()
            Using xrd As System.Xml.XmlReader = System.Xml.XmlReader.Create(csApp.SiteListStream(True))
                Console.WriteLine("Id" & vbTab & "Name")
                While xrd.Read()
                    If xrd.NodeType = System.Xml.XmlNodeType.Element
                        If xrd.Name = "cs_site"
                            Console.Write(xrd.GetAttribute("connectionid"))
                            Console.Write(vbTab)
                            Console.Write(xrd.GetAttribute("sitename"))
                            Console.WriteLine()
                        End If
                    End If
                End While
                xrd.Close()
            End Using
        Catch rex As RemotingException
            Console.WriteLine("ERROR: There is a problem with your remoting configuration!")
            Console.WriteLine(rex.Message)
        Catch ex As Exception
            Console.WriteLine("ERROR: There was problem with the call!")
            Console.WriteLine(ex.Message)
        End Try
        Console.Read()
    End Sub
End Class
                
This should print a small list in the console window. If you experience a Remoting exception such as Failed to connect to an IPC Port: The system cannot find the file specified, the most likely reason is that the CSService is not running or that the the program cannot find the configuration file or that there is a syntax error in the config file.
You should remove or comment out the entries in the config file that configures objects you don't need. Some of the objects are rarely used and are mainly intended to be used by the Content Studio infrastructure. 

The IPC configuration file

The TCP configuration file

Setting up a remoting listener in code

The instructions below assumes that you have Content Studio installed locally

Sometimes you might prefer to configure .NET Remoting programatically instead of through a config file. In this case you do not have to distribute the config file along with your application and you have full control over the configuration. To facilitate this we have prepared a C# class file that does all the dirty work for you. As with the configuration file you should remove or comment out the code that configures objects you don't need. Some of the objects are rarely used and are mainly intended to be used by the Content Studio infrastructure. 

Follow the instructions that can be found in the former section but do not create a configuration file. Instead, add a new empty class to the project and name it ChannelConfigurator.cs. Now, overwrite the content of this new class file with the content of our code file that can be obtained in the link below. Before you can build your project you need to add a reference to the System.Runtime.Remoting .NET framwork assembly. All you have to do now is to create an instance of the ChannelConfigurator class and call the OpenChannel method.

Thus now your program will look something like this:

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using ContentStudio;

namespace RemConfig
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //Configure the remoting channels by using the ChannelConfigurator class
                ChannelConfigurator chan = new ChannelConfigurator(ChannelConfigurator.TransportProtocol.TCP);
                chan.Configure();
                //Get a list of all registered sites in Content Studio
                CSApplication csApp = new CSApplication();
                using (System.Xml.XmlReader xrd = System.Xml.XmlReader.Create(csApp.SiteListStream(true)))
                {
                    Console.WriteLine("Id\tName");
                    while(xrd.Read())
                    {
                        if (xrd.NodeType != System.Xml.XmlNodeType.Element)
                            continue;
                        if (xrd.Name == "cs_site")
                        {
                            Console.Write(xrd.GetAttribute("connectionid"));
                            Console.Write("\t");
                            Console.Write(xrd.GetAttribute("sitename"));
                            Console.WriteLine();
                        }

                    }
                    xrd.Close();
                }
            }
            catch (RemotingException rex)
            {
                Console.WriteLine("ERROR: There is a problem with your remoting configuration!");
                Console.WriteLine(rex.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: There was problem with the call!");
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }
    }
}
                
VB.NET
Imports System
Imports System.Runtime.Remoting
Imports ContentStudio

Class Program
    Public Shared Sub Main(args() As String)
        Try
            'Configure the remoting channels by using the ChannelConfigurator class
            Dim chan As New ChannelConfigurator(ChannelConfigurator.TransportProtocol.TCP)
            chan.Configure()
            'Get a list of all registered sites in Content Studio
            Dim csApp As New CSApplication()
            Using xrd As System.Xml.XmlReader = System.Xml.XmlReader.Create(csApp.SiteListStream(True))
                Console.WriteLine("Id" & vbTab & "Name")
                While xrd.Read()
                    If xrd.NodeType = System.Xml.XmlNodeType.Element
                        If xrd.Name = "cs_site"
                            Console.Write(xrd.GetAttribute("connectionid"))
                            Console.Write(vbTab)
                            Console.Write(xrd.GetAttribute("sitename"))
                            Console.WriteLine()
                        End If
                    End If
                End While
                xrd.Close()
            End Using
        Catch rex As RemotingException
            Console.WriteLine("ERROR: There is a problem with your remoting configuration!")
            Console.WriteLine(rex.Message)
        Catch ex As Exception
            Console.WriteLine("ERROR: There was problem with the call!")
            Console.WriteLine(ex.Message)
        End Try
        Console.Read()
    End Sub
End Class
                

The remoting configuration class file (C#)

The remoting configuration class file (Visual Basic .NET)