none
How is JSON generated in WCF

    Question

  • Hi all

    I recently noticed that an object is firstly serialized to XML before it gets serialized to JSON by debugging the BeforeSendReply(ref Message reply, object correlationState). I saw that body of the Message was formatted as XML even though output is JSON.

    My question is where can I trap XML->JSON transformation?

    The reason for the question is because I'm doing validation and correction of the message in its XML format before it gets sent. It's a long story why this is done in BeforeSendReply and not as part of the business logic before any serialization but that is one of the customer's requirements.

    I'm using .NET 3.5 SP1/VS 2008

    I highly appreciate any sort of help.

    A.H.

     

    Saturday, February 19, 2011 11:38 AM

Answers

  • The documentation about the mapping between JSON and XML used by WCF can be found at http://msdn.microsoft.com/en-us/library/bb924435.aspx. It's not too complicated, but you don't need to know exactly the mapping to be able to intercept/change the JSON in BeforeSendReply - you simply need to use the Xml/Json reader/writer classes in WCF (namespace System.Runtime.Serialization.Json, created via the JsonReaderWriterFactory class) to convert between XML and JSON. The sample below shows an example of such interception.

      public class Post_4be9c7e0_67d8_4ab6_9e0f_7dd3fb31bd2a
      {
        [DataContract]
        public class MyDC
        {
          [DataMember]
          public string str = "The string";
        }
        [ServiceContract]
        public interface ITest
        {
          [WebGet(ResponseFormat = WebMessageFormat.Json)]
          MyDC GetDC(string str);
        }
        public class Service : ITest
        {
          public MyDC GetDC(string str)
          {
            return new MyDC { str = str };
          }
        }
        public class MyInspector : IDispatchMessageInspector, IEndpointBehavior
        {
          public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
          {
          }
    
          public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
          {
          }
    
          public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
          {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
          }
    
          public void Validate(ServiceEndpoint endpoint)
          {
          }
    
          public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
          {
            return null;
          }
    
          public void BeforeSendReply(ref Message reply, object correlationState)
          {
            XmlDictionaryReader originalReplyBodyReader = reply.GetReaderAtBodyContents();
            MemoryStream ms = new MemoryStream();
            XmlDictionaryWriter jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(ms);
            jsonWriter.WriteNode(originalReplyBodyReader, true);
            jsonWriter.Flush();
            string jsonReply = Encoding.UTF8.GetString(ms.ToArray());
            Console.WriteLine("Original reply: {0}", jsonReply);
    
            // change jsonReply
            jsonReply = jsonReply.Replace("foo bar", "i was modified");
    
            byte[] jsonReplyBytes = Encoding.UTF8.GetBytes(jsonReply);
            XmlDictionaryReader newReplyBodyReader = JsonReaderWriterFactory.CreateJsonReader(jsonReplyBytes, XmlDictionaryReaderQuotas.Max);
            Message newReply = Message.CreateMessage(reply.Version, null, newReplyBodyReader);
            newReply.Properties.CopyProperties(reply.Properties);
            newReply.Headers.CopyHeadersFrom(reply);
            reply = newReply;
          }
        }
        public static void Test()
        {
          string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
          ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
          ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "");
          endpoint.Behaviors.Add(new WebHttpBehavior());
          endpoint.Behaviors.Add(new MyInspector());
          host.Open();
          Console.WriteLine("Host opened");
    
          WebClient c = new WebClient();
          Console.WriteLine(c.DownloadString(baseAddress + "/GetDC?str=foo%20bar"));
    
          Console.Write("Press ENTER to close the host");
          Console.ReadLine();
          host.Close();
        }
      }
    
    
    • Marked as answer by Homer22 Monday, February 21, 2011 9:35 PM
    Saturday, February 19, 2011 10:08 PM