Using a Custom WSDL File in ASP.NET Web Services

CraigBlog

Syndication

Some of the work I'm doing right now involves writing a web service that has custom WSDL. By "custom" I mean "written by hand, not generated by the ASP.NET web services infrastructure". In this case, it's because we've got a bunch of external schema types that we'd like to use in a certain way, but you might want to do the same thing for a variety of reasons, including just not liking the way the generated WSDL looks.
 
As it turns out, using an external WSDL is fairly easy. It's just a little obscure - I had a hard time tracking down how to do it using Google, so I'm documenting the process here. Following, the steps required:
 
Write a custom WSDL file.
Use the tool of your choice. The one thing you're going to want to do is to omit the <wsdl:service> declaration. This bit actually will be generated by the ASP.NET infrastructure. That makes sense, since it contains a URL, and can be more easily determined at runtime.
 
Drop the WSDL in the web directory next to your .asmx file.
Presumably, you still want people to be able to download your custom WSDL, so putting it somewhere web-accessible is a good idea.
 
Mark your web service implementation class with the [WebServiceBinding] attribute.
For instance, you might do something like this:
 
[WebServiceBinding(Name = "MyBinding", Location = "MyCustom.wsdl")]
public class MyServiceImplementation : WebService
{
// ...
}
 
The most important thing to set here is the Location property, which tells ASP.NET where your custom WSDL file lives. The Name property gives the name of the <wsdl:binding> from your custom WSDL, and is needed by ASP.NET to allow it to dispatch calls onto your implementation correctly.
 
Mark your web method with the [SoapDocumentMethod] attribute.
For example:
 
[WebMethod]
[SoapDocumentMethod(Action = "urn:foo-com:service/DoSomething",
Binding = "MyBinding")]
public DoSomethingResponse DoSomething(DoSomethingRequest request)
{
// …
}
 
The Action property associates this method with the action listed in your WSDL file. It is particularly important because ASP.NET chooses which method to invoke based on the action in the incoming message.
 
The binding element associates the operation with a particular <wsdl:binding>, in much the same way that the Name property of the [WebServiceBinding] attribute does. It’s required to be on the [SoapDocumentMethod] attribute for proper operation, but I still haven’t quite figured out why you need both.
 
Observe the generated WSDL.
If you surf to the automatically-generated WSDL page (e.g. http://server/path/to/service.asmx?wsdl), you’ll observe that ASP.NET is still generating a WSDL document for you. However, because of the changes you’ve made, that WSDL consists solely of a <wsdl:import> referencing the WSDL file you wrote, and a <wsdl:service> element containing the URL for the service. It’ll look something like this:
 
<wsdl:definitions targetNamespace="urn:foo-com:service">
 
<wsdl:import namespace="" location="MyCustom.wsdl"/>
 
<wsdl:types/>
<wsdl:service name="MyService">
  <wsdl:port name="MyBinding" binding="tns:MyBinding">
    <soap:address location="http://localhost /MyService/MyService.asmx"/>
  </wsdl:port>
  <wsdl:port name="MyBinding1" binding="tns:GetContentBinding">
    <soap12:address location="http://localhost/MyService/MyService.asmx"/>
  </wsdl:port>
</wsdl:service>
 
</wsdl:definitions>
 
Luckily, Add Web Reference respects the <wsdl:import> and (assuming you write the WSDL correctly), .NET clients will be able to generate code off of this document successfully. Other toolkits should be able to as well, but YMMV.
 
Particularly when coupled with the flexibility that IXmlSerializable gives you over the serialized XML, taking control of the WSDL is a very powerful technique.

Posted Dec 15 2005, 07:06 AM by craig-andera

Comments

Bob wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-16-2005 10:56 AM
Craig,

thanks for this. I am trying to figure something out though. I get an error on the client proxy generation through Add Web Reference. c:\Inetpub\wwwroot\BlahTwoClient\Web References\localhost\Reference.map(1): Custom tool warning: Ignore duplicate WSDL document 'http://localhost/BlahTwo/Service1.asmx?wsdl' with TargetNamespace 'http://mynamespace'.

It all works but I am afraid this is wrong. I am pretty sure it's in my usage of the namespaces.
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-16-2005 11:03 AM
What does your Reference.map file look like? Are you using imports in either your WSDL or your schema?
Bob wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-16-2005 11:06 AM
I have no imports(I did but removed them).

Reference.map
<DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="file:///c:/inetpub/wwwroot/wsdl/blahtwo.wsdl" filename="blahtwo.wsdl" />
<DiscoveryClientResult referenceType="System.Web.Services.Discovery.DiscoveryDocumentReference" url="http://localhost/BlahTwo/Service1.asmx?disco" filename="Service1.disco" />
<DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://localhost/BlahTwo/Service1.asmx?wsdl" filename="Service1.wsdl" />

Thanks for your help on this.
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-16-2005 12:15 PM
Hmm. Well, I'm not really sure what the problem is. Perhaps you should delete the web references entirely (including going in to the filesystem and nuking the directory) and then start over.
Christopher Steen wrote Link Listing - December 16, 2005
on 12-16-2005 7:00 PM
ASP.NET Podcast Show #30 - Minimizing the ASP.NET ViewState
Part #2 [Via: Wallym ]
Complex data binding...
Christian Weyer wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-17-2005 2:26 AM
Craig, in WSCF 0.6 we will enable exactly this custom behavior: you can choose wheter you want your modeled WSDL to be returned by the .asmx or not.
In addition, we have developed a fixed Default***.aspx which will ship with WSCF 0.6.
Once we have WSCF 0.6 out of the door I will post the code on my blog.

Cheers!
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-17-2005 7:32 PM
Nice. I haven't been using WCSF lately, but I'll have to take a look at it again when you ship 0.6.
Bob wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-19-2005 9:31 AM
Craig,
Thanks again. I figured out what happened. You said it in your post, "assuming you write the WSDL correctly". Funny how that works. Namespace clashes.

By the way(to Christian also), I use WSCF .51 and went the binding route due to this not being in WSCF. Greatly appreciated if the Thinktecture guys get this in.

thanks again
Mike wrote WS-I Basic profile
on 01-02-2006 9:31 AM
I'm probably bumbing up against my lack of WSDL knowledge but I'm having a problem using your example to create a service that passes the WS-I Basic profile 1.1 validation step ( in Visual Stuid 2005 ).

I started with a shell web service and added a web method that takes a single string as a parameter and returns a string as the result.

I compiled and auto generated the WSDL. At this point the service passes the WS-I basic profile validation.

I then did the following:

1. Saved the auto generated WSDL to a file.
2. Commented out the <wsdl:service> section.
3. Added the WebServiceBinding attribute as you described in your blog entry. ( Location set to the saved WSDL )
4. Added the SoapDocumentMethod as you described in your blog entry.

When I run the service now I get warning that the service does not conform to the WS-I Basic Profile because the SOAP 1.1 binding was not found.

The auto gen WSDL now looks like the example in your blog entry.

Am I missing something obvious?

thanks

Mike
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 01-02-2006 12:59 PM
How are you verifying compliance? Is it possible the tool simply doesn't like the wsdl:import?

When you view the WSDL that it's creating, it includes both SOAP 1.1 and 1.2 bindings, right? That's what makes me think it's not respecting the import.
Mike wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 01-05-2006 7:21 AM
When you use the default 'debug' mode to run a web service in VS2005 it will check for compliance -controlled of course by various web.config and webservice attribute parameters.

I don't know if the visual studio isn't handling the import. I'll run it through the WS-I org tool and see if that likes it better.
Stefan wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 03-20-2006 3:04 AM
I'm experiencing the same problem as Mike. Just run the web services .asmx from the Visual Studio 2005 environment and you'll get the error. Any idea what causes this?
Mal wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 04-04-2006 8:44 PM
Nice work, Craig. Thanks.
CraigBlog wrote The Perils of WSDL First
on 04-06-2006 11:02 AM
Mike E wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 05-16-2006 12:49 PM
I'm having the same problem as Mike (up above) - maybe it's a Mike thing! Any suggestions as to how to fix this? Or how did you get around it Mike?

Thanks!
bhargavi wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 06-14-2006 10:57 PM
iam facing saop action error when my service is accessed by a java client so tell me how to access this service by a java client
hema wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 06-14-2006 11:17 PM
giving binding error when i am implementing the above example
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 06-15-2006 4:42 AM
bhargavi: Some Java clients don't set the SOAPAction header properly. You'll need to make sure it's set to the value specified in the WSDL. How you do this is dependent on the software you're using. Consult the documentation.

hema: Can you give me more information?
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 06-27-2006 6:48 AM
Mike & Mike: sorry it has taken me so long to reply. I am lame.

Since you need to generate the binding yourself, what does it look like in your WSDL file?

Also, I should point out that for the project I was using this approach on, I ultimately ditched this approach and went with an approach where we just wrote the entire WSDL by hand, then wrote an HttpHandler to return it when a GET with ?wsdl on it came in.
rajesh wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 09-12-2006 4:44 AM
when ever i try to use this webservice some other application using add webreference error is coming like
'unabel to download following file from
http://localhost:4296/AdviceSheetWebservices/AdvceSheetService.asmx?WSDL'

can u help me it's urgent
Craig wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 09-12-2006 5:00 AM
Well, what happens when you open the WSDL page in a browser?
Steve James wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 10-19-2006 6:23 AM
Did anyone sort this out? I'm getting the basic profile 1.1 error and i can't add a web reference to the service.
Steve James wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 10-19-2006 6:28 AM
Still get the basic profile error but can now add a web reference. Need to ensure the binding name in the attributes matches the binding name in the wsdl. By default this is set to <Servicename>Soap.
Christopher Steen wrote Link Listing - April 19, 2007
on 04-19-2007 8:59 PM
Silverlight [Via: gduthie ] Tim Sneath on Silverlight [Via: gduthie ] More on Lazy Loading vs. Pre-loading...
Anagha wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 05-23-2007 12:13 AM
Has anybody used IXmlSerializable class as input and return(response) type for a webservic method?
If so, do we need 2 xsd schema`s for validating input/response ?
Do we need to create custom wsdl file?
How do we create wsdl?

Please reply asap. got a deadline by end of today.
Anonymous wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 12-31-2007 8:38 AM
I also get the basic profile error. Has anybody successfully got this working? If not, maybe this Blog should be deleted so we all aren't wasting our time.
Anonymous wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 01-19-2008 7:32 AM
Create a global.asax.cs file and put the following code and twik to meet your needs:
(probably some way to do this in the web.config.) There was a good article about this on http://www.123aspx.com, but I can't find it now.

namespace localhost
{
public class Global : System.Web.HttpApplication
{
protected void Application_BeginRequest(Object sender, EventArgs e)
{
string requestPath = Request.RawUrl.Trim().ToLower();
if (requestPath.IndexOf("?wsdl") > 0 || requestPath.IndexOf("?wsdl") > 0)
{
Response.Redirect("http://localhost/MyWebService/MyWSDL.wsdl");
}
}
}
}
Anonymous wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 01-19-2008 7:35 AM
if (requestPath.IndexOf("?wsdl") > 0 || requestPath.IndexOf("?wsdl") > 0)
Should Be:
if (requestPath.IndexOf("?wsdl") > 0 || requestPath.IndexOf("?disco") > 0)


Stu wrote Another Error
on 02-04-2008 12:29 PM
I receive this error:

"Unable to import WebService/Schema. Element binding named WsdlBind from namespace ...is missing."

Anyone come across this?
Clay wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 07-07-2008 8:59 PM

I'm having trouble mapping your "urn:foo-com:service/DoSomething" to my own WSDL. Can anyone share an actual example of a working WSDL and the matching code? Thanks!

Mark wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 07-11-2008 12:08 PM

I am a new to web service world. For the leaning purpose, I have

created a web service in 2005 with one asmx.cs file, in this file, I

have one method called GetUser() which returns a custom user object,

something like

[WebMethod]

public User GetUser()

When I run it from IDE, I noticed after clicking the Service

Description link that the XSD for my custom object user is missing an

element id, which is a read only property of object, and it would

shown if it's changed to read and write. Then, I followed above example tried to use a custom wsdl that contains xsd of an int id element for my user object, but for some reasons, when I run it, this id element still disappeared, any ideas?

Thanks a lot.

Manpreet wrote re: Using a Custom WSDL File in ASP.NET Web Services
on 07-31-2008 12:35 AM

I have an ASP.Net Website Webservice and this method of specifying the custom wsdl does not work in it. Is there any idea why?

Add a Comment

(required)  
(optional)
(required)  
Remember Me?