2013-02-21 3 views
7

Chciałbym przekazać tablicę asocjacyjną do usługi wcson wcson.Przekaż mapę javascript do usługi json wcf

Więc w JavaScript Mam coś podobnego do tego:

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

I w moim usług WCF Chcę oczekiwać słownika:

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

Ale wysyła mapę jako [object Object ] zamiast serializacji, ponieważ "mapa" jest w rzeczywistości tylko obiektem, do którego przypisuję właściwości.

Czy ktoś wie, jak mogę serializować go poprawnie, aby uzyskać deserializację jako obiekt słownika przez usługę WCF?

+1

Czy próbowałeś korzystać z funkcji [JSON.stringify] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/JSON/stringify)? 'echo JSON.stringify (map);' powinien wypisać ciąg: '{" a ": 1," b ": 2," c ": 3}' – Imperative

+0

Ma tylko wcf: Konstruktor wyrzucił wyjątek podczas próbuje deserializować wiadomość – LoghamLogan

Odpowiedz

5

Domyślnie WCF nie reprezentuje Dictionary jako obiektów JSON - zamiast nich reprezentuje je jako tablice par klucz/wartość. Aby wysłać tę mapę do usługi WCF, musisz ją odpowiednio ukryć (zobacz poniższy kod).

Inną alternatywą jest użycie niestandardowego formatera wiadomości, który potrafi wstawiać słowniki na podstawie obiektów JSON. Aby uzyskać więcej informacji na temat formatów wiadomości, sprawdź to blog post.

To pokazuje jeden sposób przekazywania tego obiektu do Państwa dyspozycji:

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/Kod JS, używając jQuery do wywołania 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

Twoja słownik MetodaToKVPArray() jest właśnie tym, czego potrzebowałem!Thanks =) Oznaczone jako odpowiedź, ponieważ pokazuje dokładnie, jak przekazać poprawne dane do usługi WCF, aby deserializować obiekt Dictionary, a także ponownie go z powrotem do javascript! – LoghamLogan

4

Udało mi się to zrobić, używając JSON.stringify(map), aby uzyskać wersję serializowaną mapy. Następnie przekazywanie go do usługi WCF jako ciąg znaków, a nie słownik i deserializacji go samodzielnie w metodzie przy użyciu Json.Net framework.

Serialized Mapa:

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

WCF Usługa:

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

deserializacji go w usług WCF przy użyciu Json.Net framework:

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

To nie jest idealne, ale działa.