Monday, June 11, 2012

Debugging WCF REST Services

Recently I was working with a WCF Rest Service based on the WCF Rest 4 template. Not far removed from the original project template, I was working towards returning data from an underlying database using entity framework models and ran into some issues. There are known issues with attempting to do what I was doing, but that is for another post. In this case, I had an action returning results in Json. The method was using the inbuilt JSON serializer decorated as:

        [WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
        public List<SampleItem> GetCollection()
        {
            return new List<SampleItem>() { new SampleItem() { Id = 1, StringValue = "Hello" } };
        }

This method is very simple and is the out of the box implementation of a default GET action in the Rest 4 Template. The decorator ResponseFormat = WebMessageFormat.Json instructs the framework to utilize the DataContractJsonSerializer class to format your function's results into Json format, ready for consumption by some caller.

Under the covers the WCF Runtime is calling your method, obtaining the results, and then formatting the results into Json and return it to the client. If you want to go deep into the details of this implementation, Carlos Figuiera has a post on his blog detailing implementation of your own formatter: http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx

Now lets throw something at it that the JsonDataContractSerializer can't handle:

    [EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="CUSTOMER")]
    [Serializable()]
    [DataContractAttribute(IsReference=true)]
    public partial class CUSTOMER : EntityObject
    {

If we change our webmethod to return type CUSTOMER like this:

        [WebGet(UriTemplate = "", ResponseFormat = WebMessageFormat.Json)]
        public List<CUSTOMER> GetCollection()
        {
            return new List<CUSTOMER>() { new CUSTOMER() { Id = 1, FirstName = "Hello" } };
        }

The DataContractAttribue(IsReference=true) decoration on the CUSTOMER class causes an error in the JsonDataContract serializer.  However, our implementation of the web service is not exposed to the error within the context of the method call being evaluated.  This is shown when we execute the method from Fiddler:


Instead of an exception encoded in the HTML on the page, the web server returns a 504 error, no response returned for this request.  How do we see what happened, why did the call fail, how do we troubleshoot this?

We need to use WCF tracing in order to see the errors occuring here.  We must enable diagnostic tracing by adding a configuration block to our Web.config:

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="All"
              propagateActivity="true" >
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\log\Traces.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

With this tracing enabled, a file is written containing a tracelog of all activity that is traceable.  The level of tracing is set with the switchValue setting.  You will need to ensure that your executing process has write permissions to the file location specified.  The tracelog can be opened with the Microsoft Service Trace Viewer and we can step through each trace item and look at the details.  This reveals the real error:


The trace log gives us the error message within WCF and we can now troubleshoot the issue from there.  For more details on WCF Tracing see MSDN at: http://msdn.microsoft.com/en-us/library/ms733025.aspx

1 comment: