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?
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
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>
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