Click here to Skip to main content
Licence CPOL
First Posted 16 Mar 2007
Views 46,511
Downloads 71
Bookmarked 58 times

A Lean and Mean Web Service

By | 16 Mar 2007 | Article
Write one Web Service, use it everywhere.

What is it?

LMService is not just another Web Service. It is a write-once / use-everywhere Web Service. About the "lean" part, it has only 25 lines of code, not counting the code automatically generated by Visual Studio .NET. You will see how "mean" it is when you read the rest of the article.

The code included was developed using Visual Studio .NET 2003, and tested on Windows 2000, Windows XP, and Windows 2003.

What does it do?

Once you deploy the Web Service to a server, you can use it to invoke code in almost any .NET DLL on the server. For anything you want to do on the server, just write a .NET DLL following certain rules (to be explained later) and copy the DLL onto the server. Then you can execute your DLL code from any client machine by calling LMService.

How does it work?

LMService has only one web method, InvokeMethod, with the following signature:

public object InvokeMethod(string sDllPath, string sClassName, 
              string sMethodName, object[] pInput)
{
    // implementation of the web method
}

sDllPath is the full path of a .NET DLL which contains the code you want to invoke. sClassName is the name of a public class in the DLL. sMethodName is the name of a public method in the class, i.e., the name of the method to be invoked. Finally, pInput is an object array containing input values to be used when invoking the method. As long as you pass the right parameters, InvokeMethod will do the rest for you, including:

  • Load the DLL with the given path into the server process.
  • Create an instance of the corresponding class.
  • Call the method with the given name passing all values in the object array pInput as parameters.
  • Finally, return an output object to the caller.

As a lean and mean Web Service, LMService loads each DLL only once, caching certain information in memory to improve performance.

Execute code on a remote server as if it were local

For your convenience, I have included LMClient.dll (another three lines of code). This DLL makes it easier to call LMService. There is a static method, InvokeMethod, in the DLL. The signature of this static method is almost the same as the web method in LMService, the only difference is that you need to provide an extra parameter (the first one): the URL of the Web Service.

Suppose Hello.dll is a .NET DLL and you have copied Hello.dll onto a server where LMService is deployed. Suppose Hello.dll contains a class HelloClass with a public method Hello, and the Hello method takes your name as input string and returns the string "Hello, YourName". Here is a complete test program to invoke the Hello method on the server.

static void Main(string[] args)
{
    string sOutput = (string)LMClient.Client.InvokeMethod
    (
        "http://MyServer/LMService/LMService.asmx", // url of web service
        "C:\\Hello\\Hello.dll", // dll path
        "HelloClass", // class name
        "Hello", // method name           
        new object[1]{"Xiangyang Liu"} // array that contains user name string     
    );
    System.Console.Out.WriteLine(sOutput);}

// output of the above program is: "Hello, Xiangyang Liu"

Rules? What rules?

OK, I may have misled you. You cannot use LMService to execute code in any .NET DLL. Your code has to be written following certain rules:

  • The method to be invoked by LMService has be a public method in a public class within a .NET DLL. The public class needs a default constructor.
  • The type of each input parameter of the method can be:
    1. basic types (int, long, double, byte, string, DateTime, etc.)
    2. byte array
    3. object
    4. object array while each element in the array can be basic types, a byte array, object, or object array (while each element of the array can be ...)
  • The output of the method is subject to the same type restrictions as the input.

Note that the number of input parameters is not limited by the above rules. Here are some methods in compliance with the above rules:

public byte[] GetFile(string sFilePath)
{
    // return content of specified file in a byte array 
}

public void PutFile(string sFilePath, byte[] pData)
{
    // save data in the byte array to file with given path
}

public object[] Search(DateTime oStart, DateTime oEnd, string sFilter1, string sFilter2)
{
    // 1. find all records with timestamp between oStart and oEnd
    //    and satisfying the two search conditions
    // 2. return data is an object array, each item in the array 
    //    is an object array representing a found record
}

The above rules seem to be harsh, however, since object array (and array of object arrays) is allowed as input and output types, you can use almost any "data structure" as input/output. For example, if your method needs to return a set of records from a database table, you can use an object array as the return value while each element of the array is itself an object array representing a record in the table. The following code builds an object array that could be used as the input/output value of your method (to be invoked by LMService).

// array of 100 records
object[] pData = new object[100]; 
// first record
pData[0] = new object[3]; 
// name
((object[])pData[0])[0] = "James"; 
// age
((object[])pData[0])[1] = 13;
// data of birth
((object[])pData[0])[2] = Convert.ToDateTime("1/1/1993"); 
// second record
pData[1] = new object[3];
// name
((object[])pData[1])[0] = "Thomas";
// age 
((object[])pData[1])[1] = 10; 
// data of birth
((object[])pData[1])[2] = Convert.ToDateTime("2/2/1997"); 
...

The restriction on input/output types is necessary because LMService does not have any knowledge of the code it is going to invoke. Even if you restrict the types to string, you can still use XML format to represent any kind of data. As a famous CPian once said, "At the end of day, it is just text anyway."

Summary

Now, what do we have so far?

  • A Web Service, LMService, that can run on any server. Once deployed, you can use it to invoke .NET code on that server, as long as the code is in a .NET DLL and follows some simple rules.
  • A library LMClient.dll. Using this DLL, you can invoke code on a remote server as if you are making a local library call.

Exercise

It is easy to enhance LMService and use it to develop complicated business applications. For example, I included another simple .NET component FileLib.dll. Using this DLL and LMService, you can write a console program with only a few lines of code to upload a file to the server and/or download a file from the server, assuming you know the exact path of the file. This is left as an exercise for you. If you have to write more than a few lines of code to do this, then you are not using LMService correctly.

Hint:

  1. Copy FileLib.dll to the server first.
  2. You can also use FileLib.dll on the client-side to save the downloaded file.

I know what you are thinking

What about security and all the other important issues in building complicated business applications? Well, what do you expect from a Web Service that has only 25 lines of code? I have written my own business application framework that has a lot of useful features and addresses some of the important issues. It is free (but source code is not provided, sorry).

Warning

Deploying LMService could lead to security problems, because it allows all clients to execute almost any .NET code on your server, including code you never knew existed. In other words, you better know what you are doing. For example, if you need help to open a web project from Visual Studio .NET, or you are not familiar with creating/configuring a virtual directory in IIS, then this Web Service is not for you.

You may have noticed that I am writing C style code in C#. I know it can be annoying to some people, but honestly, I enjoyed it.

Thank you for reading my articles.

License

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

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionApplication PinmemberDamage_Inc4:15 19 Mar '07  
AnswerRe: Application PinmemberXiangyang Liu5:25 19 Mar '07  
GeneralRe: Application PinmemberDamage_Inc6:06 19 Mar '07  
GeneralRe: Application PinmemberXiangyang Liu15:38 19 Mar '07  
GeneralRe: Application PinmemberDamage_Inc19:00 19 Mar '07  
GeneralRe: Application PinmemberPete Appleton23:25 19 Mar '07  
GeneralRe: Application PinmemberXiangyang Liu11:24 20 Mar '07  
GeneralRe: Application PinmemberDamage_Inc18:09 20 Mar '07  
GeneralRe: Application PinmemberTheJerk9:32 20 Mar '07  
GeneralRe: Application PinmemberXiangyang Liu11:08 20 Mar '07  
GeneralRe: Application PinmemberDamage_Inc19:13 20 Mar '07  
GeneralRe: Application PinmemberXiangyang Liu3:51 21 Mar '07  
GeneralRe: Application PinmemberDamage_Inc7:00 21 Mar '07  
GeneralGood job Pinmembernesetk10:01 16 Mar '07  
GeneralRe: Good job PinmemberXiangyang Liu5:26 19 Mar '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 16 Mar 2007
Article Copyright 2007 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid