2002-09-12 14:43
Building a Stock-Quotes Web Service
Saurabh Nandu
March 20 2001
Level: Beginner
Introduction
I guess you might be having some information on what Web Services. If not you can read .net101's article about Web Service Part 1 -Basics. In the current article we will be concentrating on building and consuming a Web Service which delivers "Stock Quotes" on the .NET Platform. We will be using Yahoo's free service which provides "Stock Quotes" in CSV (Comma Separated Values) format and wrap it up in our web service.
Note: The quotes run around 15 minutes late and should only be used for educational purposes.
Building the Web Service
We will step through the code to understand the Web Service
programming model in .NET. To write our Web Service you can use any text editor
like notepad to type your code and save it as StockQuote.asmx.
Note: All Web
Service files are saved with the extension *.asmx.
<%@ WebService Language="C#" class="DailyStock" %>
The first line of our code defines a Web Service and the language used to be "C#". The class attribute is used to denote the class which the Web Service should call and expose. If you are using many classes in your Web Service use this attribute to denote the class that should be called first by the Web Service.
using System ;
using System.Web.Services ;
using
System.Net ;
using System.IO ;
using System.Text ;
Import the necessary Namespaces. The Namespaces System.Web.Services should be always be imported, remaining Namespaces should be imported on the basis of the requirements of your class.
public class DailyStock :
WebService
{
......
....
}
Here we define our public class DailyStock, which extends the System.Web.Services.WebService class. All the classes that you want to expose as Web Services should extend the System.Web.Services.WebServices class. Also the access modifier for the Web Service class should always be public.
[WebMethod]
public string GetQuote(string
symbol)
{
........
........
}
Above we define a public Web Method GetQuote. As in classes Web
Methods also have to be declared with the public modifier. The [WebMethod]
attribute renders the underlying method to be exposed to the Web Service. So all
the methods that you want the clients to access should be marked with the
[WebMethod] attribute.
The GetQuote method takes one input parameter, a
string containing the symbol for which the consumer wants the quote. The method
responds back with a string containing the stock quote or error messages if any.
string ret;
try
{
// The Path to the
Yahoo Quotes Service
string fullpath =
@"http://quote.yahoo.com/d/quotes.csv?s="+symbol+"&f=sl1d1t1c1ohgvj1pp2owern&e=.csv";
// Create a HttpWebRequest object on the Yahoo
url
HttpWebRequest webreq =
(HttpWebRequest)WebRequestFactory.Create(fullpath);
// Get a HttpWebResponse object from the Yahoo
url
HttpWebResponse webresp =
(HttpWebResponse)webreq.GetResponse();
// Create a StreamReader object and pass the Yahoo Server
stream as a parameter
StreamReader strm = new
StreamReader(webresp.GetResponseStream(), Encoding.ASCII);
// Read a single line from the stream (from the server)
// We read only a single line, since the Yahoo server returns all
the
// information needed by us in just one line.
ret= strm.ReadLine();
// Close the stream to the server and free the
resources.
strm.Close();
}
catch(Exception)
{
// If exception occurred
inform the user
ret="Exception Occurred" ;
}
//Return the Quote or Exception
return ret
;
This is the contents of the GetQuote method. We use a try-catch
block to intercept any errors that can occur while getting the stock quotes from
Yahoo. Inside the try-catch block we declare a string variable which holds the
full path to the yahoo service. The symbol string variable that the consume
provides gets added to this connection string (shown in bold
letters).
Once the path is constructed we make a HttpWebRequest object and a HttpWebResponse out of the connection string. Next we open up a stream to the Yahoo server using the StreamReader. The StreamReader reads one line from the server since all information that we need is provided by Yahoo in a single line. Finally the stream is closed and the output from Yahoo is returned to the Consumer.
Deploying the Web Service
Deploying the Web Service is similar to the deployment of a ASP.NET application. If you have your own web server then create a virtual directory called stockquote (you can use any name you want.) and then copy the StockQuote.asmx into this directory. This completes the Web Service deployment. To call the Web Service fire up your browser and type the path to the Web Service i.e. http://localhost/stockquote/StockQuote.asmx. The page you see is automatically generated for you by the Web Services runtime. Type the symbol (like AOL or MS etc) in the textbox provided and click the invoke button. A new browser will pop-up showing you the output of the Web Service.
Consuming the Web Service
There are basically two ways to consume Web Services. You can either call the Web Service directly through your browser and use it which we have done above. The second method is to use some application to consume it. We will see how to build a Web Application and a Console Application which will consume our Web Service. You can alternatively use Win Form Applications to consume the Web Service.
Get the Service Description
In order to communicate with the Web Service the client should know what methods are supported by the Web Service and how to communicate with them. Web Services on .NET automatically produce a XML formatted document in SDL (Service Description Language) to enable the clients gain the information they need to communicate with Web Services. Appending ?SDL after the Web Service URL causes to Web Service to generate the SDL document that the clients can use. To view the SDL of our Web Service type http://localhost/stockquote/StockQuote.asmx?SDL in your browser.
Build the Proxy Library
Applications on the .NET Platform can use Proxy libraries to call methods on a Web Service which makes consuming Web Service very easy. First step in generating a proxy library is to generate a proxy class out of the SDL of the Web Service. The .NET SDK provides a tool called WebServiceUtil.exe which helps us to generate a proxy class. To generate a proxy class of our Web Service start-up your command prompt (ms-dos prompt) and navigate to the directory in which you will be developing you client application. Then enter the following command:
WebServiceUtil
/c:proxy
/pa:http://localhost/stockquote/StockQuote.asmx?SDL
/n:Quotes
The above command generates a C# source code file called DailyStock.cs (Web Service class name is also DailyStock, remember!) in the directory from which you ran this command. Let's see what the arguments mean.
/c:proxy |
It tells the WebServiceUtil to generate a proxy class |
/pa:http://localhost/stockquote/StockQuote.asmx?SDL |
Supplies the path to the SDL of the Web Service. If you have saved the SDL of the Web Service to your Hard Disk you can even provide the local path to the SDL file. |
/n:Quotes |
Tells the tool to place the proxy class in the "Quotes" Namespace. We do this so it is easy to manage and consume our proxy library. |
Once we have the proxy class ready, we use the C# compiler to generate a proxy library out of the proxy class we just created in the above step.
csc /target:library
/r:System.dll;System.Web.Services.dll;System.Net.dll;
System.IO.dll;System.Xml.Serialization.dll
DailyStock.cs
While generating the proxy
library we use the /target:library switch to indicate that we want a library
file as a output. Also we reference some assemblies that we have used in our Web
Service. The compiler will generate a library dll by the name DailyStock.dll in
the directory the command was run.
Creating a Web Application Consumer
We will create a Web Application as our first consumer of the StockQuote Web Service. StockConsumer.aspx
<%@ Page language="C#" %>
<%@ Import
Namespace="System.Xml" %>
<%@ Import Namespace="Quotes"
%>
Import the necessary Namespaces. Remember to import the Quotes Namespace too, which is the Namespace of your proxy class
<html>
<head>
<script
runat=server>
// Wire up the onClick event for a button
protected void button1_Click(object sender, EventArgs
e)
{
//Create a object of the class
DailyStock (the proxy class)
DailyStock ds = new
DailyStock();
// Call the GetQuote method of the proxy class DailyStock and
// pass the symbol string from the textbox
string res =
ds.GetQuote(symbol.Text);
// The returned string has values which
are separated
// by commas.
// Hence we split the returned string into parts
char[] splitter = {','} ;
string[] temp =
res.Split(splitter);
// Check if the string array returned has more than one
// elements since if there are less than one elements
// then an exception must have been returned
if(temp.Length >1)
{
// The WebService returns a lot of
information about the
// stock. We only
show the relevant portions
// Set the
label to current Index
curindex.Text =
"Current Index :"+temp[1];
// Set
the label to current Date Time
curdate.Text ="Last Update on"+temp[2]+" at "+temp[3];
}
else
{
error.Text = "Error :"+res ; //set the error label
}
}
</script>
Above in the script tag on the ASP.NET page we first instantiate a instance of the class DailyStock (Web Service). Since we have generated the proxy library calling methods of the Web Service is similar to calling methods on any other library. We call the GetQuote() method of the DailyStock class which returns a string containing the full information of the symbol in a comma separated list.
We will restrain our client to display only the current index and the date/time on which the index was recorded. In order to break up the string into different parts we use the Split method of the string class to split the string into parts on the occurrence of every comma. Once we have the spitted array of strings we just set the different labels of the Web Page with the relevant values.
Rest of the code
<body>
<center>
<h2>.NET101
Stock Quote Consumer </h2>
<form runat=server >
<table border=1
celspacing=1>
<tr><th>Please enter the symbol
below</th></tr>
<tr><td>
<asp:textbox id=symbol runat=server />
<asp:button id=button1 text="Get Quote"
onClick="button1_Click"
runat=server
/>
</td></tr>
<tr><td><asp:label
id=curindex runat=server
/></td></tr>
<tr><td><asp:label id=curdate
runat=server
/></td></tr>
<tr><td><asp:label id=error
runat=server
/></td></tr>
</table>
</form>
</center>
</body>
</html>
Deploying the Web Application
Create a virtual directory named StockConsumer.
Copy the
StockConsumer.aspx file to this virtual directory.
Now create a "bin"
virtual directory in the wwwroot folder if you don't already have one.
Give permissions to the bin directory to execute code.
Now copy
the proxy dll DailyStock.dll to this directory. The bin directory is the
directory from which the ASP.NET runtime engine automatically picks up
references to external libraries in our case the DailyStock.dll.
Now
call the file http://localhost/StockConsumer/StockConsumer.aspx. Enter the symbol for the stock and click on "Get Quote" button and see
you Web Service being consumed. Note: your Web Service should be able access the
yahoo server or it will return a exception.