Description Formatters





Description Formatters

Sometimes, you will want the WSDL file created for your service to indicate that it will be modified by the SOAP extension running on it. Conversely, you will want the proxy generated for you from wsdl.exe to add the SOAP extension to any proxy classes it consumes that contain this indication.

You can accomplish this with a ServiceDescriptionFormatter. This feature enables you to create a set of XML elements to go into the binding section of the WSDL that is automatically generated. This XML can be pretty much whatever you want, provided it doesn't make the WSDL document invalid.

Imagine how powerful it would be to add a custom WSDL extension to our compression extension to indicate that the service is actually compressed SOAP! This is easy to do with .NET. The steps are as follows:

  1. Create a class that derives from the ServiceDescriptionFormat Extension class, which will serve as the WSDL operation binding element.

  2. Create a class that derives from SoapExtensionReflector. This class examines the Web method for the CompressionExtensionAttribute. If it finds that attribute, then it adds the operation binding to the WSDL, which results in the new element.

  3. Register these two classes in the web.config for the application.

Listing 6.3 shows the operation binding class for the compression extension.

A Sample Format Extension for the Compression Extension
[XmlFormatExtension("compress",
     CompressionExtensionOperationBinding.Namespace,
     typeof(OperationBinding))]
[XmlFormatExtensionPrefix("comp", CompressionExtensionOperationBinding.Namespace)] public class CompressionExtensionOperationBinding : ServiceDescriptionFormatExtension
     {
           public const string Namespace =
           "http://keithba.com/CompressionExtension";
     }

And here is the reflector class:

     public class CompressionExtensionReflector : 
     SoapExtensionReflector
     {
          public override void ReflectMethod()
          {
               ProtocolReflector reflector = ReflectionContext; CompressionExtensionAttribute attr = (CompressionExtensionAttribute)reflector.Method.GetCustomAttribute( typeof(CompressionExtensionAttribute));
               if (attr != null)
               {
                    CompressionExtensionOperationBinding compress = new CompressionExtensionOperationBinding();

reflector.OperationBinding.Extensions.Add(compress);
               }
          }
     }

Listing 6.4 shows the registration within web.config.

Configuration for Extension Formatters and Reflectors
<webServices>
     <soapExtensionReflectorTypes>
     <add
          type="CompressionService.CompressionExtensionReflector, CompressionService" />
     </soapExtensionReflectorTypes>
     <serviceDescriptionFormatExtensionTypes>
          <add
     type="CompressionService.CompressionExtensionOperationBinding, CompressionService" />
     </serviceDescriptionFormatExtensionTypes>
</webServices>

Now, the WSDL contains a new element in the SOAP binding:

<binding name="Service1Soap" type="s0:Service1Soap"> 
<soap:binding
     transport="http://schemas.xmlsoap.org/soap/http"
     style="document" />
<operation name="SubmitPO">
  <soap:operation soapAction="http://tempuri.org/SubmitPO" style="document" />
  <comp:compress />
<input>
  <soap:body use="literal" />
  </input>
<output>
  <soap:body use="literal" />
  </output>
  </operation>
  </binding>

The reverse is also possible! We can create an importer class to be run when wsdl.exe or the Add Web Reference dialog box in VS.NET imports the WSDL. Now, to do this, we need to strong name our compression extension assembly, and install it to the entire machine. Then we can add registration within the machine.config to use these classes when importing WSDLs.

Listing 6.5 shows the importer class.

Importer Class for the Compression Extension
public class CompressionExtensionImporter : SoapExtensionImporter
     {
          public override void ImportMethod( CodeAttributeDeclarationCollection metadata)
          {
               SoapProtocolImporter importer = ImportContext;
               CodeAttributeDeclaration attr = new CodeAttributeDeclaration(typeof(CompressionExtensionAttribute) .FullName);
               metadata.Add(attr);
     }
}

Listing 6.6 shows the machine.config entry.

Configuration Entries in machine.config for Registering an Importer
<webServices>
            <protocols>
              <add name="HttpSoap"/>
              <add name="HttpPost"/>
              <add name="HttpGet"/>
              <add name="Documentation"/>
            </protocols>
            <soapExtensionTypes>
            </soapExtensionTypes>
            <soapExtensionImporterTypes>
               <add
          type="CompressionService.CompressionExtensionImporter, CompressionService" />
               </soapExtensionImporterTypes>
               <serviceDescriptionFormatExtensionTypes> <add
     type="CompressionService.CompressionExtensionOperationBinding,
     CompressionService" />
               </serviceDescriptionFormatExtensionTypes>
            <wsdlHelpGenerator href="DefaultWsdlHelpGenerator.aspx"/>
</webServices>

     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows