Help! How do I send extensible data in my WS-Eventing Subscribe?

Reader Nitin raises a good question: how does an app put extensible data into the Subscribe message that's used to set up events?

Example scenario: WSD Scan
Nitin's question asks specifically about the WSD Scan protocol built into Vista and Servier 2008, so I'll use that as an example.  The scan protocol defines a ScanAvailableEvent (and includes a definition for this event in the WSDL) and the specification text says that when a client subscribes to the ScanAvailableEvent, it may supply a ScanDestinations element inside the extensible section of the Subscribe message.  How this ScanDestination element works is largely unimportant in illustrating my point, but you can imagine it's a way for the client to send some information to the scanner for use in sending events.

The thing is that WsdCodeGen (or any other WSDL processing tool) won't ever have any idea that ScanDestinations is associated with ScanAvailableEvent, since the relationship isn't defined in the WSDL or schema.  It's only included in the specification text, so there's no way to generate code that accepts ScanDestinations when subscribing for ScanAvailableEvent.

A tool that turned specification text into generated code could handle this problem; but if such a tool existed, I'd probably be out of a job.

What you can do to send custom data in Subscribe messages
Even though you can't get strongly typed generated code, WsdCodeGen does give you a way to pass DOM sections (WSDXML_ELEMENT and friends) into your generated Subscribe methods.

The way you do this is to open up your generated code by modifying your codegen.config file.  By default, you'll typically get structures that look like this:

HRESULT STDMETHODCALLTYPE
SubscribeToScanAvailableEvent
( IScannerServiceTypeEventNotify* eventSink
);

But by following a few steps, you can add two new methods to the SubscribeTo??? method so you can send extensible data in the request, and receive extensible data sent in the response:

HRESULT STDMETHODCALLTYPE
SubscribeToScanAvailableEvent
( IScanServiceNotify* eventSink
, /* [in] */ WSDXML_ELEMENT* any
, /* [out] */ WSDXML_ELEMENT** anyOut
);

Here are some easy steps to getting the versions of these methods that accept WSDXML_ELEMENT structures:

  1. Edit your codegen.config file
  2. Find any instances of any of the following elements:
  3. Add this attribute to each element: extensible="true"
    • For example, this would look like <SubscriptionFunctionDeclarations extensible="true"> ...
  4. Regenerate your code (wsdcodegen /generatecode codegen.config)
  5. Edit any calls you make to SubscribeTo??? methods so they include NULL parameters or WSDXML_ELEMENT structures.

And that's it!  Now you can send any XML you like in the Subscribe message, and extract the response contained in the SubscribeResponse.  Join me next time as I explain more about the WSDXML structures and how to properly build them.

Comments

  • Anonymous
    July 09, 2008
    Hi Dan, Thanks a lot for posting this article. I have successfully generated the code with the modifications. I have tried to create and add WSDXML_ELEMENT structure to the subscription call to ScanAvailableEvent. But I am not seeing anything new being added in soap packet sent to device. Is there any specific way to populate this structure? I have seen some WSDAPI APIs like WSDXMLAddChild and WSDXMLAddSibling. Do I need to use these APIs for populating the structure? Thanks Nitin.

  • Anonymous
    July 09, 2008
    Hi Dan, I have created the structure using WSDAPIs that I have mentioned in last post. I am able to add new extensible data into the soap packet. Eagerly waiting for your next article on WSDXML structures. Thanks Nitin.

  • Anonymous
    July 15, 2008
    Hi Dan, I have faced one more issue related with this. I have created the WSDXML_ELEMENT and passed to HRESULT SubscribeToOperation(  [in]   const WSD_OPERATION *pOperation,  [in]   IUnknown *pUnknown,  [in]   const WSDXML_ELEMENT *pAny,  [out]  WSDXML_ELEMENT **ppAny ) as third parameter. The have checked the packets sent between device and client. The response is coming properly. But when this method returns, the return code is E_FAIL and no data is there in out parameter. I have compared the data with that of inbox driver also. The response sent from device is same. Can you suggest what else I need to check? Thanks, Nitin.

  • Anonymous
    August 10, 2008
    HI, When I send Extensible data (i,e 3rd and 4th parameters) to IWSDSERVICEPOXY::SubscribeToOperation(), the API is failing wih E_FAIL. The Message traces have been examined and we found that the SERVER is responding with the RIGHT XML. In spite of the VALID SERVER response SUBSCRIBETOOPERATION is failing. However,if the third and 4th parameters of SUBSCRIBETOOPERATION() are passed NULL,then the API returns with S_OK. Please respond back if you guys gave faced SIMILAR Issue or if you can help me to troublshoot. Thanks in advance.

  • Anonymous
    April 17, 2012
    I found  root cause. of ‘ScanAvailableEvent’  subscription failure,  Root cause is the some destination response name space  schemes are missing from the WSDXML_NAME Names_Scan[] array Follow these below steps for subscription

  1. Add below name space in WSDXML_NAME Names_Scan[] array ,      { &Namespace_Scan, L"Subscribe" } ,      { &Namespace_Scan, L"SubscribeResponse" } ,      { &Namespace_Scan, L"ScanDestinations" } ,      { &Namespace_Scan, L"DestinationResponse" }
  2.  Increase the array count 409 to 413 in the WSDXML_NAMESPACE Namespace_Scan
  3.  Create below name space WSDXML_ELEMENT *any =     <wscn:ScanDestinations>        <wscn:ScanDestination>          <wscn:ClientDisplayString>Den Computer</wscn:ClientDisplayString>          <wscn:ClientContext>App1ScanID2345</wscn:ClientContext>        </wscn:ScanDestination>      </wscn:ScanDestinations>    </wse:Subscribe> Refer : blogs.msdn.com/.../building-wsdxml-sections.aspx for creating name space. WSDXML_ELEMENT *anyOut;
  4.  Call SubscribeToScanAvailableEvent(eventSink, any, & anyOut);