Understanding .NET Remoting - Hosting the Remote Object on IIS
(Page 3 of 8 )
As was mentioned earlier, your remote object can be hosted in a number of ways. Let's look at how you could host the object in Internet Information Server 5.0 (IIS) . You need to do a couple of things first to get the object hosted in IIS. The first step involves creating a new Virtual Directory. So let's go ahead and create a virtual directory called MyDiner . Create a bin subdirectory under the physical folder location pointed to by your web application's virtual root, and copy the MyDiner.dll assembly that hosts the Diner remote object into the bin subfolder. There's just one more thing to do before we are set. This step involves creating a remote configuration file called remoting.cfg that you need to place in the virtual root.
The format of the information that you need to provide in remoting.cfg is as follows:
Name#[Name of the Application(Needs to be same as the virtual root)]
WellKnownObject#[FullyQualifiedTypeName]#[AssemblyName]#[ObjectURIEndpoint]#[ObjectMode] So going by the above format, the remoting.cfg file for our Diner object should look something like this:
Name#MyDiner
WellKnownObject#MyDiner.Diner#MyDiner#MyDiner/Diner.soap#Singleton Make sure that the name you provide in the Name# section is the same name as the virtual root of your web application. Once you have done this, point your browser to the URI Endpoint that you provided in the remoting.cfg . If everything went off well, you should see the Services Description Language(SDL) contract for the Diner object. (Please note that in Beta 2, the contract would be in Web Services Description Language (WSDL) standard. For more pointers on WSDL, please refer to the Related Links section below).
Accessing the Remote Object From an ASP.NET Page Now let's try to access the remote Diner Object. Let's use an ASP.NET page hosted on another machine to access this remote object.
Method 1: (Explicitly Registering the Channel & activating the object without a configuration file) To activate the remote Diner object, we need to do a couple of things first. First, we need to register a channel. The channel will then serve as the conduit to carry the activation and service requests to the remote object. You can register the channel by using the ChannelServices.RegisterChannel . The most commonly used channels (that ship out-of-the-box) are the HTTPChannel and the TCPChannel . You will find them in the System.Runtime.Remoting.Channels.HTTPChannel & System.Runtime.Remoting.Channels.TCPChannel namespace respectively. Here's an example of how you would create and register an HTTPChannel.
HTTPChannel chan = new HTTPChannel();
ChannelServices.RegisterChannel(chan);
..
ChannelServices.UnregisterChannel(chan); Once you register the channel, you are ready to activate the remote object at the well known URI and make method calls on it. To do this, you need to call Activator.GetObject . This method takes the Type of object to invoke and it's remote URI endpoint as its parameters.
// Create an instance of the remote object
Diner dinerObj = & _
(Diner)Activator.GetObject(typeof(Diner),"http://bingo:80/MyDiner/Diner.soap");
// Get Today's Menu from the remote Pizza Service
if(dinerObj != null) m_listPizza = dinerObj.getPizzaMenu(); Once you get a reference to the Diner object from the Activator.GetObject method call, you can invoke methods on it as if it were a local object. The actual call is made on the proxy that's created by the remoting runtime during the Activator.GetObject call and this proxy ( RealProxy ) is responsible for routing the call to the remote object. You would need to reference the classes & types in the server assembly from your client application.
In our case, we need to reference the Diner class in our client code. So, you can either XCOPY the server assembly directly to the bin subfolder of your client application's virtual root. This is the easiest way to reference the server assembly. Please note, that though you are copying the server assembly to the client's bin folder, it will be used only to reference the types exposed by the remote object. As an analogy, this is very similar to how a typelibrary is registered on a client's machine in COM to early bind to the interfaces and types in the server at compile time, though the actual call could be remoted using DCOM.
Alternatively, you could also use SOAPSUDS.EXE (that ships with the framework) to point to the URI endpoint and make it generate a metadata proxy containing the server types. SOAPSUDS uses the Service Description Language (SDL) contract file (will be WSDL in Beta 2) and constructs a metadata proxy that the client can use. This proxy inherits from System.Runtime.Remoting.Services.RemotingClientProxy , which you can confirm by opening up the proxy using the IL Disassembler (ILDASM). The following command shows you how to generate a metadata proxy using SOAPSUDS.
soapsuds -url:http://MyRemoteServer/MyDiner/Diner.soap -oa:MyDiner.dll Take a look at the codebehind C# source that's used by the ASP.NET client to activate and invoke methods on the remote Diner Object.
namespace PizzaRemotingClientHTTP
{
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.HTTP;
using MyDiner;
public class RemoteClient : Page
{
public RemoteClient() {
connectToPizzaRemotingService();
}//constructor
private void connectToPizzaRemotingService() {
HTTPChannel chan = new HTTPChannel();
try {
// Register the HTTP Channel
ChannelServices.RegisterChannel(chan);
// Create an instance of the remote Diner object
Diner dinerObj = (Diner)Activator.GetObject(typeof(Diner), & _
"http://bingo:80/MyDiner/Diner.soap");
// Get Todays Menu from the remote Pizza Service
if(dinerObj != null)
m_listPizza = dinerObj.getPizzaMenu();
//Unregister the HTTP channel
ChannelServices.UnregisterChannel(chan);
}//try
catch(Exception e) {
//Unregister the channel
ChannelServices.UnregisterChannel(chan);
}//catch
}//connectToPizzaRemotingService
// Data Source that will be bound to the repeater
public ICollection PizzaMenu {
//Property Accessor
get {
return m_listPizza;
}
}//PizzaMenu
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
// Bind the data to controls in this chain if this
// not a postback
if(!IsPostBack) {
DataBind();
}//IsPostback
}//onLoad
public System.Web.UI.WebControls.Repeater pizzaRepeater;
ArrayList m_listPizza = null;
}//class
}// namespace You can compile the code-behind assembly by using the following command:
csc /out:PizzaRemotingClientHTTP.dll
/target:library
/r:System.Runtime.Remoting.dll,System.Web.dll,MyDiner.dll PizzaRemotingClientHTTP.cs Make sure that you copy the codebehind assembly ( PizzaRemotingClientHTTP.dll ) in the bin subfolder of the consumer's virtual root. The ASP.NET consumer page uses the connectToPizzaRemotingService method in the RemoteClient object of the codebehind assembly to invoke the object exposed at the URN endpoint http://bingo/MyDiner/Diner.soap and calls its getPizzaMenu method. It then uses an ASP.NET Datalist control to render the ArrayList returned from the getPizzaMenu method.
Next: Method 1 (contd.) >>
More ASP.NET Articles
More By Wrox Team