Wednesday, October 20, 2004

Rewriting WSDL.EXE

The other day, I blogged about how easy it is to generate WSDL directly from a web service assembly, without having to set up an actual web service. Well, I decided to take it a step farther and see if I could generate the proxies directly, too. As it turns out, that's pretty easy, too.


The code turned out to be a bit long for a blog post, so I added it to my wiki instead. You can find the article here.


In addition to generating the proxy class without generating WSDL, I went ahead and added the code to walk over the generated code and strip out any type that isn't the proxy itself. Because we have several web services that share a set of types, and since we have defined these common types in a separate shared assembly to avoid type identity problems, this means the generated code looks just how we like it.


I haven't made the code bulletproof or terribly generic, since it's just for our use here at my client, but it should serve as a reasonable starting point for anyone that wants to produce custom proxies. One variation I can think of that would be useful would be to generate every type into its own file - that way if you had some types that you wanted to share and some that you didn't, it would be easy to automate which get tossed and which get kept.

8 comments:

  1. There's probably a fair amount of demand for this kind of functionality that strips out the types which are generated along with the proxy class. This seems to be the #1 question in the web services newsgroups: "how do I share my type XYZ between a web service and its consumer?"



    Getting caught by the SOA police is not the only issue you can run into if you break one of the SOA tenets (share schema, not types) this way.



    One issue is that you will need to deliver the assembly containing the type(s) to the consumers and pay special attention to versioning.



    Another potential gotcha is that by default XML serialization does not serialize private members. This might create some surprises down the road unless you know what you are doing.

    ReplyDelete
  2. I don't consider this sharing types. I consider it a more convenient way to generate proxies for the times where I'm writing both sides. Others can still generate proxies however they like.



    As for versioning, that's already a problem no matter how you generate your proxies - I can't see that this makes a bad problem any worse.



    Agreed that private state not being serialized is an issue if you're not aware of it. But if someone generated a proxy (say) by hand, they still have the same issue.

    ReplyDelete
  3. I recently ran into this problem myself and in fact I am here at your site because the MS rep sent me here as an alternative to manually modifying the reference.cs file generated by

    Visual Studio. I wanted to be able to put an attribute on the WebMethod to tell the generation tool not to generate types for the method and/or the each parameter. He is recommending the VS team look at the issue. Based on some simple searches on the web, it seems I am not the only one who feels this way. It just makes sense when you are writing both sides or sharing complex objects in a rather large web service implementation.



    BTW, if you have an enum as a formal parameter, the generated proxy class for the enum does not necessarily come out in the same order as your original enum specification. Therefore MyColorEnum.Blue != VSProxy.MyColorEnum.Blue. If you create a converter to work between them, you have to use an if or a switch otherwise there is no guarantees.

    ReplyDelete
  4. This is a fairly powerful approach that has evolved slightly since I originally wrote the article. Another thing you might want to have a look at is Christian Weyer's WsContractFirst tool. I showed him this code, and he was thinking of integrating it into his tool, which is much better developed. Check it out at http://www.thinktecture.com/Resources/Software/WSContractFirst/default.html

    ReplyDelete
  5. I have an issue where the provided .wsdl file is being generated

    incorrectly with the WSDL.exe tool. I have to use digital client

    certificates for authentication and it has been determined...by another

    business...that the proxy class was generated by the wsdl.exe tool

    incorrectly for use with the client certificates. The solution was

    stated to be to 'manually write a proxy class without using the

    wsdl.exe tool'. I am using C# with

    framework 1.1 in Visual Studio 2003. Is there a 'How To' article or something.

    Basically I need to create the proxy class without using the wsdl.exe tool.



    Thanks for any help on this matter.



    ReplyDelete
  6. Not sure. But what the WSDL tool does isn't that complicated. If I were you, I'd just take the code wsdl.exe generates and modify it so it works rather than trying to start from scratch.

    ReplyDelete
  7. Are there any attributes available for a customized port name, port type and binding names ? If so please help me out.

    ReplyDelete
  8. That's really perfect, because of your tool I can now create proxy's without that crude object model duplication that Visual Studio enforces with their WSDL.exe.

    ReplyDelete