views:

4491

answers:

3

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"&gt;
  <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/"&gt;
    <SOAP-ENV:Body>
     <ProcessMessage xmlns="http://internalservice.net/messageprocessing"&gt;
      <message xmlns:SOAPSDK4="http://internalservice.net/messageprocessing"&gt;
       <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"&gt;
    <soap:Body>
     <ProcessMessage xmlns="http://internalservice.net/messageprocessing"&gt;
      <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.

Update: SOLVED! -

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

<ProcessMessage xmlns="http://internalservice.net/messageprocessing"&gt;

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

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

Thanks for looking. Kev

A: 

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...
    }
}
FlySwat
A: 

@Jonathon - thanks for reply, sadly the web service as fixed in stone. It's deployed to 50+ servers, a re-deploy is not an option.

@Jonathon - thanks again to taking a look. I got to the bottom of the problem. All I had to do was specify an empty namespace for the default namespace in the XML I am sending from classic ASP client. Now I can go to bed :-)

Kev
Why the downvote?
Kev
+1  A: 

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

FlySwat
Yep...bookmarked...:) +1
Kev