none
WCF REST JSON requestformat for complex type

    Question

  • Hi, Can someone tell me how to use a WebGet with a complex type in the json request?

    I've found quite allot of posts which explain this with a POST. Since we have a script which is being added to websites of our customers we need to use a GET.

    [WebGet(UriTemplate="Send?collection={collection}", RequestFormat=WebMessageFormat.Json)]
    public void Send(FaqOptionCollection collection)
    
    

    Tuesday, December 14, 2010 12:15 PM

Answers

  • You can change the QueryStringConverter used by the WebHttpBehavior to accept more than just "primitive" types. There's a public built-in converter in WCF, the JsonQueryStringConverter, which uses the DataContractJsonSerializer to deserialize non-primitive types. The example below shows how to replace the converter used in the behavior.

      public class Post_605526ee_2181_41a2_8d0e_ced1f5e2b825
      {
        public class FaqOptionCollection : List<FaqOption>
        {
          public override string ToString()
          {
            StringBuilder sb = new StringBuilder();
            sb.Append('[');
            for (int i = 0; i < this.Count; i++)
            {
              if (i > 0) sb.Append(',');
              sb.Append(this[i].ToString());
            }
            sb.Append(']');
            return sb.ToString();
          }
        }
        [DataContract]
        public class FaqOption
        {
          [DataMember]
          public string topic;
          [DataMember]
          public string keyword;
          public override string ToString()
          {
            return string.Format("FaqOption[topic={0},keyword={1}]", topic, keyword);
          }
        }
        [ServiceContract]
        public interface ITest
        {
          [WebGet(UriTemplate = "Send?collection={collection}", RequestFormat = WebMessageFormat.Json)]
          void Send(FaqOptionCollection collection);
        }
        public class Service : ITest
        {
          public void Send(FaqOptionCollection collection)
          {
            Console.WriteLine("Input: {0}", collection);
          }
        }
        public class MyWebHttpBehavior : WebHttpBehavior
        {
          protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
          {
            return new JsonQueryStringConverter();
          }
        }
        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(), "");
          WebHttpBehavior behavior = new MyWebHttpBehavior();
          endpoint.Behaviors.Add(behavior);
          host.Open();
          Console.WriteLine("Host opened");
    
          Util.SendRequest(baseAddress + "/Send?collection=[{\"topic\":\"foo\",\"keyword\":\"foo2\"},{\"topic\":\"bar\",\"keyword\":\"bar2\"}]", "GET", null, null);
          //ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
          //ITest proxy = factory.CreateChannel();
    
          //Console.WriteLine(proxy.EchoString("Hello"));
          //Console.WriteLine(proxy.EchoDC(new MyDC()));
          //Console.WriteLine(proxy.Add(3, 5));
    
          //((IClientChannel)proxy).Close();
          //factory.Close();
    
          Console.Write("Press ENTER to close the host");
          Console.ReadLine();
          host.Close();
        }
      }
    
    
    • Marked as answer by Yi-Lun Luo Monday, December 20, 2010 9:13 AM
    Tuesday, December 14, 2010 3:28 PM
  • In short all you have to do is:

    1. register the custom behavior. Example:

    <system.serviceModel>
     <extensions>
      <behaviorExtensions>
       <add name="myClientCredentials" type="Microsoft.ServiceModel.Samples.MyClientCredentialsConfigHandler, CustomCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
     </extensions>
    <system.serviceModel>

    2. add your endpoint behavior. Example:

    <behaviors>
     <endpointBehaviors>
      <behavior name="myClientCredentialsBehavior">
       <myClientCredentials creditCardNumber="123-123-123"/>
      </behavior>
     </endpointBehaviors>
    </behaviors>

    3. configure your endpoint to use the endpoint behavior

    <endpoint behaviorConfiguration="myClientCredentialsBehavior" >

     

    I have taken this example from http://msdn.microsoft.com/en-us/library/ms730868.aspx 

     

    HTH,

    Francois

    • Marked as answer by Yi-Lun Luo Monday, December 20, 2010 9:13 AM
    Thursday, December 16, 2010 10:53 AM

All replies

  • You can change the QueryStringConverter used by the WebHttpBehavior to accept more than just "primitive" types. There's a public built-in converter in WCF, the JsonQueryStringConverter, which uses the DataContractJsonSerializer to deserialize non-primitive types. The example below shows how to replace the converter used in the behavior.

      public class Post_605526ee_2181_41a2_8d0e_ced1f5e2b825
      {
        public class FaqOptionCollection : List<FaqOption>
        {
          public override string ToString()
          {
            StringBuilder sb = new StringBuilder();
            sb.Append('[');
            for (int i = 0; i < this.Count; i++)
            {
              if (i > 0) sb.Append(',');
              sb.Append(this[i].ToString());
            }
            sb.Append(']');
            return sb.ToString();
          }
        }
        [DataContract]
        public class FaqOption
        {
          [DataMember]
          public string topic;
          [DataMember]
          public string keyword;
          public override string ToString()
          {
            return string.Format("FaqOption[topic={0},keyword={1}]", topic, keyword);
          }
        }
        [ServiceContract]
        public interface ITest
        {
          [WebGet(UriTemplate = "Send?collection={collection}", RequestFormat = WebMessageFormat.Json)]
          void Send(FaqOptionCollection collection);
        }
        public class Service : ITest
        {
          public void Send(FaqOptionCollection collection)
          {
            Console.WriteLine("Input: {0}", collection);
          }
        }
        public class MyWebHttpBehavior : WebHttpBehavior
        {
          protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
          {
            return new JsonQueryStringConverter();
          }
        }
        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(), "");
          WebHttpBehavior behavior = new MyWebHttpBehavior();
          endpoint.Behaviors.Add(behavior);
          host.Open();
          Console.WriteLine("Host opened");
    
          Util.SendRequest(baseAddress + "/Send?collection=[{\"topic\":\"foo\",\"keyword\":\"foo2\"},{\"topic\":\"bar\",\"keyword\":\"bar2\"}]", "GET", null, null);
          //ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
          //ITest proxy = factory.CreateChannel();
    
          //Console.WriteLine(proxy.EchoString("Hello"));
          //Console.WriteLine(proxy.EchoDC(new MyDC()));
          //Console.WriteLine(proxy.Add(3, 5));
    
          //((IClientChannel)proxy).Close();
          //factory.Close();
    
          Console.Write("Press ENTER to close the host");
          Console.ReadLine();
          host.Close();
        }
      }
    
    
    • Marked as answer by Yi-Lun Luo Monday, December 20, 2010 9:13 AM
    Tuesday, December 14, 2010 3:28 PM
  • How can I define that behavior in the web.config? I have a WCF Service application.

    • Edited by Peter Derwa Thursday, December 16, 2010 7:12 AM better question
    Thursday, December 16, 2010 7:08 AM
  • In short all you have to do is:

    1. register the custom behavior. Example:

    <system.serviceModel>
     <extensions>
      <behaviorExtensions>
       <add name="myClientCredentials" type="Microsoft.ServiceModel.Samples.MyClientCredentialsConfigHandler, CustomCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
     </extensions>
    <system.serviceModel>

    2. add your endpoint behavior. Example:

    <behaviors>
     <endpointBehaviors>
      <behavior name="myClientCredentialsBehavior">
       <myClientCredentials creditCardNumber="123-123-123"/>
      </behavior>
     </endpointBehaviors>
    </behaviors>

    3. configure your endpoint to use the endpoint behavior

    <endpoint behaviorConfiguration="myClientCredentialsBehavior" >

     

    I have taken this example from http://msdn.microsoft.com/en-us/library/ms730868.aspx 

     

    HTH,

    Francois

    • Marked as answer by Yi-Lun Luo Monday, December 20, 2010 9:13 AM
    Thursday, December 16, 2010 10:53 AM