asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Profit from Web Services
By Robert Chartier
Rating: 3.6 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Analyze the Existing Solution


    When organizations wishes to upgrade or modify their existing solutions, they must take a close look at the solutions in place. They will need to determine exactly how the solutions are implemented, and they must also list items that the new solutions will accommodate.

    Our existing Stock Data Feed Application solution consists of three major components:

    1. Delayed Stock Ticker
    2. Real Time Stock Ticker
    3. News Feed

    Both the Delayed Stock Ticker and the Real Time Stock Ticker are simple COM objects installed on the server, which the current interface creates, uses, and destroys as needed. This COM object actually speaks directly to a connection coming into the application through a Satellite feed from the original quotation provider. All historical data is also persisted to the SQL Server database whenever a change comes down. The difference between the Delayed and Real Time Tickers is that the data for the Delayed Ticker is simply held back for about 20 minutes before being sent out over the Satellite.

    The News Feed is based on all of the integration that StockData has done in the past with data providers that supply News and Press releases from public companies. This is also stored in a local database.

    So, StockData is really a central repository of useful stock data, which the company resells in a variety of ways. Its main method of integration with other organizations is a URL which clients can access to get an XML feed of the data requested. For example, if they wanted to get a delayed quote, they would need to have their application request a URL similar to:

    http://www.stockdata.net/feeds/delay.aspx?ticker=MSFT

    This would simply send back an XML document containing the full details of the Delayed Quote for Microsoft, similar to:

    
    <?xml version="1.0" ?>
    <quote type="delayed">
        <ticker>MSFT</ticker>
        <lasttrade>53.260</lasttrade>
        <change>-1</change>
    	etc...
    </quote>
    
    
    And then the client application would need to process this XML document into something useful. There is an equivalent feed for the real time and news data. This method seems the easiest to implement, but it is very prone to difficulties and not very flexible. What happens if StockData wanted to add an additional piece of information to the feed? If the client application consuming this service is not intelligent enough to handle this, it could potentially break. Something else to consider is the fact that there is no real way to describe the Types of each field coming over the wire. How will the client know if the <change> node will always be an integer value or not? What will it be when it is not available? Can it be a float value? There are many questions that need to be asked, answered, and thoroughly documented.

    Another major drawback to this method is the time needed for integration between the two parties. There is more than just sharing the simple URL. StockData also ships a fair amount of documentation consisting of formatting rules for the feed, what happens during exceptions, etc. So far, the average time to setup a client setup and have it working correctly is at least one full week. This is a very time-consuming process that StockData would love to eliminate.

    Lastly, there has been very little effort put into securing these feeds. Currently the StockData restricts access by IP address of the requesting party. If the client wishes to add a new node (with a new IP address), it needs to contact StockData and have it manually add the additional node. What happens if the client is sitting behind a larger proxy? StockData would have to give access to all machines behind that proxy, not a very secure method at all. Additionally, the existing solution has no real way to track who is using what feed.

    How Can Web Services Help?

    Now that we have an overview of the existing solution, here's how Web Services can improve the situation. This is a list of drawbacks to the existing solution:

    1. Fixed XML document structure (no flexibility)
    2. Long integration time
    3. No robust security mechanism

    Fixed XML document structure

    In the underlying protocols of Web Services, using XSD (Xml Schema Definition Language) for the Type system provides the ability to create and use custom Types. Thus, we are no longer limited to guessing the Type and use of each node coming into the feeds. XSD lets us add more Types to the feed in order to extend the functionality of the service with very little or no impact on the client.

    Long integration time

    A Web Service is described by a Web Service Description Language (WSDL) file (http://www.w3.org/TR/wsdl). This file contains everything you need to know about the Web Service, including all of its custom Types (if any); a list of all of the supported operations to find and bind to each; etc. Essentially this WSDL document should be all that is needed to get the service online fast.

    For StockData, integration with clients simply means pointing the client to the correct WSDL file and allowing them to integrate. Within the .NET Framework, Microsoft has supplied a tool for automatically generating a Proxy class for any WSDL file. One command and client integration is finished. All things considered, if the choice came down to two Stock providers, one that used Web Services and one that didn't, most would choose the Web Services provider because of the shorter integration time.

    No robust security mechanism

    StockData has chosen to keep its security mechanism very simple, only because there is no easy way to implement anything more complex. With the current system in place -- tracking IP addresses and limiting access based on those addresses -- there is little more we can do to limit access and control on a more granular scale. What Web Services brings to the plate is the ability to send and receive authentication information along side the normal message, without adding that unwanted complexity.

    Within Web Services (more specifically the Simple Object Access Protocol (SOAP)) there are a few major sections. The first, an Envelope, could optionally contain a Header with the required Body. The optional Header section of the message can be easily used to send the authentication information to the server. You will see later exactly how easy it is to do this, but for now remember that Web Services provide a way to simply and easily add authentication information to the message.

    Since our security model is more than a simple IP Address validation routine, an additional Authorization layer can be implemented.

    Author's note about Authentication vs. Authorization:

    Authentication answers the question: "Is this person allowed to use have access to the system." For example, a simple login username and password. If they provide valid login credentials, they are Authenticated as that valid user. Authorization answers the question "Is this Authenticated user allowed to access this specific resource on the system". For example, we have a valid user, but is this valid user also allowed to delete this file?

    For example, StockData has a client that wants to have its developers test out a new system. These developers should only have access to the free Delayed Ticker because the client does not want to be charged for the costly Real Time Ticker for testing purposes. Additionally this client still has its production application consuming the Real Time Ticker. In order to facilitate this need, StockData will setup two accounts for that client, one that has access to the Delayed (for the developers) and another account that has access to the additional Real Time Ticker. Both can be Authenticated to the system, but only one has Authorization to use the Real Time Ticker.

    See how Web Services enables a more flexible and robust solution that will save a ton of time. In the next few sections we will take a look at how StockData leveraged Web Services in order to create this flexible and robust solution.

    Payment Models

    One of the first things to consider is the sales aspect of Web Services. We need to create a flexible set of payment packages which will suit most, if not all, of our clients' needs.

    Typically there are two types of models available:

    1. Pay before usage
    2. Pay after usage

    And both of these models can be broken down into two types:

    1. Interval
    2. Time

    StockData could setup some sort of flexible packages to offer to its clients based on these criteria. For example:

    NameDescriptionCost
    Package 1Pay for use for all of 2002. Any amount of transactions5000
    Package 2Cost per transaction, regardless of time or amount0.05
    Package 3Pay for 100,000 transactions only5000
    Package 4Only 8000 transactions per month Additional cost per transaction0.08

    Of course a payment model such as this is not limited to Web Services specifically, but it gives you the idea of the flexibility available to the new StockData system once it is in place. The following example dives into the creation and implementation of StockData's new Web Services, along with a beefed up security and payment tracking system.

    Implementing a Flexible Use Tracking System

    Download complete source code for this article

    Start off by creating a system which will be able to track all of the usage for the Web Services. It will also provide the Authentication and Authorization mechanism needed. This entire article uses Visual Studio .NET and SQL Server 2000.

    First, create the database that will be responsible for tracking users and the resources they have access to. Only bare-bones functionality is included. Feel free to extend these as you see fit.

    Figure 4.1 Users table
    Column NameData TypeLengthAllows NullsKeys
    usernamenvarchar50noPK
    passwordnvarchar50no

    Figure 4.2 Resources table
    Column NameData TypeLengthAllows NullsKeys
    Idnumeric9noPK Identity
    Namenvarchar50no

    Figure 4.3 UserResources table (to match users with resources)
    Column NameData TypeLengthAllows NullsKeys
    resource_idnumeric9noPK
    usernamenvarchar50noPK

    Figure 4.4 ResourceHits table (to track hits for each user to each resource)
    Column NameData TypeLengthAllows NullsKeys
    hit_idnumeric9noPK Identity
    Whenhitdatetime8nodefault:getDate()
    Resourcenamenvarchar50no
    usernamenvarchar50no

    I've created a few stored procedures that will query the User table and the UserResources table. Pay attention to the "CheckUserResource" Stored Procedure. That is where hits are getting inserted automatically into the ResourceHits table when checking for a username/resource authentication. Consider creating a few more procedures for inserting, updating and deleting content out of each table for the administration features that you will want to implement later. Lastly, I've populated the three tables with some sample data to start off. Throw in some testing values also.

    Change over to VS .NET and create a simple set of classes to interact with the database. Create a new C# Class Library, named "Tracking", and then change the name of the default class to User (including the file name). Take a look at figure 4.5 for the code.

    Figure 4.5 Sample code for our User object

    
    using System;
    using System.Data.SqlClient;
    
    namespace Tracking {
    	/// <summary>
    	/// Summary description for Class1.
    	/// </summary>
    	public class User {
        private string username;
        private string password;
        private string conString;
    
        public User(string ConString) {conString=ConString;}
    
        public System.Boolean Login(string username, string password) {
          this.username=username;
          this.password=password;
          System.Data.SqlClient.SqlConnection conn = Connect(conString);
          System.Data.SqlClient.SqlCommand cmd;
          cmd = conn.CreateCommand();
          cmd.CommandType = System.Data.CommandType.StoredProcedure;
          cmd.CommandText = "checkUser";
          cmd.Parameters.Add(new SqlParameter("@username", System.Data.SqlDbType.NVarChar ,
    	50 , System.Data.ParameterDirection.Input ,
    		false , 0 , 0, "username" , System.Data.DataRowVersion.Default , this.username));
          cmd.Parameters.Add(new SqlParameter("@password", System.Data.SqlDbType.NVarChar ,
    	50 , System.Data.ParameterDirection.Input , 
    		false , 0 , 0, "password" , System.Data.DataRowVersion.Default , this.password));
          cmd.Parameters.Add(new SqlParameter("@isvalid", System.Data.SqlDbType.TinyInt,
    	1, System.Data.ParameterDirection.Output, false ,
    		0 , 0, "password" , System.Data.DataRowVersion.Default , 0));
          try {
            cmd.ExecuteNonQuery();
            System.Boolean valid =Convert.ToBoolean(cmd.Parameters["@isvalid"].Value);
            Disconnect(conn);
            return valid;
          } catch( Exception exc ) {
            Disconnect(conn);
            return false;
          }
        }
        public System.Boolean Authorize(string resource) {
          System.Data.SqlClient.SqlConnection conn = Connect(conString);
          System.Data.SqlClient.SqlCommand cmd;
          cmd = conn.CreateCommand();
          cmd.CommandType = System.Data.CommandType.StoredProcedure;
          cmd.CommandText = "CheckUserResource";
          cmd.Parameters.Add(new SqlParameter("@username", System.Data.SqlDbType.NVarChar ,
    	50 , System.Data.ParameterDirection.Input ,
    		false , 0 , 0, "username" , System.Data.DataRowVersion.Default , this.username));
          cmd.Parameters.Add(new SqlParameter("@resourcename", System.Data.SqlDbType.NVarChar ,
    	50 , System.Data.ParameterDirection.Input ,
    		false , 0 , 0, "resourcename" , System.Data.DataRowVersion.Default , resource));
          cmd.Parameters.Add(new SqlParameter("@isvalid", System.Data.SqlDbType.TinyInt,
    	1, System.Data.ParameterDirection.Output, false ,
    		0 , 0, "password" , System.Data.DataRowVersion.Default , 0));
          try {
            cmd.ExecuteNonQuery();
            System.Boolean valid =Convert.ToBoolean(cmd.Parameters["@isvalid"].Value);
            Disconnect(conn);
            return valid;
          } catch( Exception exc ) {
            Disconnect(conn);
            return false;
          }
        }
        private System.Data.SqlClient.SqlConnection Connect(string conString) {
          System.Data.SqlClient.SqlConnection  conn = new SqlConnection(conString);
          conn.Open();
          return conn;
        }
        private void Disconnect(System.Data.SqlClient.SqlConnection conn) {
          conn.Close();
        }
    	}
    }
    
    
    Now that there is a way to hit the database and query for Authentication and Authorization information, a simple Web Service can be created that will use the User object to control access to its methods.

    Author's Note: Since I have no access to an actual Stock Ticker object, whenever it can return a result, I will return a random number in its place. Also, in order to simplify the example, I'm limiting this to the two Quote methods, and I will no longer show you anything regarding the News.

    In VS .NET, right click the Solution, and choose Add New Project to add a new C# ASP.Net Web Service named "StockData". See figure 4.6 for the sample code for our Web Service. It contains methods to retrieve the stock data without any sort of access control. Later I will show you how to integrate our User object into this Web Service. Most of the sample code should be familiar.

    Figure 4.6 Sample code for Web Service

    
    using System;
    using System.Collections;
    using System.Configuration;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Web;
    using System.Web.Services;
    
    namespace StockData {
    	/// <summary>
    	/// Summary description for Service1.
    	/// </summary>
    	[WebService(Namespace="http://rob.santra.com/StockData/")]
    	public class Stock : System.Web.Services.WebService {
    		public Stock() {
    			//CODEGEN: This call is required by the ASP.NET Web Services Designer
    			InitializeComponent();
    		}
    
    		#region Component Designer generated code
    		
    		//Required by the Web Services Designer 
    		private IContainer components = null;
    				
    		/// <summary>
    		/// Required method for Designer support - do not modify
    		/// the contents of this method with the code editor.
    		/// </summary>
    		private void InitializeComponent()
    		{
    		}
    
    		/// <summary>
    		/// Clean up any resources being used.
    		/// </summary>
    		protected override void Dispose( bool disposing )
    		{
    			if(disposing && components != null)
    			{
    				components.Dispose();
    			}
    			base.Dispose(disposing);		
    		}
    		
    		#endregion
    
        [WebMethod]    public Quote DelayedQuote(string ticker) {
          return new Quote(ticker, "Delayed Quote");
        }
        [WebMethod]
        public Quote RealTimeQuote(string ticker) {
          return new Quote(ticker, "Real Time Quote");
        }
      }
      public class Quote {
        public Quote(){}
        public Quote(string Ticker, string QuoteType) {
          System.Random rnd = new System.Random();
          quoteType=QuoteType;
          ticker=Ticker;
          lastTrade = rnd.Next(0, 100);
          change = rnd.Next(0, 5);
        }
        private string quoteType="";
        private string ticker="";
        private double lastTrade=0;
        private double change=0;
        public string QuoteType { get{return quoteType;} set{quoteType=value;} }
        public string Ticker { get{return ticker;} set{ticker=value;} }
        public double LastTrade { get{return lastTrade;} set{lastTrade=value;} }
        public double Change { get{return change;} set{change=value;} }
      }
    }
    
    
    So now that the two pieces of our puzzle are done, they just need to be put together. As state in Section 2, use SOAP Headers to exchange security information with the client. To take advantage of SOAP Headers, first create a class.

    Figure 4.7 SOAP Tracking Header

      
    public class TrackingHeader : System.Web.Services.Protocols.SoapHeader{
        private string username;
        private string password;
        private string uuid;
    
        public TrackingHeader() {}
        public string UserName {
          get { return username; }
          set { username=value; }
        }
        public string Password {
          get { return password; }
          set { password=value; }
        }
        public string UUID {
          get { return uuid; }
          set { uuid=value; }
        }
      }
    
    
    Notice that this class is inherited from System.Web.Services.Protocols.SoapHeader, and that the System.Web.Services.Protocols namespace has been added to the project. Next, create a public instance of this class within the class in our Stock class that needs it:
    
    Public TrackingHeader header = new TrackingHeader();
    
    
    Next, decide which methods we want to require Headers for. Both methods in the service will require Header information. We will need to add the following attribute to both methods:
    
    [SoapHeaderAttribute("header", Direction=SoapHeaderDirection.InOut, Required=true)]
    
    
    This ensures that each method requires that the "header" SoapHeader is present for both directions.

    Now that the Headers are setup, they can be used to interact with the User object for Authentication and Authorization. Figure 4.8 shows the new methods with User object interaction.

    Author's Note: We need to add our Tracking project in as a reference to our Web Service project (don't forget to import the namespace also: "using Tracking;"). Also, for the Web Service, use the web.config file to pull out connection strings. Within the appSettings node, I've added the key:

    
       <add key="tracking" value="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=tracking" />
    
    

    Figure 4.8: Interacting with the User object

    
        [WebMethod]
        [SoapHeaderAttribute("header", Direction=SoapHeaderDirection.InOut, Required=true)]
        public Quote DelayedQuote(string ticker) {
          string QuoteType="Delayed Quote";
          user = new Tracking.User(ConfigurationSettings.AppSettings["tracking"]);
          if(user.Login(header.UserName, header.Password) && user.Authorize(QuoteType)) 
            return new Quote(ticker, QuoteType);
          else
            throw new Exception("You do not have access to this resource");
        }
    
        [WebMethod]
        [SoapHeaderAttribute("header", Direction=SoapHeaderDirection.InOut, Required=true)]
        public Quote RealTimeQuote(string ticker) {
          string QuoteType="Real Time Quote";
          user = new Tracking.User(ConfigurationSettings.AppSettings["tracking"]);
          if(user.Login(header.UserName, header.Password) && user.Authorize(QuoteType)) 
            return new Quote(ticker, QuoteType);
          else
            throw new Exception("You do not have access to this resource");
        }
    
    
    
    The normal HTTP Browser test page does not support the SOAP Headers, so it can't be used to test the behavior. A new project to test this Web Service must be created. In this case, create a new C# Console application. Add the reference to the WSDL file (http://rob.santra.com/stockdata/stockdata.asmx?WSDL) and then use the code in figure 4.9 to test the service.

    Figure 4.9: The Test Client

    
    using System;
    using TestClient.com.santra.rob;
    
    namespace TestClient {
      class Class1 {
        [STAThread]
        static void Main(string[] args) {
          TestClient.com.santra.rob.TrackingHeader header = new TestClient.com.santra.rob.TrackingHeader();
          header.UserName="robert";
          header.Password="chartier";
          TestClient.com.santra.rob.Stock stock = new TestClient.com.santra.rob.Stock();
          stock.TrackingHeaderValue=header;
          try {
            TestClient.com.santra.rob.Quote quote = stock.RealTimeQuote("MSFT");
            Console.WriteLine("MSFT LastTrade: " + Convert.ToString(quote.LastTrade));
          } catch(Exception e) {
            Console.WriteLine("Error:" + e.ToString());
          }
          string foo = Console.ReadLine();
        }
      }
    }
    
    
    Play around with the security information in the header (change to another user) and also try to execute a method that the user is not allowed to access within the service. Notice that the Web Service throws an exception back to the client. This fully demonstrates Authentication, Authorization, and Usage Tracking.

    Conclusion

    In order to make this a fully functioning system within your infrastructure, there will be a few more features that you should consider implementing, such as a reporting solution, administration, throttling usage, tight integration with in-house billing system, and greater security (HTTPS or other). Feel free to take the work that I have started here as a good foundation and work off of it. Drop me a line and let me know how you have improved and extended its functionality.

    About the Author

    Robert Chartier has developed IT solutions for more than nine years with a diverse background in both software and hardware development. He is internationally recognized as an innovative thinker and leading IT architect with frequent speaking engagements showcasing his expertise. He's been an integral part of many open forums on cutting-edge technology, including the .NET Framework and Web Services. His current position as vice president of technology for Santra Technology (http://www.santra.com) has allowed him to focus on innovation within the Web Services market space.

    He uses expertise with many Microsoft technologies, including .NET, and a strong background in Oracle, BEA Systems Inc.'s BEA WebLogic, IBM, Java 2 Platform Enterprise Edition (J2EE), and similar technologies to support his award-winning writing. He frequently publishes to many of the leading developer and industry support Web sites and publications. He has a bachelor's degree in Computer Information Systems.

    Robert Chartier can be reached at rob@aspfree.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 7, 2005 - Hosting Indigo Web Services
    In the second article of his series on Indigo web services, Chris Peiris explains how to host an Indigo web service and examines the IIS, self hosting, and Windows Activation Service hosting options. He then provides step-by-step instructions and sample code for an IIS-hosted and self-hosted Indigo web service.
    [Read This Article]  [Top]
    Jun 8, 2005 - Indigo Programming Model
    In the first part of his series on Microsoft Indigo, Chris Peiris examines the basics of SOA, explains how Indigo fits into the picture and the problems it solves. He then introduces Indigo's programming model and finishes by building a sample Indigo web service using the Microsoft .Net Framework 2.0.
    [Read This Article]  [Top]
    Nov 10, 2004 - Business Intelligence with Microsoft SQL Server Reporting Services - Part 3
    Adnan Masood concludes his discussion of Microsoft SQL Server Analysis services and Microsoft SQL Server Reporting services. In the final part, he discusses Reporting Server web services and using custom code in reports.
    [Read This Article]  [Top]
    Jul 8, 2004 - Using IE's Web Service Behavior To Create Rich ASP.NET Applications
    This article explains the features of the IE Web service behavior and shows how to asynchronously communicate with an ASP.NET Web service directly from the client.
    [Read This Article]  [Top]
    Jul 6, 2004 - Using .NET and Excel 2003 To Validate E-Mails
    Calvin Luttrell shows how to validate e-mail addresses stored in Excel 2003 and provides a special function for solving that pesky problem Yahoo! mail servers cause.
    [Read This Article]  [Top]
    Jun 9, 2004 - Modifying Web Services Documentation
    This short article describes a quick and easy way to provide some security to an ASP.NET Web service by modifying its associated documentation file.
    [Read This Article]  [Top]
    Jun 2, 2004 - Kerberos Authentication with Web Services Enhancements 2.0
    Kerberos authentication is the cornerstone of Windows operating system authentication architecture. Web Services Enhancement 2.0 (WSE 2.0) extends Kerberos support to ASP.NET Web services. Chris Peiris explains the support for this new feature in WSE 2.0.
    [Read This Article]  [Top]
    Dec 15, 2003 - Realizing a Service-Oriented Architecture with .NET
    Chip Irek examines the architectural issues and component design issues of building a .NET application in a service-oriented architecture.
    [Read This Article]  [Top]
    Nov 24, 2003 - Consuming Asynchronous Web Services
    Thiru Thangarathinam shows how to use asynchronous Web services, Windows Service applications, server-based timer components and .NET XML API classes to create high-performance, scalable, and flexible applications.
    [Read This Article]  [Top]
    Nov 12, 2003 - Implementing Paging and XSLT Extensions Using XSLT in .NET - Part 2
    Part one showed how to transform XML data into HTML by using an XSL stylesheet from within a .NET application. This part explains how to make use of XSLT Extension objects and invoke a C# class method from an XSL stylesheet.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry

    internet.commediabistro.comJusttechjobs.comGraphics.com

    Search:

    WebMediaBrands Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs