locked
WCF JSON Multiple Parameters RRS feed

  • Question

  • Hi,

    I've been experimenting with calling a WCF services from a Windows Mobile device using HttpWebResponse/HttpWebRequest.  The format of the data exchange is Json.  The test service has the following method signature:

    public string Process(Data dData)
    

    { return string.Format("you entered: {0} {1}", dData.StringValue, dData.BoolValue); }
    When I make the call eveything is fine and I can see a trace of the exchange using TcpTrace.  However when I change the method signature to receive multiple parameters, I receive a HTTP server 500 error.

    public string Process(Data dData, Data dData2)
    {
           return string.Format("you entered: {0} {1} {2} {3}", dData.StringValue, dData.BoolValue, dData2.StringValue, dData2.BoolValue);
    }
    The code on the client is as follows:

    Data dData1 = new Data();
                dData1.BoolValue = true;
                dData1.StringValue = "Hello WCF World";
    
                Data dData2 = new Data();
                dData2.BoolValue = false;
                dData2.StringValue = "HW";
    
                //DataContractJsonSerializer dcjSerialiser = null;
                JsonSerializer jsSerialiser = null;
                //string strJson = null;
                //byte[] bData = null;
    
                Uri uUri = new Uri("http://localhost:8080/WcfTest/Service.svc/process");
    
                HttpWebRequest hwrRequest = (HttpWebRequest)WebRequest.Create(uUri);
                hwrRequest.Method = "POST";
                hwrRequest.ContentType = "application/json; charset=utf-8";
                //hwrRequest.ContentLength = bData.Length;
    
                //using(MemoryStream msStream = new MemoryStream())
                //{
                    //dcjSerialiser = new DataContractJsonSerializer(dData1.GetType());
                    jsSerialiser = new JsonSerializer();
                    jsSerialiser.NullValueHandling = NullValueHandling.Ignore;
                    //dcjSerialiser.WriteObject(msStream, dData);
    
                    using(Stream sData = hwrRequest.GetRequestStream())
                    {
                        //sData.Write(bData, 0, bData.Length);
                        //dcjSerialiser.WriteObject(sData, dData1);
                        //dcjSerialiser.WriteObject(sData, dData2);
    
                        using(StreamWriter swWriter = new StreamWriter(sData))
                        {
                            using(JsonWriter jwWriter = new JsonTextWriter(swWriter))
                            {
                                jsSerialiser.Serialize(jwWriter, dData1);
                                jsSerialiser.Serialize(jwWriter, dData2);
                            }
                        }
    
                        sData.Close();
                    }
    
                    //strJson = Encoding.UTF8.GetString(msStream.ToArray());
                    //bData = Encoding.UTF8.GetBytes(strJson);
                    //msStream.Close();
                //}
    
                using(HttpWebResponse hwrResponse = (HttpWebResponse)hwrRequest.GetResponse())
                {
                    StreamReader srReader = new StreamReader(hwrResponse.GetResponseStream());
                    Console.WriteLine(srReader.ReadToEnd());
                }
    Is it possible to send multiple parameters?

    Any help would be appreciated,

    Mark
    Thursday, September 24, 2009 1:44 PM

Answers

  • If you use multiple parameters, you need to "wrap" the request in its own object (and note it on the [WebInvoke] attribute), otherwise you'd get an invalid JSON. For example, the request you're sending is this:

        {"StringValue":"Hello WCF World","BoolValue",true}{"StringValue":"HW","BoolValue":false}

    which is not a valid JSON. You need to wrap it like the following:

        {"data1":{"StringValue":"Hello WCF World","BoolValue",true},"data2":{"StringValue":"HW","BoolValue":false}}

    And your contract has to be as shown below:

    [

    OperationContract]
    [
    WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest,
                      RequestFormat =
    WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    string Process(Data dData1, Data dData2);


    The code below shows the whole thing end-to-end:

        public class Post_044876ce_2643_4f2b_b9f4_250f920454ae_2Param
        {
            [DataContract]
            public class Data
            {
                [DataMember]
                public string StringValue;
                [DataMember]
                public bool BoolValue;
            }
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                [WebInvoke(
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
                string Process(Data dData1, Data dData2);
            }
            public class Service : ITest
            {
                public string Process(Data dData1, Data dData2)
                {
                    if (dData1 == null) { return "dData1 == null"; }
                    if (dData2 == null) { return "dData2 == null"; }
                    return string.Format("you entered: {0} {1}, {2} {3}",
                        dData1.StringValue, dData1.BoolValue,
                        dData2.StringValue, dData2.BoolValue);
                }
            }
            public static void Test()
            {
                string baseAddress = "http://localhost:8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
                host.Open();
                Console.WriteLine("Host opened");
    
                Util.SendRequest(baseAddress + "/Process", "POST", "application/json", "{\"dData1\":{\"BoolValue\":true,\"StringValue\":\"Hello\"}, \"dData2\":{\"BoolValue\":false,\"StringValue\":\"World\"}}");
    
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }
        public static class Util
        {
            public static string SendRequest(string uri, string method, string contentType, string body)
            {
                string responseBody = null;
    
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
                req.Method = method;
                if (!String.IsNullOrEmpty(contentType))
                {
                    req.ContentType = contentType;
                }
                if (!String.IsNullOrEmpty(body))
                {
                    byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
                    req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
                    req.GetRequestStream().Close();
                }
    
                HttpWebResponse resp;
                try
                {
                    resp = (HttpWebResponse)req.GetResponse();
                }
                catch (WebException e)
                {
                    resp = (HttpWebResponse)e.Response;
                }
                Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
                foreach (string headerName in resp.Headers.AllKeys)
                {
                    Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
                }
                Console.WriteLine();
                Stream respStream = resp.GetResponseStream();
                if (respStream != null)
                {
                    responseBody = new StreamReader(respStream).ReadToEnd();
                    Console.WriteLine(responseBody);
                }
                else
                {
                    Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
                }
                Console.WriteLine();
                Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
                Console.WriteLine();
    
                return responseBody;
            }
        }
    
    • Proposed as answer by Carlos Figueira Friday, September 25, 2009 11:45 PM
    • Marked as answer by markpirvine Saturday, September 26, 2009 9:19 AM
    Thursday, September 24, 2009 2:03 PM

All replies

  • If you use multiple parameters, you need to "wrap" the request in its own object (and note it on the [WebInvoke] attribute), otherwise you'd get an invalid JSON. For example, the request you're sending is this:

        {"StringValue":"Hello WCF World","BoolValue",true}{"StringValue":"HW","BoolValue":false}

    which is not a valid JSON. You need to wrap it like the following:

        {"data1":{"StringValue":"Hello WCF World","BoolValue",true},"data2":{"StringValue":"HW","BoolValue":false}}

    And your contract has to be as shown below:

    [

    OperationContract]
    [
    WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest,
                      RequestFormat =
    WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
    string Process(Data dData1, Data dData2);


    The code below shows the whole thing end-to-end:

        public class Post_044876ce_2643_4f2b_b9f4_250f920454ae_2Param
        {
            [DataContract]
            public class Data
            {
                [DataMember]
                public string StringValue;
                [DataMember]
                public bool BoolValue;
            }
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                [WebInvoke(
                    BodyStyle = WebMessageBodyStyle.WrappedRequest,
                    RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
                string Process(Data dData1, Data dData2);
            }
            public class Service : ITest
            {
                public string Process(Data dData1, Data dData2)
                {
                    if (dData1 == null) { return "dData1 == null"; }
                    if (dData2 == null) { return "dData2 == null"; }
                    return string.Format("you entered: {0} {1}, {2} {3}",
                        dData1.StringValue, dData1.BoolValue,
                        dData2.StringValue, dData2.BoolValue);
                }
            }
            public static void Test()
            {
                string baseAddress = "http://localhost:8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
                host.Open();
                Console.WriteLine("Host opened");
    
                Util.SendRequest(baseAddress + "/Process", "POST", "application/json", "{\"dData1\":{\"BoolValue\":true,\"StringValue\":\"Hello\"}, \"dData2\":{\"BoolValue\":false,\"StringValue\":\"World\"}}");
    
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }
        public static class Util
        {
            public static string SendRequest(string uri, string method, string contentType, string body)
            {
                string responseBody = null;
    
                HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
                req.Method = method;
                if (!String.IsNullOrEmpty(contentType))
                {
                    req.ContentType = contentType;
                }
                if (!String.IsNullOrEmpty(body))
                {
                    byte[] bodyBytes = Encoding.UTF8.GetBytes(body);
                    req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
                    req.GetRequestStream().Close();
                }
    
                HttpWebResponse resp;
                try
                {
                    resp = (HttpWebResponse)req.GetResponse();
                }
                catch (WebException e)
                {
                    resp = (HttpWebResponse)e.Response;
                }
                Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
                foreach (string headerName in resp.Headers.AllKeys)
                {
                    Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
                }
                Console.WriteLine();
                Stream respStream = resp.GetResponseStream();
                if (respStream != null)
                {
                    responseBody = new StreamReader(respStream).ReadToEnd();
                    Console.WriteLine(responseBody);
                }
                else
                {
                    Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
                }
                Console.WriteLine();
                Console.WriteLine("  *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*  ");
                Console.WriteLine();
    
                return responseBody;
            }
        }
    
    • Proposed as answer by Carlos Figueira Friday, September 25, 2009 11:45 PM
    • Marked as answer by markpirvine Saturday, September 26, 2009 9:19 AM
    Thursday, September 24, 2009 2:03 PM
  • Carlos,

    Thanks for the reply and code snippet.

    Mark
    Saturday, September 26, 2009 9:22 AM
    • Proposed as answer by TaylorCode Monday, August 1, 2011 12:19 PM
    Monday, August 1, 2011 12:19 PM
  • Link doesn't work. FYI

    Monday, October 14, 2013 3:33 PM