views:

447

answers:

4

We have a set of assemblies which implement web services operations.

To build the client proxies, we first build and deploy the web services (assemblies and ASMX files) on the server.

Then we use wsdl.exe to point to the ASMX endpoints and generate the classes for the client proxies.

I've seen that it is possible to create the proxies from wsdl files (instead of asmx endpoints) using wsdl.exe or disco.exe.


Is there a tool to generate wsdl files or event better proxy classes directly from the server assemblies without the need to use a web server?


UPDATE:

First I would like to say I appreciate you guys taking the time to put into this. I also would like to say that I know how hard it is to give advice without knowing all the details of a given scenario. That said, let me detail more the scenario and address some points you guys made:

1) This is a somewhat large project that has been in development for over a couple of years now. The decision to use ASMX web services was made before the existence of WCF.

2) I already thought about writing our own proxy generator and that may be an option if we don’t find a tool that does it.

3) We still want to bind to the WSDL contract. What I’m trying to avoid is having a dependency on a web server during the build process.

4) We already auto-generate the proxies in our automated build which runs in TFS Build and that has not been an issue per se. The issue, as I was told, is having to split the build in two parts: server & client. There may be alternatives to avoid the split using some fancy MSBUILD task, but my knowledge on that matter is limited.

5) I do expect the build to brake on TFS Build if the client side code and server side code don’t match during compilation. That should have been addressed on the developer’s machine before check-in.

6) We have strict control over the server and the client parts. This set of web services serve as a back-end to a Click Once Windows Forms application. Everything runs on an intranet. Every time the contract changes, it is done in tandem with a new version of the client application.

7) WCF is not an option in the short term for this set of web services. When I joined the project over a year ago I was given the task of creating a new set of web services for interoperability with other internal systems. Those web services were designed upfront to be easily upgradable to WCF once upper management allowed us to use WCF. I’ll have to take a look into svcutil.exe, but if it does what we need, I’ll have another point in trying to convince upper management to adopt WCF.

+3  A: 

Well, both classic ASMX web services and modern WCF services have the ability to automatically generate WSDL for you. If you go to the URL for a web service endpoint, you can get the WSDL simply by adding ?WSDL to the end of the URL. You generally do not want to generate proxies from the code of the service itself...the point of web services is to decouple you from implementation, and allow you to bind to contract (which is what WSDL is...a contract.) You can generate client proxies in a few ways...either with wsdl.exe, svcutil.exe, or via visual studio's "Add Web Reference" or "Add Service Reference" options.

If you really need to, you could write you're own proxy generator. I recently wrote a dynamic proxy generator that allowed WCF service proxies to be generated at runtime using lightweight code generation (ILEmit) via the Castle Windsor IOC container. There are a wide variety of options, but the key is that you bind to the WSDL (your contract), and not the actual C# code of the service. The most ideal option would be to write the WSDL, and generate both your client proxies and service contract interfaces and data/message contracts from the WSDL. That is called contract-first service development, and there are a few products for .NET that allow contract-first development.

EDIT:

You commented that I did not really answer your question. Perhaps that is true, however, there is no real good answer to your question. You are trying to auto-generate a client proxy on build. That is really not a good idea, and will likely lead to some significant build problems when your service changes.

An example scenario. Assume you have IServiceA, which has a single method that takes a data contract in as a parameter, and returns a different data contract as a result:

[ServiceContract]
public interface IServiceA
{
    [OperationContract]
    SecureOutput SomeSecureOperation(SecureInput input);
}

public class SecureInput
{
    public UserCredentials Credentials { get; set; }
    public byte[] EncryptedData { get; set; }
}

public class SecureOutput
{
    public byte[] EncryptedData { get; set; }
}

Lets say that the above service utilizes synchronous encryption to encrypt and decrypt the data, but that is later determined to be insecure. So you change the data contracts:

[ServiceContract]
public interface IServiceA
{
    [OperationContract]
    SecureOutput SomeSecureOperation(SecureInput input);

    [OperationContract]
    byte[] GetPublicKey();
}

public class SecureInput
{
    public UserCredentials Credentials { get; set; }
    public byte[] UserPublicKey { get; set; }
    public byte[] EncryptedData { get; set; }
}

public class SecureOutput
{
    public byte[] EncryptedData { get; set; }
}

The service now utilizes asynchronous encryption, and uses the users public key to encrypt return data. The service also has a new operation to allow clients to get the service's public key so they can encrypt input data. The contract of your service has changed, and requires you to update the client-side code. You should version your service...however we are dealing with security, and the old one must be deprecated in favor of the new one to maintain security. If you auto-generate your client proxies at build time, you have a serious problem. Your client code is no longer compatible with the new proxy, and your build fails.

When dealing with web services, it is best to handle proxy generation manually. If the proxy needs to be regenerated (which, if you properly version your services, should be rare once a contract is solidified), then you can't simply generate without breaking something. You will need to generate the proxy, then update anything that consumes it to conform with the new interface. I can't think of any scenario where I would want to generate my proxies at build time, nor would I want to regenerate my proxy every build. I can't recommend such a scenario to anyone, either. I apologize for not directly answering your question, but I hope my explanation will help you build a better solution.

jrista
That really doesn't answer my question. As you can see in my post, today I already use wsdl.exe with ASMX endpoints. What I want is to be able is to have a single MSBUILD project that compiles server and client side assemblies at once. If ASP.NET is able to generate WSDL from the types and members of an assembly I was guessing that another tool could do that too - and maybe even shortcut directly to generating the proxy classes.
Alfred Myers
Well, there really isn't a good answer to your question. The problem with autogenerating proxies for a service, is that if the service changes, and you don't update your proxy BEFORE compiling the whole system, your likely going to have severe problems building whenever your service changes. See my answer for an updated scenario.
jrista
I've added some more info about our scenario in an update to the question.
Alfred Myers
A: 

There's no way to do this with ASMX web services.

However, since Microsoft says: ASMX Web Services are a “Legacy Technology”, this might be a good time for you to think about Migrating ASP.NET Web Services to WCF.

The reason being that svcutil.exe can export metadata from compiled assemblies, which you should then be able to turn around and use to create proxy code, also using svcutil.exe.

I agree with the answer from jrista: the proxy code is one kind of generated code, and I don't believe it should be generated during a build. It should be generated by a developer and should, in fact, be checked into source control.

John Saunders
I have to agree with John on this...migrating from ASMX to WCF would be the best idea. WCF provides a much richer framework to build services upon, and the svcutil.exe utility is more flexible than the wsdl.exe utility.
jrista
It's also not very difficult if you follow the recommendations of the migration guidance, and if you stick to the `basicHttpBinding` binding, which is just SOAP over HTTP, just like ASMX.
John Saunders
I've updated the question to explain why we aren't using WCF.
Alfred Myers
+1  A: 

You could use ServiceDescriptionReflector to build the WSDL file from an assembly.

See this guide: http://www.pluralsight.com/community/blogs/craig/archive/2004/10/18/2877.aspx

EDIT:

After generating the WSDL with ServiceDescriptionReflector you can use the WSDL.exe tool to generate the proxy classes.

Kevin Thiart
A: 

I've created a tool which can generate a WSDL file from a compiled c# assembly (dll) which contains one or more WebServices. Normally you require a running service (IIS or other) which hosts the .asmx so that you can retrieve the WSDL using /MyWebService.asmx?wsdl

This tool generate a WSDL file using reflection to retrieve all information from an assembly (dll).

Download can be found at http://wsdlgenerator.codeplex.com

Stef