views:

1300

answers:

3

I have a .wsdl file that my web service (old asmx style) must implement. That is taken care of. When I publish the web service you can call it with ?wsdl parameter to get a generated wsdl.

How do I include my .wsdl file so that is the one that is returned instead of the generated one?

Is it possible to do with an attribute in my web service class?

+2  A: 

Is it a given to stay with "old-style" ASMX? Or could you move up to WCF? That's really the most current webservice offering by Microsoft, and if you're doing something new and you're on .NET 3.0 or higher - why spend time on "old" technology?

In WCF, you could definitely define a static physical WSDL file to be used by clients connecting to your metadata endpoint (your "...?wsdl" URL). Not sure if you can do it in ASMX, too.

OK, on ASMX / .NET 2.0, you could of course always put the actual WSDL file under the root of your web site, and then just reference it like this:

http://yourwebserver/YourVirtDir/MyService.wsdl

I don't know if there's a way to "redirect" the

http://yourwebserver/YourVirtDir/MyService.asmx?wsdl

call to go to that fixed URL instead. I'm sure someone else will know, though!

Marc

marc_s
For now I am stuck on .NET 2.0 and can't use WCF. But I do think that it is possible to work with "contract first" even with asmx and point your ?wsdl request to a separate file.
Örjan Jämte
It's not possible to point "?wsdl" to a separate file. Just serve the .wsdl file at a separate URL like marc_s suggested.
John Saunders
A: 

You can generate a WSDL and DISCO file by pointing the disco.exe tool that ships with the .NET Framework at your web service.

 disco.exe http://webserver/MyWebService.asmx

The following files are created:

 results.discomap
 MyWebService.disco
 MyWebService.wsdl
bryanbcook
I don't need to generate a wsdl. The caller has defined the wsdl. I have done an implemetation of an ASP.NET Web Service (.asmx) and now I would like to redirect the references to ?wsdl to this supplied .wsdl file that I got.
Örjan Jämte
Then change the disco file to point to your wsdl
bryanbcook
-1: this doesn't work.
John Saunders
+1  A: 

To avoid the confusion of having two different WSDLs available on two different URLs (i.e., the *.asmx?wsdl URL and a custom URL) in your web service application, you could write an HttpModule that intercepts the request to the *.asmx?wsdl URL and returns your custom WSDL instead.

EDIT: Here's an example, adapted and simplified from some code I previously wrote that makes a custom WSDL available at the standard *.asmx?wsdl URL.

using System;
using System.IO;
using System.Web;
using System.Web.Services.Configuration;

namespace DemoWebService
{
 public class CustomWsdlModule :
  IHttpModule
 {
  public void
  Init(HttpApplication application)
  {
   // hook up to BeginRequest event on application object
   application.BeginRequest += new EventHandler(this.onApplicationBeginRequest);
  }

  public void
  Dispose()
  {
  }

  private void
  onApplicationBeginRequest(object source, EventArgs ea)
  {
   HttpApplication application = (HttpApplication)source;
   HttpRequest request = application.Request;
   HttpResponse response = application.Response;

   // check if request is for WSDL file
   if ( request.Url.PathAndQuery.EndsWith(".asmx?wsdl", StringComparison.InvariantCultureIgnoreCase) )
   {
    // if Documentation protocol is not allowed, throw exception
    if ( (WebServicesSection.Current.EnabledProtocols & WebServiceProtocols.Documentation) == 0 )
    {
     throw new System.InvalidOperationException("Request format is unrecognized.");
    }

    // get path to physical .asmx file
    String asmxPath = request.MapPath(request.Url.AbsolutePath);

    // build path to .wsdl file; should be same as .asmx file, but with .wsdl extension
    String wsdlPath = Path.ChangeExtension(asmxPath, ".wsdl");

    // check if WSDL file exists
    if ( File.Exists(wsdlPath) )
    {
     // read WSDL file
     using ( StreamReader reader = new StreamReader(wsdlPath) )
     {
      string wsdlFileContents = reader.ReadToEnd();

      // write WSDL to response and end response without normal processing
      response.ContentType = "text/xml";
      response.Write(wsdlFileContents);
      response.End();
     }
    }
   }
  }
 }
}

This simplified code assumes that your custom WSDL is in the same folder as your .asmx file with a .wsdl extension. The HttpModule needs to be hooked into your web service application via the web.config file:

<?xml version="1.0"?>
<configuration>
    <!-- ... -->
    <system.web>
  <!-- ... -->
  <httpModules>
   <add
    type="DemoWebService.CustomWsdlModule"
    name="CustomWsdlModule"/>
   <!-- ... -->
  </httpModules>
  <!-- ... -->
    </system.web>
    <!-- ... -->
</configuration>
GBegen
-1: The simpler way to avoid the confusion is simply to remove the `Documentation` protocol from the `protocols` element in web.config.
John Saunders
I suppose this was better suited to be a comment on marc_s' answer than an answer on its own.However, there is still value in the documentation protocol and having your WSDL at the one URL that developers are familiar with seeing as the WSDL URL for a .asmx web service. This is why I would make sure that if I wanted my custom WSDL available online, I would use an HttpModule or other URL rewriting technology to put my custom WSDL at the expected location.
GBegen
You seem to be assuming that would work. I'd suggest you not make such assumptions.
John Saunders
I only make the assumption because I have previously done it in production code. I have adapted and simplified my code into an example and added it into my above answer.
GBegen
+1: for the sample code.
Örjan Jämte