martijnvanschie
martijnvanschie

Reputation: 41

Unable to create "ShareLibrary" with datacontract using SVCUTIL

Case: I have a set of xsd files that define common types used in WSDL definitions (Header, ApplicationError). Each webservice inports, next to the service specific types, one or more of these shared types.

When generating a proxy for services I keep getting copies of these shared types per service proxy, so I desides to put these in a shares library and use /reference to include these types. I could not get this to work.

First of all, generating a proxy and including all *.xsd workes fine, and contract are generated. Then using the svcutil per xsd, with the /dconly parameter, does not work. Both /XmlSerializer as /DataContractSerializer. Only /importXmlType (or xsd.exe) work.

Then if I put them in a class project, add the generated code, compile and use this on for the /reference parameter, I still get code generated for these types.

Even if I use the classes, generated for the proxy, they are still not recognized by svcutil.

Anyone have experience with this pattern, and perhaps has encounters these same issues?

Error messages for both XmlSerializer as DataContractSerializer svcutil /dconly /ser:XmlSerializer ApplicatieFout-v0200-b03.xsd

Error: Type 'ApplicatieFout' in namespace 'http://schemas.customer.nl/ApplicatieFout-v0200' cannot be imported. Form on element 'FoutCode' must be qualified. E ither change the schema so that the types can map to data contract types or use ImportXmlType or use a different serializer.

If you are using the /dataContractOnly option to import data contract types and are getting this error message, consider using xsd.exe instead. Types generated by xsd.exe may be used in the Windows Communication Foundation after applying the XmlSerializerFormatAttribute attribute on your service contract. Alternatively , consider using the /importXmlTypes option to import these types as XML types to use with DataContractFormatAttribute attribute on your service contract.

Upvotes: 2

Views: 964

Answers (1)

Petru Gardea
Petru Gardea

Reputation: 21658

In our support activities, we see requests like yours quite often, sufficient to call out a pattern. Without seeing the actual XSDs and WSDLs, it is hard (for anyone) to say if you ran into a product bug or something else.

However, what I learned over the years is that in general tools that deal with XSD to code binding are always limited; to work around those limitations, the solution is to start with a careful planning of the XSD content and how WSDLs must use that content. It is easier if I control the process of generating WSDL and XSD; when I "inherit" or "adopt" other's, I apply my own refactoring.

On .NET, my solution to your case is a to use a little trick based on WSDL's specification support for componentized authoring. Let's assume you have WSDLs for two services, Abc and Xyz. I build a "wrapper" WSDL like so:

<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    targetNamespace="http://services.paschidev.com/wrapper/usecase_a/1/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:import namespace="http://services.paschidev.com/service_abc/1/" location="AbcService.wsdl" />
  <wsdl:import namespace="http://services.paschidev.com/service_xyz/1/" location="XyzService.wsdl" />
  <wsdl:types />
</wsdl:definitions>

Feed this through your utility (successfully tested this with Visual Studio 2010, Add Service Reference command), and you're done.

The fine print... For all this to work with a high success rate, all the WSDLs you wish to combine must follow this rule: common XSD must come from common sources.

If service Abc needs {urn:paschidev-com:xsd:common:1}something and Xyz needs the same, then a {urn:paschidev-com:xsd:common:1}something must come from the same source URI for both WSDLs.

The test is rather simple for me: I use QTAssistant's (I am associated with it) Extract XSDs command by pointing it at the wrapper WSDL. When prompted, I let it create an XSR project; if the collection created from the generated XSDs compiles fine, it means that there are no duplicate XSD definitions. If the compilation gives "already defined" errors, a report tells me which XSD component is duplicated, i.e. comes from two or more different source Uris. I refactor each component to keep one source uri; then try again.

Sometimes, even if I get the XSDs right, svcutil or xsd might still choke; if that happens, it is then something unrelated to the wrapper; it would manifest itself even without this wrapper. Which means it is always a good idea to ensure that before any refactoring happens, each individual WSDL works well on its own.

Upvotes: 1

Related Questions