Monday, July 25, 2011

Working with WCF Web Api 4.0 for Hypermedia (HATEOAS)


I wanted to enable Hypermedia - (HATEOAS) support in an existing WCF REST Service as a POC.

Steve, has a really nice post on how to go about this. Did pretty much everything mentioned. But my REST Service used POCO classes as both the EF 4.0 Model as well as DataContract, (just for the sake of faster turnaround time of the POC) and a  sample of the POCO looks like :

    [Serializable]
    [DataContract]
    [KnownType(typeof(Quote))]
    [KnownType(typeof(Address))]
    public class Customer
    {
        [Key]
        [DataMember]
        public int CustomerID { get; set; }
        [DataMember]
        public string PrimaryInsurerFirstName { get; set; }
        [DataMember]
        public string PrimaryInsurerLastName { get; set; }
        [DataMember]
        public int PrimaryInsurerAge { get; set; }
        [DataMember]
        public virtual ICollection<Address> Address { get; set; }
        [DataMember]
        public virtual ICollection<Quote> Quote { get; set; }
          }

As per Steve’sCode sample, used WCF Web API 4 and included necessary Media Type Formatters and all the associated infrastructure. Instead of typical 
RouteTable.Routes.Add(new ServiceRoute("Service", new StructureMapServiceHostFactory(), typeof(Service)));

i used RouteTable.Routes.MapServiceRoute<Service>("msi", config); (WCF Web Api extensions )

But as soon as i try to access the root of the service (http://localhost/Service) got the following exception, and it was not at all hosting the REST Service as before :





Looking at the error its clear that Serialization of Interface is not possible using XMLSerializer, hence using List<Address> solved the error. :) 

But the question is why did this error occur? Earlier i had the same Datacontract and it worked perfectly fine. So what happened when i implemented WCF Web API 4.0 .


First thing was to figure out why the service is not getting Hosted/Started properly. Ideally WCF should throw error when we try to call  Operation/Method which returns or accepts Customer, a runtime exception maybe. But this was more of Compilation Error in a way,  that for any request associated with this RestService , it was not able to start the service. 

Hence using reflector, and tracing out the entire WCF Request Processing Pipeline,

I conclude that :

          In order to Host/Start a Service, the runtime loops through all the Operations in a ServiceContract and makes sure that Service is well formed before it accepts any incoming requests. This is accomplished using  “DispatcherBuilder.BindOperations()”

          WCF Web API extends typical WCF Dispatch Behavior and uses XmlFormatter by default, while WCF 4.0 uses DataContractSerializer by default.


As per above If i comment out the Method which works with Customer Object, everything works fine and the service gets hosted as before without issues. But we just cant do that!!

Now we can solve this by :
1.  Change all the Interfaces to Concrete Implementation in the Customer POCO.

2.  Add the [DataContractFormat] attribute for the Service Contract and override the default XMLSerializer used by WCF Web API 4.0.




1 comment:

  1. Nice to see you posting on your blog. Good post!

    ReplyDelete