Reputation: 899
I have a webservice
. I need to call a custom WSDL
with some validations on fields etc.
I have gone through some article and done some steps which I'll show below.
[WebService(Namespace = "http://tempuri.org/")]
//[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[WebServiceBinding(Name = "CustomWSDL", Location = "http://localhost:62783/Service1.wsdl")]
public class Service : System.Web.Services.WebService
{
public Service () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
[SoapDocumentMethod(Action = "urn:foo-com:service/HelloWorld", Binding = "CustomWSDL")]
public string HelloWorld(string i) {
return "Hello World";
}
}
Now, My WSDL
looks like this.
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="HelloWorld">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="i" >
<s:simpleType>
<s:restriction base="s:string">
<s:minLength value="1"/>
</s:restriction>
</s:simpleType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="HelloWorldResult">
<s:simpleType>
<s:restriction base="s:string">
<s:minLength value="1"/>
</s:restriction>
</s:simpleType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse" />
</wsdl:message>
<wsdl:portType name="ServiceSoap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn" />
<wsdl:output message="tns:HelloWorldSoapOut" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ServiceSoap" type="tns:ServiceSoap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap:operation soapAction="http://tempuri.org/HelloWorld" style="document" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="ServiceSoap12" type="tns:ServiceSoap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="HelloWorld">
<soap12:operation soapAction="http://tempuri.org/HelloWorld" style="document" />
<wsdl:input>
<soap12:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap12:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!--<wsdl:service name="Service">
<wsdl:port name="ServiceSoap" binding="tns:ServiceSoap">
<soap:address location="http://localhost:62783/Service.asmx" />
</wsdl:port>
<wsdl:port name="ServiceSoap12" binding="tns:ServiceSoap12">
<soap12:address location="http://localhost:62783/Service.asmx" />
</wsdl:port>
</wsdl:service>-->
</wsdl:definitions>
wsdl:service
should be commented. So, its commented.Since I need to use the custom WSDL, I had one problem with WsiProfiles.BasicProfile1_1
. So, I had to remove that using web.config.
<system.web>
<webServices>
<conformanceWarnings>
<remove name='BasicProfile1_1'/>
</conformanceWarnings>
</webServices>
So, into the main part.
My Webservice compiles successfully without any errors. Now, I'm importing the webservice into the application and i'm getting my new WSDL along with the auto generated WSDL
. But, it gives me an error when i try to build saying.
Element binding named CustomWSDL from namespace http://tempuri.org/ is missing.
I went through MSDN and some other articles for this error but none could fix my issue.
What is the mistake i have done when creating this WSDL??
Note: MyReference: http://craigandera.blogspot.com/2005/12/using-custom-wsdl-file-in-aspnet-web_15.html
I have done exactly the same thing which he has described in the blog.
Upvotes: 2
Views: 9124
Reputation: 42494
Are you sure you need this as an ASMX Service? That technology stack is superseded by Windows Communication Foundation. New developments are better done in that stack.
I'll answer your question using the ASMX tool stack.
You can handcraft a service implementation like the way you are trying, but it's much easier to have the tools do the heavy lifting for you.
For asmx, that tool is called Web Services Description Language Tool (wsdl.exe) and is in your path if you start a Visual Studio Command prompt.
wsdl.exe
Utility to generate code for xml web service clients and xml web services using ASP.NET from WSDL contract files, XSD schemas and .discomap discovery documents. This tool can be used in conjunction with disco.exe.
I copied your wsdl and saved it in a file. After that I ran the wsdl tool to instuct it to generate a server implementation for me:
wsdl /serverInterface /n:Any.AweSome.NameSpace /l:csharp custom.wsdl
Usage: wsdl.exe <options> <url or path> <url or path> ...
Used Options:
/serverInterface
Generates interfaces for server-side implementation of an ASP.Net
Web Service. An interface is generated for each binding in the wsdl
document(s). The wsdl alone implements the wsdl contract (classes
that implement the interface should not include either of the following
on the class methods: Web Service attributes or Serialization
attributes that change the wsdl contract). Short form is '/si'.
/language:<language>
The language to use for the generated proxy class. Choose from 'CS',
'VB', 'JS', 'VJS', 'CPP' or provide a fully-qualified name for a class
implementing System.CodeDom.Compiler.CodeDomProvider. The default
language is 'CS' (CSharp). Short form is '/l:'.
/namespace:<namespace>
The namespace for the generated proxy or template. The default namespace
is the global namespace. Short form is '/n:'.1
The result is an interface that your service implementation should implement:
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")]
[System.Web.Services.WebServiceBindingAttribute(Name="ServiceSoap", Namespace="http://tempuri.org/")]
public interface IServiceSoap {
/// <remarks/>
[System.Web.Services.WebMethodAttribute()]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
string HelloWorld(string i);
}
Based on this output you can deduce what is wrong/missing from your current attempt:
[WebServiceBinding(Name = "CustomWSDL"..]
should not be CustomWSDL but ServiceSoap I would suggest you change your current implementation by generating an interface and implement that interface as follows, leaving the annotation in the interface class:
// at the top of the file add
using Any.AweSome.NameSpace;
// NO MORE ATTRIBUTES HERE!
// NOTICE the IServiceSoap at the end
public class Service : System.Web.Services.WebService, IServiceSoap
{
// AND ALSO NO MORE ATTRIBUTES HERE
public string HelloWorld(string i)
{
return "foo";
}
}
If for some reason in the future the WSDL and therefore the generated interface changes, you can easily adapt your existing implementation for the new interface.
1. A namespace is not mandatory and if you don't add the option the interface is generated in the global::
namespace which you need to add in front of your interface.
Upvotes: 1
Reputation: 620
Change
[WebServiceBinding(Name = "CustomWSDL", Location = "Service1.wsdl")]
to
[WebServiceBinding(Name = "ServiceSoap", Location = "Service1.wsdl")]
Instructions from the link provided read "The Name property gives the name of the from your custom WSDL, and is needed by ASP.NET to allow it to dispatch calls onto your implementation correctly."
Upvotes: 1