Monday, July 12, 2010

SSIS and WCF – The Devil in the Wsdl

I want to elaborate on a fix that wasn't so obvious to me...

The plan seemed simple enough. Current Application requires email reports to sent, some from the web GUI, others according to certain conditions and schedules. Instead of duplicating the report logic in multiple places, let's place it all in one WCF Service application (sending the reports offline via MSMQ) and then call the service from both the web GUI and an SSIS job that runs according to the conditions and schedules.

Not too much to ask, right?

Enter SSIS.

Web Service Task

SSIS offers a task for calling web services - you guessed it: the Web Service Task - which claims to support WCF too so long as the WCF uses Basic Http Binding.

So you add the Web Service Task, configure the Wsdl url and then...error:

Item has already been added. Key in dictionary: 'anyType' Key being added: 'anyType'

Error

Some friendly souls encountered this error before and offered sage advice here and here but the solution requires some spelling out.

The Wsdl needs to contain type definitions for the service methods and data contracts etc. These are split over a number of xsd files, all referenced in the Wsdl:

Wsdl file with Xsd references

Here’s the catch: Wcf generates Wsdl that creates circular references within the xsd files.

Here’s the content of Xsd2:

Xsd2

Note that Xsd2 refers to Xsd3 and Xsd1 even though they are already referenced in the Wsdl.

The result: SSIS in Visual Studio blindly builds a list of valid types based on these Xsd files and thus tries to add some types twice – and fails on validation.

This validation is usually a good thing, but flags Wcf-generated Wsdl content as a false positive.

The Solution

The way out of this mess?

  1. Look through the Xsd references in your Wsdl
  2. Peek at the Xsd files too (copy the urls to your browser of choice)
  3. Eliminate from the Wsdl file all references to Xsd files already referenced in earlier Xsd files.

In my case this meant deleting all the Xsd references from the Wsdl except for the first one.

[The irony, of course, is that I encountered a row of other issues – setting the Input and Output parameters for the Task, for starters – and decided to ditch the Web Service Task in favor of a Execute Script Task, which uses an old-fashioned web service reference in the script editor.

So much for that…]