Generating a mock/stub WCF web service from a WSDL

When working on integration projects you sometimes need to build a stub or mock service to emulate the behavior of the targeted system in your dev environment.

Visual Studio’s Add Service Reference dialog provides an easy way for generating the client code based on the WSDL of the service that you are invoking. Unfortunately there is no such dialog to generate a server side stub / mock.

There are various approaches you can take here but using svcutil.exe has been the most pain-free for me.

Here’s an example of how to go about it:
svcutil /mc UserService.wsdl UserTypes.xsd

The /mc parameter generates a class file with all the data types defined in the .xsd as well as the interfaces for all the operations defined in the WSDL. It also provides you with a starter .config file that you’ll then need to tweak to define the port on which the service is going to be hosted.

Once you have these files create a new WCF Service Library project, add the generated class files. Then create an implementation class that implements the interfaces that is generated. To keep things simple you might want to write code for just the operations that your calling from the client side.

Now here’s a gotcha for those stubbing out a service generated by Oracle WebLogic. The Action (SOAP Action) attribute on the operations are sometimes the same for all the operations in the interface. WCF doesn’t support this since it doesn’t conform to the WSDL specifications. You’ll easily know that you’ve hit this issue when you get the following exception when trying to host your stubbed service.

System.InvalidOperationException: The operations xxx and yyy have the same action (). Every operation must have a unique action value.
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ActionDemuxer.Add(String action, DispatchOperationRuntime operation)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime..ctor(DispatchRuntime dispatch)
at System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore()
at System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)

To overcome this you can create a custom Dispatch Behavior that uses an alternate algorithm to assign incoming messages to operations. The Dispatch by Body Element WCF sample comes with a sample implementation that works well.

All you need to do is add the two class files in this zip file (it’s the same code that comes with the WCF samples) DispatchByBodyBehavior

Next open up the class generated by svcutil and add the DispatchByBodyBehavior attribute to the ServiceContractInterface. You should now be able to host the service in WCF without any issues.

public interface IDispatchedByBody
Message OperationForBodyA(Message msg);
[OperationContract(ReplyAction = "*"),
DispatchBodyElement("bodyB", "")]
Message OperationForBodyB(Message msg);
[OperationContract(Action="*", ReplyAction="*")]
Message DefaultOperation(Message msg);

Generating a mock/stub WCF web service from a WSDL

Microsoft .NET Framework 3.5 SP1 breaks Microsoft CCF (Customer Care Framework)

So your seeing this exception in your WCF client application after installing SP1 on .NET Framework 3.5

System.ServiceModel.Security.MessageSecurityException occurred Message="The HTTP request is unauthorized with client authentication scheme ‘Negotiate’. The authentication header received from the server was ‘Negotiate

As described in this bug report Microsoft classifies this as a known issue, with the bug being resolved as ‘By Design’.

Your fix is to add an identity element to the WCF endpoint like this.

    <userPrincipalName value="[email protected]" />

But the problem with CCF is that the url for some of the endpoints are read through code from a database and set through the proxy class. Now when you do this the identity from the config file does not flow through resulting in the same exception you see above.

One option is to uninstall the service pack on the client. This is not as easy as it seems because the the 3.5 service pack also updates assemblies in the 2.0 and 3.0 frameworks to their SP2 levels.

To get back to pre 3.5 SP1 you need to uninstall all the frameworks and re-install them again avoiding the 3.5 SP1. The exact steps to do this is outlined here by Microsoft engineer, Aaron Stebner.

But what if you don’t have the luxury of walking all your end-users through the uninstall? A suggested fix from Microsoft (targeting CCF) is as follows:

  1. Set up a cNAME in DNS for the servername you are using in database urls.
  2. Use setspn -a HOST/CNAME domain\apppooluser
  3. Change all the database urls to this CNAME
  4. Do an iisreset
  5. Test

For example if the database urls are http://ccfserver/…..

  1. Create a  CNAME CCFALIAS in DNS
  2. setspn -a HOST/CCFALIAS ccf\aspuser
  3. Change all database urls to ccfalias
  4. iisreset
  5. Test if you reach /urls with this alias from web servers and from clients

Be careful not to set HOST/CCFSERVER spn for aspuser. Note we are setting HOST/CCFALIAS spn which is CNAME for ccfserver in DNS. If by mistake you set host/ccfserver it can wreak havoc  for Kerberos.

Microsoft .NET Framework 3.5 SP1 breaks Microsoft CCF (Customer Care Framework)