Use Fiddler to Test RESTful WCF Services

Fiddler is one of the common tools for .NET developers especially for ASP.NET developers who try to debug their HTTP requests and responses.

But Fiddler is a more general product for debugging any HTTP request and response. So this great tool can be used for testing any hosted site or service. Here I want to show you how you can use Fiddler to test RESTful Windows Communication Foundation services in .NET 3.5 (or 3.0).

I don't want to step in details of creating a RESTful WCF service. .NET 3.5 introduces WebHttpBinding as a new binding to build RESTful services in WCF and this has made the process pretty easy and fast.

First let me develop a very simple RESTful service with WCF 3.5. This service has two methods. One is a simple function that returns a string value based on an HTTP GET verb and the other is a function that returns a string based on HTTP PUT verb and the data that is passed to it.

Implement the Service

This sample service has two methods (GetData and PutData) that get a name via the URI and use it in their internal processing. The second method also gets some details about the contact via the data that is passed to it via PUT verb. The interface for the service is pretty simple: two methods for GET and PUT verbs and a data contract class. Here is the code for the interface:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using System.ServiceModel.Web;

 

namespace FiddlerWCFSample

{

    [ServiceContract(Namespace = "api.nayyeri.net")]

    public interface IRESTService

    {

        [OperationContract]

        [WebGet(UriTemplate = "api/{name}/",

            ResponseFormat = WebMessageFormat.Xml,

            BodyStyle = WebMessageBodyStyle.Bare,

            RequestFormat = WebMessageFormat.Xml)]

        string GetData(string name);

 

        [OperationContract]

        [WebInvoke(Method = "PUT",

            UriTemplate = "api/{name}/",

            ResponseFormat = WebMessageFormat.Xml,

            BodyStyle = WebMessageBodyStyle.Bare,

            RequestFormat = WebMessageFormat.Xml)]

        string PutData(string name, ContactDetails details);

    }

 

    [DataContract(Name = "ContactDetails", Namespace = "")]

    public class ContactDetails

    {

        [DataMember(IsRequired = true)]

        public string SiteUrl { get; set; }

    }

}

The service implementation is even simpler than this:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

 

namespace FiddlerWCFSample

{

    public class RESTService : IRESTService

    {

        #region IRESTService Members

 

        public string GetData(string name)

        {

            return string.Format("Hello {0}!", name);

        }

 

        public string PutData(string name, ContactDetails details)

        {

            return string.Format("Hello {0} ({1})!", name, details.SiteUrl);

        }

 

        #endregion

    }

}

And there is nothing else for the service implementation!

IIS 7.0 Module to Rewrite Requests

Without a good HTTP rewriting mechanism the RESTful service doesn't look good so I also write an IIS 7.0 module to rewrite all incoming requests to the service file.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Web;

 

namespace FiddlerWCFSample

{

    public class RewriterModule : IHttpModule

    {

        #region IHttpModule Members

 

        void IHttpModule.Dispose()

        {

            return;

        }

 

        void IHttpModule.Init(HttpApplication context)

        {

            context.BeginRequest += new EventHandler(context_BeginRequest);

        }

 

        void context_BeginRequest(object sender, EventArgs e)

        {

            HttpContext context = ((HttpApplication)sender).Context;

 

            string requestPath = context.Request.Path.ToLower();

 

            if (requestPath.Contains(".svc"))

                return;

 

            context.Request.Headers.Add("X-REWRITE-URL", context.Request.Url.AbsolutePath);

            context.RewritePath("~/service.svc", requestPath.Replace("/sampleservice", ""),

                context.Request.QueryString.ToString(), false);

        }

 

        #endregion

    }

}

Host the Service

The last step before testing the service, as you know, is configuring and hosting the service. Configuring a RESTful WCF service requires the usage of WebHttpBinding. Below is the basic configuration that I used for my service. Note that you can also self-host the service but IIS hosting is a more common case for RESTful services on production.

<?xml version="1.0"?>

<configuration>

  <system.serviceModel>

    <services>

      <service name="FiddlerWCFSample.RESTService"

              behaviorConfiguration="MetadataBehavior">

        <endpoint address="" behaviorConfiguration="WebBehavior"

                binding="webHttpBinding"

                contract="FiddlerWCFSample.IRESTService"/>

        <endpoint address="mex"

                  binding="mexHttpBinding"

                  contract="IMetadataExchange"/>

      </service>

    </services>

 

    <behaviors>

      <endpointBehaviors>

        <behavior name="WebBehavior">

          <webHttp />

        </behavior>

      </endpointBehaviors>

      <serviceBehaviors>

        <behavior name="MetadataBehavior">

          <serviceMetadata httpGetEnabled="true" httpGetUrl="" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

  <system.webServer>

    <modules runAllManagedModulesForAllRequests="true">

      <add name="UrlRewriter" type="FiddlerWCFSample.RewriterModule, FiddlerWCFSample" />

    </modules>

  </system.webServer>

</configuration>

Test the Service

Alright! Now we're on the point that this post is trying to cover. Testing a RESTful WCF service, especially for some HTTP verbs like PUT, requires some extra effort to be able to build your request data and PUT them on the server. There are different ways to do this and one of them is writing your own code to use an HTTP client to put the data on the server.

For an HTTP GET verb method, test would be easy. You enter the URL in your browser and test the method as I do for my GetData method.

Test the Service  

But what about a PUT verb method? There is an easy and fast way to do this via Fiddler that I'm going to show you.

To test the GetData method with Fiddler, I can use the Request Builder tab to build a request to the appropriate URL with GET method and then execute my request.

Fiddler - Build a GET request

After executing the request, I get a 200 success status from the server. If I navigate to Session Inspector tab and open TextView then I'm able to see the XML response from the server.

Fiddler - Test the response for GET request

But for a PUT verb method, like PutData in my example, you need to do some more work when building your request. After choosing the correct URL for your request in Request Builder tab, you need to choose the PUT verb method from the left drop down list as well.

The next step is to write the request body by hand. In my example, I have to write the XML code text by hand. The last point, which is very important, is to set the Content-Type request header of your request to the XML MIME type which is "application/xml". Note that this is for my example with XML requests but you would need to use another text type for Json requests.

Fiddler - Build a PUT request

After executing this request I get the response that I expected to get.

Fiddler - Test the response for PUT request

That's it! I found that using Fiddler is one of the best and even the best way to test a RESTful WCF service quickly and easily.

I uploaded the source code sample for this post here so you can download the code and test it for your own.

[advertisement] Axosoft OnTime 2008 is four developer tools in one: bug tracking, project wiki, feature management, and help desk. It manages your development process so developers can focus on coding. Installed or Hosted – Free Single-user license -- Free 30-day team trial.

7 Comments : 04.23.08

Feedbacks

Pingback from Dew Drop - April 24, 2008 | Alvin Ashcraft's Morning Dew

I found this great article that tells you how to do testing for WCF services exposed as web services

 avatar
#3
Bill
12.17.2008 @ 8:11 AM

Great example. Very clear and understandable. Outstanding

 avatar
#4
My Best Blog Posts in 2008
12.31.2008 @ 1:40 PM

In the past 3.5 years of blogging, I haven’t had such best pick up collections in the end of the year, but now that everybody is writing one, why shouldn’t I write my own?! Collecting this list, I could realize some interesting facts that completely changed

 avatar
#5
Anthony
01.19.2009 @ 3:07 PM

I have been implementing a WCF Restful application. All the GET methods works great, but when testing the "POST" request I'm getting the following error:

The server encountered an error processing the request. The exception message is 'Unable to deserialize XML body with root name 'User' and root namespace '' (for operation 'PostUser' and contract ('IUserManager', 'http://tempuri.org/')) using DataContractSerializer.

This is my service method I'm calling:

[OperationContract]

[WebInvoke(Method="POST", UriTemplate = "users", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml)]

string PostUser(User newUser);

Here's my DataContract for the "User" object:

[DataContract(Name = "User", Namespace = "WCFPlusRest")]

[Serializable]

public class User

{

[DataMember(IsRequired = true)]

public string Username { get; set; }

[DataMember(IsRequired = true)]

public string FirstName { get; set; }

[DataMember(IsRequired = true)]

public string LastName { get; set; }

[DataMember(IsRequired = true)]

public string Role { get; set; }

[DataMember(IsRequired = true)]

public List<string> Hobbies { get; set; }

}

And when doing the request using fiddler:

POST /WcfPlusRest/UserManager/rest/users HTTP/1.1

User-Agent: Fiddler

Host: localhost:8731

Content-Type: application/xml

Content-Length: 245

<User>

<Username>rperez</username>

<FirstName>Robert</firstName>

<LastName>Perez</lastName>

<Role>Designer</role>

<Hobbies>

<Hobbie>Party</hobbie>

<Hobbie>travel</hobbie>

<Hobbie>Sing</hobbie>

</Hobbies>

</User>

I have been looking for a solution for a couple of days but I can't find any answer. Do you have any idea of what I might be doing wrong? The problem seems to be when trying to parse and serialize the XML sent into an "User" object, but it should be working according to your post.

Thanks

-aB

 avatar
#6
Robert Edwards
02.04.2009 @ 8:42 PM

Anthony -

It might have something to do with your properties. Give them an explicit name [DataMember(Name="UserName")]

That helped me.

 avatar
#7
Robert Edwards
02.04.2009 @ 9:26 PM

Also, your xml should have the namespace you're using:

<User xmlns="WCFPlusRest">

...

</User>

Leave a Comment