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.

November 2007 - Posts

  • 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>
     
     
More Posts