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:
Delayed Stock Ticker
Real Time Stock Ticker
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:
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:
Fixed XML document structure (no flexibility)
Long integration time
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:
Pay before usage
Pay after usage
And both of these models can be broken down into two types:
Interval
Time
StockData could setup some sort of flexible packages to offer to its clients based on these criteria. For example:
Name
Description
Cost
Package 1
Pay for use for all of 2002. Any amount of transactions
5000
Package 2
Cost per transaction, regardless of time or amount
0.05
Package 3
Pay for 100,000 transactions only
5000
Package 4
Only 8000 transactions per month Additional cost per transaction
0.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.
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 Name
Data Type
Length
Allows Nulls
Keys
username
nvarchar
50
no
PK
password
nvarchar
50
no
Figure 4.2 Resources table
Column Name
Data Type
Length
Allows Nulls
Keys
Id
numeric
9
no
PK Identity
Name
nvarchar
50
no
Figure 4.3 UserResources table (to match users with resources)
Column Name
Data Type
Length
Allows Nulls
Keys
resource_id
numeric
9
no
PK
username
nvarchar
50
no
PK
Figure 4.4 ResourceHits table (to track hits for each user to each resource)
Column Name
Data Type
Length
Allows Nulls
Keys
hit_id
numeric
9
no
PK Identity
Whenhit
datetime
8
no
default:getDate()
Resource
namenvarchar
50
no
username
nvarchar
50
no
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.
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:
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:
[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.
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.
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]
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]
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]
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]
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]
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]
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]
Chip Irek examines the architectural issues and component design issues of building a .NET application in a service-oriented architecture. [Read This Article][Top]
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]
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.