ReBuildAll Blog
Thoughts (mostly) on .NET development

WSDLMerge updated   (Web services)   
I wrote about a tool I made in this blog before (see the original article here). The tool called WSDLMerge can merge WSDL documents and XSD documents that it references into a single file.

I just updated this tool. The updated source code and now also precompiled binary version is available from the project's site.

I ran into some problems with some WSDL files, which made me update the tool. Some people also wanted a binary version instead of just source, so that is now also uploaded.

I had a WSDL file that referenced different XSD files, but with the same targetNamespace. This made WSDLMerge ignore the second import.

Also, the include statements are now getting parsed as part of the XSD files. The included schema is inlined into the schema that invokes the include.

WCF service namespaces (getting rid of tempuri.org)   (Web services)   
Creating WCF servics is really very easy with Visual Studio. All the basic code is generated for you when you add a service to an existing web project or start a new WCF Service Application project. Modifying the "contract" is pretty straightforward too: you just modify the interface for your service, and then the actual implementation. WCF will do everything for you, generate the WSDL, etc. All your clients need to do is download/refresh the WSDL and they are able to use your service. Easy, right?

But when you look at the WSDL that gets generated for your service, you will notice that there are a lot of references to an XML namespace http://tempuri.org. Lets just say if you publish such a service or develope a solution for yor client who will then publish the service with this namespace to their customers - it is just very unprofessional.

Changing the namespace, however, can be more trickier than you thought.

The following article will show you how to deal with namespace changes in WCF. This will work in both WCF 3 / 3.5 and WCF 4. There are some minor changes, for example, with the configuration, but the same things apply.


Quick reference

For those who are impatient to see how this is done, here is a quick reference of the changes we will apply to a simple WCF service to change the namespace. There are four places to change:

- Apply the Namespace property to the ServiceContractAttribute on the service contract interface
- Apply the Namespace property to the ServiceBehaviorAttribute on the class that implements the service
- Apply the Namespace property to the DataContractAttribute on every class that is involved with the service (parameters, return values)
- Change the namespace for the binding, either on the binding class or in the .config file

And now in detail.


The contract namespace

The first step of course is changing the contract namespace. This is pretty easy, and probably something everyone tries first. It is however, not enough. But lets get started anyway.

Assume I have just generated a new WCF service application. I renamed the default Service1 name to RebuildallService, so I have an interface called IRebuildallService and a class called RebuildallService. The .svc file is called RebuildallService.svc. A little too many service words, but I will leave it that way for now :)

The service contract looks like this:

    [ServiceContract]
    public interface IRebuildallService
    {

The ServiceContractAttribute accepts a property called Namespace, and you might have guessed we are going to use that. This will change the namespace on the contract.

So the code now looks lke this:

    [ServiceContract ( Namespace = "http://schemas.umbraworks.net/rebuildall" )]
    public interface IRebuildallService
    {

If I compile and check the WSDL, I will get certain parts with the tempuri.org namespace and others parts with my new namespace. In practice, the wsdl:definitions XML elements will be in the new namespace, but all data and other parts of the WSDL will stil exist in tempuri.org.

A note on namespaces: namespaces ARE NOT URLS!. They might look like one, like in my examples, but there is no such subdomain as schemas actually in existence. Namespaces follow the URI format, but are not actual addresses. They can be used to identify schemas, because usually a company owns a domain name. Thus using that as the schema namespace creates something unique. And that is exactly what namespaces should be: unique.


The service namespace

So, what else do we need to change? The next step is of course the service implementation itself. Currently, it looks like this:

    public class RebuildallService : IRebuildallService
    {

What we want to do is apply the ServiceBehaviorAttribute, which also has a Namespace property.

    [ServiceBehavior(Namespace = "http://schemas.umbraworks.net/rebuildall")]
    public class RebuildallService : IRebuildallService
    {

Looking at the WSDL after this change you will notice that a big part is now in the desired namespace and there are two things left in the tempuri.org namespace: the data types we use and the wsdl:binding element.


The data types

Lets change the namespace for the data types, since it is a rather straightforward change. Currently the example service (the default implementation that Visual Studio provides) contains the following definition for a data type:

    [DataContract]
    public class CompositeType
    {

You might have guessed, we will add the Namespace attribute to the DataContractAttribute.

    [DataContract(Namespace = "http://schemas.umbraworks.net/rebuildall")]
    public class CompositeType
    {

This will change our data types to exist in our new namespace.

If your data is more complex and you have several classes, be sure to apply the Namespace property along with the DataContract attribute to every one of them. Do this also for your enums, otherwise they will exist in the tempuri.org namespace!


The binding

The final element is changing the binding namespace. If you use code-only WCF, you would specify this in the constructor of the Binding class, but since most of the time you will use config files to specify the binding, I will show how to proceed in this latter case.

In WCF4 you have default bindings, so your web.config file will be pretty empty. In WCF3/3.5 the config file will contain the binding by default, so there you can change it more easily.

Anyhow, what you need to do is add the bindingNamespace element to the endpoint element of the service element. Like so:

    <services>
      <service name="WcfNamespaces.RebuildallService">
        <endpoint address="RebuildallService.svc" bindingNamespace="http://schemas.umbraworks.net/rebuildall"
                  binding="basicHttpBinding" contract="WcfNamespaces.IRebuildallService" />
      </service>
    </services>

For WCF4, I would need to add this entire section into my config file. For WCF3/3.5 only the new attribute needs to be added. The WcfNamespaces, in case you wonder, is the .NET namespace my test project was in.

And with this final change, the WSDL will not be in our own custom namespace, and http://tempuri.org is gone for good :)

Some thoughts about namespaces

In the example above, I placed all services, descriptions, bindings and data types in the same namespace. This is of course not needed, you can specify different namespaces for everything, and WCF will handle this. The WSDL will be more fragmented: WCF generates a separate document for different namespaced entities. But there is nothing technically preventing you from doing this.