While working on new functionality for Imtech Fields Explorer I have noticed that there are Web Services in SharePoint 2007 which are missing the DISCO and the WSDL files. If you ever tried to attach a web reference to such Web Service you know that it will fail. While you might think that it's impossible, I have found a way of creating a WSDL file for an existing Web Service.

One of the SharePoint 2007 Web Services which is missing the WSDL file is the SharePointPublishingToolboxService which is being used by SharePoint Designer. If you type the URL in your browser you will see a typical Web Service information screen:

CMS Content Area Toolbox Info service information screen

As soon as you click on the Service Description link, which should take you to the WSDL definition of the Web Service, you will see an error page instead:

WSDL doesn't exist error when clicked on the Service Description link of the SharePointPublishingToolboxService

Because there is no WSDL file, you won't be able to create a Web Reference to that Web Service as well. But there is a way to create the WSDL manifest for an existing Web Service:

public static void GenerateWsdl(Type webServiceType,
    string webServiceUrl, string outputPath)
{
    ServiceDescriptionReflector reflector =
        new ServiceDescriptionReflector();
    reflector.Reflect(webServiceType, webServiceUrl);

    if (reflector.ServiceDescriptions.Count == 1)
    {
        XmlTextWriter wtr = new XmlTextWriter(outputPath,
            Encoding.UTF8);
        wtr.Formatting = Formatting.Indented;
        reflector.ServiceDescriptions[0].Write(wtr);
        wtr.Close();
    }
}

To generate WSDL manifest for the SharePointPublishingToolboxService I have mentioned above you would call this method like:

GenerateWsdl(typeof(SharepointPublishingToolboxService),
    "http://sharepoint/_vti_bin/contentareatoolboxservice.asmx",
  @"C:\contentareatoolboxservicewsdl.aspx");

While the GenerateWsdl method works properly and creates the WSDL manifest but it isn't sufficient yet. If you click on the Service Description link now, you will see the WSDL manifest as with any other Web Service. You still won't be able to create a Web Reference to the Web Service however as the URL's are hard-coded in the WSDL manifest. Comparing the WSDL file we've just generated you will find the following difference:

Comparing the generated WSDL manifest and one of a working SharePoint 2007 Web Service

The above screen contains the WSDL page for the SharePoint 2007 Publishing Web Service which works properly. The URL's are written to the output depending on the request URL. As soon as you copy & paste the two soap:address lines, you will be able to use the SharePointPublishingToolboxService in your custom code. Before you run the Web Service you will also have to add the following lines to the header of the WSDL file so that you can benefit of dynamically writing the request URL:

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0,
Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>
<%@ Import Namespace="Microsoft.SharePoint" %>

<% Response.ContentType = "text/xml"; %>

Not that the <@ Assembly … @> line has been wrapped for brevity. In your code you will have to make it one line.