Using Remoting in 3-Tier Scenario
Introduction
Now a days more and more applications are being built with distributed architecture. Remoting provides a communication mechanism between such distributed pieces of your application. Typically your application will talk with some remote component via remoting. However, you can also build more complex applications where in the remote object in turn talks with some other objects over remoting. In this article I will show you with an example how this can be achieved. If you need a backgrounder for remoting then you may refer my article
here.
Sample Scenario
Let us consider an example. Assume that you want to develop a web form that allows the users to place order for certain stationary items. The list of stationary items along with their description is obtained from a business
object layer (BOL). When user selects the items he wants to order the order is placed via the business logic component. The communication between the order entry web form and business logic component happens via remoting. The business logic component then communicates with a data access layer (DAL) which performs actual task of dealing with the database. This communication also happens via remoting. So, remoting is involved in two places - web form to BOL and BOL to DAL.
Structure of our application
Our sample application consists of 5 pieces. They are:
- OrderEntryPL: A web form for posting orders for stationary items.
- OrderEntryBOL: A business logic component that performs some validations
and further talks with the DAL.
- OrderEntryBOLStarter: Since above BOL is a remote component it needs to be
published on the network so that others can consume it. The BOL started does
just that.
- OrderEntryDAL: A data access layer that actually talks with the database
for inserting new orders and fetching data.
- OrderEntryDALStarter: Just as in case of BOL starter this application
publishes DAL component on the network so that others can consume it.
Entire source code is available for download along with this article. I will
be presenting only the important parts of the code in-line with this
article.
Developing the Presentation Layer
The presentation layer consists of a single web form with DataGrid control that looks as shown
below:

At the class level of WebForm1 we declare two variables:
private OrderEntryBOL.Bol bol;
private DataSet ds=new DataSet();
The first variable is used to hold reference to the remote object of BOL. The
second variable is of type DataSet and is used to pass new order back to the BOL.
Note: At compile time you need to have BOL and DAL assemblies available
locally. However, after deployment you can remove them as objects will be served
via remoting infrastructure.
In the Page_Load event handler we get reference to the remote object as
follows:
bol=(OrderEntryBOL.Bol)
Activator.GetObject
(typeof(OrderEntryBOL.Bol),
@"tcp://localhost:8086/MyBolURI");
Here, we call GetObject method of Activator class and pass type of the class
whose instance we want to get hold of along with its URL. Note that the URL
should exactly match as published by the BOL starter application (discussed
later).
Next, we bind the DataGrid by calling BindGrid() function. This function
calls GetProduct() method on BOL and binds the grid.
private void BindGrid()
{
DataGrid1.DataSource=bol.GetProductList();
DataGrid1.DataBind();
}
Use can now select the items he wants to order along with the quantities.
When he clicks on the Place Order button, following code is executed.
FillDataSet();
Label2.Text=(bol.PlaceOrder(ds)).ToString();
Here, we call the PlaceOrder of the BOL passing a DataSet as a parameter.
This DataSet contains a DataTable containing our order details. Note that we
have created this DataSet programmatically in our code (FillDataSet function),
code for which is not presented here for the sake of simplicity.
Let us now look into BOL class.
Developing the Business Objects Layer
The BOL consists of a single class called Bol and is inherited from
MarshalByRefObject class. This is necessary for all remotable objects. This
class has just two methods GetProductList() and PlaceOrder(). We have already
used both of these methods previously. Note that you can place additional
validation logic in these methods if required.
The consturctor of BOL is doing one interesting thing.
public Bol()
{
db=(Dal)Activator.
GetObject(typeof(OrderEntryDAL.Dal),
"tcp://localhost:8085/MyDalURI");
...
}
As you can see, it is getting hold of a remotable instance of DAL using the
same Activator.GetObject method. This instance is used in other methods to
actually communicate with the database.
Developing BOL Starter
Inheriting your class from MarshalByRefObject makes it "remoting capable" but
in order that others can consume it, you need to "publish" it on the network.
The BOL starter application does this publishing work for the BOL class. The BOL
starter application is a console application that contains following Main()
method:
static void Main(string[] args)
{
TcpChannel chan = new TcpChannel(8086);
ChannelServices.RegisterChannel(chan);
RemotingConfiguration.
RegisterWellKnownServiceType
(typeof(OrderEntryBOL.Bol),
"MyBolURI",WellKnownObjectMode.SingleCall);
Console.WriteLine("OrderEntryBOL.Bol Published...");
Console.ReadLine();
}
Here, we first created a channel for our remote communication and register it
with the remoting infrastructure. Then we register our class calling
RegisterWellKnownServiceType method of RemotingConfiguration class. Note how we
have passed a unique URL to this method. This is the same URI that you need to
use from any consumer application. Note, how we used the combination of port and
URL there. This application simply publishes the BOL and waits forever! This is
important because if this publisher application ends, the remote component will
not be available any more.
Developing the Data Access Layer
DAL consists of a single class called Dal. As in the case of BOL this class
is also derived from MarshalByRefObject class. This class has two methods -
GetProductList() and InsertOrder(). These methods use classes from
System.Data.SqlClient namespace to talk with the database.
Developing DAL Starter
DAL starter application is identical to BOL starter except that it publishes
DAL class with a unique URL.
static void Main(string[] args)
{
TcpChannel chan = new TcpChannel(8085);
ChannelServices.RegisterChannel(chan);
RemotingConfiguration.
RegisterWellKnownServiceType
(typeof(OrderEntryDAL.Dal),
"MyDalURI",WellKnownObjectMode.SingleCall);
Console.WriteLine("OrderEntryDAL.Dal Published...");
Console.ReadLine();
}
How to run the application?
In order to run the application you need to follow these steps:
- Create a database in SQL server/MSDE
- Create required tables in the database
- Change database connection string in DAL
- Start the DAL starter application
- Start BOL starter application
- Run the Order Entry web application
The database table structure is as follows:
- Products Table - productid (int), productdescription (varchar), productqtyinstock (int)
- Orders Table - orderid (int),productid (int),departmentid (int),qty (int),status (char)
Please note that the table structure is just to illustrate our example. It lacks appropriate relations and database design rules.
Summary
In this article we saw how to create really distributed application via
remoting. All the layers of the application can reside on a single machine or
different machines. Remoting infrastructure makes it easy to develop such
distributed application with very less amount of code. You can easily store the
URIs in config files so that event that much hard coding can be avoided.