Click here to Skip to main content
15,885,244 members
Articles / Programming Languages / C#

Remoting An Interface Based Approach

Rate me:
Please Sign up or sign in to vote.
2.94/5 (5 votes)
15 Feb 2010CPOL8 min read 34.7K   519   9   6
Remoting sample using Interfaces and NTier approach

Introduction

Overview

This is my first article on remoting and the reason I put up this article is to share with the CodeProject community/users my views on .NET Remoting. I would love to have a critical analysis of my work so that I can improve upon it further.

Last but not the least, I would like to appreciate the authors of existing articles (which I used as reference for learning and development). I will not go too much into explaining the technical jargons since there are plenty of articles and reference materials on the web, but rather jump straight into a stripped down case study of my existing work. I would keep adding my explanation and comments accordingly.

But if you still would like a technical overview on this subject, then you should read the article ".NET Remoting with an easy example By Syed Nadeem ul Hassan" posted here. This article by and large touches most of the remoting facts very well.

Updated 2010-2-16

Anybody interested in WCF, please visit my blog at http://wcfguru.blogspot.com/.

Background

The example is an XML Webservice implementation of the requirement which I want to replace with .NET Remoting. The idea here is to do away with the more bulky and verbose SOAP based communication and strip it down to an efficient binary communication between the client and server using TCP protocol.

Image 1

As you notice here, I have the Business Logic in the Customers Class which is interfaced to the client/third party using XmlWebservice host (WsCustomers.asmx). Since the Webservice WSDL would be enough for the client to be informed about the functions that the webservice is serving, I decided that there was no need to have an additional interface wrapper over the Business logic.

The new design logic using .NET Remoting is best explained in the diagram below:

Image 2

Before you start writing the code to implement remoting, I suggest you spend some time to identify the methods that the business object needs to expose through remoting. Ensure that all such methods are part of the interface definition. Next, create a separate Project for the interface declaration which you should compile as an independent .DLL file. This interface will be the blueprint/template for your business object. My sample interface is defined below:

C#
public interface ICustomers
{
    DataSet GetCustomerByTelAndBirthDate(parameters);
    DataSet GetCustomerbyCustID(parameters);
}

Note: Interface definitions should not have access modifiers.

The Business Object Logic

The class having the Business Logic should implement this Interface and subclass the MarshalByRefObject class as per the outline code given below:

C#
public class Customers : MarshalByRefObject,ICustomers
{
    public DataSet GetCustomerByTelAndBirthDate(parameters here)
    {
        //define logic here
    }

    public DataSet GetCustomerbyCustID(parameters here)
    {
        //define logic here
    }
}

The MarshalByrefObject is in System namespace so you need not add a reference to System.Runtime.Remoting namespace in the business object. You have to define the functions with the exact names and signatures in your Business object which implements the Interface.

Brief Information Regarding the Return Values from the Business Object

As you see, all my functions are returning DataSets. I thought it was better to provide the client feedback of the result of each and every method call before they start processing the resultset hence all the Datasets returns always have 2 tables. The client can check the Feedback Table and then either process the Datatable with the result to give the user an error/feedback message.

The details of the Tables in the resulting DataSets are as follows:

  1. The Table with the result of the query
  2. The Table with the Feedback
    For the feedback, the business logic calls the getFeedBack(double errCode,string errDesc) function from the a class called DBSupportLayer as outlined in the Helper Class below. The function is of the type STATIC and so the calling function does not need to instantiate this class to call the getFeedbackFunction.
  3. Both the Tables above are sent back to the client as a single DataSet

HELPER CLASSES

DBSupportLayer Class

I use this class to generate a SqlCommandObjects and any database related miscellaneous functions that would support my business object. In the real world scenario, this class might look something like the one below:

  • C#
    public static SqlCommand CreateInsertCustomersCommand(Parameters xxxx) 
  • C#
    public static SqlCommand CreateUpdateCustomersCommand(Parameters xxxx) 
  • C#
    public static DataTable getFeedBackPointsUpdate(Parameters xxx) 
  • etc...

In the sample provided, I have stripped it down to process only one function, i.e., to return the feedback dataTable only. The outline of this class is as displayed below:

C#
namespace Test.BizObjCustomers
{
    public class DBSupportLayer
    {
        public static DataTable getFeedBack(double errCode,string errDesc)
        {
            try
            {
                //Your code here
                return table;
            }
            catch(Exception e)
            {
                return table;
            }
        }
    }
}

ErrorCodes Class

I also have a list of ReturnCodes/ErrorCodes and Descriptions defined in a class ErrorCodes.

The partial snippet of the class in as below:

C#
public class ErrorCodes
{
    public static short __NO_DATA_FOUND= 1;
    public static string NO_DATA_FOUND = "ERROR-NO-DATA-FOUND";
    public static short __OPERATION_SUCCESSFUL=0; 
    public static string OPERATION_SUCCESSFUL="OPERATION-SUCCESSFUL";
}

This class helps me to keep all my return codes in one place. I could have used a database or XML for maintaining the return codes, but find this method easier as there is no requirement of loading the data from any data source and hence makes my job easier.

THE SERVER

Now that we have the Customers class and ICustomers interface implemented, let us move forward and define the server application. I will keep the server as a console application for this article and follow up the article with one for hosting the remoted server as a Windows service as well as on IIS later based on the feedback.

I want to use TCP protocol for my remote server that will service the client calls faster and also keep configuration files to avoid hardcoding and keep maintenance/changes flexible.

The following steps are involved for the Server Application:

  1. Creating a new Project of the type Console Application.
  2. Add reference to the ICustomers.dll (Interface) and Customers.dll (Business Object).
  3. Add an application config file. In this file, we will setup the following:
    • Specify the Database configuration
    • Specify the remoted server settings
  4. Add reference to System.Runtime.Remoting namespace in the project.
  5. For using Remoting and TCP in your project, add the following lines at the top of your code:

C#
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp; 

The snapshot of the Server config file is below along with the inline comments of the tags that are being used. It should be very easy to understand.

Image 3

Since we are using the config file for the remoting server settings, the command RemotingConfiguration.Configure("Server.exe.config") should get our remoted server up and running.

THE CLIENT

If you were able to understand the server application, then the client application should be like a piece of cake. As I said at the beginning of my article, the reason we are having the Interface Layer for the business object is that the client should only use the Interface DLL file and still be able to execute remote calls. Let me show you the snippet of the client config file below:

Image 4

Using the Code

As you can see in the config file, the client is referring to the Interface 'ICustomers' instead of the BusinessObject directly. For this. the client should add reference to the Test.CustomerInterface.ICustomers.dll.

Other standard assemblies for remoting that have to be included by the client are:

C#
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

The client application is just having the following lines of importance:

  1. C#
    ICustomers obj=(ICustomers) RemotingHelper.GetObject(typeof(ICustomers)); 

    Read and configure the client based on the config file.

  2. C#
    DataSet ds=obj.GetCustomerbyCustID(433249,ref sMess);

    Execute the GetCustomerbyCustID method on the remote server using the interface object.

Additional Reading

Now you would be wondering what is this RemotingHelper class. This is a class that I have copied and pasted from the Remoting Guru (Ingo Rammers) website which I found extremely useful for reading Config files for the client.

You can get the complete details of this code from here.

My code is just having a copy and paste of it.

USE SOAPSUDS IF YOU OPT FOR CLIENT ACTIVATED OBJECTS(CAO)

This addition here is based on a question by one of the readers of my article on using
Interfaces with CAO. I would say try avoiding CAO but in case you are required to use
CAOs, then better use the SOAPSUDS generated proxy of the Business class.

This proxy again is devoid of any Business logic and server that purpose for which we used Interfaces. Soapsuds has versioning issues though but works for CAOs. Anyway I am adding the details of using soapsuds in my project.

  1. Go to Visual Studio Command Prompt and create a Proxy of the Business Object using soapsuds:
    C#
    soapsuds -ia:Test.BizObjCustomers -oa:CustomerProxy.dll
  2. Copy the CustomerProxy.dll into the BIN folder of the client.exe app.
  3. Remove any reference of the Interface from the client.
  4. Add a reference of CustomerProxy.dll to the client project
  5. Change the client config file wellknown type from:
    C#
    type="Test.CustomerInterface.ICustomers,Test.CustomerInterface"

    to:

    C#
    type="Test.BizObjCustomers.Customers,CustomerProxy"
  6. Add skeleton of the BizObjAssembly using the proxy generated before by adding to your project using Test.BizObjCustomers;
  7. Change the following lines of code in your main function from:
    C#
    ICustomers obj=(ICustomers) RemotingHelper.GetObject(typeof(ICustomers));

    to:

    C#
    Customers obj=(Customers)RemotingHelper.GetObject(typeof(Customers));
  8. Call the function on the remote server (should work fine)
    C#
    DataSet ds=obj.GetCustomerbyCustID(433249,ref sMess); 

Using the soapsuds procedure of deployment, you will not send the whole Business object .DLL along with the compiled code that we are worried could be reverse engineered.

Points of Interest

XML
<wellknown mode="Singleton" type="Test.BizObjCustomers.Customers, Test.BizObjCustomers">

A word of caution, the second parameter above should be exactly the same as the default namespace of the project. So take a little bit of care here as I spent quite some time trying to locate the problem by just writing BizObjCustomers.

In this article, I have shared my ideas of using .NET Remoting using Config files and implementing it on the client using Interfaces. Also I have demonstrated it using a 3 tier application where I have the business logic interacting with the database using only Stored procedures (refer to the code). In this manner, we are able to use the resources of both the servers effectively (if at all you are having such a setup). Changes at one layer do not effect the other layer and this setup is extremely useful in real business scenarios.

So happy remoting...

Well I almost forgot!!!! Do add your valuable comments.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
India India
I love fooling around(but seriously) with new technologies.Believe that software programs need to constantly evolve with new technologies and older approaches need to change for the better.

I blog on WCF/LINQ/Adobe Flex which are currently the areas that interest me the most.

You can follow my blogs on areas that may interest you at:
http://wcfguru.blogspot.com
http://linqguru.blogspot.com
http://codewallet.blogspot.com/

Comments and Discussions

 
QuestionGAC'ed Test.CustomerInterface.ICustomers.dll. Pin
KeithDouglasCa24-Sep-12 10:48
KeithDouglasCa24-Sep-12 10:48 
GeneralNeed some help with your paypal class. Pin
Binoj Daniel15-Apr-10 3:22
Binoj Daniel15-Apr-10 3:22 
QuestionWindows Service Server? Pin
Beaner22-May-09 12:13
Beaner22-May-09 12:13 
GeneralInterface based approach in .NET 2.0 Pin
balazs_hideghety17-Oct-07 0:41
balazs_hideghety17-Oct-07 0:41 
AnswerRe: Interface based approach in .NET 2.0 Pin
WCFguru17-Oct-07 18:19
WCFguru17-Oct-07 18:19 
Hey you cannot use the interfaced based approach for CAO's in your case.
But you have a workaround for this best explained in the article
http://www.codeproject.com/csharp/caofactoryguide.asp
If you still cant figure out then I will put up a small example for you.Big Grin | :-D
AnswerRe: Solution to CAO activated calls(use SoapSuds) Pin
WCFguru17-Oct-07 19:55
WCFguru17-Oct-07 19:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.