Wednesday, February 29, 2012

ActionFilterAttribute and ASP.Net Web API

Similar problem to my post around IDependencyResolver,

Custom action filters for web api controllers need to be derived from  System.Web.Http.Filters.ActionFilterAttribute

.... rather than System.Web.Mvc.ActionFilterAttribute

Thursday, February 23, 2012

IDependencyResolver and ASP.Net Web API

I've started playing around with the new ASP.Net Web Api (available as part of MVC 4), and was completely stumped as to why the GetService method on IDependencyResolver was not being called when my API controller was being requested. 

Controllers that were derived from Controller, GetService was called, however any controller deriving from ApiController GetService was not being fired (resulting in the No parameterless constructor defined for this object exception being thrown). 

Little did I know, IDependencyResolver for ApiControllers is a completely different type and is 'set' on a different resolver. 

Web API: System.Web.Http.Services.IDependencyResolver

Http: System.Web.Mvc.IDependencyResolver
And for setting the resolver for ApiControllers, it should be done as GlobalConfiguration.Configuration.ServiceResolver.SetResolver()

Rather than DependencyResolver.SetResolver()

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