Reputation: 7470
I have Dictionary which will return from server, i converted it json string format as below:
public static class Extensions
{
public static string ToJson<T>(this T obj)
{
MemoryStream stream = new MemoryStream();
try {
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(T));
jsSerializer.WriteObject(stream, obj);
return Encoding.UTF8.GetString(stream.ToArray());
}
finally
{
stream.Close();
stream.Dispose();
}
}
public static T FromJson<T>(this string input)
{
MemoryStream stream = new MemoryStream();
try {
DataContractJsonSerializer jsSerializer = new DataContractJsonSerializer(typeof(T));
stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
T obj = (T)jsSerializer.ReadObject(stream); return obj;
}
finally
{
stream.Close();
stream.Dispose();
}
}
}
[WebMethod]
public string callme()
{
Dictionary<int, string> myObjects = new Dictionary<int, string>();
myObjects.Add(1, "This");
myObjects.Add(2, "is");
myObjects.Add(3, "cool");
string json = myObjects.ToJson();
return json;
}
so Result is:
{"d":"[{\"Key\":1,\"Value\":\"This\"},{\"Key\":2,\"Value\":\"is\"},{\"Key\":3,\"Value\":\"cool\"}]"}
How I parse that in jquery? I m trying this but not help
$.ajax({
type: "POST",
url: "web.asmx/callme",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg){
$.each(msg.d, function (i) {
$("#data2").append(i.Key + " " + i.Value + "<br/>");
});
}
});
Upvotes: 1
Views: 15192
Reputation: 895
The only way it worked for me was
var $nomeP = $("#<%= tbxBuscaJornalista.ClientID %>").val();
$.ajax({
url: "MyPage.asmx/MyMethod",
dataType: "json",
type: "POST",
data: "{ 'variableName': '"+$nomeP+"' }",
contentType: "application/json; charset=utf-8",
success: function (msg) {
$.each(msg.d, function (index, value) {
$("#somePanel").append(index + " " + value + "<br/>");
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert("Error: " + errorThrown + " XmlRequest: " + XMLHttpRequest);
}
});
Please notice the line data: "{ 'variableName': '"+$nomeP+"' }"
which shows I had to enclose the variable name (same as expected in code-behind) and the value in single quotes. Otherwise it would not work. Also, I tried to iterate and use $(this).Key
and $(this).Value
but that wouldn't work either. I was forced to use the function (index, value)
approach.
Upvotes: 1
Reputation: 4279
Based on JotaBe answer above, I created this extension method:
public class KeyValue<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
public KeyValue()
{
}
}
public static class KeyValue_extensionMethods
{
public static List<KeyValue<TKey, TValue>> ConvertDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
{
var keyValueList = new List<KeyValue<TKey, TValue>>();
foreach (TKey key in dictionary.Keys)
keyValueList.Add(new KeyValue<TKey, TValue> { Key = key, Value = dictionary[key] });
return keyValueList;
}
}
Which then allows me to consume it using {object}.ConvertDictionary() syntax. For example:
[WebMethod(EnableSession = true)] [Admin(SecurityAction.Demand)]
public List<KeyValue<Guid, string>> Data_GuidanceItems_FileMappings()
{
return TM_Xml_Database.GuidanceItems_FileMappings.ConvertDictionary();
}
Upvotes: 1
Reputation: 39045
You'll have to do this things before it works:
ScriptService
attribute to your web serviceScriptMethod
attribute in your web serviceIf you do so, you don't even need to parse create the JSON in the server yourself. The WS infrastructure will do it for you.
Then, simply use msg.d on the client site. It will be automatically deserialized from the JSOn string.
Look here Using jQuery to Consume ASP.NET JSON Web Services for what you need to do on client side.
Here you have a full working sample with client and server side.
Be aware that before ASP.NET 3.5 the response message brought the data directly. In 3.5 and later, the data is in the .d property of the message.
EDIT2: Easier way to do it I made a mistake in the 1st edit: .asmx can't serialize a Dictionay as XML. So, when I tested the solution in the first edit via the .asmx page, I got an error. But JSON can serialize a Dictionary which has a string or an object as key.
So, you can use this class to convert your Dictionary<int,string>
to Dictionary<string,string>
using this generic class:
public class DictionaryConverter
{
public static Dictionary<string,TValue>
ConvertDictionary<TKey,TValue>(Dictionary<TKey,TValue> dict)
{
Dictionary<string,TValue> newDict
= new Dictionary<string, TValue>();
foreach(TKey key in dict.Keys)
{
newDict.Add(key.ToString(), dict[key]);
}
return newDict;
}
}
This class can convert any Dictionary with any key type to a Dictionary<string,Tvalue>
dictionary, which can be serialized as JSON, but not as XML. It uses the key type toString()
method to convert the key in string. This will work perfectly for int
and many other types. This method could be extended to receive a delegate to convert the key to string if necessary.
On client side you get the same thing with this solution and the one in the firs edit. The advantage of the one in the first edit is that it can also support serialization to XML: you can invoke the method through the .asmx page, and use the WebMethod as a regualr XML WebMethod.
EDIT: Serializing Dictionary<> in .asmx web service:
The serializer used with asmx doesn't support serializing dictionaries for XML. You can create a custom class and convert your dictionary to a list of this custom class, which has a key and a value property (the serializer doesn't support serializing KeyValuePair
or Tuple
, either, so you must use your own class).
This class serves two purposes:
Allows to convert a dictionary in a list of elements of the class
public class KeyValue<TKey, TValue>
{
public KeyValue()
{
}
public TKey Key { get; set; }
public TValue Value { get; set; }
public static List<KeyValue<TKey,TValue>> ConvertDictionary
(Dictionary<TKey,TValue> dictionary)
{
List<KeyValue<TKey, TValue>> newList
= new List<KeyValue<TKey, TValue>>();
foreach (TKey key in dictionary.Keys)
{
newList.Add(new KeyValue<TKey, TValue>
{ Key = key, Value = dictionary[key] });
}
return newList;
}
}
Your web method should look like this:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)] // it's JSON by default
public List<KeyValue<int,string>> GetKeyValueList()
{
List<KeyValue<int, string>> list
= KeyValue<int,string>.ConvertDictionary(yourDictionary);
return list;
}
Notes:
GetKeyValueList
On the client side you get an array of Objects with Key and Value properties, which can be accesed like this:
msg.d[0].Key
msg.d[0].Value
This is the jquery ajax call:
$(document).ready(function () {
$.ajax({
url: 'MyService.asmx/GetKeyValueList',
type: "POST",
data: "{}",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (msg) {
// use msg.d array of objects with Key and Value
}
});
});
Upvotes: 3
Reputation: 17825
$.each(msg.d, function() {
$("#data2").append(this.Key + " " + this.Value + "<br/>");
});
Also, it appears that your serialization is not working correctly, as the response coming back isn't being entirely parsed into JSON. The contents of d
shouldn't be a string, it should be an object/array.
Upvotes: 2