2013-02-21 4 views
7

Я хотел бы передать ассоциативный массив службе json wcf.Передача javascript-карты на службу json wcf

Так в JavaScript У меня есть что-то похожее на это:

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

И в моей службы WCF Я хочу ожидать Словарь:

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

Но он посылает карту как [объект Object ] вместо того, чтобы сериализовать его, потому что «карта» на самом деле является просто объектом, которому я присваиваю свойства.

Кто-нибудь знает, как я могу сериализовать его, чтобы правильно его десериализовать как объект словаря службой WCF?

+1

Вы пробовали функцию [JSON.stringify] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify)? 'echo JSON.stringify (map);' должен выводить строку: '{" a ": 1," b ": 2," c ": 3}' – Imperative

+0

Выполняется только сброс wcf: форматирование выдало исключение, попытка десериализации сообщения – LoghamLogan

ответ

5

По умолчанию WCF не представляет Dictionary как объекты JSON - вместо этого они представляют собой массивы пар ключ/значение. Поэтому, чтобы отправить эту карту в службу WCF, вам нужно будет ее скрытно отобразить (см. Код ниже).

Другой альтернативой является использование настраиваемого форматирования сообщений, который знает, как заполнять словари на основе объектов JSON. Для получения дополнительной информации о формировщиках сообщений, проверьте это blog post.

Это показывает один из способов передачи этого объекта к вашим услугам:

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, используя jQuery для вызова ajax):

<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> 
+0

Ваш метод dictionaryToKVPArray() - это то, что мне нужно для этого!Спасибо =) Отмечено как ответ, потому что он точно показывает, как передать правильные данные службе WCF для десериализации объекта Dictionary, а также снова вернуть его в javascript! – LoghamLogan

4

Мне удалось получить эту работу, используя JSON.stringify(map), чтобы получить сериализованную версию карты. Затем передайте его в службу WCF как строку, а не словарь, и десериализуйте ее самостоятельно в методе, используя Json.Net framework.

Serialized Карта:

{'a':'0','b':'1','c':'2'} 

службы WCF:

[OperationContract][WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)] 
public void doDictionaryStuff(string serializedMap); 

Десериализация его в службе WCF с помощью Json.Net framework:

public void doDictionaryStuff(string serializedMap) 
{ 
    Dictionary<string, int> map = JsonConvert.DeserializeObject<Dictionary<string,int>>(serializedMap); 
    //do stuff with the dictionary. 
} 

Это не идеал, но он работает.