Wednesday 30 January 2013

Single file WSDL generation in WCF

Sometimes it is convenient or even necessary (e.g. some interoperability scenarios) to have WCF generate a single WSDL file without references to external schema. Luckily, there are some 3rd party libraries available to help out: WCFExtras and WCFExtrasPlus. These are both available from NuGet. WCFExtrasPlus is based on WCFExtras and is slightly more up-to-date. Note that there seems to be 2 versions of WCFExtras as well. At the time of writing NuGet gives you WCFExtras 2.0.

Steps

My steps here are based on an IIS hosted WCF service.

Firstly, use NuGet to reference WCFExtras in the WCF host project.

Secondly, edit your Web.config file to include the following behaviour extension:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="wsdlExtensions" type="WCFExtrasPlus.Wsdl.WsdlExtensionsConfig, WCFExtrasPlus, Version=2.3.0.2, Culture=neutral, PublicKeyToken=f8633fc5451b43fc"/>
      </behaviorExtensions>
    </extensions>
    ... snip ...
</system.serviceModel>

If the version is different you can use something like Telerik JustDecompile to get the correct information to use in the type attribute of the add element.

Next create an endpoint behaviour referencing the new extensions:

<system.serviceModel>
    ... snip ...
    <behaviors>
      <endpointBehaviors>
        <behavior name="SingleFileBehaviour">
          <wsdlExtensions singleFile="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    ... snip ...
</system.serviceModel>

You now need to update your endpoint definitions to use the new behaviour, something like this:

<endpoint address="" 
binding="wsHttpBinding"
bindingNamespace="http://schemas.example.com/Example"
bindingConfiguration="wsHttpBindingConfiguration"
behaviorConfiguration="SingleFileBehaviour"
contract="Example.ServiceContracts.IExampleService" />

Fixing problems

Most execution problems seem to stem from namespacing issues. In WCFExtras there is a class called WCFExtras.Wsdl.SingleFileExporter that does the work. The first thing it does is check that the number of generated WSDL documents is not greater that 1 and this will be the case is your namespaces are wrongly defined. Here’s my checklist to avoid problems:

1. If you define service contracts in a separate interface ensure the ServiceContract attribute has a namespace.

[ServiceContract(Name = "ExampleService", "Namespace = http://schemas.example.com/Example")]

2. In the service class add a ServiceBehavior attribute also with a namespace (failure to do this will result in the service being given the http://tempuri.org namespace). The namespace must match that of the service contract.

[ServiceBehavior(Namespace = "http://schemas.example.com/Example")]

3. Check the binding namespace on the endpoint configuration in Web.config (see above).

4. Check the namespaces on any DataContract or MessageContract attributes.

5. If you are building at x86 you might want to set the project output path to be bin\ to avoid having multiple folders with different copies of the dlls. 

Wednesday 30 January 2013

Saturday 12 January 2013

ReSharper plugins folder on Windows 7

Here’s a quick reminder that applies to ReSharper 5.1 in Visual Studio 2010 on Windows 7.

ReSharper plugins on Windows 7 live in the following location:

C:\Users\<User Name Here>\AppData\Roaming\JetBrains\ReSharper\v5.1\vs10.0\Plugins\