Introduction
A Web Service interface can be used by multiple service providers to offer the same service but with different implementation and access points. If you have a WSDL document file path or URL, you can reverse engineer it to create a dummy Web Service component, then define your own implementation, or keep the Web Service component in a library for future use. If you don�t know where to find an interesting WSDL, you can use the UDDI browser to search WSDL in a UDDI registry.
Uses of WSDL.EXE
- It can be used to generate server stubs. If a programmer needs to upgrade a web service using Microsoft .NET when the existing web service is in VB 6.0 or any similar language, this up-gradation should not affect the existing client of this web service, i.e. the WSDL generated by the new application should remain the same. By using WSDL.EXE, we can produce server stubs for different languages like C#, VB.NET and C++.NET.
- It can be used to generate the client proxy.
- If you are developing client applications for a web service and if you don�t have access to the target web service, or the target is under development, then for testing purposes, you can create a dummy web service of the target web service from the WSDL file.
- It can be used to invoke XML web services dynamically. Did you ever think about invoking your XML Web Services dynamically without having to generate a client side proxy class at design/compile time with wsdl.exe or Visual Studio .NET? No need to know the exact Web Service description and endpoint at compile/design time. Just get your WSDL from UDDI (or from wherever you want, e.g. XMethods), specify the type to instantiate and the methods to call ... voila! Can be used from any .NET application or even an unmanaged resource.
- We can manually write the stub code by seeing the WSDL file, but this may generate a different WSDL if we don't follow the proper procedure, and especially if parameters for web methods contain complex data types then building a class for such complex data types just by seeing the WSDL file is very difficult, and if the WSDL generated by this new code is not the same as the WSDL generated by the old code then the existing clients may not be able to access this web service.
Using the tool
Let's assume that, what is shown below is the WSDL generated by any of your old application (VB 6.0):
="1.0" ="utf-8"
<wsdl:definitions
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://tempuri.org/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/">
<s:element name="GetDetails">
<s:complexType>
<s:sequence>
<s:element minOccurs="0"
maxOccurs="1" ref="EmpType" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="GetDetailsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetDetailsResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
<s:schema elementFormDefault="qualified">
<s:element name="EmpType" type="EmployeeType" />
<s:complexType name="EmployeeType">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1"
form="unqualified" name="EmployeerID"
type="s:int" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Name"
type="NameType" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="SSN"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="CurrentAddress"
type="AddressType" />
<s:element minOccurs="0" maxOccurs="unbounded"
form="unqualified" name="PreviousAddress"
type="AddressType" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="DriverLicense"
type="s:string" />
<s:element minOccurs="0" maxOccurs="unbounded"
form="unqualified" name="Phone"
type="PhoneType" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="DOB" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="YOB" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="NameType">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Surname"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="First"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Middle" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Gen"
type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="AddressType">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="StreetNumber" type="s:int" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="StreetName" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="City" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="State" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Zip" type="s:string" />
</s:sequence>
</s:complexType>
<s:complexType name="PhoneType">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Type" type="s:string" />
<s:element minOccurs="0" maxOccurs="1"
form="unqualified" name="Number" type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</wsdl:types>
<wsdl:message name="GetDetailsSoapIn">
<wsdl:part name="parameters" element="tns:GetDetails" />
</wsdl:message>
<wsdl:message name="GetDetailsSoapOut">
<wsdl:part name="parameters" element="tns:GetDetailsResponse" />
</wsdl:message>
<wsdl:portType name="EmpServiceSoap">
<wsdl:operation name="GetDetails">
<wsdl:input message="tns:GetDetailsSoapIn" />
<wsdl:output message="tns:GetDetailsSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="EmpServiceSoap" type="tns:EmpServiceSoap">
<soap:binding
transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<wsdl:operation name="AddEmployee">
<soap:operation
soapAction="http://tempuri.org/GetDetails"
style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="EmpService">
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
<wsdl:port name="EmpServiceSoap" binding="tns:EmpServiceSoap">
<soap:address
location="http://localhost/Employee/EmpService.asmx" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Now, I can develop the server stub from the above WSDL for any .NET language, using the following way:
////////////////syntax of wsdl.exe ////////////
>Wsdl.exe <url or path of wsdl file> /language: /server.
Here, the switch <url or path of wsdl file>
specifies a URL or a path to a WSDL contract. /language:
specifies the language to use for the generated proxy/stub class. Choose from 'CS', 'VB', 'JS', 'VJS'. The default is 'CS' (C#). Short form is '/l:'. /server:
generates an abstract class for an XML web service implementation, using ASP.NET, based on the contracts. The default is to generate client proxy classes.
Procedure to create a web service from a given WSDL file
- Go to Visual Studio .NET 2003 command prompt.
- Type WSDL EmpService.wsdl /l:CS /server.
The output you will get will be as below:
Microsoft (R) Web Services Description Language
Utility [Microsoft (R) .NET Framework,
Version 1.1.4322.573] Copyright (C) Microsoft Corporation 1998-2002.
All rights reserved. Writing file
�C:\ProgramFiles\CommonFiles\System\MAPI\1033\nt\EmpService.cs�
Now, if you open the "EmpService.cs" file, you will find the following code:
using System.Diagnostics;
using System.Xml.Serialization;
using System;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Services;
[System.Web.Services.WebServiceBindingAttribute(Name=
"EmpServiceSoap", Namespace="http://tempuri.org/")]
public abstract class EmpService :
System.Web.Services.WebService
{
[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.
SoapDocumentMethodAttribute("http://tempuri.org/GetDetails",
RequestNamespace="http://tempuri.org/",
ResponseNamespace="http://tempuri.org/",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=
System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public abstract string AddEmployee(
[System.Xml.Serialization.XmlElementAttribute(Namespace="")]
EmployeeType EmpType);
}
public class EmployeeType
{
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public int EmployeerID;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public NameType Name;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string SSN;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public AddressType CurrentAddress;
[System.Xml.Serialization.XmlElementAttribute("PreviousAddress",
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public AddressType[] PreviousAddress;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string DriverLicense;
[System.Xml.Serialization.XmlElementAttribute("Phone",
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public PhoneType[] Phone;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string DOB;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string YOB;
}
public class NameType
{
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Surname;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string First;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Middle;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Gen;
}
public class PhoneType
{
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Type;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Number;
}
public class AddressType
{
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public int StreetNumber;
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool StreetNumberSpecified;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string StreetName;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string City;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string State;
[System.Xml.Serialization.XmlElementAttribute(
Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
public string Zip;
}
If you look at the above class, it has classes for each complex type defined in the WSDL file. Now, you can add this file to your web service. You can find that the abstract
keyword is preceded before 'class EmpService
' and the method 'string AddEmployee(int a,int b);
', in the above file.
Now, we can remove 'abstract
' keyword and provide the implementation for the method.