Calling ASP.NET web service from ASP using SOAPCli

2019-05-13 07:15发布

问题:

I have an ASP.NET webservice with along the lines of:

[WebService(Namespace = "http://internalservice.net/messageprocessing")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class ProvisioningService : WebService
{
    [WebMethod]
    public XmlDocument ProcessMessage(XmlDocument message)
    {
        // ... do stuff
    }
}

I am calling the web service from ASP using something like:

provWSDL = "http://servername:12011/MessageProcessor.asmx?wsdl"
Set service = CreateObject("MSSOAP.SoapClient30")
service.ClientProperty("ServerHTTPRequest") = True
Call service.MSSoapInit(provWSDL)

xmlMessage = "<request><task>....various xml</task></request>"
result = service.ProcessMessage(xmlMessage)

The problem I am encountering is that when the XML reaches the ProcessMessage method, the web service plumbing has added a default namespace along the way. i.e. if I set a breakpoint inside ProcessMessage(XmlDocument message) I see:

<request xmlns="http://internalservice.net/messageprocessing">
  <task>....various xml</task> 
</request>

When I capture packets on the wire I can see that the XML sent by the SOAP toolkit is slightly different from that sent by the .NET WS client. The SOAP toolkit sends:

<SOAP-ENV:Envelope 
    xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" 
    xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <ProcessMessage xmlns="http://internalservice.net/messageprocessing">
            <message xmlns:SOAPSDK4="http://internalservice.net/messageprocessing">
                <request>
                    <task>...stuff to do</task>
                </request>
            </message>
        </ProcessMessage>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Whilst the .NET client sends:

<soap:Envelope 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <ProcessMessage xmlns="http://internalservice.net/messageprocessing">
            <message>
                <request xmlns="">
                    <task>...stuff to do</task>
                </request>
            </message>
        </ProcessMessage>
    </soap:Body>
</soap:Envelope>

It's been so long since I used the ASP/SOAP toolkit to call into .NET webservices, I can't remember all the clever tricks/SOAP-fu I used to pull to get around stuff like this.

Any ideas? One solution is to knock up a COM callable .NET proxy that takes the XML as a string param and calls the WS on my behalf, but it's an extra layer of complexity/work I hoped not to do.

回答1:

Kev,

I found the solution, but its not trivial.

You need to create a custom implementation of IHeaderHandler that creates the proper headers.

There is a good step by step here:

http://msdn.microsoft.com/en-us/library/ms980699.aspx

EDIT: I saw your update. Nice workaround, you might want to bookmark this link regardless :D



回答2:

I take it you have access to the Services code, not just the consuming client right?

Just pull the namespace out of the XmlDocument as the first part of the method.

Something like:

XmlDocument changeDocumentNamespace(XmlDocument doc, string newNamespace) 
{   
    if (doc.DocumentElement.NamespaceURI.Length > 0) 
    {
        doc.DocumentElement.SetAttribute("xmlns", newNameSpace);
        XmlDocument newDoc = new XmlDocument();
        newDoc.LoadXml(doc.OuterXml);
        return newDoc;
    }
    else 
    {
        return doc;
    }
}

Then:

[WebService(Namespace = "http://internalservice.net/messageprocessing")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class ProvisioningService : WebService
{
    [WebMethod]
    public XmlDocument ProcessMessage(XmlDocument message)
    {
        message = changeDocumentNamespace(message,String.Empty);
        // Do Stuff...
    }
}


回答3:

I solved this:

The SOAP client request node was picking up the default namespace from:

<ProcessMessage xmlns="http://internalservice.net/messageprocessing">

Adding an empty default namespace to the XML sent by the ASP client overrides this behaviour:

xmlMessage = "<request xmlns=''><task>....various xml</task></request>"