8.4 Interfaces in Different Namespaces
Here's an interesting twist on the above scenario: What if we placed the bindings in different namespaces, for example, IQuoteMgmt in a namespace called http://LearnXmlWS.com/QuoteMgmt and IOrderMgmt in another namespace called http://LearnXmlWS.com/OrderMgmt? Listing 8.11 shows the code for SupplierIface3 that has two bindings, each in its own namespace.
Listing 8.11 A Web service with two bindings in two different namespaces (VBWSBook\Chapter8\Supplier3.asmx.vb)
<WebServiceBinding( _ Name:="IOrderMgmt", _ [Namespace]:="http://LearnXmlWS.com/OrderMgmt"), _ WebServiceBinding( _ Name:="IQuoteMgmt", _ [Namespace]:="http://LearnXmlWS.com/QuoteMgmt"), _ WebService([Namespace]:="http://LearnXmlWS.com/Supplier")> _ Public Class SupplierIface3 Inherits System.Web.Services.WebService <WebMethod( _ Description:="Places the order then returns the new order id"), _ SoapDocumentMethod(Binding:="IOrderMgmt")> _ Public Function PlaceOrder(ByVal newOrder As Order) _ As String 'returns a new order id End Function <WebMethod(), _ SoapDocumentMethod(Binding:="IOrderMgmt")> _ Public Function CheckStatus(ByVal OrderId As String) _ As OrderInfo 'returns an orderinfo structure End Function <WebMethod(), _ SoapDocumentMethod(Binding:="IQuoteMgmt")> _ Public Function GetPriceQuote(ByVal newOrder As Order) _ As QuoteInfo() 'returns an orderinfo structure End Function End Class
The result is that each binding (interface) is defined in its own WSDL document. This is because bindings belong to the WSDL document's targetNamespace and you can have one targetNamepace only per WSDL document. These separate WSDL documents are imported into the main WSDL document using the <import> element as shown in Listing 8.12.
Listing 8.12 Each binding is defined in a separate WSDL document that is then imported into the main WSDL document using <import>.
<definitions targetNamespace="http://LearnXmlWS.com/Supplier" ...> <import namespace="http://LearnXmlWS.com/QuoteMgmt" location="http://vbwsserver/vbwsbook/Chapter8/ supplier3.asmx?schema=schema1"/> <import namespace="http://LearnXmlWS.com/OrderMgmt" location="http://vbwsserver/vbwsbook/Chapter8/ supplier3.asmx?schema=schema2" /> <import namespace="http://LearnXmlWS.com/QuoteMgmt" location="http://vbwsserver/vbwsbook/Chapter8/_ supplier3.asmx?wsdl=wsdl1" /> <import namespace="http://LearnXmlWS.com/OrderMgmt" location="http://vbwsserver/vbwsbook/Chapter8/_ supplier3.asmx?wsdl=wsdl2" /> <types /> <service name="SupplierIface3"> <port name="IQuoteMgmt" binding="i2:IQuoteMgmt"> <soap:address location="http://vbwsserver/vbwsbook/Chapter8/_ supplier3.asmx" /> </port> <port name="IOrderMgmt" binding="i1:IOrderMgmt"> <soap:address location= "http://vbwsserver/vbwsbook/Chapter8/supplier3.asmx" /> </port> </service> </definitions>
To access the IQuoteMgmt binding definition, you navigate to the .asmx file with a query string of wsdl=wsdl1 (for example, supplier3.asmx?wsdl=wsdl1). Similarly, IOrderMgmt definition is at supplier3.asmx?wsdl=wsdl2. Similarly, types used by the methods of each interface, for example, Order and QuoteInfo, are defined in the schemas located at supplier3.asmx?schema= schema1 and supplier3.asmx?schema=schema2. In this case, the interfaces, type definitions, and implementation definition (the service) are all separated in different locations. For complex Web services that implement many interfaces, separating interface definitions makes them easier to maintain and be independent of one another.
Running wsdl.exe with /server on the WSDL in Listing 8.12 generates two separate classes: one for each binding, as in the previous case where both bindings belonged to the same class. The difference in this case is that class has a WebServiceBinding attribute on it with its Namespace property set to http://LearnXmlWS.com/QuoteMgmt for IQuoteMgmt and http:// LearnXmlWS.com/OrderMgmt for IOrderMgmt.
When you run wsdl.exe on the WSDL document in Listing 8.12, it needs to get the other WSDL documents referenced by <import> elements. This works fine as long as you tell wsdl.exe to access the main WSDL document using http, (for example
If however, you give wsdl.exe a file path instead of a URL, it will not be able to retrieve the imported WSDL documents. So if you save the WSDL document in Listing 8.12 to disk and issue the following command:
you will get an error about undefined types because wsdl.exe cannot read the schema or the WSDL documents referenced by <import>s.