Create a .wsdl file from an asmx web service with NAnt

There are places where we are still stuck with .net framework 2.0 – so WCF is still not available. I’m currently working on such a project.

I’m using asmx web services, and i needed to be able to export the wsdl file generated by the framework, as part of an automated build.
It turns out that it seems there’s no way to generate a wsdl file from a web application directly without a web server.

So I decided to turn to NAnt and Cassini (the web server integrated with visual studio) and came with the following target :

<target name="generate-wsdl-files"
        depends="build"
        description="Regenerate wsdl files needed to access the web services">
    <property name="cassini.port" value="1083" />
    <property name="webservices.url" value="http://localhost:${cassini.port}" />
    <property name="wsdl.dir" value="${project::get-base-directory()}\ExportWSDL" />
    <property name="project.web.path" value="${project::get-base-directory()}\Sources\Web" />

    <exec program="${framework::get-tool-path('WebDev.WebServer.exe')}"
          spawn="true"
          pidproperty="cassini.pid">
      <arg value="/port:${cassini.port}" />
      <arg value="/path:&quot;${project.web.path}&quot;" />
      <arg value="/vpath:&quot;/&quot;" />
    </exec>

    <sleep seconds="3" />

    <exec program="${framework::get-tool-path('disco.exe')}" workingdir="${wsdl.dir}">
      <arg value="${webservices.url}/WebServices/AWebService.asmx" />
      <arg value="${webservices.url}/WebServices/AnotherWebService.asmx" />
    </exec>

    <delete>
      <fileset basedir="${wsdl.dir}">
        <include name="*.disco"/>
        <include name="*.discomap"/>
      </fileset>
    </delete>

    <exec program="taskkill">
      <arg value="/PID" />
      <arg value="${cassini.pid}" />
    </exec>
  </target>

What this target does is basically:

  • set a bunch of properties: cassini port, export directory, the local path for the web project, etc.
  • line 9: start cassini (I believe you must have Visual Studio installed on the machine to do that), and very importantly spawns the process (meaning that NAnt will go on not waiting for the process to stop). The PID of the process is retained in a property (cassini.pid)
  • line 17: wait a couple of seconds for cassini to start and load the application (YMMV)
  • line 19: use the disco.exe tool from the sdk to produce a wsdl from a url – Note that you have to pass the list of all the asmx entries
  • line 24: delete the unnecessary .disco and .discomap files
  • line 31: kill the cassini process using taskkill

Enjoy!

Leave a Reply