Consuming a WSDL Webservice from ASP

2002-9-11 11:09:13【作者】 畅享网 【进入论坛】
广告

Consuming a WSDL Webservice from ASP

 


By
Dave@123aspx.com 

Click here for the live demo

(Look at the bottom of the homepage)   


Last week I exposed my site, 123aspx.com, as a SOAP webservice.   However, most webmasters feel you need to run ASP.NET or the SOAP toolkit to take advantage this service.  This isn't necesarily true, with a little ingunetiy and the latest XML parser from Microsoft, you can consume SOAP services from a traditional ASP page. This tutorial will show you how. 

Overview

This example application uses the 123aspx.com webservice as an example.  I'll be using the following three files to demonstrate consuming this service from ASP:.  

global.asa -- used to populate an Application level variable with the SOAP data when the application starts.

 i_soapcall.asp -- an include file used to call the SOAP webservice.

default.asp -- a standard ASP page used to display the formatted SOAP data. 
 
Global.asa

The global.asa file is fired everytime the website starts.  Specically the event Sub Application_OnStart is called. Inside of this sub, we are going to populate an application level variable with our SOAP data. Lets take a look at the code. 

<SCRIPT LANGUAGE=VBScript RUNAT=Server>

Sub Application_OnStart
   
Dim ASPNETResources
   
ASPNETResources = GetASPNetResources()   
   
Application("ASPNETExpires") = 12    'set the content to expire in 12 hours.
   
If Len(ASPNETResources) >0 then    'populate the application level variables
       
Application.Lock
       
Application("ASPNETResourcesUpdated")=Now()
       
Application("ASPNETResourceList")=ASPNETResources
       
Application.UnLock
   
End if

End Sub

</script>

<!-- #include file="i_soapcall.asp" --> 

When Application_OnStart first fires, we dimension a variable called ASPNETResources, which is populated by a function call GetASPNetResources(), GetASPNetResources(), found inside of the include file i_soapcall.asp, returns a string of HTML. We will be getting to i_soapcall.asp shortly.  Lets go over some of the logic of the global.asa code.   Once we have made our function call, we are storing an an expiration time of 12 hours the variable Application("ASPNETExpires"). We'll use this later in default.asp. We also check to see if the function was sucessful and returned a string with a length greater than 0.  If ASPNETResources was populated, then we need to record the time it was populated, Application("ASPNETResourcesUpdated"), and store the results in the application level variable, Application("ASPNETResourceList"). 
 
Default.asp

The default.asp is used to display the formatted contents of our webservice request.  Let's start out by looking at the code of default.asp. 

<%

Dim     ASPNETResources   

If len( Application("ASPNETResourceList") )>0 then    'we have our latest resources

REM -- check to see if they expired
   
If DateDiff("h",Now(),Application("ASPNETResourcesUpdated")) > Application("ASPNETExpires") Then   
       
REM -- we need to update the latest resurces 
      
ASPNETResources = GetASPNetResources()
       
Application.Lock
       
Application("ASPNETResourcesUpdated")=Now()
       
Application("ASPNETResourceList")=ASPNETResources
       
Application.UnLock
   
End if 'datediff...

Else    'for some reason the application level variable is empty, fill it.
   
ASPNETResources = GetASPNetResources()
   
Application.Lock
   
Application("ASPNETResourcesUpdated")=Now()
   
Application("ASPNETResourceList")=ASPNETResources
   
Application.UnLock

End if

Response.Write     Application("ASPNETResourceList")

%> 

The first thing we want to check is to see if our application level variable, Application("ASPNETResourceList"), has been populated. We do that by checking it's length: 
   
If len( Application("ASPNETResourceList") )>0 then 'we have our latest resources 
If indeed, there is data, we need to check to see if  the data has expired.  Using the DateDiff function, we can check to see if the data has expired past our timespan of 12 hours which was set in our global.asa as Application("ASPNETExpires"). 
   
If DateDiff("h",Now(),Application("ASPNETResourcesUpdated")) > Application("ASPNETExpires") Then    
If our data has expired or, if for some reason, Application("ASPNETResourceList") is empty, we call our soap service to populate our variable with data. We are using the same logic that we did in the global.asa. Once we have our data, we execute a Response.Write() to send our formatted results to the client. 
 
Now the Good Stuff - i_soapcall.asp
 

Now to the heart of the matter, it's what we've all been waiting for, how is this mysterious function GetASPNetResources(), consuming a webservice from legacy ASP? Remeber that our SOAP service is really serving up a XML formatted text file.   If we can somehow, progromattically, get to that XML file, then we should be able to parse it. Well in our case, it turns out it's really not that difficult. Inside of our function, we call two objects: 

Function GetASPNetResources()   
   
Set SoapRequest = Server.CreateObject("MSXML2.XMLHTTP")
   
Set myXML =Server.CreateObject("MSXML.DOMDocument") 
SoapRequest is the server-side component that can make POST and GET requests across the web.  For more info on the MSXML2.XMLHTTP component, you can visit MSDN. 
myXML will be used to create an in-memory XML document of our SOAP service.  Now that we have our objects, let's call our SOAP service. 
   
myXML.Async=False
   
SoapURL = "
http://64.85.12.73/WebSvc/whatsnew123apx_ds.asmx/GetNew123aspXResources?"
   
SoapRequest.Open "GET",SoapURL , False
   
SoapRequest.Send()

if Not myXML.load(SoapRequest.responseXML) then 'an Error loading XML
       
returnString = ""
   
Else    'parse the XML
 
First we we set the Asyncronous property of our XMLDocument object to false. This will require the entire SOAP xml document to get loaded into memory before we continue processing code.  We set  SoapURL to the url of our webservice, and then we open a connection to our webservice using: 
   
SoapRequest.Open "GET",SoapURL , False 
SoapRequest.Open takes 5 parameters. Only the first two are required and the remaining three are optional. Here is a breakdown of the 5 parameters: 
   
oServerXMLHTTPRequest.open bstrMethod, bstrUrl, bAsync, bstrUser, bstrPassword
   
Parameters
   
bstrMethod
       
HTTP method used to open the connection, such as PUT or PROPFIND.
   
bstrUrl
       
Requested URL. This must be an absolute URL, such as "
http://Myserver/Mypath/Myfile.asp".
   
bAsync (optional) 
    
Boolean. Indicator as to whether the call is asynchronous. The default is False (the call does not return immediately).
   
bstrUser (optional)
       
Name of the user for authentication.
   
bstrPassword (optional)
       
Password for authentication. This parameter is ignored if the user parameter is Null or missing 
With our open connection, we make a  request across the web by calling SoapRequest.Send(). The webserver sends the results back, and they are stored in the property SoapRequest.responseXML,as text. We take this text and load it asycronously into an in-memory resident XML Dom object by calling the load method of myXML. If any xml parsing errors occur, the document is not loaded and we decide to return an empty string.  If the XML document was loaded successfully, we parse document and look for our data. 
 
Parsing the XML Document 

Our SOAP service returns 4 fields: Name, URL, Domain, and DateUpdated. In this version of calling our SOAP service, we are only going to display the Name and URL fields.  So how do we get at these fields? We search for them specifiing the XPath syntax for searching. 
   
REM -- The XML Nodes are CASE SENSITIVVE!
   
Set nodesURL=myXML.documentElement.selectNodes("//URL")
   
Set nodesName=myXML.documentElement.selectNodes("//Name")
   
NumOfNodes = nodesURL.Length 

The "//" characters are used to denote "find all instances of " in XPath. Therefore, using "//URL" will return an arry of nodes in the XML document named "URL".  We have to be careful here, because XML is case sensitive, calling "//url" will not return any nodes at all. We check the length of the array by calling nodesURL.Length. 
 
The Hard Part is Over 

We've called our SOAP service, and now we have access to our nodes, all that's left is to format and display it to the HTML client. 
   
ResourceList = "<font face=verdana size=2>Latest ASP.NET Resources</font><ul>"
   
For i = 0 to NumOfNodes -1 
    
ResourceList = ResourceList & "<li><a href=" & nodesURL(i).text & "><font face=verdana size=2>" & nodesName(i).text & "</font></a></li>"
   
next
   
ResourceList =ResourceList & "</ul>"
   
returnString = ResourceList
   
GetASPNetResources = returnString 

Because the array of nodes is a zero based array, we run a For loop to a maximum of NumOfNodes -1. We dynamically build a string, wrapping <li> </li> around our Names and URLs.  We could have easily have built an HTML table or some other structure.  We store our formatted HTML string in returnString, and pass returnString back to the function call  GetASPNetResources = returnString. 

A screen shot of our formatted results. 


  
 
That's All! 

That's all their is to calling a SOAP service from a legacy ASP page.   We've called our SOAP service and passed it into an XML object using Microsoft's parsers:

MSXML2.XMLHTTP and MSXML.DOMDocument. We've looped through the collection of nodes and created an HTML formatted string. We've simulated ASP.NET caching by storing the HTML formatted string in an Application level varable. Here is the code in its entirety. 
 
All the code 

Global.asa 

<SCRIPT LANGUAGE=VBScript RUNAT=Server>

Sub Application_OnStart
   
Dim ASPNETResources

ASPNETResources = GetASPNetResources()   
   
Application("ASPNETExpires") = 12    'set the content to expire in 12 hours.
   
If Len(ASPNETResources) >0 then    'populate the application level variables
       
Application.Lock 
       
Application("ASPNETResourcesUpdated")=Now()
       
Application("ASPNETResourceList")=ASPNETResources
       
Application.UnLock
   
End if

End Sub

</script>

<!-- #include file="i_soapcall.asp" --> 
 
Default.asp 

<%@ Language=VBScript %>

<%Option Explicit%>

<!-- #include file="i_soapcall.asp" -->

<HTML>

<HEAD>

<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">

</HEAD>

<BODY>

<%

Dim     ASPNETResources   

If len( Application("ASPNETResourceList") )>0 then    'we have our latest resources

REM -- check to see if they expired
   
If DateDiff("h",Now(),Application("ASPNETResourcesUpdated")) > Application("ASPNETExpires") Then   
       
REM -- we need to update the latest resurces
       
ASPNETResources = GetASPNetResources()
       
Application.Lock 
      
Application("ASPNETResourcesUpdated")=Now()
       
Application("ASPNETResourceList")=ASPNETResources
       
Application.UnLock
    End if 'datediff...

Else    'for some reason the application level variable is empty, fill it.
   
ASPNETResources = GetASPNetResources()
   
Application.Lock
   
Application("ASPNETResourcesUpdated")=Now()
   
Application("ASPNETResourceList")=ASPNETResources
   
Application.UnLock

End if 'len(..

Response.Write     Application("ASPNETResourceList")

%>

<P>&nbsp;</P>

</BODY>

</HTML> 
 
 i_soapcall.asp 

<script language="vbscript" runat="server">

Function GetASPNetResources()   
   
Dim returnString
   
Dim myXML
   
Dim SoapRequest
   
Dim SoapURL

Set SoapRequest = Server.CreateObject("MSXML2.XMLHTTP")
   
Set myXML =Server.CreateObject("MSXML.DOMDocument")

myXML.Async=False
   
SoapURL = "
http://64.85.12.73/WebSvc/whatsnew123apx_ds.asmx/GetNew123aspXResources?"
   
SoapRequest.Open "GET",SoapURL , False
   
SoapRequest.Send()

 if Not myXML.load(SoapRequest.responseXML) then 'an Error loading XML
       
returnString = ""
   
Else    'parse the XML

Dim nodesURL
       
Dim nodesName
       
Dim nodesDateUpdated
       
Dim nodesDomain
       
Dim NumOfNodes
       
Dim ResourceList
       
Dim i

REM -- The XML Nodes are CASE SENSITIVVE!
       
Set nodesURL=myXML.documentElement.selectNodes("//URL") 
      
Set nodesName=myXML.documentElement.selectNodes("//Name")

REM -- uncomment the following lines if we want to access the DataUpdated and the Domain Nodes
       
REM --Set nodesDateUpdated = myXML.documentElement.selectNodes("//DateUpdated")
       
REM --Set nodesDomain = myXML.documentElement.selectNodes("//Domain")

REM -- the number of nodes in the list
       
NumOfNodes = nodesURL.Length
       
ResourceList = "<font face=verdana size=2>Latest ASP.NET Resources</font><ul>"

For i = 0 to NumOfNodes -1
           
ResourceList = ResourceList & "<li><a href=" & nodesURL(i).text & "><font face=verdana size=2>" & nodesName(i).text & "</font></a></li>"
       
next

ResourceList =ResourceList & "</ul>" 
       
returnString = ResourceList 
   
Set nodesURL = Nothing
       
Set nodesName = Nothing
   
End If 
   
Set SoapRequest = Nothing
   
Set myXML = Nothing 
    
GetASPNetResources = returnString

End Function

</script> 

如果您希望与本文章的作者或其所在机构,进一步交流,请联系:畅享网 姜小姐
jill.jiang@amteam.org | 021-51096826-112 | 在线联系
老孙的IT运维管理之道[原创]用户的BSM用户的IT业务管..

从企业实际的IT运营角度来看,BSM是推动IT与业务融合,实现、改善WCNG司IT管理和治理的最佳实践之一。

吕建伟 专栏和CIO问答软件项目实施管理

现实中很少能按照正规流程来的,所以只能把流程中的各个环节拆开,个个击破,以后就可以见招拆招了。

ITIL实施:CIO时刻准备着

千军易得,一将难求,要推进ITIL实施,CIO扮演的角色不容忽视。吹响集结号,CIO出击的时刻已经来到。

节能与优化IT 企业CIO过冬良策

当前金融危机的影响还在继续漫延,很多企业都在苦寻过冬的良策,在这种情况下,节能与优化技术与产品无疑成为CIO们关注的首要对象,本次选题就是针对节能与优化IT来为CIO们提供过冬的良……