Compartilhar via


How to eliminate tempuri.org from your service WSDL

tempuri.org is the default namespace applied to WCF Services and Workflow Services.  You can and should specify your service namespace.

It is recommended that you explicitly specify a name and namespace for the service contract, and an action for each operation to avoid using " https://tempuri.org" and to prevent interface and method names from being exposed in the service’s contract
MSDN Library - Service Contract Versioning

Where is tempuri.org in the WSDL?

If you browse the service WSDL you will see tempuri.org all over the place.  Here is a default WCF service WSDL.

 <wsdl:definitions name="Service1" targetNamespace="https://tempuri.org/" xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/" xmlns:soap="https://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="https://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="https://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:soap12="https://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="https://tempuri.org/" xmlns:wsa="https://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="https://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="https://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="https://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="https://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsa10="https://www.w3.org/2005/08/addressing" xmlns:wsx="https://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsam="https://www.w3.org/2007/05/addressing/metadata">
   <wsdl:types>
     <xsd:schema targetNamespace="https://tempuri.org/Imports">
       <xsd:import schemaLocation="https://localhost:63720/Service1.svc?xsd=xsd0" namespace="https://tempuri.org/"/>
     </xsd:schema>
   </wsdl:types>
   <wsdl:message name="IService1_DoWork_InputMessage">
     <wsdl:part name="parameters" element="tns:DoWork"/>
   </wsdl:message>
   <wsdl:message name="IService1_DoWork_OutputMessage">
     <wsdl:part name="parameters" element="tns:DoWorkResponse"/>
   </wsdl:message>
   <wsdl:portType name="IService1">
     <wsdl:operation name="DoWork">
       <wsdl:input wsaw:Action="https://tempuri.org/IService1/DoWork" message="tns:IService1_DoWork_InputMessage"/>
       <wsdl:output wsaw:Action="https://tempuri.org/IService1/DoWorkResponse" message="tns:IService1_DoWork_OutputMessage"/>
     </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="BasicHttpBinding_IService1" type="tns:IService1">
     <soap:binding transport="https://schemas.xmlsoap.org/soap/http"/>
     <wsdl:operation name="DoWork">
       <soap:operation soapAction="https://tempuri.org/IService1/DoWork" style="document"/>
       <wsdl:input>
         <soap:body use="literal"/>
       </wsdl:input>
       <wsdl:output>
         <soap:body use="literal"/>
       </wsdl:output>
     </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="Service1">
     <wsdl:port name="BasicHttpBinding_IService1" binding="tns:BasicHttpBinding_IService1">
       <soap:address location="https://localhost:63720/Service1.svc"/>
     </wsdl:port>
   </wsdl:service>
 </wsdl:definitions>

Tip: Use a constant to ensure consistency

I like to use a constant to provide a consistent namespace across my services

 public class Constants
 {
     // Ensures consistency in the namespace declarations across services
     public const string Namespace = "https://contoso.com/services/";
 }

How to eliminate tempuri.org from WCF Services WSDL

Step 1: Declare a namespace on your service contract

The namespace can be anything.  People typically use a URI of some form but it does not have to point to an actual web page.  Often people will use a version identifier in the namsepace but there are no rules about what you should do.

 // Eliminate tempuri.org from the contract
 // If you don't want to us a constant, put the URI here
 // [ServiceContract(Namespace = "https://contoso.com/services")]
 [ServiceContract(Namespace = Constants.Namespace)]
 public interface IService1
 {
     [OperationContract]
     void DoWork();
 }

Step 2: Declare a namespace on your service

The service namespace is added with a ServiceBehavior attribute.  Using the constant ensures that the namespace is the same for the contract and the service.

 // If you don't want to us a constant, put the URI here
 // [ServiceBehavior(Namespace = "https://contoso.com/services")]
 [ServiceBehavior(Namespace = Constants.Namespace)]
 public class Service1 : IService1
 {
     public void DoWork()
     {
     }
 }

Step 3: Set the binding namespace

 <system.serviceModel>
     <services>
       <service name="EliminateTempUri.Service1">
         <!-- Use a bindingNamespace to eliminate tempuri.org -->
         <endpoint address=""
                   binding ="basicHttpBinding" 
                   bindingNamespace="https://contoso.com/services"
                   contract="EliminateTempUri.IService1"
         />
       </service>
     </services>
     <behaviors>
       <serviceBehaviors>
         <behavior name="">
           <serviceMetadata httpGetEnabled="true" />
           <serviceDebug includeExceptionDetailInFaults="false" />
         </behavior>
       </serviceBehaviors>
     </behaviors>
     <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
   </system.serviceModel>

 

How to eliminate tempuri.org from Workflow Services WSDL

For workflow services the process is slightly different.  Workflow services do not have a contract (it is inferred from the activities) so here is the process.

Step 1: Declare a namespace on each receive activity

I wish it were possible to use a constant here but sadly it is not.  For each receive activity you must declare the namespace and contract name using a special syntax of {namespace}IContractName.  In this example I’ve set the ServiceContractName property to {https://contoso.com/services}IService

image

Step 2: Declare a namespace for the Workflow Service

  1. Open the Workflow Service and click in the designer outside of an activity.  This will allow you to set the properties of the service itself. 
  2. Set the Name property to use the same namespace as you see below.

image

Step 3: Set the binding namespace

Many people do not declare a <service> tag for their Workflow Services but if you want to eliminate tempuri.org you will need to declare it.

For a Workflow Service the A,B,Cs of WCF configuration are a little different.

  • Service Name – use the ConfigurationName property from the WorkflowService
  • A – Address – should be blank when hosted in IIS / AppFabric
  • B – Binding – use the binding of your choice.  Typically basicHttpBinding
  • C – Contract – use the interface name from the ServiceContractName property (without the namespace)
 <!-- For Workflow Services name is the ConfigurationName property -->
 <service name="Service2">
   <!-- contract must match the receive activity -->
   <!-- Use a bindingNamespace to eliminate tempuri.org -->
   <endpoint address=""
             binding ="basicHttpBinding"
             bindingNamespace="https://contoso.com/services"
             contract="IService"
   />
 </service>

Test It Out

  1. Right click on your WCF or Workflow Service in Visual Studio and select View In Browser.
  2. Click on the link to view the WSDL
  3. Search in the browser for tempuri.org – there should be no matches

image

Happy Coding!

Ron Jacobs

https://blogs.msdn.com/rjacobs

Twitter: @ronljacobs https://twitter.com/ronljacobs