Friday, April 13, 2007

Resolving mutipart WSDL documents with DiscoveryClientProtocol

Following on from yesterday's post on the WSDL that's generated by WCF, I ran up Relector and started digging into WSDL.exe. It doesn't do exactly the same thing that I want to do, its job is to generate proxy classes for web services, but still has to download and resolve mutiple linked WSDL and XSD files when given the URL of the root WSDL file. It turns out that is uses a class in the .NET framework, DiscoveryClientProtocol that does all the work of resolving and downloading the WSDL and XSD classes. It can even save them all to disk. I got quite excited when I also found out about ServiceDescriptionImporter, the name suggested that it could create a single ServiceDescription (the class that represents a WSDL file in memory) instance from a number of files, but alas it's the class that actually generates proxy class code. Matt Ward has an interesting article about how he used these classes to write the web reference functionality in SharpDevelop. Here's a little NUnit test showing the basic functionality of DiscoveryClientProtocol, it loads all the parts of the WSDL into its Documents collection, I then write the Keys of the documents (actually the URLs) to the console and finally save the documents to disk in 'My Documents\Wsdl":
using System;
using System.IO;
using System.Collections;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Services.Discovery;
using NUnit.Framework;

namespace MH.WsdlWorks.Tests
{
    [TestFixture]
    public class DiscoveryClientProtocolSpike
    {
        const string wsdlUrl = "http://localhost:1105/EchoService.svc?wsdl";

        [Test]
        public void DiscoveryClientProtocolTest()
        {
            DiscoveryClientProtocol client = new DiscoveryClientProtocol();
            client.Credentials = CredentialCache.DefaultCredentials;
            client.DiscoverAny(wsdlUrl);
            client.ResolveAll();

            foreach (DictionaryEntry dictionaryEntry in client.Documents)
            {
                Console.WriteLine("Key: {0}", dictionaryEntry.Key.ToString());
            }

            string myDocuments = Path.Combine(
                System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Wsdl");
            client.WriteAll(myDocuments, "wsdlDocumentsMap.xml");
        }
    }
}

No comments: