
{"id":2103,"date":"2015-09-17T17:47:30","date_gmt":"2015-09-17T21:47:30","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=1703"},"modified":"2015-09-17T17:47:30","modified_gmt":"2015-09-17T21:47:30","slug":"cannot-return-jtoken-from-wcf-web-service","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=2103","title":{"rendered":"Cannot return JToken from WCF Web Service"},"content":{"rendered":"<p>This blog entry is mostly for documentation purposes, so I don&#8217;t forget what happened.<\/p>\n<div style=\"background-color:white;border: solid 1px; padding: 5px\"><b>TL;DR<\/b>: WCF&#8217;s <code>DataContractJsonSerializer<\/code> cannot deal with <code>JToken<\/code> or <code>JObject<\/code>. If you attempt to include those in your data contract, you will get <code>InvalidDataContractException<\/code> at runtime, and zero bytes response.<\/div>\n<p>I have a WCF web service written in C# that returns an object with a bunch of strings, along the lines of<\/p>\n<pre><code>[DataContract]\nclass MyData\n{\n    [DataMember] public string FirstName { get; set; }\n    [DataMember] public string LastName { get; set; }\n    [DataMember] public string Addresses { get; set; }\n}<\/code><\/pre>\n<p>Internally it is represented as a name-value bag in some storage. Over time I ended up storing structured data in some values, e.g. <code>Addresses<\/code> is an array of records encoded in JSON, along the lines of<\/p>\n<p><code>[{\"Where\":\"1 Main St.\",\"From\":\"2014-02-01\", \"To\":\"2015-07-11\"},{\"Where\":\"Under a bridge\",\"From\":\"2015-07-12\"}]<\/code><\/p>\n<p>The actual data is not addresses, but the idea is the same.<\/p>\n<p>I use <code>[WebInvoke(..., ResponseFormat=WebMessageFormat.Json]<\/code> on the service method to make WCF serialize the response as JSON. Left as is, it comes out on the wire like this:<\/p>\n<p><code>{\"FirstName\":\"Vasya\",\"LastName\":\"Pupkin\",\"Addresses\":\"[{\\\"Where\\\":\\\"1 Main St.\\\", \\\"From\\\":\\\"2014-02-01\\\",\\\"To\\\":\\\"2015-07-11\\\"},{\\\"Where\\\":\\\"Under a bridge\\\",\\\"From\\\":\\\"2015-07-12\\\"}]\"}<\/code><\/p>\n<p>Note all the escaped quotation marks. I wanted it to come out as a normal JSON sub-object, like so:<\/p>\n<p><code>{\"FirstName\":\"Vasya\",\"LastName\":\"Pupkin\",\"Addresses\":[{\"Where\":\"1 Main St.\",\"From\":\"2014-02-01\",<br \/>\n\"To\":\"2015-07-11\"},{\"Where\":\"Under a bridge\",\"From\":\"2015-07-12\"}]}<\/code><\/p>\n<p>So, I changed the data contract to include <code>JToken<\/code> and assigned addresses:<\/p>\n<pre><code>[DataContract]\nclass MyData\n{\n    [DataMember] public string FirstName { get; set; }\n    [DataMember] public string LastName { get; set; }\n    [DataMember] public JToken Addresses { get; set; }\n}<\/code><\/pre>\n<p>This compiled and passed tests, but when put to actual use it resulted in an exception during response generation:<\/p>\n<p><code>System.Runtime.Serialization.InvalidDataContractException: Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself.<\/code><\/p>\n<p>The client did not get any response at all. It looks like I am not the first one to encounter this problem:<\/p>\n<p><a href=\"http:\/\/stackoverflow.com\/questions\/12916865\/how-to-have-a-wcf-datacontract-with-a-json-dynamic-member\">http:\/\/stackoverflow.com\/questions\/12916865\/how-to-have-a-wcf-datacontract-with-a-json-dynamic-member<\/a><br \/>\n<a href=\"http:\/\/stackoverflow.com\/questions\/30759607\/self-hosted-wcf-rest-service-error-type-newtonsoft-json-linq-jtoken-is-a-rec\">http:\/\/stackoverflow.com\/questions\/30759607\/self-hosted-wcf-rest-service-error-type-newtonsoft-json-linq-jtoken-is-a-rec<\/a><\/p>\n<p>So, no go. I now have a choice between switching to NewtonSoft serializer or explicitly defining the content type. Switching to NewtonSoft is desirable, but risky for a big web service already in production. Creating a class for <code>Address<\/code> is no big deal, but it means that on every read I will be deserializing JSON from the internal storage, only to have it serialized again by WCF. Looks like a lot of unnecessary monkey business and possible performance hit (I know, it&#8217;s premature optimization, but still).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This blog entry is mostly for documentation purposes, so I don&#8217;t forget what happened. TL;DR: WCF&#8217;s DataContractJsonSerializer cannot deal with JToken or JObject. If you attempt to include those in <a href=\"https:\/\/ikriv.com\/blog\/?p=2103\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[3,8],"tags":[],"class_list":["entry","author-ikriv","post-2103","post","type-post","status-publish","format-standard","category-dotnet","category-cs"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2103"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/2103\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}