A Web Service is programmable logic that provides data and
services to other applications by exposing its features over the Internet or
Intranet using Standard Internet protocols like HTTP, XML and SOAP. The Simple
Object Access Protocol (SOAP) defines a lightweight protocol for information
exchange.exchange and the SOAP specification can be found at SOAP Specification
Version 1.1. It is fast becoming the universally accepted Internet standard for
data exchange with the input from companies like Microsoft, IBM and
Developmentor. It is used for many things from simple data exchange to RPC like
functionality.
Since web services are exposed using Internet standards like
HTTP, XML and SOAP, any application that can communicate using these standards
can interact with a web service.
For more information on an introduction to web services,services
please take a look at the article Web Services with ASP.NET on MSDN.
Handling of Web Services
Web services are saved with the extension .asmx. Whenever the
ASP.NET runtime receives a request for an .asmx file, it redirects the request
to a handler called WebServicesHandlerFactory. A Handler is a class that
receives the requests from the ASP.NET runtime and services the needs of the
client by executing appropriate code.
This mapping is established in the global config.web (this is
similar to the IIS Metabase) file that can be found in
C:WINDOWSMicrosoft.NETFrameworkv1.0.2204 when you install Visual Studio.Net
Beta 1. This file is a global file that holds configuration settings for the
entire ASP.NET and this can be overridden for the individual applications by
modifying the config.web file that can be found in the root directory of that
ASP.NET application.
In the config.web file, for the handling of web services, it is
specified as:
This indicates whenever any client makes a request for an .asmx
file, ASP.NET runtime creates an instance of the WebServiceHandlerFactory class
(that resides in the System.Web.Services namespace) and hands the request over
to it. The attribute verb=* shows that all HTTP requests like GET, POST, PUT for
an .asmx file should be handled by the WebServicesHandler class.
Role of SDL in exposing Web Services
Web services provide Well-defined interface through an XML based
language called Services Description Language (SDL). This language describes the
functionality of the web service and describes each of the methods, the
parameters they take, and what they return. It is similar to the way a COM
object exposes its functionalities through functionality through a Type
Library.
Since SDL is an XML based grammar, any application in the
Internet can query the web services for its contract and invoke methods of it
without worrying about the language or the platform in which it is implemented.
Microsoft has already announced that SDL is going to be renamed as WSDL (Web
Services Description Langauge) with the new specifications implemented in the
Language) and will be based on open Internet standards like XML and SOAP, in the
Beta 2 of the Visual Studio.Net. More information on this can be found in this
link: W3C Acknowledges Web Services Description Language (WSDL) 1.1.
A Fictitious E-Commerce Scenario About
UDDI
UDDI is a specification that defines a way to publish and
discover information about web services in the Internet. When a business wants
to expose its web services to its partners, it can do that using a common web
services description file in XML format that is written using UDDI
specification. This XML file is called Business Registry and it gives
information about the business entity and the web services it has. Once the
business registers information about its web services in the business registry
using the UDDI Programmers API specification, it is automatically replicated to
all the other UDDI nodes using UDDI Cloud Services. Once this is done, the
information about web services is freely available to anyone who needs to know
what services are exposed by a given business.
The information available in the Business Registry can be
classified into 3 parts: white pages that includes address, contact, and known
identifiers; yellow pages that identifiy the industry category that the business
falls in and green pages that gives technical information about the services
exposed by the business. Developers can use the green pages in the Business
Registry to locate information about the technical details of web services, and
the yellow pages of the Business Registry to find companies in a given industry
with a given type of service.
UDDI uses standards-based technologies such as HTTP, XML and
SOAP to create a uniform service description format and service discovery
protocol.
More information about UDDI can be found in the official UDDI
website.
Store Locator Application
In the first part of the article, we will see how an Fictitious
Web portal called www.storelocator.com has created a Store Locator
application that uses Web services to increase its Business opportunities by
providing data to its customers using rich Web services. This Website has an
E-Commerce engine that collects data from their partners and expose that data to
their consumers in a meaningful manner. This web service has a method called
GetStores that provides information about the list of stores that are available
in an area based on the zip code and the name of the store. It also has a web
method called GetProducts that returns the list of products available in a store
based on the StoreID of the store.
For this application we will create a simple application with
two tables. A Store table that stores a list of the stores throughout the
country and a Product table that holds information about all the products
available in all the stores.
To create this Web service, we create a new Visual C# web
service project and add these methods. Call it ProdStoreWebService. Then we will
add the following methods to the web service.
GetStores that provides a list of stores in a particular area
based on the name of the Store and the Zip Code. GetProducts that gives the
list of products available in a particular Store based on the
StoreID.
ADO.NET
The above methods use ADO.NET to access the SQL Server 2000
Database. ADO.NET comes with two kinds of Managed Providers called ADO Managed
Providers and SQL Managed Providers.
ADO Managed Providers use the native OLEDB library to
communicate with heterogeneous data sources. SQL Managed Providers use a
protocol called tabular data stream to access the SQL Server and it is optimized
to provide high performance data access. In this article, we use SQL Managed
Providers for all the data access. For more information on ADO.NET, please take
a look at this article ADO.NET for the ADO Programmer from MSDN.
Implementation of the GetStores
Method
One of the methods exposed by the ProdStore web service is a
GetStores method that takes a ZipCode and a StoreName and returns the list of
Stores in that area.
The attribute [WebMethod] indicates that the method is to be
exposed as a web service and when it is deployed, Visual Studio.NET runtime
provides all the plumbing required to make this method discoverableavailable to
the clients who wish to use this web service.
[WebMethod]
public DataSet GetStores(String ZipCode,String
StoreNameLike)
strCommand = "Select * from
Store Where StoreName Like '%" + StoreNameLike + & _
"%' and Zip='" +
ZipCode + "'";
Here we create a SQLConnection object passing the
ConnectionString as the argument.
connSQL = new SQLConnection(strConn);
The following lines are enclosed within a try..catch block to
catch any errors that may occur during the execution of those
statements.
try
{
In this line an instance of SQLDataSetCommand object is created
and supplied with SQL Command to be executed and the SQLConnection object
SQLDataSetCommand acts as the link between a table within a dataset and a table
in a server.
cmdSQL = new SQLDataSetCommand(strCommand,connSQL);
To populate the Dataset with the results from the query, the
FillDataSet method of the SQLDataSetCommand object is called.
cmdSQL.FillDataSet(dstStores,"Store");
}
Throw the errors back to the client whenever an Exception
occurs. You can have multiple catch statements to catch different kinds of
Exceptions with the code to catch the most inclusive Exception (to avoid
unreachable code compiler error) class in the last catch block.
catch(Exception ex)
{
throw
ex;
}
The statements in finally are always executed regardless of
whether the statements in the try block are executed successfully or not. Here
we inspect the state property of the SQLConnection to check whether the
connection is open. If the Connection is open, it is closed.
finally
{
if ( connSQL.State == DBObjectState.Open
)
connSQL.Close();
}
Before we exit from the function, the Dataset is returned as the
return value of the function.
return dstStores;
I will briefly explain the advantage of returning a Dataset from
a web service in the latter section of this article.
Implementation of GetProducts Method
The GetProducts method takes StoreId as an argument and returns
the list of products in that store. It is similar to the GetStores method except
for the change in the query. The code is available for download along with the
support material of this article.
Advantages of Characteristics of
Datasets
Let us go over some of the characteristics of Datasets and see
how they make a perfect fit in the disconnected Internet environment.
Datasets can be considered as a Memory Resident disconnected
copy of the database with all the relationships between the tables established.
Datasets can be Typed or UnTyped. You can create a Strongly typed
Dataset by associating an .xsd schema file with it. The schema contains the
table names, column names, the data types of the columns and information about
constraints.
Typed Datasets allow Visual Studio.Net to provide
Intellisense feature and allows tables and columns to be accessed as if they are
objects. It also makes programming less error-prone.
Since Datasets use
XML based marshalling, any application written in any platform that is capable
of understanding XML can process the dataset that is created using ADO.NET.
Components can exchange datasets without worrying about the details of
the application that has created the dataset. For example, a business object in
the middle tier might create and populate a dataset, then send it to another
component elsewhere in the application for processing.
Creating clients that consume web
services
Now that we have created the web service, we will see how to
create an ASP.NET web client that invokes the methods of the web services. The
important step in consuming web services is creating a Proxy class that mediates
between the client and the actual web service that might be present anywhere in
the Internet.
There are two different approaches to creating a proxy class.
Using the WebServiceUtil tool that is supplied with Microsoft.NET
framework SDK and the advantage of this approach is that you do not require a
copy of Visual Studio.NET.
Using the Add Web Reference option and
letting Visual Studio.NET create the proxy class for us. We will see both
these approaches.
Creating the Proxy class using
WebServiceUtil
WebServiceUtil is a Console Application that is supplied with
the Microsoft.NET Platform SDK. The proxy created by Visual Studio.NET can only
work with SOAP. If you want to create a proxy that has to make HTTP Requests
like GET and POST to access the web service, then WebServiceUtil comes in handy
for you.has to be used.
This utility makes a request for the SDL of the remote web
service via HTTP and generates a proxy class. To create a proxy for our web
service in C#, the following command can be used.
The switch /c:proxy is used to indicate that a proxy class needs
to be created.
/pa: - Indicates the path of the web service for which
the proxy class needs to be created.
/out: - Specifies the path and the
name of the output proxy class file to be created.
/language:Csharp:
-Specifies that a C# proxy class has to be created.
By default,
WebServiceUtil generates a C# proxy class. To override the default setting, the
language can be specified.
The proxy created by the WebServiceUtil looks
like this:
Once the proxy class is created, open a new Visual C# Project
with the Class library as the project template and add the generated proxy class
to the project ensuring that the class is enclosed in a namespace. Add a
reference to System.XML, System.XML.Serialization, System.Web,System.Web and
System.Web.Services to serialize the requests to the web service into XML
format. Since the web and service returns a Dataset to the client, a reference
to the System.Data namespace is also added. Then build the project by choosing
Build from the Build menu.
Creating an ASP.NET client for the
WebService
Now we have created a proxy class library that can be used by
the client to make calls to the actual web service. The proxy receives the
requests from the client, packages the parameters in a SOAP Request using XML
standards and marshals it across the Internet or Intranet to the web service.
The web service receives the request from the proxy, executes the methods and
sends the results back to the proxy in the form of a SOAP Response. Finally the
proxy unpacks the response and passes the results to the client.
We will create an ASP.NET Web form client to access the Web
Service. Open a new Visual C# Web Application and add a reference to the proxy
class library which was created in the previous step. And also add a reference
to the System.Web.Services namespace. Import the Proxy class library's namespace
by adding the line of code:
Using ProdStoreWebServiceProxy;
String zip;
String storeName;using
ProdStoreWebServiceProxy;
This code resides in the file called webFormStoreLocator.cs that
is linked to the webFormStoreLocator.aspx file using the codebehind
attribute.
The ASP.NET web form client that invokes the web services
methods looks like this.
The Data View obtained from the Dataset is bound to the Data
Grid Control by assigning the custom default view of the Store table to the
DataGrid control gridStores.
Visual Studio.NET has a feature called Add Web Reference that
automates all the plumbing required for creating the proxy class. When you add a
web reference of the web service to your project, Visual Studio.NET
automatically generates a proxy class that interfaces with the web and it also
provides a local representation of the web service.
To add the 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 disco file is an
XML data file that is used for controlling the dynamic discovery of the web
service for the clients by obtaining SDLs and Schemas together.
On the left side of the dialog box, it shows the discovery
document and by clicking View Contract you can view the Service Description
Language (SDL) that exposes the Contract of the web service. When you Click Add
Reference, Visual Studio.NET creates a folder with the name of the server name
under the Web References folder. By default, the name of the server is
considered as the namespace for the local Proxy class. To assign a different
namespace for the proxy, rename the server name folder with the new name. Now,
import the proxy namespace into the current project. Once we have the proxy
namespace imported into the current application, the Web Callable methods
(methods that are decorated with the keyword Web Method) can be invoked
transparently as explained in the previous step.
Creating a Transactional Web service
In the remaining part of the article, we will see how to create
a transactional web service that uses the COM Components developed in Visual
Basic 6 and hosted in Component Services in Windows 2000, to provide
functionality to the consumers of the web services.
There are many cases when it becomes neither practical nor
necessary to upgrade a COM component simply to incorporate its features into a
.NET application. It often makes more sense to access existing functionality
through the excellent interoperation services provided by the runtime. This
allows companies to leverage the existing investments in the existing middle
tier objects written to run under MTS or COM+.
Middle tier COM objects
In this section, we will create two VB6 COM components called
Store_DB and Product_DB, with Store_DB having the clsStore class and Product_DB
having clsProduct. Both these classes are marked with the MTSTransactionMode
property as Uses Transaction.
For simplicity, we will consider the StoreAdd method of the
clsStore class and the ProductAdd method of the ClsProduct class.
Let's look at the code for the clsStore class.
Implements IobjectConstruct
The IObjectConstruct interface is implemented to control the
Object Construction process of the COM+ object and pass parameters
administratively from the Component Services Manager. When you enable Object
Construction for your component, (In the Component Services Manager, right click
the component and go to the Activation tab and check the Enable Object
Construction checkbox) it allows you to specify the Constructor
String.
Once this is done, when the object is constructed, COM+ calls
the Construct method of IObjectConstruct and passes in the
IObjectConstructString object. This has a property called ConstructString that
gives the constructor string specified in the Component Services Manager. The
ConnectionString for the database is a good example that can be stored in
component services manager.
Private Sub IObjectConstruct_Construct(ByVal pCtorObj As
Object)
'Assign the Connection String to the module level
variable
mstrConnectionString = pCtorObj.ConstructString
End
Sub
The StoreAdd method takes several parameters related to a
store.
Here we call the utility function RunSPReturnRS that has the
standard code to execute a stored procedure based on the parameters supplied to
it. RunSPReturnRS takes a ConnectionString as an argument.
Set rstStore = RunSPReturnRS(mstrConnectionString,
_
This line returns the newly added StoreId to the
caller.
StoreAdd = rstStore("StoreID").Value
Before exiting the function, SetComplete of ObjectContext is
called to set the Done and the Consistency bit to true that indicates that the
object can be deactivated and all the data manipulation operations can be
committed.
GetObjectContext.SetComplete
In the Error Handler, the SetAbort method of the ObjectContext
interface is called. This call negates the execution of all the database
manipulation statements by setting the Consistency bit to false and the Done bit
to True.
GetObjectContext.SetAbort
And the error is raised back to the client using the Err.Raise
statement
The code for the clsProduct class's ProductAdd method is similar
to the above method except that it executes a different stored procedure and it
is available for download. Now the COM object (Unmanaged code) we created should
be made accessible to the .NET Managed code environment.
Difference between Managed code and Unmanaged
Code
When you compile your Visual Studio.NET source code, the
compiler gives out MSIL (Microsoft Intermediate Language). MSIL code converts
into native code at runtime by a Just In Time (JIT) Compiler. MSIL code should
supply all the metadata necessary for the Common Language runtime (CLR) to
provide services such as Garbage Collection, Memory Management, Cross-Language
Integration, Code Access Security etc. All code that is based on MSIL executes
as Managed Code.
Unmanaged code is the one that was created without taking the
requirements of the CLR into account. This code executes in the runtime
environment with minimal services from runtime. For example, the above COM
object that we created using VB 6 executes as unmanaged code.
Invoking Unmanaged Code from Managed
Code
Since web services are written using managed code, invoking
unmanaged Code (COM object) from managed code (.NET Application) requires a
Runtime Callable Wrapper (RCW) that wraps around the COM objects and exposes
them to the clients as if it is a managed code.
Whenever any request for a COM object is made, the request is
received by the RCW that marshals the requests to the underlying COM object.
Once the COM object is finished with its execution, it returns the results back
to the RCW that in turn forwards the results to the caller.
You can create a RCW for a COM object using any of the following
methods:
When you add a reference to the COM object (by navigating to the
COM tab of the Add Reference Dialog box) to a Visual Studio.NET application, it
automatically creates a RCW for you.
You can use the tool
tlbimp(TypeLibrary Importer) that is part of the Microsoft.NET Framework that
converts the type library of a COM object to a .NET assembly Meta data. For
example, Tlbimp C:ProjectsASPTodayStore_DBStore_DB.dll
/out:Store_DB_Meta.dll creates a metadata Assembly named Store_DB_Meta.dll for
the COM component Store_DB.dll. The switch out: indicates the name of the output
file to be created.
You can also use the TypeLibConverter class that is
a member of the System.Runtime.InteropServices to generate the assembly
metadata.
Implementation of the Web Service
Let us create the Web Callable method called AddStoreAndProducts
that takes the information about a Store and the various products available in
that Store. This web service internally calls two different COM objects to carry
out the execution.
It creates an instance of the clsStore class and calls the
StoreAdd method to add Store information into the Store Table and the method
returns the StoreId of the newly inserted Store to the WebService. This returned
StoreID is used when inserting all the products in that store.
Since both the VB objects are marked with MTSTransactionMode
property as Uses Transaction, they will take part in the same transaction as
that of the caller, if the caller is running in a Transaction. Otherwise they
will not run in any Transaction. In this case, since web services are marked to
run in a transaction, the transaction context of the web service will be
inherited by the COM objects and they will also take part in the same
transaction as that of the web service which will ensure that either both Store
and Product Information are written to database in its entirety or nothing is
written.
Due to the Stateless nature of the web, Web services can only
participate as the root object of a transaction. For example, if a web service
method with the TransactionMode property of Required or RequiresNew calls
another web method with a TransactionMode property of Required, each web service
method will have their own separate Transaction.
Web services support the following values for the
TransactionMode enum property.
NotSupported
Required
RequiresNew
Supported
Let's dissect the code of the AddStoreAndProducts
method.
The TransactionMode property for the Web Method is specified
along with the WebMethod Attribute.
The Split method that is popular among ASP Programmers now has
become part of the class Regex that is contained in the namespace
System.Text.RegularExpressions. The comma-delimited lists of the products are
assigned to an array by using the Split function.
We will loop through the array and for every element in the
array; we will call the ProductAdd method and insert all the products into the
Product table.
To see some of the real time, working web services in action,
please take a look at Microsoft.com Demo Web Services.
Prerequisites
To execute the code that is available for download, you need to
have the following software installed on your machine:
Windows 2000
Professional/Server
SQL Server 2000 Beta2 or SQL Server 7.0
Visual Studio.NET Beta1
Visual Studio 6.0
What does the future hold for us?
In the future, Web services will play an important role in
allowing disparate applications written using different tools in different
platforms to interact with each other using Internet as the glue. Web services
will also introduce new business opportunities by exposing Software As Services.
For Example, a credit card company can expose Credit card Validation as a
Service for other businesses to take advantage of it. Since Web services are
based on Internet standards, they do not need to be written using Visual
Studio.NET and they do not have any dependency towards the Windows Operating
System. But the great advantage to using Microsoft Technologies is that it is
very easy, simple and automatic to create and assemble rich Next Generation Web
Services.
I hope you find this article useful and Thanks for
reading.