2009-10-02 17 views
20

Tengo un contrato de datos con un miembro de datos tipeado como Dictionary<string, string>.¿Cómo serializar Dictionary <string, string> a través de WCF?

La referencia del servicio web generado expone esto como un miembro con el tipo ArrayOfKeyValueOfstringstringKeyValueOfstringstring[].

¿Alguien ha visto esto antes?

+0

Es posible que desee echar un vistazo a esta página la documentación de WCF (que es mucho más reciente que esta pregunta): https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/collection-types-in-data-contracts –

Respuesta

23

WCF sólo se serializa estructura, porque lo que termina en el cable debe ser autónomo suficiente para ser útil para el cliente cualquier, no sólo los clientes .NET.

Algunos clientes desarrollados en una plataforma diferente pueden no compartir el concepto de 'diccionario', por lo que sería demasiado restrictivo serializar un Diccionario a una representación que conlleve un conocimiento implícito sobre la clase subyacente.

Es posible que el cliente no esté orientado a objetos.

Un diccionario es más que estructura - sino que también contiene el comportamiento (por ejemplo, cuando se asigna a una tecla que ya existe, se sobrescribe esa clave, etc.) y que el comportamiento no puede viajar a través del cable.

En otras palabras, los diccionarios y muchos otros tipos .NET no son interoperables, por lo que WCF no intentará conservarlos en un ServiceContract.

Probablemente sea mejor que diseñe un DataContract personalizado para sus datos.

+2

that doesn no significa que el proxy del cliente no pueda generarse convertir los datos nuevamente en un diccionario.¿Qué hace la opción "Tipo de colección de diccionario" del cuadro de diálogo "Configurar referencia de servicio" de Visual Studio cuando se establece en System.Collections.Generic.Dictionary? – xr280xr

5

Como WCF tiene que convertir todo a XML, tiene que caber como XML ... Las colecciones generalmente se convierten en matrices.

Un diccionario es muy difícil de representar como xml, es por eso que tiene este tipo en el otro lado. Puede especificar que SvcUtil.exe use colecciones específicas en lugar de matrices en el código proxy generado, pero no estoy seguro de que funcione para un diccionario. Yo diría que debería evitar el uso de un Diccionario aquí y usar una Colección más simple.

Lo que haría sería crear mi propio tipo de datos, [DataContract], hacer que tenga dos campos de tipo Cadena, luego hacer una Colección de estos que llene con todo lo que encuentre en el Diccionario. Luego envió esa colección a través del cable, luego la convierte de nuevo en un diccionario en el otro lado.

+0

¿No es algo así como una secuencia de de dah? – kenny

+1

@Kenny: no, el DataContractSerializer estándar no admite atributos en nodos XML (por razones de rendimiento) –

+2

@kenny: francamente. sí. y hay mucha gente por ahí que escribió diccionarios serializables, usando una clave muy natural y valores de elementos xml. un diccionario es solo una lista de pares. el único argumento válido es el de Mark Seemann sobre el comportamiento. Pero un diccionario ciertamente no es difícil de representar en xml. ¡Además, Python serializa correctamente los diccionarios, usando la misma representación que el código en sí mismo! simplemente haz 'str (mydict)' para obtenerlo. –

1

Hay una manera de hacerlo ... El contrato de operación es en realidad una cadena. Escapo de la cuerda de Json para mantenerla como una cuerda. Luego, en el método web, desapego la cadena y la analizo en un diccionario usando NewtonSoftJson. Utilicé el diccionario, pero también podría hacer el diccionario si quisiera. Espero que esto sea útil ...

que utiliza la biblioteca JSON NewtonSoft ...

código C#

using Newtonsoft.Json; 
[OperationContract] 
    [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, 
     RequestFormat = WebMessageFormat.Json)] 
    public void testMethod(string jsonData) 
    { 
     string data = Uri.UnescapeDataString(jsonData); 
     Dictionary<string, string> x = jsonConvert.DeserializeObject<Dictionary<string, string>>(data); 
     foreach (KeyValuePair<string, string> kvp in x) 
     { 

     } 
    } 

códigoJS

var Data = { 
    width: 400, 
    height: 200, 
    someString: "somedata" 
}; 

$.ajax({ 
    type: "POST", 
    url: "Service1.svc/testMethod", 
    contentType: "application/json; charset=utf-8", 
    dataType: "json", 
    timeout: 1000000,    
    data: '{"jsonData": "' + escape(JSON.stringify(Data)) + '"}', 
    error: function(error) { 
    }, 
    success: function (data) { 
    }, 
}); 
Cuestiones relacionadas