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
January 21, 2002
      Previous article -
January 18, 2002
   
 
   
   
   
Using Object-Oriented Principles for Building a Web Service   Danny RyanTommy Ryan  
by Danny Ryan, Tommy Ryan
 
CATEGORIES:  .NET Framework, Data Access, Site Design  
ARTICLE TYPE: Tutorial Reader Comments
   
    ABSTRACT  
 
Article Rating
 
   Useful
  
   Innovative
  
   Informative
  
 9 responses

In this article, Danny and Tommy Ryan will show how to use traditional object-oriented principles to make your Web Services more maintainable, scalable, and reusable. They will walk you through an example of a Web Service where they apply some important object-oriented principles to create a better implementation of an application that uses Web Services. The application will show how to migrate a Web Service to a new multi-tiered architecture that uses interfaces and inheritance to implement the functionality for two system requirements.

   
                   
    Article Discussion   Rate this article   Related Links   Index Entries  
   
 
    ARTICLE

In this article, we will show how to use traditional object-oriented principles to make your Web Services more maintainable, scalable, and reusable. We will walk you through an example of a Web Service where we apply some important object-oriented principles to create a better implementation of an application that uses Web Services. The application will show how to migrate a Web Service to a new multi-tiered architecture that uses interfaces and inheritance to implement the functionality for two system requirements.

Getting Started

Note that this article assumes that you have created a few simple Web Services. Please see the GotDotNet site if you need to get primed on Web Services. There is a section of GotDotNet that points you to resources for XML Web Services. Also, there is a section in the GotDotNet Quickstart Tutorial that steps you through some of the basics. Another useful resource is Thiru Thangarathinam's article entitled Creating Web Services Using Visual Studio.Net. Also in this article, we will be using many of the object-oriented features of VB.NET. Take a look at the article on Microsoft's site entitled Object-Oriented Programming in VB.NET or Object Oriented Features in VB.NET by Kaushal Sanghavi on ASPToday if you need to see a primer on VB.NET's object-oriented features.

Introduction to the Goal Server Web Service

Throughout this article, we are going to develop a couple of parts of a sample application that are used to generate goals for users via a Web Service. Let's take a look at a subset of the system requirements that we wish to implement for the first version of the Goal Server Web Service.

The Data that Supports the Requirements

The Web Service for this article is built upon a simple database that stores goals for Users. The following diagram shows the tables involved and their relationships to each other.

alt=

This database contains three stored procedures that the Web Services use to retrieve goals from the database. These are getUserGoalByUserID , getGoalMaxID , and getGoalText. The first stored procedure is for obtaining goals that a User has set, which are termed as a UserGoal. The second procedure is written to obtain the upper bound of a generic goal list. The last procedure is for returning the text of a specified generic goal. Generic goals are simply termed as a Goal in the system. Generic goals are an arbitrary list of goals stored as a starting point for users when they want to set their own goals. See the Create Procedure statements below for what is in each procedure.

/* Start of getUserGoalByUserID procedure */
CREATE PROCEDURE getUserGoalByUserID
(@UserID int) 
AS

SELECT 
GoalID 'PKId', [Text]
FROM 
UserGoal
WHERE
UserID= @UserID
/* End of getUserGoalByUserID procedure */
/* Start of getGoalMaxID procedure */
CREATE PROCEDURE getGoalMaxID AS

SELECT     
MAX(ID) AS MaxGoalID
FROM         
Goal
/* End of getGoalMaxID procedure */
/* Start of getGoalText procedure */
CREATE PROCEDURE getGoalText
(@ID int)  
AS

SELECT
[Text] from Goal
WHERE 
ID = @ID
/* End of getGoalText procedure */

A Simple Implementation of our Requirements

Let's take a look at a simple realization of our requirements. With this implementation, we are going to put all of the code into the Web Service.

Looking at the FatGoalService Web Service, we find the GetRandomDailyGoal Web Method. This code implements Requirement 1.1.

Take a look at the code necessary to generate a random daily goal.

  ' Web Method that retrieves a random Daily Goal
  <WebMethod()> Public Function GetRandomDailyGoal() As String
    Dim conMLG As New SqlConnection(GetConnectionString())
    Dim cmdMLG As New SqlCommand()
    Dim drGoal As SqlDataReader
    Dim intMaxGoalID As Integer
    Dim rndGoalID As New Random()
    Dim intRandomGoalID As Integer
    Dim strGoalText As String

    conMLG.Open()

    ' Setup up the command for execution
    cmdMLG.Connection = conMLG
    cmdMLG.CommandType = CommandType.Text

    ' Run the first command to get the upper bound of the current goal list
    cmdMLG.CommandText = "EXEC getGoalMaxID"
    intMaxGoalID = cmdMLG.ExecuteScalar()

    ' With the max Goal ID, obtain a random number that can be used to retrieve 
    ' a goal
    intRandomGoalID = rndGoalID.Next(1, intMaxGoalID)

    ' Now run the command again with the random ID to retrieve the Goal Text 
    cmdMLG.CommandText = "EXEC getGoalText @ID=" + intRandomGoalID.ToString()

    conMLG.Close()

    strGoalText = cmdMLG.ExecuteScalar()

    Return strGoalText

  End Function

Note that we are using the Random .NET Framework class to generate a random number with an upper bound of the goal list in the Goal table. Also, note that the basic architecture involved here is a Web Method calling directly to a stored procedure that returns the results.

Next, take a look at the Web Method for System Requirement 1.2, retrieving the goal list for a user.

  ' Web Method that retrieves a goal list by user id
  <WebMethod()> Public Function GetGoalsByUserID(ByVal intUserID As Integer) As DataSet
    Dim dsGoal As DataSet = New DataSet()
    Dim conMLG As New SqlConnection(GetConnectionString())
    Dim cmdMLG As New SqlCommand()

    cmdMLG.Connection = conMLG
    cmdMLG.CommandType = CommandType.Text
    cmdMLG.CommandText = "EXEC GetUserGoalByUserID @UserID=" + intUserID.ToString()

    Dim daMLG As SqlDataAdapter = New SqlDataAdapter(cmdMLG)

    conMLG.Open()
    daMLG.Fill(dsGoal)
    conMLG.Close()

    Return dsGoal

  End Function

Again, we find this Web Method uses the same basic architecture. Now that we've seen the code for the Web Service, let's go ahead and invoke the Web Methods. We can do this with the built in test harness that ASP.NET provides. We can test the Web Service by directly accessing the *.asmx file. ASP.NET will intercept the request for this resource and display the Web Methods that are available on our Web Service.

First let's select the GetRandomDailyGoal method. If we submit the "Invoke" button, we will get an XML response from the GetRandomDailyGoal Web Method.

alt=

Here we see that a goal is generated. Hit refresh a few of times to verify that the goal returned is randomly selected.

Next, invoke the GetGoalsByUserID , passing in 1 for the intUserID. Scrolling down the XML to the DataSet representation we see a goal list is generated for the user based on the User Id:

Image 3

How Can We Improve This Implementation?

If this is your first Web Service, this represents at least a good morning of work (earning you at least a second cup of coffee). But, in this article, our goal is to create a Web Service that is more maintainable, scalable, and reusable. With all of the code in the Web Service, we run into a number of issues that impede these goals. These issues become even more evident as our application grows or when the requirements change.

This example is not very complex, but what we do with the improved implementation will allow us to address maintainability, scalability, and reusability for future growth and changes to the application. Let's discuss these factors and then move onto what we changed in the improved version of the application.

Factors

Maintainable

First, this code might be considered easy to maintain because it is in one file. This is fine for a simple Web Service, but as our application grows we should not have all logical layers of the application in one file. If we need to make any changes to the application, only one person at a time can do this. As this application grows, we will find that our coding will require copying and pasting of code (since we will most likely do the same type of data access code). If we find that we want to change the data access code, we will have to go and change every Web Method. This leads to inefficiencies. We could solve this by putting these shared routines into private functions inside of our Web Service. This would partially address the maintainability issue in our Web Service. We still have the issue of contention when we need multiple developers working on one file. Therefore, we need to separate these routines into logical layers (you will see this later in the article).

Disclaimer: For this sample application you could argue that we have made it more difficult to maintain. We have moved the implementation to a separate library, and now we have more layers of code to maintain. Well, that is true, and you will just have to trust us when we say that as the application grows this code separation will pay off. If you are very confident that you will not have to reuse any of the code that is in the Web Service and the code is small (like in this example), then you might find that distributing your code into several classes is not the right move. For the purpose of this article, we are assuming that your applications will grow and requirements will change.

Scalable

All of our code is contained within the same Web Services code-behind file ( FatGoalService.asmx.vb). You might ask "What's wrong with having all your code in one Web Service?"; because you know that it will be compiled class when it is run in the CLR (Common Language Runtime). You are correct, but if we need to address bottlenecks in the code, we will have to distribute the code into separate classes that can be put in different assemblies. By extracting out the code into separate classes, we will be able to distribute the application as we wish. For example, with this architecture we could leverage the use of Component Services. This would allow us to take advantage of features such as object pooling. Also, if we have them in separate components, we can address bottlenecks in processing a request by distributing components across multiple servers.

Again, with an example of this size it might seem like more trouble than it is worth, but we are looking to set up an architecture that can grow with time.

Reusable

In the future, we may wish to create new applications that could benefit from the logic and data access that is embedded in our FatGoalService Web Service. By putting our code into several different classes we have the potential to reuse parts of the application. For example, the site http://www.mylifetimegoals.com/?WROXEMPTOKEN=180659ZhEaANU51sACzT6SGvlO reuses the data access components that are used by the ThinGoalService Web Service (the new version of the FatGoalService that we will show later in the article).

You probably notice from these benefits that many of the reasons why you built multi-tier applications with your Windows DNA and/or Windows .NET applications also apply to creating your Web Services. Web Services represent a new way to interface our applications and the object-oriented software development practices still apply.

Using Object-Oriented Programming Features

To respond to the challenges of creating maintainable, scalable, and reusable applications, we are going to demonstrate the central principles of object-oriented programming - abstraction, encapsulation, and inheritance.

Abstraction

Abstraction as defined by http://www.whatis.com/?WROXEMPTOKEN=180659ZhEaANU51sACzT6SGvlO is "the process of taking away or removing characteristics from something in order to reduce it to a set of essential characteristics". In the ThinGoalService we have abstracted a Goal Interface (we will talk more about interfaces in the "Inheritance" section) that is used for the two essential types of Goals in our Goal Server, SystemGoal and UserGoal. The abstraction of a Goal Interface allows the programmer of the Web Services (or of an ASP.NET WebForms application) to access all goals in a uniform manner. This helps with providing consistency across the application, which will produce more maintainable applications in the long run. We do not see this benefit immediately with this application, but as our system grows we will reap the benefit.

Encapsulation

Encapsulation is the process of hiding the implementation behind an established interface (method or property signature). Encapsulation allows you to hide the complexity of what is implemented in your method or property procedure (for simplicity sake, we will call these operations). With proper encapsulation, we reduce the dependencies between objects and have the ability of changing implementation behind an operation without affecting the consumer of our object.

For our ThinGoalService implementation, each logical layer (Business, Data access, and Data layers) is encapsulated into separate classes. This helps us down the road when we want to reuse parts of the system. Also, we have included a Resource class. This encapsulates the common functions that we will need to provide for the application in general. The first member of this class is the ConnectionString property procedure. This hides the complexity of pulling the connection string from the web.config file. This Resource class will be used in this application for common functions that can be used in this application and other applications in the future (see the end of Designing and Implementing the Data Classes, Data Access Layer, and Utility Classes section for the code for this class).

Inheritance

When we speak of inheritance, we need to be clear on what type of inheritance we are using. The two types of inheritance are implementation and interface inheritance.

In VB6 we had interface inheritance, but not implementation inheritance. Interface inheritance allows you to inherit the interface or signature of an object, but not the code. In VB6 we could define our own interfaces with a Public Non-creatable Class (placing signatures to empty operations). This was a hack at an interface and true interfaces had to be created in IDL (different language). Now in VB.NET the language truly supports the definitions of interfaces (see Designing and Implementing the Goal Interface and the Business Layer section of this article for a code example that implements an Interface). We use interface inheritance in the business layer to prepare for upcoming versions of the application where we will want to share the same interface among the various goal types.

Implementation inheritance, contrary to interface inheritance, does allow us to reuse or inherit code. This is a big benefit to VB.NET over what you can do in VB6. We will take advantage of this object-oriented feature in our data classes by inheriting the System.Data.DataSet.NET Framework Class.

Now let's look at the code in the Web Service that uses this new architecture.

High Level Design of Improved Architecture

For this article, we're going to simplify things a little and reuse the data, tables, and stored procedures that we used in our FatWebService.asmx. Here's where most of the reuse of code ends, though. From here we will take code that needs to be distributed and place it a namespace called GoalLibrary. GoalServerCom is the namespace that contains the definition of the WebMethods that are available for the Web Service. GoalServerCom depends on the GoalLibrary for business services and data services.

Image 4

The GoalLibrary is structured as follows:

Image 5

Now let's start digging into each layer.

Designing and Implementing the Data Classes, Data Access Layer, and Utility Classes

With the goal of improving our application, we'll want to take all of the data access code in our Web Service and put it into a data access layer (in DataAccess.vb). We will use this layer for retrieving and storing persistent data. Along with the data access layer, we will go ahead and create a data class (in Data.vb) to represent the System Goals (used by Requirement 1.1) and the User Goals (used by Requirement 1.2). Finally, we will create a utility class (in Resource.vb) for our application. Although this class won't be doing much initially, you can expect it to grow in the future, as your application requires shared utility functions for your components.

Let's look at what we have for the SystemGoalData and UserGoalData data classes. Since they are quite similar, let's just focus on SystemGoalData. Here is the class diagram for SystemGoalData:

Image 6

The SystemGoalData class will be used to represent System Goals. The class inherits System.Data.Dataset so that we can store structured data from the database (reusing what .NET provides for transporting data). We extend the DataSet functionality by adding constants that we use when retrieving data from the DataSet. We'll use the constructor to build a dataset and then set the class to the created dataset. Take a look at the Data.vb file for the UserGoalData data class implementation; it's basically the same.

Here's the SystemGoalData class's code:

Public Class SystemGoalData

    Inherits DataSet

    Public Const SOURCE_TABLE As String = "Goal"
    Public Const PKID_FIELD As String = "GoalID"
    Public Const TYPE_ID_FIELD As String = "TypeId"
    Public Const GOAL_NAME_FIELD As String = "GoalName"
    Public Const GOAL_TEXT_FIELD As String = "Description"
    Public Const TYPE_NAME_FIELD As String = "TypeName"

    Public Sub New()
      Dim table As DataTable = New DataTable(SOURCE_TABLE)

      With table.Columns
        .Add(PKID_FIELD, GetType(System.Int32))
        .Add(TYPE_ID_FIELD, GetType(System.Int32))
        .Add(GOAL_NAME_FIELD, GetType(System.String))
        .Add(GOAL_TEXT_FIELD, GetType(System.String))
        .Add(TYPE_NAME_FIELD, GetType(System.String))
      End With

      Me.Tables.Add(table)

    End Sub

  End Class

Next, let's design and build the data access layer that will use these data classes. Here's what we designed for the data access layer:

Image 7

In the data access layer, we'll share a connection ( conMLG) and command ( cmdMLG) that are initialized in the constructor event of the class.

Continuing to focus on Requirement 1.1, we see that we use the GetMaxID function for getting the highest Goal ID in the system (note that the assumption is that the Goal ID's will be contiguous from Goal ID 1 to the maximum Goal ID). This number will be used as an upper bound for generating a random goal number.

    Public Function GetMaxID() As Integer
      Dim intMaxGoalID As Integer

      ' Setup up the command for execution
      cmdMLG.CommandType = CommandType.Text

      ' Run the first command to get the upper bound of the current goal list
      cmdMLG.CommandText = "EXEC getGoalMaxID"

      conMLG.Open()
      intMaxGoalID = cmdMLG.ExecuteScalar()
      conMLG.Close()

      Return intMaxGoalID
    End Function

With Requirement 1.1, we return a random daily goal.In the data access layer, we have the exposed public function GetSystemGoalByID in the data access to return a System Goal. This method simply calls the private RetrieveSystemData function.

    Public Function GetSystemGoalByID(ByVal intGoalID As Integer) As SystemGoalData
      Return RetrieveSystemData("EXEC getGoalText @ID=" + intGoalID.ToString())
    End Function

Within RetrieveSystemData , we will use our data class to get a system goal.

    Private Function RetrieveSystemData(ByVal strCommandText As String) As SystemGoalData

      Dim dataSystemGoal As SystemGoalData = New SystemGoalData()

      cmdMLG.CommandType = CommandType.Text
      cmdMLG.CommandText = strCommandText

      Dim daMLG As SqlDataAdapter = New SqlDataAdapter(cmdMLG)

      conMLG.Open()
      daMLG.Fill(dataSystemGoal)
      conMLG.Close()

      Return dataSystemGoal

    End Function

Note the return type on both the GetSystemGoalByID and RetrieveSystemData is SystemGoalData. Therefore, we will need to import the GoalLibrary.Data namespace for the data access layer.

Finally, we have to reuse that connection code we were so proud of in our FatWebService example. With our improved design, let's put it in a common utility class. Here's the code for Resource.vb:

Imports System.Web
Imports System.Web.Configuration
Imports System.Collections.Specialized

Namespace GoalLibrary.Common

  Public Class Resources

    Private Shared configConnectionString As String
    Private Const SITERESOURCES_CONFIG_SECTION As String = _
      "GoalLibrary.Common.Resources"

    ' This constructor takes in the appSettings Config Section and 
    ' pulls out the desired keys.
    Public Sub New(ByVal appConfigSettings As Object)
      Dim appSetting As NameValueCollection = CType( _
        appConfigSettings, NameValueCollection)

      configConnectionString = appSetting("MLGConnectionString").ToString()
    End Sub

    Public Shared ReadOnly Property ConnectionString() As String
      Get
        ConnectionString = configConnectionString
      End Get
    End Property

  End Class

End Namespace

We'll use this in our data access layer, so we can't forget to import the GoalLibrary.Common namespace in our data access class.

We have now designed and constructed the data, data access, and utility components. Let's continue on to the next tier and address the business layer.

Designing and Implementing the Goal Interface and the Business Layer

When building the data classes, we created a class for System Goals and for User Goals. System Goals are goals that are not associated to a specific user. If we look at the database, System Goals are stored in the Goal Table. User Goals, on the other hand, are stored in the UserGoal table and have a one-to-many relationship with the User table.

Although the System and User Goals may be different, they do share some attributes and operations. We want the Goal interface to be reusable for both System goals and for User goals. Therefore, we need to determine the attributes and operations that are common to all goal types. To keep it simple, we came up only a couple of operations - Add , Delete , Update , and GetItem. Note that you could also implement attributes, although we won't cover that in this article.

Here is a look at the Goal Interface implementation:

Namespace GoalLibrary.Interfaces

  Interface IGoal

    Function Add(ByVal strGoalText As String) As Integer

    Sub Delete(ByVal intGoalID As Integer)

    Sub Update(ByVal intGoalID As Integer, ByVal strGoalText As String)

    Function GetItem(ByVal intGoalID As Integer) As DataSet

  End Interface

End Namespace 

Now, let's continue to design the business services. We will focus on the SystemGoal Class. Because we are implementing the Goal interface, we will need to include all of the operations from the interface (Add , Delete , Update , and GetItem). We know that we will need a function for getting a random goal, so we can extend the interface to include a method for this purpose (called GetRandomGoal).

Here we see the class diagram:

Image 8

Moving forward to coding the SystemGoal class, we know that we will need to make sure that we have imported the GoalLibrary.Data, GoalLibrary.DataAccess, GoalLibrary.Interfaces. Let's take a close look at the code involved in the SystemGoal class.

Public Class SystemGoal

To implement the IGoal interface, we add:

    Implements IGoal

Next, we're going to declare and instantiate some private variables for the System Goals and for retrieving the number of goals.

    Private dsSystemData As SystemGoalData
    Private glGoalDA As GoalDA

    Public Sub New()
      dsSystemData = New SystemGoalData()
      glGoalDA = New GoalDA()
    End Sub

Here's the core function for the class that returns the random goal.

    Public Function GetRandomGoal() As String
      ' You must first get the upper bound of the GoalID 
      ' (assumption is that Goal ID's are
      ' continuous from 1 to the max value in the database).
      Dim intMaxGoalID As Integer
      Dim intRandomGoalID As Integer
      Dim randomGoalID As Random = New Random()

      intMaxGoalID = glGoalDA.GetMaxID()

      ' With the max Goal ID, obtain a random 
      ' number that can be used to retrieve a goal
      intRandomGoalID = randomGoalID.Next(1, intMaxGoalID)

      dsSystemData = GetItem(intRandomGoalID)

      Debug.WriteLine(dsSystemData.Tables("Table").Columns(0).ToString())
      Return dsSystemData.Tables("Table").Rows(0).Item(SystemGoalData.GOAL_TEXT_FIELD)

    End Function

Finally, let's add all of the functions from the IGoal interface.

    Public Function Add(ByVal strGoalText As String) As Integer Implements IGoal.Add
      ' Implementation goes here
    End Function

    Public Sub Delete(ByVal intGoalID As Integer) Implements IGoal.Delete
      ' Implementation goes here
    End Sub

    Public Sub Update(ByVal intGoalID As Integer, ByVal strGoalText As String) Implements IGoal.Update
      ' Implementation goes here
    End Sub

Note that GetItem is the only function that we need to meet Requirements 1.1 and 1.2.

    Public Function GetItem(ByVal intGoalID As Integer) As System.Data.DataSet Implements IGoal.GetItem
      ' Perform validation (if necessary)

      dsSystemData = glGoalDA.GetSystemGoalByID(intGoalID)

      If Not dsSystemData Is Nothing Then
        If dsSystemData.Tables("Table").Rows.Count = 1 Then 
          Return dsSystemData
        Else
          Throw New Exception("Random goal could not be retrieved.")
        End If
      End If

    End Function

    End Sub

  End Class

Our improved Web Service - Fifty pounds thinner

Here's the fun part. Now that we have moved the data, utility, and business services, our web service code becomes very clean. Here's the Web Service code behind file contents:

Imports System.Web.Services
Imports GoalLibrary.BusinessServices
Imports GoalLibrary.Data

Public Class ThinGoalService
    Inherits System.Web.Services.WebService

  ' Web Method that retrieves a random Daily Goal
  <WebMethod()> Public Function GetRandomDailyGoal() As String
    Dim glSystemGoal As SystemGoal = New SystemGoal()

    Return glSystemGoal.GetRandomGoal()

  End Function

  ' Web Method that retrieves a goal list by user id
  <WebMethod()> Public Function GetGoalsByUserID(ByVal intUserID As Integer) As DataSet
    Dim glUserGoal As UserGoal = New UserGoal()
    Dim dsGoals As UserGoalData = New UserGoalData()

    Return glUserGoal.GetList(intUserID)

  End Function

End Class

What next?

Now that we have improved our Web Service, we are ready to consume the service. You can do this from a Web Client, WinForm, or perhaps even a Console Application. The process for doing this depends on the tools available to you. Visual Studio.NET makes this process quite simple, although it is not difficult to do without Visual Studio.NET. Either way, a proxy class must be created in order to consume the web service. Once you have the proxy class, you can declare and instantiate a variable of type Web Service like you would do when declaring and instantiating any other class.

Conclusion

In this article, we took a Web Service (appropriately named FatGoalService) and applied a few object-oriented techniques to improve the implementation. The FatGoalService was migrated to a new architecture that uses implementation and interface inheritance to satisfy the system requirements. We extracted out a data class, utility class, data access layer, and business layer to create an architecture that can grow in the future. Although these classes are all in one assembly, we can easily move our *.vb files that contain classes into separate assemblies (versus having to extract the code from Fat Web Methods).

Note that with the example as simple and small as we have in this article, the benefits of using object-oriented techniques may not be as apparent as in a large application (in fact, with a small example it may seem like more trouble than it's worth for the benefits reaped). But, again, as our application scope increases, we will reap the benefits of implementing an architecture that will grow with time.

 
 
   
  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
   
  • Moving DNA Applications from COM+ to .NET drill down reporting (October 18, 2001)
  • Web Services and the Future of Web Services with .NET (October 3, 2001)
  • Architectural guidelines for creating Web Applications using the .NET Framework (October 2, 2001)
  • Creating High Performance Web Applications Using Web Services (September 21, 2001)
  • Object Oriented Features in VB.NET (May 18, 2001)
  • Creating web services using Visual Studio.Net (April 19, 2001)
  •  
           
     
     
      Related Sources
     
  • Microsoft’s Programmable XML Web Services : http://msdn.microsoft.com/library/periodic/period00/webplatform.htm
  • SOAP and the .NET Framework : http://msdn.microsoft.com/library/techart/hawksoap.htm
  • Object-Oriented Programming in VB.NET: http://msdn.microsoft.com/vbasic/technical/upgrade/programming.asp
  • GotDotNetQuickstart tutorial: http://samples.gotdotnet.com/quickstart/aspplus/Default.aspx
  • GotDotNet : http://www.gotdotnet.com/
  • There is a section of GotDotNet that points you to resources for XML Web Services.: http://www.gotdotnet.com/team/XMLwebservices/default.aspx
  • My Lifetime Goals (site that uses the web services in this article): http://www.mylifetimegoals.com/
  •  
     
           
      Search the ASPToday Living Book   ASPToday Living Book
     
      Index Full Text Advanced 
     
     
           
      Index Entries in this Article
     
  • abstraction
  •  
  • architecture
  •  
  • business layer
  •  
  • code behind technique
  •  
  • code reuse
  •  
  • data source tier
  •  
  • database structure
  •  
  • Dataset object
  •  
  • encapsulation
  •  
  • enhancements
  •  
  • Goal Server web service
  •  
  • implementation inheritance
  •  
  • improving
  •  
  • inheritance
  •  
  • interface inheritance
  •  
  • maintainability
  •  
  • Next method
  •  
  • object oriented programming
  •  
  • Random class
  •  
  • reusable code, use
  •  
  • scalability
  •  
  • stored procedures
  •  
  • System namespace
  •  
  • System.Data namespace
  •  
  • VB.NET
  •  
  • Visual Basic
  •  
  • web service
  •  
  • WebMethod attribute
  •  
     
     
    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.asptoday.com/OffSiteRedirect.asp?Advertiser=www.wrox.com/&WROXEMPTOKEN=180659ZhEaANU51sACzT6SGvlO). 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 © 2002 Wrox Press. All Rights Reserved.