Wednesday, April 13, 2011

Classic Asp Web Service Problem

I'm trying to create a code to allow an existing classic asp program to use an asp.net web service. Updating from the classic asp is not an option, as I'm working in a big company and things are the way they are.

I've been browsing through a chunk of tutorials supposedly helping in this, but I haven't managed to get them to work yet. As a beginner I might've made some real obvious mistakes but I just don't know what.

First, the web service is located on an external server. The method "Greeting" needs a String parameter by which it determines which String is sent back. Inputting "g" to it procudes this xml:

  <?xml version="1.0" encoding="utf-8" ?> 
  <string xmlns="http://server1/Logger_WebService/">Greetings and welcome!</string> 

I assume the xpath for getting the contents is either "string/*" or "*"?

Next, my web service itself looks like this:

    <WebMethod()> _
    Public Function Greeting(ByVal stringel As String) As String

        If stringel.ToLower = "g" Then
            Return "Greetings and welcome!"
        Else
            Return "Bye then!"
        End If

    End Function

The web service works fine from a regular asp.net solution.

Now here's the problem, the classic asp code looks like this (4 different ways I've tried to get this to work, SOAP toolkit is installed on the web service server, all examples taken and modified from tutorials):

'******* USING GET METHOD
Dim wsurl="http://server1/Logger_WebService/service.asmx/Greeting?g"
Dim xmlhttp
Set xmlhttp=Server.CreateObject("MSXML2.ServerXMLHTTP")
xmlhttp.open "GET",wsurl,false
xmlhttp.send
Dim rValue
'rValue=xmlhttp.responseXML.selectSingleNode("string")    'use XPATH as input argument
' or you can get response XML
rValue=xmlhttp.responseXML
Set xmlhttp=nothing

'------------------------------------------------------

'******* USING POST METHOD
Dim wsurl="http://server1/Logger_WebService/service.asmx/Greeting"
Dim xmlhttp
Set xmlhttp=Server.CreateObject("MSXML2.ServerXMLHTTP")
xmlhttp.open "POST",wsurl,false
xmlhttp.send "stringeli=g"
Dim rValue
rValue=xmlhttp.responseXML.selectSingleNode("string")
' or you can get response XML
' rValue=xmlhttp.responseXML
Set xmlhttp=nothing

'------------------------------------------------------

Response.Write consumeWebService() 

Function consumeWebService() 
    Dim webServiceUrl, httpReq, node, myXmlDoc 

    webServiceUrl = "http://server1/Logger_WebService/service.asmx/Greeting?stringel=g"

    Set httpReq = Server.CreateObject("MSXML2.ServerXMLHTTP") 

    httpReq.Open "GET", webServiceUrl, False 
    httpReq.Send 

    Set myXmlDoc =Server.CreateObject("MSXML.DOMDocument")
    myXmlDoc.load(httpReq.responseBody) 

    Set httpReq = Nothing 

    Set node = myXmlDoc.documentElement.selectSingleNode("string/*")

    consumeWebService = " " & node.text

End Function

'------------------------------------------------------

  Response.Write(Helou())

  Public Function Helou()
     SET objSoapClient = Server.CreateObject("MSSOAP.SoapClient")
     objSoapClient.ClientProperty("ServerHTTPRequest") = True

    ' needs to be updated with the url of your Web Service WSDL and is
    ' followed by the Web Service name
    Call objSoapClient.mssoapinit("http://server1/Logger_WebService/service.asmx?WSDL", "Service")

    ' use the SOAP object to call the Web Method Required  
    Helou = objSoapClient.Greeting("g")    
  End Function

I seriously have no idea why nothing works, I've tried them every which way with loads of different settings etc. One possible issue is that the web service is located on a server which in ASP.Net required me to input this "[ServiceVariableName].Credentials = System.Net.CredentialCache.DefaultCredentials". I do this from within company network, and there are some security and authorization issues.

I only need to be able to send information anyhow, not receive, as the actual method I will be using is going to insert information into a database. But for now, just getting the Hello World thingie to work seems to provide enough challenge. :)

Thx for all the help. I'll try to check back on holiday hours to check and reply to the comments, I've undoubtedly left out needed information.

Please, talk as you would to an idiot, I'm new to this so chances are I can understand better that way. :)

From stackoverflow
  • You might be missing the SOAPAction header. Here's a working example:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class GreetingService : WebService
    {
        [WebMethod]
        public string Greet(string name)
        {
            return string.Format("Hello {0}", name);
        }
    }
    

    And the calling VBS script:

    Dim SoapRequest
    Set SoapRequest = CreateObject("MSXML2.XMLHTTP")
    
    Dim myXML 
    Set myXML = CreateObject("MSXML.DOMDocument")
    
    
    myXML.Async=False
    SoapRequest.Open "POST", "http://localhost:4625/GreetingService.asmx", False
    SoapRequest.setRequestHeader "Content-Type","text/xml;charset=utf-8"
    SoapRequest.setRequestHeader "SOAPAction", """http://tempuri.org/Greet"""
    
    Dim DataToSend
    DataToSend= _
        "<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/"">" & _
            "<soapenv:Header/>" & _
            "<soapenv:Body>" & _
                "<tem:Greet>" & _
                    "<tem:name>John</tem:name>" & _
                "</tem:Greet>" & _
            "</soapenv:Body>" & _
        "</soapenv:Envelope>"
    
    SoapRequest.Send DataToSend
    
    If myXML.load(SoapRequest.responseXML) Then
        Dim Node
        Set Node = myXML.documentElement.selectSingleNode("//GreetResult")
        msgbox Node.Text
    
        Set Node = Nothing
    End If
    
    Set SoapRequest = Nothing
    Set myXML = Nothing
    
  • You might consider writing a bit of .NET wrapper code to consume the web service. Then expose the .NET code as a COM object that the ASP can call directly. As you've seen, there is no tooling to help you in classic ASP, so consider using as much .NET as possible, for the tooling. Then, use COM to interoperate between the two.

  • Might want to double-check the version of the MSXML components. Are you using Windows Authentication? I've noticed some odd XML parsing problems with IIS 7, Classic ASP, and MSXML.

    It would also help to get a useful error. Check the ** myXML.parseError.errorCode** and if its not 0 write out the error.

    Reference Code:

    If (myXML.parseError.errorCode <> 0) then
        Response.Write "XML error: " & myXML.parseError.reason
    Else
        'no error, do whatever here
    End If
    'You get the idea...
    
  • A colleague finally got it working after putting a whole day into it. It was decided that it's easier by far to send information than it is to receive it. Since the eventual purpose of the web service is to write data to the DB and not get any message back, we attempted the thing by simply writing a file in the web service.

    The following changes were needed:

    First, in order to get it to work through the company networks, anonymous access had to be enabled in IIS.

    The web service needed the following change in the web.config:

    <webServices>
      <protocols>
        <add name="HttpGet"/>
      </protocols>
    </webServices>
    

    And the web service code-behind was changed like so:

    <WebMethod()> _
        Public Function Greeting(ByVal stringel As String) As String
    
            Dim kirj As StreamWriter
            'kirj = File.CreateText("\\server1\MyDir\Logger_WebService\test.txt")
            'if run locally, the line above would need to be used, otherwise the one below
            kirj = File.CreateText("C:\Inetpub\serverroot\MyDir\Logger_WebService\test.txt")
    
            kirj.WriteLine(stringel)
            kirj.Close()
            kirj.Dispose()
    
            Return stringel
        End Function
    

    As we got the above to work, it was a simple matter of applying the same to the big web method that would parse and check the info and insert it into the database.

    The classic asp code itself that needs to be added to the old page, which was the biggest problem, turned out to be relatively simple in the end.

    function works()
        message = "http://server1/mydir/logger_webservice/service.asmx/Greeting?" & _
          "stringel=" & "it works"
        Set objRequest = Server.createobject("MSXML2.XMLHTTP")
    
        With objRequest
        .open "GET", message, False
        .setRequestHeader "Content-Type", "text/xml"
        .send
        End With
    
        works = objRequest.responseText
    end function
    works()
    

    Took about a week's worth of work to get this solved. :/ The hardest part was simply not ever knowing what was wrong at any one time.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.