views:

743

answers:

3

I have a similar problem as this question. I have multiple web services that I am consuming with WCF, which all share types. The services themselves are written in Java and I do not have access to them. The shared types have the same signatures, but svcutil.exe gives this error when running:

Error: There was a validation error on a schema generated during export:
    Source:
    Line: 8 Column: 3
   Validation Error: The complexType 'http://MyServer.MyService:CommonType' has already been declared.

With CommonType having the same signature in both web services being consumed. Here's how I'm calling svcutil:

svcutil.exe /o:GeneratedServices.cs /n:*,MyNamespace.Generated http://MyServer.MyService1?WSDL http://MyServer.MyService2?WSDL

I know that wsdl.exe has /mergeTypes flag, which works for these services, but there are some options on svcutil.exe that I'd really like to use. I did have someone demonstrate that it is possible to me, however the backend was also using .NET and WCF, and I've been unsuccessful with the Java backend I'm using.

+3  A: 

First - are they exactly the same? In particular, the SOAP namespaces must match (in addition to everything else). If they don't, then they are different (incompatible) types; you will have to use 2 different references (in different C# namespaces to avoid conflicts), and shift data between the two types.

If the types are the same and it still doesn't work, then you can perhaps use the /r switch with svcutil to consume the types from an existing assembly. Try using it once to get the first types (just from 1 of the urls) - then compile that code into an assembly. Use svcutil against the second endpoint with the /r flag identifying the assembly you generated moments ago.

Note; a related topic is to write a partial class for one-or-more of the types - for example, to provide conversion methods/operators on the types themselves. This might make things simpler. For example, you could write an implicit (or explicit) static conversion operator between two similar types in different namespaces.

Marc Gravell
A: 

ANSWER EXTENDED WITH CAVEATS (and context): And don't forget, svcutil.exe is just a tool. You can modify or extend the generated code - there's no prohibition against it. Though of course there are downsides to customizing generated code and you should do it only with eyes wide open.

In the earlier days, when fitting heterogeneous clients and servers together via web services, I regularly resorted to modifying the generated WSDL, modifying the code generated from the WSDL (I wrote numerous sed scripts to swap namespaces when connecting AXIS and .NET), and other custom-fit approaches. Some of the web services that have been around the longest still require this. One example is the MS Office Research Service, which does not ship a WSDL at all...

Another approach that may or may not work is to extend the generated .NET code via partial classes. This is a great way to adjust XML namespaces, add optional elements (like a version string?), and make other tweaks. And when you re-generate the code, your extensions won't get overwritten.

EDIT: Judging by the downvote, some people think this is too risky!!! I understand completely.

Cheeso
While true, it isn't always a good idea. For *extending* the code (adding methods etc), you should use a partial class. If you modify the code, you don't have a good route to update the service (if that is a requirement), and you risk breaking it (fairly easy to do).
Marc Gravell
Yes, of course. Partial classes make this easy.
Cheeso
Just saw this jump (edit) - I don't think it deserves the downvote; will fix in a few hours when I get some votes back! (or when I get up...) [fixed]
Marc Gravell
My downvote is on the concept of modifying generated code. Edit the answer to say "you can extend ... using partial classes", and I'll upvote again.
John Saunders
A: 

Since it exists in both services then you are ending up with two declarations after running svcutil against both services. I don't think svcutil.exe is smart enough to reallize that the same type exists in both web services.

You may need to manually eliminate the duplicate declaration. If they are truly identical then you should be able to fix it up to use only one of them and eliminate the other.

AaronLS
That won't work because the service method call for that specific type. If MyServiceAlpha.DoSomething() takes a MyServiceAlpha.Widget as a parameter, it won't take a MyServiceBeta.Widget.
swilliams
That may be the case, but I have created services that shared types before. So I don't think that just because they are used by two different services necessarily makes them different.
AaronLS