2 minute read

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.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples"), DispatchByBodyElementBehavior] public interface IDispatchedByBody { [OperationContract(ReplyAction="*"), DispatchBodyElement("bodyA","http://tempuri.org")] Message OperationForBodyA(Message msg); [OperationContract(ReplyAction = "*"), DispatchBodyElement("bodyB", "http://tempuri.org")] Message OperationForBodyB(Message msg); [OperationContract(Action="*", ReplyAction="*")] Message DefaultOperation(Message msg); }

Tags: ,

Categories:

Updated: