smilu
smilu

Reputation: 899

Calling custom WSDL in asp.net web service(ASMX)

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.

1) C# code behind

[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";
    }
}

The location was set as service1.wsdl. Then i changed to just check it.

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>

According to the author the 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

Answers (2)

rene
rene

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:

  • The [WebServiceBinding(Name = "CustomWSDL"..] should not be CustomWSDL but ServiceSoap
  • The SoapDocumentMethod needs a complete different set of attributes.

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

SKYWALKR
SKYWALKR

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

Related Questions