Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a javascript map to json wcf service

I would like to pass an associative array to a json wcf service.

So in JavaScript I have something akin to this:

var map = { };
map['a'] = 1;
map['b'] = 2;
map['c'] = 3;

And in my wcf service I want to expect a Dictionary:

[OperationContract][WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public void setDictionary(Dictionary<string, int> myDictionary);

But it sends the map as an [Object object] rather than serializing it because the 'map' is actually just an object I'm assigning properties to.

Does anyone know how I can serialize it to correctly to get it deserialized as a Dictionary object by the WCF service?

like image 494
Logham Avatar asked Feb 21 '13 12:02

Logham


1 Answers

By default, WCF does not represent Dictionary as JSON objects - it represents them as arrays of key/value pairs instead. So to send that map to the WCF service, you'll need to covert it appropriately (see code below).

Another alternative is to use a custom message formatter, which knows how to populate dictionaries based on JSON objects. For more information on message formatters, check this blog post.

This shows one way of passing that object to your service:

Service.svc:

<%@ ServiceHost Language="C#" Debug="true" Service="StackOverflow_15001755.Service"
                CodeBehind="StackOverflow_15001755.svc.cs" 
                Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Service.svc.cs:

using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace StackOverflow_15001755
{
    [ServiceContract]
    public class Service
    {
        static Dictionary<string, int> dictionary;

        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public void setDictionary(Dictionary<string, int> myDictionary)
        {
            dictionary = myDictionary;
        }

        [WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public Dictionary<string, int> getDictionary()
        {
            return dictionary;
        }
    }
}

Test.html (HTML/JS code, using jQuery for the ajax call):

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type="text/javascript" src="scripts/jquery-1.7.2.js"></script>
    <script type="text/javascript" src="scripts/json2.js"></script>
</head>
<body>
    <script type="text/javascript">
        function StackOverflow_15001755_Test() {
            function dictionaryToKVPArray(obj) {
                var data = [];
                for (var key in obj) {
                    data.push({ Key: key, Value: obj[key] });
                }

                return data;
            }

            function KVPArrayToDictionary(arr) {
                var result = {};
                arr.forEach(function (item) {
                    result[item.Key] = item.Value;
                });

                return result;
            }

            var map = {};
            map['a'] = 1;
            map['b'] = 2;
            map['c'] = 3;
            var data = dictionaryToKVPArray(map);

            var baseUrl = "/StackOverflow_15001755.svc";
            $.ajax({
                type: 'POST',
                url: baseUrl + '/setDictionary',
                contentType: 'application/json',
                data: JSON.stringify({ myDictionary: data }),
                success: function (result) {
                    $('#result').text('Sent the dictionary');
                    $.ajax({
                        type: 'GET',
                        url: baseUrl + '/getDictionary',
                        success: function (result) {
                            var newMap = KVPArrayToDictionary(result);
                            $('#result2').text(JSON.stringify(newMap));
                        }
                    });
                }
            });
        }
    </script>
    <input type="button" value="StackOverflow 15001755" onclick="StackOverflow_15001755_Test();" /><br />
    <div id='result'></div><br />
    <div id='result2'></div><br />
</body>
</html>
like image 114
carlosfigueira Avatar answered Sep 20 '22 13:09

carlosfigueira