This is a copy from originally published in http://www.pluralsight-training.net/community/blogs/kirillg/archive/2006/06/18/28380.aspx , now link dead

How to control WSDL namespaces in WCF is a common question, so I will tackle this first. I will assume WSDL basics to be known.

WSDLs exported by WCF

WCF services by default export a tree of WSDLs, i.e. several WSDLs, imported one from another using wsdl:import construct.

This is because different WSDL elements exported by WCF service have different lifecycles: wsdl:service, wsdl:binding, wsdl:portType and schemas.  For example schemas are prescribed by vertical industry standard; contract is written once for all providers; binding is prescribed by a vertical industry standard; service is implemented by individual provider.

Each of these WSDL elements has a namespace uri associated with it. In WSDL such namespace uri is assigned by the @targetNamespace attribute on <wsdl:definitions> root that contains one of these elements. Hence there are four types of namespaces in WSDLs generated by WCF.

There is always one WSDL generated for one target namespace URI. I.e. if the namespaces uris match for wsdl:portType and wsdl:binding , these elements are bundled into the same WSDL. XML Schemas are always exported as separate documents.

Compatibility note:

wsdl:import – the construct that allows to build the WSDL tree and put wsdl:service, wsdl:binding and wsdl:portType into different namespaces – was not very well supported by early toolkits. For example if your service is required to be consumed by early versions of InfoPath or Visual Studio ATL  sproxy.exe tool, you will need to set the target namespaces for wsdl:service, wsdl:binding and wsdl:portType to the same URI.

Control WSDL Namespaces

Here is how you control target namespaces for wsdl:service, wsdl:binding , wsdl:portType and schemas. WSDL has also wsdl:message – those are bundled together with the wsdl:portType

Service namespace

This is the target namespace of the root WSDL where <wsdl:service…/> element resides containing endpoints (<wsdl:port>)

Code

Set via ServiceBehavior attribute on the service class (not the contract!)

[ServiceBehavior(Name=”MyService”, Namespace=”http://myservice.com/&#8221;,

ConfigurationName=”MyServiceConfiguration”)]

public class MyService : IMyServiceContract

default for ConfigurationName (used in config) and Name (exported name into WSDL) is the name of the class. Default for the namespace is the “http://tempuri.org”

 WSDL

<wsdl:definitions name=”MyService”  targetNamespace=”http://myservice.com/&#8221; …>

<wsdl:service name=”MyService”>

Note, we had an unfortunate bug in RC0 that caused stack overflow when you used this setting. This is fixed in later bits.

Binding namespace

This is the target namespace for the WSDL that contains wsdl:binding elements. wsdl:binding is where WCF exports bindings together with certain serialization aspects.

Config

<services>

<service name=”MyServiceConfiguration”…>

<endpoint name=”MyServiceEndpoint”

bindingNamespace=”http://myservice.com/binding&#8221;

contract=”Namespaces.MyServiceContract” …>

Code

Binding b = new CustomBinding();

b.Namespace = “http://myservice.com/binding&#8221;;

se = sh.AddServiceEndpoint(typeof(MyServiceContract), b, “http://myservice.com:8080&#8221;);

WSDL

<wsdl:definitions targetNamespace=”http://myservice.com/binding&#8221; …>

<wsdl:binding name=”MyServiceEndpoint”>

Contract namespace

This is the target namespace for the WSDL that contains wsdl:portType . ServiceContract is exported there.

Code

[ServiceContract(Name = “MyServiceContract”, Namespace = “http://gadgets.org/contract&#8221;)]

public interface MyServiceContract {}

WSDL

<wsdl:definitions targetNamespace=”http://gadgets.org/contract”&gt;

<wsdl:portType name=”MyServiceContract”>

Schema namespace

DataContract types , XmlSeriazer types and wrapper elements defined by MessageContract are being exported into schemas.  Schemas namespace are set on individual DataContract , XmlSerializer or MessageContract attributes.

Code

[DataContract(Name=”Order”, Namespace=”http://gadgets.org/types&#8221;)]

public class Order

{

[DataMember]

public string Id;

}

[MessageContract(IsWrapped = true, WrapperNamespace=”http://gadgets.org/messages&#8221;)]

public class MyServiceUpdateRequest

{

[MessageBodyMember(Namespace = “http://startrek.net/messages&#8221;)]

public Order Order;

}

WSDL

wsdl:types is always put into the same WSDL as wsdl:portType. It always contains a single xsd:schema referencing all the schemas used by that portType.

<wsdl:definitions targetNamespace=”http://gadgets.org/contract”&gt;

<wsdl:types>

<xsd:schema targetNamespace=”http://gadgets.org/contract/Imports”&gt;

<xsd:import schemaLocation=”http://myservice.com:8080/?xsd=xsd0&#8243; namespace=”http://gadgets.org/messages”/&gt;

<xsd:import schemaLocation=”http://myservice.com:8080/?xsd=xsd1&#8243;

namespace=”http://schemas.microsoft.com/2003/10/Serialization/”/&gt;

<xsd:import schemaLocation=”http://myservice.com:8080/?xsd=xsd2&#8243; namespace=”http://gadgets.org/types”/&gt;

</xsd:schema>

</wsdl:types>

<wsdl:message name=”MyServiceUpdateRequest”>

<wsdl:part name=”parameters” element=”q1:MyServiceUpdateRequest” xmlns:q1=”http://gadgets.org/messages”/&gt;

</wsdl:message>

XSD

<xs:schema elementFormDefault=”qualified” targetNamespace=”http://gadgets.org/messages&#8221; xmlns:xs=”http://www.w3.org/2001/XMLSchema&#8221; xmlns:tns=”http://gadgets.org/messages”&gt;

<xs:import schemaLocation=”http://localhost:8080/?xsd=xsd2&#8243; namespace=”http://gadgets.org/types”/&gt;

<xs:element name=”MyServiceUpdateRequest”>

<xs:complexType>

<xs:sequence>

<xs:element minOccurs=”0″ name=”Order” nillable=”true” type=”q1:Order” xmlns:q1=”http://gadgets.org/types”/&gt;

</xs:sequence>

</xs:complexType>

</xs:element>

</xs:schema>

<xs:schema elementFormDefault=”qualified” targetNamespace=”http://gadgets.org/types&#8221; xmlns:xs=”http://www.w3.org/2001/XMLSchema&#8221; xmlns:tns=”http://gadgets.org/types”&gt;

<xs:complexType name=”Order”>

<xs:sequence/>

</xs:complexType>

<xs:element name=”Order” nillable=”true” type=”tns:Order”/>

</xs:schema>

Note there is the third schema whenever you use DataContract / XmlFormatter as a formatter for your service contract. This defines several helper elements and types for certain CLR types schema representation.

Posted Jun 18 2006, 10:08 AM by kirill-gavrylyuk

Anuncios