Showing posts with label wcf. Show all posts
Showing posts with label wcf. Show all posts

Tuesday, December 11, 2012

Svcutil and xsd imports

When wanting to generate a client proxy through svcutil, I always forget the exact syntax when I have a WSDL with xsd imports - i.e. when you get the syntax wrong (or don't have the xsd's included in the command line at all) you'll no doubt get the following errors:

Error: Schema with target namespace 'http://namespace/v1' could not be found.

Error: Cannot import wsdl:portType. 

etc...

The basic command line syntax is svcutil [location of wsdl] [location of xsds] - where if there are multple xsds, then the locations are seperated by a space, e.g:

svcutil C:\MyWsdl.wsdl C:\Folder1\Xsd1.xsd C:\Folder2\Xsd2.xsd

A lot of the wsdls I build share xsds, which are in different locations, however some share the same location - but I just need to specify the location and then specify a wildcard  *.xsd, which will result in all xsd files in the folder being picked up by svcutil - e.g.

svcutil C:\MyWsdl.wsdl C:\Folder1\*.xsd C:\Folder2\*.xsd

Tuesday, December 20, 2011

Adding Soap Headers at the client using OperationContextScope

Pretty much a reminder for me, because I always forget exactly how to add custom headers at the client end dynamically, i.e. that is not part of the service contract. 

You can achieve this using the OperationContextScope - http://msdn.microsoft.com/en-us/library/aa395196.aspx

What this also means that you can access the headers in the response message using OperationContext.Current.IncomingMessageHeaders

Sunday, November 13, 2011

Performance and loading testing WCF services with JMeter - Part 2

A while ago I wrote a brief post about JMeter and performance / load testing WCF services. This post will list the steps I'm normally go through to set up JMeter from scratch to test a service, it also includes the steps for parameterising the request payload using a CSV file. 

  • Add a new thread group to the test plan. The loop count when using a CSV data set means how many times to process the file.

  • Under the thread group add a CSV Data Set Config element (available under Config Element). Typically I have the CSV file in the same location as the .jmx file which allows you to just specify the file name. In the below example RequestPayloads.csv contains a payload per line, request is the variable name that will be used as a placeholder to insert the sample into the soap envelope. This will become clearer in the next step. 

  • Add a Loop Controller to the thread group (which is located under Logic Controller), and tick the Forever option.  This will ensure all entries in the CSV file will be processed (rather than having to configure the thread group to have the right amount of loops to completly process the file). Under the Loop Controller add a SOAP/XML-RPC Request element. Enter the appropriate endpoint (URL) and SOAP action (ensure that this is ticked). The request body is where it gets interesting. Here I have stripped out the entire body of the request (i.e. the elements between the SOAP Body element - <soapenv:Body>), and replaced it with ${request} - where request is the name of the variable we set in the CSV Data Set Config element. 

  • Each line in the the CSV file contains the appropriate xml to replace ${request} - so for example, the service that JMeter is testing is expecting an body element called DoStuffRequest, so each line in my CSV file contains:

<DoStuffRequest><anotherElement><name>john</name></anotherElement></DoStuffRequest>

<DoStuffRequest><anotherElement><name>sam</name></anotherElement></DoStuffRequest>

<DoStuffRequest><anotherElement><name>peter</name></anotherElement></DoStuffRequest>

  • To determine how successful our request are (and to prove that the the CSV file is being processed) we'll need to add some listeners. Add a View Results Tree element under the thread group. Start the test, you should see something similar to the below where the each individual request is logged. Select the Request tab and check that it's been formatted correctly using the CSV file etc. Select the Response data tab and check the it's the response that you're expecting. 

  • A couple of other listeners that I normally use is the Summary Report, and a Spline Visualizer. Summary report is good for latency metrics, where the Spline visualizer is good to determine the behaviour of a service over time (e.g. does the latency slowly increase?). 

  • To increase the load that the service is under, up the thread count in the Thread Group element, which will result in more threads processing the CSV data set.

Tuesday, October 4, 2011

WCF Routing Service and routing on content

If you're wanting to do some content based routing on the message payload using XPath (i.e. creating a XPath filter type), ensure you have routeOnHeadersOnly set to true (which is set on the routing behaviour <routing routeOnHeadersOnly="True">), if not a FilterInvalidBodyAccessException will be thrown, which has the following message:

A filter has attempted to access the body of a Message. Use a MessageBuffer instead if body filtering is required.

Setting routeOnHeadersOnly to false, the message will be buffered.

Monday, August 15, 2011

ReplyAction="*"

Recently came across the problem where the ReplyAction property in the OperationContract attribute was set to * - ReplyAction="*". wscf.blue was generating it with this, since the format SOAP action wasn't selected.

This was a problem as the operation was excluded when WCF generated the wsdl - after working out that is was ReplyAction="*" was the problem, I googled it, and found this on StackOverflow  

Monday, August 8, 2011

AppFabric’s E2EActivityId and non .Net 4.0 clients

Recently came across the scenario where the client wanted to supply the ActivityId that is to be used in AppFabric, however they weren't a .Net 4.0 client. If the client supplied the ActivityId in SOAP header request, then the framework will use this, rather than creating its own (assuming the monitoring level is End-To-End).

For .Net 4.0 clients, it's very easy to specify the value at the client end using Trace.CorrelationManager.ActivityId and ensuring that <endToEndTracing propagateActivity="true"/> is set in the client config. However endToEndTracing is new to .Net 4.0.

Initially I tried: OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("ActivityId", "http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics", activityId.ToString()))

where activityId was my guid in the client, however the ActivityId type also has a correlation id property, which is an attribute in XML. And that's the problem, I'm not aware of a method of adding a SOAP header element where you want to set a custom attribute on the element. The framework will ignore the ActivityId header if no correlation id is supplied as well.

So the option I went with was modifying the MessageContract to include the ActivityId header, so when you create the request at the client, you have the option of setting the Activity and Correlation Id. Here is the ActivityId type:

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics")]

[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics", IsNullable = false)]

public class ActivityId

{

[System.Xml.Serialization.XmlAttributeAttribute()]

public Guid CorrelationId;

[System.Xml.Serialization.XmlTextAttribute()]

public Guid Value;

}

Next, add a property of this type to the request message contract:

        [System.ServiceModel.MessageHeaderAttribute(Namespace = "http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics")]


public ActivityId ActivityId;

Done. FYI – the schema definition for the ActivityId type is available here http://msdn.microsoft.com/en-us/library/cc485806(PROT.10).aspx

Monday, June 13, 2011

soapUI and wsHttpBinding

Below are the steps required to allow soapUI to consume a WCF service which is using wsHttpBinding.

  1. By default Message Security is turned on for wsHttpBinding, which isn't supported by soapUI. So the security mode for the binding needs to be set to None:


    <bindings>
    <wsHttpBinding>
    <binding>
    <security mode="None">
    </security>
    </binding>
    </wsHttpBinding>
    </bindings>


  2. After creating the new soapUI project, the only update that is required is to select the 'Add default wsa:To' check box (as WS-Addressing is part of the wsHttpBinding). Enable/Disable WS-A addressing should already be selected, along with the appropriate SOAP action. The below options are available when you click the WS-A button, available as part of the Request window.


Monday, May 2, 2011

IErrorHandler.ProvideFault & serialization issues using XmlSerializer

I'm pretty much repeating what I posted here on the MSDN forum, but my work around seems to be doing fine so I thought it's worth noting down in case someone else comes across this problem.

If you're using the XmlSerializer rather than the default DataContractSerializer, beware that once you are out of the context of the service implementation (i.e. in a behaviour), WCF will use the DataContractSerializer. Why is this a problem?

Well, if you have implemented IErrorHandler, and are recreating the fault message that is returned to the client (e.g. using the CreateMessageFault method from the FaultException instance), the message has been serialized again. The trouble is, there is no way as far as I am aware of specifying which serializer to use (hence the reason for my post on MSDN) and WCF resorts back to its default of the DataContractSerializer.

I'm using a fault contract when creating the FaultException - i.e. FaultException and my ErrorInfo type in decorated with the appropriate Xml attribute indicating its Xml type and namespace. Eg:

[XmlType("ErrorInfo", Namespace="http://FaultContract")]
public class ErrorInfo

When this is returned back to the client, a different namespace arrives for the ErrorInfo type (rather than FaultContract), which means the client can't deserialize it. The xml namespace instead is http://schemas.datacontract.org/2004/07/ etc which is not what the client is expecting.

The reason this is happening is that the DataContractSerializer is looking for the DataContract attribute to determine what to use for the xml namespace. Since the ErrorInfo type isn't decorated with this attribute, which makes sense - I'm not using the DataContractSerializer, a default namespace is used instead.

To fix this, I have decorated the ErrorInfo type with both the XmlType attribute, and DataContract attribute:

[DataContract(Name="ErrorInfo", Namespace="http://FaultContract")]
[XmlType("ErrorInfo", Namespace="http://FaultContract")]
public class ErrorInfo

This now handle both scenarios, the Fault message created within the context of the service (where you can specify the serializer to use), and the Fault message created within a behaviour.
This took me a while to determine why this was occuring, but eventually I was able to isolate where the problem was (the behaviour). When I turned the IErrorHandler behaviour off, the client was able to deserialize the ErrorInfo type correctly (as the correct namespace was used).

Thursday, April 14, 2011

EventProvider class - make sure it's a singleton

For emitting user defined events into AppFabric's monitoring database, I'm using the WCFUserEventProvider class (which is available in the WCF 4.0 samples). Basically this class wraps the EventProvider class which is the underlying class thatprovides the ability to emit user defined events to ETW.

During some performance/load testing of a WCF service, the apppool process continued to use more and more memory, which resulted in gradual reduction in throughput. Eventually I discovered I was instantiating a new instance if the WCFUserEventProvider class (therefore creating a new instance of the EventProvider class) everytime an user defined event was logged.

Once I changed my implementation to just have a static instance of EventProvider, no more memory leakage, and the throughput remained constant.

It's the construction of the EventProvider class that is the costly part, not the actual submitting of the event.

Tuesday, December 14, 2010

Perfomance improvements using AppFabric's Auto-Start

Ron Jacobs has recently put up a post around how to leverage AppFabric's Auto-Start feature.

The post is here: http://blogs.msdn.com/b/rjacobs/archive/2010/12/09/wcf-and-appfabric-autostart.aspx

Long story short, you need to use a custom service host, and call the code which will perform the caching functionality etc within the ServiceHostFactoryBase.CreateServiceHost method (the factory method which creates the service host).

So this implies, Auto-Start creates the ServiceHost before the first call to the WCF service.

Monday, October 18, 2010

Performance and loading testing WCF services with JMeter

JMeter is great for performance and load testing WCF services. It's a free Java app available for download here - http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi.

JMeter has numours components available to create a test plan such as
  • logic controllers, which allows you define conditions when requests are sent (e.g. every 2nd thread make a request using this web request).
  • timers, define the stand down period before a thread will make another request
  • assertions, parse the response to assert that the request was successful
  • listeners, various ways to display the response data received by JMeter.
An example on how to create a web service test plan using JMeter is available here - http://jakarta.apache.org/jmeter/usermanual/build-ws-test-plan.html

EDIT: I've created a new post on how to set up with a CSV data set.

Wednesday, August 18, 2010

WCF Client performance improvement

Recently I had to try various methods to overcome performance problems due to a large schema which represented the canonical model that is to be used in our SOA layer.

The biggest bottleneck was the initial call made to the service which used the model in its service contract. WCF generates serialization code on the fly when the first service request is sent – and due to the size and structure of the schema – the amount of generated code was large – 20mb!

The reason why the structure was an issue is because the model dictates that you use a generic message wrapper type which contains an element which allows you to specify the request and response type (basically in the XSD definition, this element contains several hundred choices that it could be – so when it’s deserialized – this is of type object – with several hundred XmlElementAttribute attributes above it as it could be any of these types specified in the XmlElementAttribute attributes. A truncated example of the deserialized code is below.

[System.Xml.Serialization.XmlElementAttribute("exampleRequest1", typeof(ExampleRequest1))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse1", typeof(ExampleResponse1))]

[System.Xml.Serialization.XmlElementAttribute("exampleRequest200", typeof(ExampleRequest200))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse200", typeof(ExampleResponse200))]
… you get the idea
public object Item {…


So the generated serialization code needs to handle every possible combination that could possibly be thrown at it (so it can handle the all the possible types that are declared in the XmlElement attributes). So in other words, a lot of if statements

To overcome the cost of generating the serialization code, I used the steps described in this MSDN article - http://msdn.microsoft.com/en-us/library/aa751883.aspx. I went with option 3: “Compile the generated serialization code into your application assembly and add the XmlSerializerAssemblyAttribute to the service contract that uses the XmlSerializerFormatAttribute. Do not set the AssemblyName or CodeBase properties. The default serialization assembly is assumed to be the current assembly”.

I used the following method to generate my assembly with the serialization code:

  • Add the XmlSerializerAssembly attribute and XmlSerializerFormat to my service contract (example below).

[ServiceContract(Name = "ITest", Namespace = "http://testnamespace"), XmlSerializerFormat]
[XmlSerializerAssemblyAttribute()]
public interface ITest
{

  • Compile my assembly
  • Run svcutil against my assembly – an example of the command line: svcutil C:\Source\Project\TestServiceContract \bin\TestServiceContract.dll /t:xmlserializer.
  • Copy the generated file that was produced in step 3 to the project folder of the assembly and include the generated file in the project.
  • Rebuild the assembly.
  • Done.
In the above example TestServiceContract.dll only contains the service contract definition, not the implementation. Using this approach to resolve the serialization cost means you have to share the service contract assembly with the client and service (meaning, the client must use the ChannelFactory) – so the service definition should live in its own assembly. Sharing the assembly means both the client and the service has access to the serialization code.

One option I looked at was the ServiceKnownType attribute – which is specific to the DataContractSerializer. The positives with the DataContractSerializer is it really is fast. So even with the below

[System.Xml.Serialization.XmlElementAttribute("exampleRequest1", typeof(ExampleRequest1))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse1", typeof(ExampleResponse1))]

[System.Xml.Serialization.XmlElementAttribute("exampleRequest200", typeof(ExampleRequest200))] [System.Xml.Serialization.XmlElementAttribute("exampleResponse200", typeof(ExampleResponse200))]
you get the idea
public object Item {…


If I update my service contract to the following:
[ServiceContract(Name = "ITest", Namespace = "http://testnamespace"), DataContractFormat]
[ServiceKnownType(typeof(ExampleRequest1))]
[ServiceKnownType(typeof(ExampleResponse1))]
public interface ITest
{


The service performance is amazingly faster. In fact, even though I am still using the ChannelFactory, so the channel isn’t cached (I’ll get onto that later) – the cost of generating the channel is very cheap (I’m assuming since the amount of types that need to be reflected when creating the channel is considerably low since we have specified the types the Service is interested in by using ServiceKnownType).

However, since we build our services using the Contract First pattern – the DataContract serializer is not an option since the payload that is produced across the wire doesn’t resemble at all the original XSD – in other words you have no control on how the XML will look.

So the next bottleneck in performance was the generation of the channel. Since the ChannelFactory is being used, the channel is not cached; however if you are using a generated proxy class by svcutil, ClientBase caches its internal ChannelFactory. More details are here: http://blogs.msdn.com/b/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx.

Again an assumption on my part for why the channel generation is costly in this example: in the client improvement article by Wenlong Dong, when the channel is created, all of the required CLR types are reflected, and because of the Item property in the example and all of the possible types it could be – there are a lot of the types that are reflected (which is where I believe ServiceKnownType mention before resolves this issue since the channel generation is fast, ServiceKnownType must supress the unneeded types that are not used by the service). I needed a solution like this using the XmlSerializer. And I worked it out using the below process

  1. Generate the XmlSerializer file against the service dll with all the required XmlElement attributes (i.e. many XmlElement attributes above the Item property).
  2. Copy the generated serialization file to the service folder; add it to the project etc…
  3. Remove all the XmlElement attributes for the Item property – and add [System.Xml.Serialization.XmlElementAttribute(Order = 0)]
  4. Rebuild the project that contains the CLR schema definitions.
  5. Latency is very low.
So the key with the above is the XmlSerializer code must be generated with the expected types for the Item property (Item property decorated with multiple XmlElement attributes). Doing so means you can remove all the expected types since the XmlSerializer can still handle serializing since it’s an expected type in the serialization code (since we generated the code with the required types in step 1).

So using the assumption for why the channel generation is so costly - the cost of generating the channel is now reduced as it doesn’t have to worry about reflecting as many types (which according to Wenlong, is the biggest cost) – however serialization is successful as I said before since we generated the serialization code is aware of these types.

Wednesday, July 28, 2010

WCF and FitNesse - how to load the client's config file

Firstly, here is a great post on how to get started with FitNesse - http://schuchert.wikispaces.com/Acceptance+Testing.UsingSlimDotNetInFitNesse. This is what I used to get started. What I wanted to do was use FitNesse to perform integration tests for my web services - which means the assembly that the fitsharp runner loads, must also load the config file for that assembly (as it contains the service model configuration which is required when we create the client proxy within the loaded assembly).

Under the Create a page with necessary configuration heading in the above link, it defines how to setup your test fixtures to use the .Net test runner. The line we're interested in the one below.


!define COMMAND_PATTERN {%m -r fitSharp.Slim.Service.Runner,c:\tools\nslim\fitsharp.dll %p}

We need to update this line to include a reference to the our test project's config file. So an example would be:


!define COMMAND_PATTERN {%m -a c:\projects\someapplication\acceptancetests\acceptancetests.dll.config -r fitSharp.Slim.Service.Runner,c:\tools\nslim\fitsharp.dll %p}

This allows you to load the config where your acceptancetests.dll makes a call through a WCF proxy (i.e. acceptancetests.dll contains the type which Runner.exe will call - and this type calls the service)

Wednesday, May 12, 2010

AppFabric's exception handling pattern and the IErrorHandler behaviour

So currently the following is true:
  • AppFabric only logs unhandled exceptions from the service implementation (i.e. the exception that is handled by IErrorHandler - if that behaviour is implemented)
  • Throwing an exception in IErrorHandler.HandleError will result in w3wp.exe throwing a unhandled Microsoft .Net framework exception and the exception isn't logged again in AppFabric. Regardless of this, the fault (constructed in IErrorHandler.ProvideFault) is still successfully provided to the client as this method is called before HandleError.
  • AppFabric does log the inner exception if provided.