CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Steve Hebert's Development Blog

Steve's Blog - From .Net to dotMath and everything in between.

Manually Mapping WSDL soap:address location on the fly

 .Net does a nice job of sensing the underlying protocol when generating WSDL. For instance,  if I run a service as "myService" on SSL, the underlying WSDL is wired to contain the <soap:address> location mapped to "https://..." instead of "http://..."  However there are times when this sensing is not enough. A good relational setup between your load-balancer/encryptor setup should limit the change need to http->https, but this implementation also offers other flexibility as well.  I just can't think of a good use-case right now.

 When running with a front-end encryption appliance for offloading the cpu cost of SSL, the webservers themselves typically run on the http/port 80/non-encrypted protocol.  Since .Net senses this, the WSDL is generated with "http://" prefixes in the soap:address which is incorrect for consumers of the service.

 Handling this took a bunch of digging and feels extremely hack-ish.  But it's a necessity in this scenario.  To accomplish this task take the following steps:

  1. Derive a class from SoapExtensionReflector that overrides the ReflectMethod(). 
  2. Handle the remapping in the ReflectMethod() of the class created above.
  3. Reference your new class under the webServices/soapExtensionReflectorTypes in web.config.

Here is a sample of the derived class:

    public class SoapAddressReflector : SoapExtensionReflector
    {
        public override void ReflectMethod()
        {
            ServiceDescription sd = ReflectionContext.ServiceDescription;

            foreach (Service service in sd.Services)
            {
                foreach( Port port in service.Ports)
                {
                    foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
                    {
                       
                        SoapAddressBinding address = (SoapAddressBinding)extension;
                        address.Location = RemapHttpReferencesToHttps(address.Location);
                    }
                }
            }
        }

        private string RemapHttpReferencesToHttps( string location )
        {
                return location.Replace("http:", "https:");
        }
    }
}

Here is the code to add to the web.config file:

      <webServices>
        <soapExtensionReflectorTypes>
          <add type="Reuters.DataScopeSelect.Web.Api.SoapAddressReflector, Reuters.DataScopeSelect.Web.Api"/>
        </soapExtensionReflectorTypes>
      </webServices>

 

For a bogus webservice named "myService" running server-native on http, the modified wsdl appears as follows:

 - <wsdl:service name="myService">

- <wsdl:port name="myServiceSoap" binding="tns:ExtractionServiceSoap">
  <soap:address location=https://mypublicservice.com/myservice.asmx />
  </wsdl:port>
- <wsdl:port name="myServiceSoap12" binding="tns:myServiceSoap12">
  <soap12:address location=https://mypublicservice.com/myservice.asmx />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>
 
 


Check out Devlicio.us!

Our Sponsors

Free Tech Publications