Programmer to ProgrammerTM  
Wrox Press Ltd  
   
  Search ASPToday Living Book ASPToday Living Book
Index Full Text
 
ASPToday Home
 
 
Home HOME
Site Map SITE MAP
Index INDEX
Full-text search SEARCH
Forum FORUM
Feedback FEEDBACK
Advertise with us ADVERTISE
Subscribe SUBSCRIBE
Bullet LOG OFF
                         
      The ASPToday Article
September 21, 2001
      Previous article -
September 20, 2001
   
 
   
   
   
Creating High Performance Web Applications Using Web   Thiru Thangarathinam  
by Thiru Thangarathinam
 
CATEGORIES:  .NET Framework, Performance  
ARTICLE TYPE: Cutting Edge Reader Comments
   
    ABSTRACT  
 



Today’s software applications are expected to deliver a wide variety of solutions to address different kinds of customer and business needs. Web services can be used to implement solutions of this kind and they can fundamentally transform the ability of the businesses to interact and exchange information with each other. However building high performance applications becomes a challenge, the moment we start integrating web services into our applications. This is primarily due to the fact that the web service we are trying to invoke can be present anywhere in the Internet. To make matters worse, we do not have any control over the public networks on which our request has to travel as well as the over the machines on which the web services reside. If you take all these aspects into consideration, you will agree that making a synchronous blocking web service call from a web page may not be a wise choice as it is going to have tremendous impact on the user’s browsing experience in the site. So the usage of web services does require a careful evaluation of several aspects including the impact on the performance and throughput of the application and so on. In this article, Thiru demonstrates us how we can take advantage of the excellent features of the web services, but still providing the consumers with the best possible browsing experience on the site by incorporating some of the new features of the .NET framework.

   
                   
    Article Discussion   Rate this article   Related Links   Index Entries  
   
 
    ARTICLE

Introduction

Even though web services are very powerful and based on open Internet protocols like XML, HTTP and SOAP (that accounts for platform independence using XML based messaging that enables components on other platforms to exchange information with components running on the .NET platform), but still using them in a business web site requires very careful consideration of the performance implications. For example, before showing a particular page if you try to call out two or three web services across the Internet to get the data, then the responsiveness of the site is going to be severely impacted. At the same time, you cannot avoid calling out to web services to get the data you want. However, if you carefully plan up your web application, you can take advantage of the functionalities of the web services without impacting the performance of the application.

In this article, we will consider the very common example of a Stock Ticker application and understand how to use features such as asynchronous web services, windows service applications, server based timer components and .NET XML API classes to create high-performance, effective and high-performance solutions that are scalable and flexible.

Architecture of the System

Here our requirement is to get the stock quote from the remote web service and display the stock quote in different kind of applications such as a windows forms based application and a web forms application. The following different pieces are tied together to construct this application.

Introduction

Before we start looking at the code, let me briefly introduce some of the new .NET features like Windows Service, Timer Component, ASP:XML server control and .NET Framework XML API that we will be using in this application.

Windows Service

There are times where you may want to have your code always running on your server. If you have ever done any work in MSMQ, you might have created an application that polls the message queue for every predefined amount of time and checks for new messages. In that case, the application that checks the queue for messages should always be running as a Windows NT Service to be able to have the ability to poll the message queue frequently. These windows services do not have any user interface and we can configure windows services in such a way that they can be automatically started when the computer starts or they can be paused and restarted at any time.

Essentially, a Windows Service is similar to a UNIX daemon and it starts up automatically every time the system is booted up or manually (depending upon settings) and then waits silently in the background for requests for its service. A Windows Service practically has no interaction with the desktop and when connected to from a remote client, transparently handles the connection and exchange of information to the client.

Prior to Visual Studio.NET, if you want to write a windows service application, either you have to use the template provided by ATL (Active Template Library that exposes a set of classes used for COM programming in the Windows environment) or if you are a VB programmer, you have to embed custom NT service controls in VB to achieve the same functionality. But with Visual Studio.NET, you can easily create an application that has the capability to run as a Service. Visual Studio.NET is supplied with a new project template called Windows Service that provides all the plumbing required for creating the application that can run as a Service. When you create a Visual Studio.NET project as a Service, you can write code to respond to the actions like what should happen when the service is started, paused, resumed and stopped.

Once you create the service, it has to be installed using InstallUtil.exe (Command line utility) which is used to install the service in the local computer. After you install the service, you can start, stop, pause and resume it using Service Control Manager.

Timer Component

One of the new exciting features of the .NET framework is the ability to create applications that can raise events at scheduled intervals. The Timer component that is contained in the System.Timers namespace is a server side component that exposes methods and properties through which we can capture events raised by the timer component and take specific actions according to the requirements.

You can create an instance of the Timer component by using any one of the following ways.

The Timer component exposes a property named Interval, the value of which determines theinterval at which the Elapsed event is raised. As the name suggests, the Elapsed event is raised whenever the specified time interval expires and we can write code in this event to implement the custom processing logic that we want to execute.

In this article, we are going to use a timer component that is placed on the windows service, to raise events at the elapsed intervals that will allow us to make a request to a remote web service in an asynchronous fashion. Since this timer component is placed in the Windows service application (that is always running), we can continue to make requests to the remote web service at periodic intervals. This frequency of requests is determined by the value of the Interval property. It is also important to note that the server based timer component is different from the windows based timer control that is contained in the System.Windows.Forms namespace. Since the server-based timer components are designed for use with worker threads in a multithreaded environment, they can be more efficient in multithreaded environment unlike their windows based counterparts.

For more information on timer components, please take a look at the following link from MSDN.

Introduction to Server-Based Timers.

.NET Framework XML API

The .NET Framework provides a set of XML classes for developers to create applications based on XML. Microsoft has made every attempt to keep the programming model of these classes to be in line with the ADO.NET programming model, which also provides a wealth of functionality to work with XML. These XML classes are contained in the System.XML namespace. The methods and properties of the classes present in the System.XML namespace are similar to its predecessor, the MSXML parser component. Eventually the System.XML namespace is likely to replace the MSXML parser.

All the .NET framework XML classes are derived from two abstract classes called XmlReader and XmlWriter. XmlReader provides a fast, forward-only, read-only cursor for reading an XML document and XmlWriter provides a mechanism for producing XML document streams. The output produced by these classes conforms to the W3C recommendations. In this article, we will be using XmlTextWriter and XmlTextReader classes for writing into and reading from an XML file.

For more information on XML classes in the .NET Framework, please take a look at the following article from MSDN. XML in .NET: .NET Framework XML Classes and C# Offer Simple, Scalable Data Manipulation.

ASP:XML Server control

One of the coolest features of .NET is the ability to apply XSLT transforms to XML data and create HTML pages on the fly. This can be done using the high performance, built-in server control called ASP:XML and is identified by the tag asp:xml.

The input XML data to the control can be in any one of the following formats: an object of type System.Xml.XmlDocument, an XML string or an XML file. Similarly the XSL data can be in any one of the following formats: an object of type System.Xml.Xsl.XslTransform or an XSL file.

We will be using the following two properties of the control in the later part of this article to perform the transformation.

Indicates the name of the XML file to be used as input data

Indicates the name of the xsl file that contains the transformations to be applied to the XML data

Implementation of the System

We will split the implementation of the whole application into three different parts.

This windows service application invokes the web service asynchronously at scheduled intervals, which is determined by the interval property of the Timer component. This application gets the stock quote from the web service and it stores that value in the XML file named stocks.XML that is created on the fly.

In this section, we will see how this XML file (that has the updated stock information) can be used by different applications. Towards this end, we will consider the following:

Implementation of Web Service

A Web service can be defined as programmable logic that is exposed via the internet using internet protocols such as HTTP, XML and SOAP. Since web services are exposed using standard internet protocols, any application that can communicate using these standards can interact with a web service. Web services provide well-defined interface of their functionality through an XML based language called Web Services Description Language (WSDL). This language not only describes the functionality of the web service but also describes each of its methods, the parameters they take, and their return value. It is similar to the way a COM object exposes its functionalities through a type library.

For an introduction to web services, take a look at the article Web Services with ASP.NET from MSDN.

In this article, we will be implementing a web service called StockQuoteWebService. This web service basically invokes the stored procedure called StockQuoteGet written using procedural extensions to T-SQL, to get the stock information from a SQL Server database. The stored procedure is defined as follows:

create procedure StockQuoteGet 
@Name char(4)
as
select * from Stocks 
where Name = @Name
GO

As you can see, the stored procedure is very simple and it returns the stock quote from the stocks table based on the name of the company passed in as the argument.

Here is the C# code that is required to implement this web service. Please note that this source code can be found in the code-behind file QuoteService.asmx.cs of the web service QuoteService.asmx.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Data.SqlClient;

[WebMethod(EnableSession=false,Description="This Method returns the stock quote based on & -
name of the company")]
public string GetQuote(string sName)
{
  DataSet oDataSet;
  SqlConnection oSQLConnection;
  SqlDataAdapter oSQLCommand;
  DataTable dtStockTable;        
       string sConnectionString;
  string sPrice;

  sConnectionString = "server=localhost;uid=sa;pwd=;database=ASPToday";
       oSQLConnection = new SqlConnection(sConnectionString);
       oSQLCommand = new SqlDataAdapter("StockQuoteGet", oSQLConnection);

       oSQLCommand.SelectCommand.CommandType = CommandType.StoredProcedure;

oSQLCommand.SelectCommand.Parameters.Add(new SqlParameter("@Name", SqlDbType.Char,4));
       oSQLCommand.SelectCommand.Parameters["@Name"].Value = sName;

       oDataSet = new DataSet();
       oSQLCommand.Fill(oDataSet, "Stocks");			
       //Assign the table to the DataTable object variable
       dtStockTable = oDataSet.Tables["Stocks"];
  //Return the value present in the Price column
  sPrice  = dtStockTable.Rows[0]["Price"].ToString();			    return sPrice;
            
}

Let us walk through the code line by line to understand the execution path of the web service.

We start our implementation by importing all the required namespaces.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;

Since we need to access the Sql Server database to get the stock quote, we import the namespace System.Data.SqlClient using the code shown below. This namespace contains all the classes required for accessing the SQL Server database using native calls (TDS - Tabular Data Stream protocol) allowing us to create high performance applications that are scalable.

using System.Data.SqlClient;

The attribute WebMethod specifies that this method is web-callable. When the ASP.NET runtime sees this attribute, it provides all the underlying plumbing required for exposing this method to the Internet clients. We also specify that we do not want to store state information across requests from a single consumer by setting the EnableSession property to false. The Description property allows us to provide a brief description of the functionality of our web service.

 [WebMethod( EnableSession=false,Description="This Method returns the stock quote based on the name of the company")]

In this line, we create an instance of the SqlConnection object passing to it the connection string that is required to establish connectivity with the database.

oSQLConnection = new SqlConnection(sConnectionString);

Once we create an instance of the SqlConnection object, we can then create the SqlDataAdapter object.

We pass the name of the stored procedure we want to execute and the previously created SqlConnection as arguments to the constructor of the SqlDataAdapter object.

oSQLCommand = new SqlDataAdapter("StockQuoteGet", oSQLConnection);      
   
  
 

Here, we indicate that we want to execute the stored procedure by setting the CommandType property to Stored Procedure.

oSQLCommand.SelectCommand.CommandType = CommandType.StoredProcedure;

Since our stored procedure takes the company name symbol as an argument, we add the Name parameter in the following line.

oSQLCommand.SelectCommand.Parameters.Add(new SqlParameter("@Name", SqlDbType.Char,4));

After we add the parameter, we assign the passed name to the Value property of the parameter object.

oSQLCommand.SelectCommand.Parameters["@Name"].Value = sName;
oDataSet = new DataSet();

We then populate the dataset with the results of the stored procedure execution by invoking the Fill method of the SqlDataAdapter object.

oSQLCommand.Fill(oDataSet, "Stocks");

The Tables collection of the dataset object contains all the tables that are returned as a result of the stored procedure execution. From this collection, we retrieve the Stocks table and assign it to the DataTable object using the following line of code.

//Assign the table to the DataTable object variable
dtStockTable = oDataSet.Tables["Stocks"];

Once we get the DataTable object, we can then easily extract the value present in the Price column and assign it to the local variable sPrice.

//Return the value present in the Price column
sPrice  = dtStockTable.Rows[0]["Price"].ToString();

Finally, we return the value present in the variable sPrice to the caller.

return sPrice;

Implementation of Windows Service application

To create a Windows Service application in Visual C#, select File->New Project and then select Visual C# Projects from the Project Types and Windows Service from the List of templates.

Once we create the new project WinPollingService, we rename the default service class (Service1) to QuotePollingService.

The following figure shows the Properties window of our QueuePollingService. Through this window, we can set properties such as CanStop and CanShutdown to either true or false. These settings determine what methods can be called on our service at runtime. For example, when the CanStop property is set to true, the OnStop method will be automatically called when the service is stopped through the Service Control Manager.

Once we set all the properties to appropriate values, we need to add the installers that are required for installing our windows service application as a service. To add these installers, we click on Add Installer (shown in the above figure) in the properties window of the QuotePollingService class.

Before we start looking at code, let us briefly explore some of the theory behind the creation of Windows Service applications.

The three main classes involved in Windows Service creation are:

The ServiceBase class exposes the following methods and we can override these methods to determine what happens when we change the state of the service (like starting, stopping, etc) in the Services Control Manager.

We can write code in the following events depending on the requirements.

These classes are used to install and uninstall the service. As we already mentioned, these classes are automatically added when we click Add Installer in the properties windows of the service class. After we add both the classes, we need to change the Account property of the ServiceProcessInstaller instance to use the LocalSystem account. This is shown in the following diagram.

Now that we have configured all the properties, we can carry out operations such as installing or uninstalling the Service by using the InstallUtil.exe utility.

Since our windows service depends on the methods of the StockQuoteService to get the stock quote, we add reference the web service that we created in the previous step. In Visual Studio.NET, we can do this using the Add Web Reference option.

To add a web reference, right click on the project in the Solution explorer and select Add Web Reference. In the Add Web Reference dialog box, enter the path of the .disco file of the web service.

The file .disco is an XML data file that is used for controlling dynamic discovery of the web service for the clients by obtaining WSDLs and Schemas together.

When you add a web reference of a web service to your project, Visual Studio.NET automatically generates a proxy class that not only interfaces with the web service but also provides a local representation of the web service.

Let us look at the code required to implement our windows quote polling service. The following code can be found in the file QuotePollingService.cs in the Windows service project.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Xml;
using System.Data.SqlClient;

public class QuotePollingService : System.ServiceProcess.ServiceBase
{
  private System.ComponentModel.IContainer components;
  private localhost.QuoteService m_oService;
  private System.IAsyncResult m_oAsyncResult;
  private System.Timers.Timer timer1;
  private string m_sName;

  static void Main()
  {
    System.ServiceProcess.ServiceBase[] ServicesToRun;	
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new QuotePollingService() };

    System.ServiceProcess.ServiceBase.Run(ServicesToRun);
  }
  protected override void OnStart(string[] args)
  {
    / TODO: Add code here to start your service.
    m_sName = "MSFT";
    m_oService = new localhost.QuoteService();
    timer1.Enabled = true;
  }

  private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  {
    //Invoke the GetQuote method in asynchronous fashion with the //callback method
    m_oAsyncResult = m_oService.BeginGetQuote(m_sName ,new AsyncCallback(WriteResult), null);				
  }

  private void WriteResult(IAsyncResult oRes )
  {
    string sResult;
    sResult = m_oService.EndGetQuote(oRes);
    XmlTextWriter oXmlTextWriter = new XmlTextWriter ("c:\\Inetpub\\wwwroot\\StockWebFormsClient & -
	\\stocks.xml", null);
    oXmlTextWriter.Formatting = Formatting.Indented;
    oXmlTextWriter.WriteStartDocument(false);			
    oXmlTextWriter.WriteComment("This file represents the stock quote returned from the web service");
    oXmlTextWriter.WriteStartElement("stockquotes");
    oXmlTextWriter.WriteStartElement("stockquote", null);	
    oXmlTextWriter.WriteStartElement(m_sName, null);     
    oXmlTextWriter.WriteElementString("price", sResult);
    oXmlTextWriter.WriteEndElement();					
    oXmlTextWriter.WriteEndElement();
    oXmlTextWriter.WriteEndElement();
    //Write the XML to file and close the oXmlTextWriter
    oXmlTextWriter.Flush();
    oXmlTextWriter.Close();
  }

}

We start by importing all the required namespaces. As you can see, we have also imported the System.Xml namespace to have access to the XML related classes.

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Xml;
using System.Data.SqlClient;

In the following lines of code, we declare objects of type QuoteService and IAsyncResult.

private localhost.QuoteService m_oService;
private System.IAsyncResult m_oAsyncResult;
static void Main()
{

Here, we declare an Array of type ServiceBase.

System.ServiceProcess.ServiceBase[] ServicesToRun; 
  

All the services contained by the application can be added and run together. Since we are creating only one service named QueuePollingService, we add that to the array.

ServicesToRun = new System.ServiceProcess.ServiceBase[] { new QuotePollingService() };

The Run method of the ServiceBase class is the main entry point for the service. In the following line of code, we call the Run method and pass the previously created array as an argument.

System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}

The OnStart method will be executed when the service is started from the Service Control Manager. In this method, we create an instance of our QuoteService and we also enable the timer component to let it raise the Elapsed event at periodic intervals.

protected override void OnStart(string args)
{
  // TODO: Add code here to start your service.  
  m_sName = "MSFT";
  m_oService = new localhost.QuoteService();  
  timer1.Enabled = true;
}

As we already said, the windows service application has a timer component that has its interval property set to 5000 milliseconds. Whenever this interval elapses, the timer component automatically fires the Elapsed event. In this event, we call the BeginGetQuote method of the web service and pass the company symbol as the first argument. We also pass an instance of the AsyncCallback delegate object. To the constructor of the AsyncCallback class, we pass the name of the callback method that is to be called back when the asynchronous operation is completed, as an argument. The BeginGetQuote method returns an object of type IAsyncResult that can be used to check the status of the asynchronous operation.

private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{    
  //Invoke the GetQuote method in asynchronous fashion with the //callback method
  m_oAsyncResult = m_oService.BeginGetQuote(m_sName ,new AsyncCallback(WriteResult), null);
}

The WriteResult method is called once the web service has finished its execution and it is also passed an object of type AsycnResult that encapsulates the results of the asynchronous web service call that we made.

private void WriteResult(IAsyncResult oRes )
{
string sResult;

We get the result by calling the EndGetQuote method passing to it the AsyncResult object that holds the results of the invocation as an argument.

  sResult = m_oService.EndGetQuote(oRes);

Here we create an instance of the XmlTextWriter object and specify the path of the XML file to be created.

XmlTextWriter oXmlTextWriter = new XmlTextWriter&-
("c:\\Inetpub\\wwwroot\\StockWebFormsClient\\stocks.xml", null);

To format the XML Document, we assign the value Indented to the Formatting property of the XmlTextWriter. When this option is set, child elements are indented using Indentation and IndentChar properties. The IndentChar property decides which character to use for Indenting and the Indentation property determines how many IndentChars to write for each level in the hierarchy.

Here we use the default values for Indentation and IndentChar, which are two and spaced respectively.

oXmlTextWriter.Formatting = Formatting.Indented;

We use StartDocument to write out the XML declaration with the version and the standalone attributes. The version attribute will be set to "1.0" and the standalone will have the value "no" as we pass false as an argument to the WriteStartDocument method.

oXmlTextWriter.WriteStartDocument(false); 
  

In this line, we write a Comment to indicate that the QuotePollingService application has created this file.

oXmlTextWriter.WriteComment("This file represents the stock quote returned from the web service");

Here we write out the specified start tag with the name of the element as stockquotes.

oXmlTextWriter.WriteStartElement("stockquotes");

We then write out another element with the name being stockquote.

oXmlTextWriter.WriteStartElement("stockquote", null);	

We add this line of code to create an element with the name being the value contained in the m_sName variable.

oXmlTextWriter.WriteStartElement(m_sName, null);

Finally, we write out an element of type string by invoking the WriteElementString method of the XmlTextWriter object.

oXmlTextWriter.WriteElementString("price", sResult);

In the following lines, we write out the corresponding end tag elements.

  oXmlTextWriter.WriteEndElement();
  oXmlTextWriter.WriteEndElement();
  oXmlTextWriter.WriteEndElement();

After we are done writing the elements, we flush the contents and then close the XmlTextWriter object.

  //Write the XML to file and close the oXmlTextWriter
  oXmlTextWriter.Flush();
  oXmlTextWriter.Close();
}

A sample XML file that is generated by the above code looks like this.

Now that we have created the Windows Service application, let us install the application using the InstallUtil.exe utility. Before we install the application using InstallUtil, we need to navigate to the directory path that contains the WinPollingService.exe file and then execute the following command from the command prompt.

InstallUtil WinPollingService.exe 

Executing the above command in the command prompt results in the following output being created.

Implementation of Client Applications

Now that we have created the windows service application that periodically refreshes the contents of the XML file with the latest stock quote information, we will look at how this XML file can be used by different applications. To illustrate this, we will consider the following two client applications:

We will start our explanation with the windows forms application

Windows Forms Application

We create a new Visual C# Windows application using the following New Project dialog box and call it as StockWinFormsClient.

To the windows form, we add a timer control and set its Interval property to 5000. We also add three label controls and name them lblStock, lblName and lblMessage respectively. The label control lblStock is the one that displays the stock quote that is obtained from the XML file.

Since we set the interval property of the timer control to 5000, the Tick event of the timer control will be fired for every 5000 milliseconds.

private void timer1_Tick (object sender, System.Timers.ElapsedEventArgs e)
{
  try
  {

Here, we invoke the UpdateDisplay method and pass the name of the XML file to be read as an argument.

UpdateDisplay("c:\\Inetpub\\wwwroot\\StockWebFormsClient\\stocks.xml");
  }
  catch(Exception ex)
  {
    MessageBox.Show(ex.Message);
  }
 
}

The UpdateDisplay method loops through the contents of the XML file and identifies the element with the name "price" by verifying the NodeType and Name properties of the XmlTextReader object.

private void UpdateDisplay(string sPath)
{
  try
  {
    XmlTextReader oXmlReader = new XmlTextReader (sPath); 
    while (oXmlReader.Read())
    { 
      if (oXmlReader.NodeType == XmlNodeType.Element)
      {
        if (oXmlReader.Name == "price")
        { 

Once the element is identified, we read the contents of the element by invoking the ReadElementString method.

    lblStock.Text = oXmlReader.ReadElementString();
    }
  } 
}
oXmlReader.Close();
}
catch(Exception ex)
{
  MessageBox.Show(ex.Message);
}
 
}

When we execute this application, we get an output that is similar to the following.

Web Forms Application

Now, let us have a look at how we can use the XML file, that is created by the windows service application, to display the stock quote information in a web forms application.

We start by creating a new project called StockWebFormsClient as shown in the following figure.

Once we create the project, we add the asp:xml server control to the web form and set its DocumentSource and TransformSource properties to stocks.XML and stock.xsl respectively.

The entire code of the web form page named WebForm1.aspx is as follows:

<%@ Page language="c#" Codebehind="& -
WebForm1.aspx.cs" AutoEventWireup="false" Inherits="StockWebFormsClient.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
  <HEAD>
    <meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
    <meta content="C#" name="CODE_LANGUAGE">
    <meta content="JavaScript (ECMAScript)" name="vs_defaultClientScript">
    <meta content=http://schemas.microsoft.com/intellisense/ie5 name="vs_targetSchema">
  </HEAD>
  <body MS_POSITIONING="GridLayout">

  <form id="TesWebForm" method="post" runat="server">
  <asp:label id="Label1" style="Z-INDEX: 101; LEFT: 149px; & -
  POSITION: absolute; TOP: 255px" runat="server" Height="38px" & -
  Width="471px" ForeColor="Maroon">The above content is generated through the & -
  use of asp:xml server control
  </asp:label>

  <asp:xml id="Xml1" runat="server" TransformSource="stocks.xsl" & -
  DocumentSource="stocks.xml">
  </asp:xml>

  </form>

  </body>
</HTML>

The stocks.xsl file that is used for transforming the contents of the stocks.XML file to HTML looks like the following.

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="stockquotes">
  <table cellspacing="0" width="100%" border="1" borderColor="DarkGoldenrod">
  <tr align="center">
  <td>
  <b>
  MSFT : <xsl:value-of select="stockquote/MSFT/price" />
  </b>
  </td>
  </tr>
  <br></br>
  <br></br>
  <tr align="center">
  <td>
  <b>

The stock price is obtained from the XML file generated through the asynchronous web service.

</b>
  </td>
  </tr>
  </table>
  </xsl:template>
</xsl:stylesheet>

If we run the application, we get the following output.

As we can see from the above figure, the first half of the page is generated by the asp:xml server control and the second half of the page that has the static display, originates from the parent web form.

Putting it all together

Now that we have constructed the different parts of the application, let us test the application by going through the following steps.

Conclusion

In this article, we have seen the following.

Although the application we created was simple in functionality, it should provide a solid foundation for understanding how to build high performance, scalable, flexible and reliable web applications using some of the new features of the .NET framework such as XML based web services, windows service applications, XML API classes and the server based timer component.

Related ASPToday and CSharpToday Articles

Accessing a Web Service a Mobile Device using Mobile.NET

Creating a Windows Service in C# - A Network Status monitor

Using MSMQ And Windows NT Services

Creating Web Services using Visual Studio.NET

 
 
   
  RATE THIS ARTICLE
  Please rate this article (1-5). Was this article...
 
 
Useful? No Yes, Very
 
Innovative? No Yes, Very
 
Informative? No Yes, Very
 
Brief Reader Comments?
Your Name:
(Optional)
 
  USEFUL LINKS
  Related Tasks:
 
 
   
  Related ASPToday Articles
   
  • Accessing a Web Service from a Mobile Device using Mobile.Net-Part1 (August 17, 2001)
  • Using MSMQ and Windows NT services (part 2) (August 15, 2001)
  • Creating web services using Visual Studio.Net (April 19, 2001)
  •  
           
     
     
      Related Sources
     
  • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconserverbasedtimers.asp: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconserverbasedtimers.asp
  • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp02222001.asp: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp02222001.asp
  • http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmag01/html/xml0101.asp: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnmag01/html/xml0101.asp
  •  
     
           
      Search the ASPToday Living Book   ASPToday Living Book
     
      Index Full Text Advanced 
     
     
           
      Index Entries in this Article
     
  • Account property
  •  
  • Add method
  •  
  • Add Web Reference option
  •  
  • ASP:XML server control
  •  
  • CanShutDown property
  •  
  • CanStop property
  •  
  • Close method
  •  
  • CommandType property
  •  
  • description
  •  
  • Description parameter
  •  
  • DocumentSource property
  •  
  • EnableSession parameter
  •  
  • Fill method
  •  
  • Flush method
  •  
  • Formatting property
  •  
  • IAsyncResult interface
  •  
  • implementing
  •  
  • InstallUtil tool
  •  
  • Interval property
  •  
  • Name property
  •  
  • nodeType property
  •  
  • OnContinue method
  •  
  • OnPause method
  •  
  • OnShutDown method
  •  
  • OnStart method
  •  
  • OnStop method
  •  
  • ReadElementString method
  •  
  • references
  •  
  • Run method
  •  
  • SelectCommand property
  •  
  • server controls
  •  
  • server-side controls
  •  
  • ServiceBase class
  •  
  • ServiceInstaller
  •  
  • ServiceProcessInstaller class
  •  
  • SQLCommand object
  •  
  • SqlDataAdapter class
  •  
  • SQLParameter object
  •  
  • SQLParameters collection
  •  
  • stock quotes
  •  
  • stock ticker application
  •  
  • stored procedures
  •  
  • System namespace
  •  
  • System.Timers namespace
  •  
  • System.XML namespace
  •  
  • timer component
  •  
  • Timer Control
  •  
  • TransformSource property
  •  
  • Value property
  •  
  • Visual Studio.Net
  •  
  • web forms
  •  
  • web service
  •  
  • WebMethod attribute
  •  
  • windows service
  •  
  • WinForms
  •  
  • WriteElementString method
  •  
  • WriteEndElement method
  •  
  • WriteStartElement method
  •  
  • XMLTextReader object
  •  
  • XMLTextWriter object
  •  
     
     
    HOME | SITE MAP | INDEX | SEARCH | REFERENCE | FEEDBACK | ADVERTISE | SUBSCRIBE
    .NET Framework Components Data Access DNA 2000 E-commerce Performance
    Security Admin Site Design Scripting XML/Data Transfer Other Technologies

     
    ASPToday is brought to you by Wrox Press (http://www.wrox.com/). Please see our terms and conditions and privacy policy.
    ASPToday is optimised for Microsoft Internet Explorer 5 browsers.
    Please report any website problems to webmaster@asptoday.com. Copyright © 2001 Wrox Press. All Rights Reserved.