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. | 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. | | | 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> </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> | |
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |
More ASP Articles More By Dave - 123aspx.com developerWorks - FREE Tools! | This demonstration gives you an overview of IBM® Rational® Build Forge Express Edition, a global offering that provides a framework to automate and execute software processes. Rational Build Forge provides a software assembly line that can support all of your tools, technologies, and platforms so you can achieve a repeatable, reliable, and traceable build and release process. FREE! Go There Now!
| | | | Building a software-as-a-service solution requires addressing a few key technical challenges. In this webcast, we'll focus on the role of IBM Tivoli Directory Server and WebSphere Portlet Factory in creating a Software as a Service solution. We will demonstrate how to use Tivoli Directory Server to prevent the user population of one tenant from accessing the virtual portal and portlet components of another tenant. We will also use the dynamic profile capability of WebSphere Portlet Factory to create multiple highly customized applications from one code base. FREE! Go There Now!
| | | | Download the Rational Application Developer (RAD) v7.5 open beta code and start developing applications for the JEE5 standard which features EJB3.0, JPA, JSF 1.2, JSP 2.1 and Servlet 2.5 standards. When you use this beta you will see how you can increase developer productivity for already existing applications with improved support for refactoring, as well as adding new features to existing applications. In addition, the beta provides tooling for JD Edwards, Oracle, SAP, Siebel and PeopleSoft to improve the developer productivity with these enterprise systems. FREE! Go There Now!
| | | | Join this webcast to see how IBM Data Studio Developer and pureQuery can take the pain out of Java data access. uApplications developed using both Java and SQL have become a common requirement. Database connectivity using Java Database Connectivity (JDBC) to create an application is a multi-step tedious process, and tooling that covers both SQL and Java has been unavailable, until now. IBM Data Studio introduces the pureQuery platform: a high-performance, Java data access platform focused on simplifying the tasks of developing, managing, and optimizing database applications and services. FREE! Go There Now!
| | | | Analysts, architects, and developers who have existing COBOL or PL/I skills and want to extend those skills to deploy new workloads on the mainframe can use the IBM Enterprise Modernization Sandbox for System z to find hands-on walkthroughs of common real world scenarios. The scenarios provide examples of how to rapidly design, create, assemble, test, and deploy high-quality Web, Web services, portal, and SOA applications for IBM CICS, IBM IMS, and IBM WebSphere Application Server. FREE! Go There Now!
| | | | Portfolio Management is about effectively managing portfolio value by aligning portfolio investments with business goals. This complimentary e-kit provides a collection of materials that can help you understand how IBM Rational enables and automates best practices for improved governance and clear visibility into portfolio and project performance across the entire IT project lifecycle. FREE! Go There Now!
| | | | Regression testing -- in which code is thoroughly tested to ensure that changes have not produced unexpected results -- is an important part of any development process. But many testing environments neglect the terminal-based applications that still form the backbone of many industries. In this tutorial, you'll learn how the Rational Functional Tester Extension for Terminal-Based Applications works with other Rational Functional Tester to help test terminal-based applications quickly and easily. FREE! Go There Now!
| | | | Get a free trial download of the latest version of IBM Rational Performance Tester V7.0.1, a load and performance testing solution for teams concerned about the scalability of their Web-based applications. Combining multiple ease-of-use features with granular detail, Rational Performance Tester simplifies the test-creation, load-generation and data-collection processes that help teams ensure the ability of their applications to accommodate required user loads. FREE! Go There Now!
| | | | As businesses grow increasingly dependent upon Web applications, these complex entities grow more difficult to secure. Most companies equip their Web sites with firewalls, Secure Sockets Layer (SSL), and network and host security, but the majority of attacks are on applications themselves – and these technologies cannot prevent them. This paper explains what you can do to help protect your organization, and it discusses an approach for improving your organization’s Web application security. FREE! Go There Now!
| | | | The discipline of assembling and delivering software is maturing beyond standard developer-centric compile/test software builds. The end-to-end software development lifecycle is emerging as the new focus moves “Beyond the Build.” Join this on demand webcast to learn about methods for streamlining software delivery and key capabilities of the IBM Rational Build Forge framework for automating build and release management in environments of any size. FREE! Go There Now!
| | | | All FREE IBM® developerWorks Tools! | |