PDA

View Full Version : Error in sending json data to C# webmethod



MikeandIke
10 Jun 2014, 7:27 AM
When using an Ajax.Request to a C# WebMethod (.asmx) I get the following specified error, regardless of the content of the method being called.


"Message":"Cannot convert object of type System.String to type System.Collections.Generic.IDictionary"

This code is a remake of my other project where this same error is occurring, this is mostly stripped down and the error is not due to the connection to the database or anything like that, another webmethod runs correctly as long as it does not have to receive variables.
My assumption is that this error is due to the way the method receives json data.

ExtJS


createSortingBar: function (fields) {
return {
xtype: 'toolbar',
dock: 'top',
cls: 'panel-grid x-toolbar x-docked-top',
items: [{
fieldLabel: 'Name',
name: 'comboName',
xtype: 'combo',
store: fields,
displayField: 'name',
valueField: 'value',
width: 600,
}, {
xtype: 'button',
text: 'Submit',
cls: 'large-button-icon',
handler: function (btn, e) {
var comboValue = btn.ownerCt.getComponent(0).getValue();
var encodedValue = JSON.stringify('[{"ID":'+comboValue+'}]');
console.log(encodedValue);
Ext.Ajax.request({
url: Test061014.ApplicationPath + '/Director.asmx/getData',
params: encodedValue,
headers: { 'Content-Type': 'application/json' },
scope: this,
success: function (conn, response, options, eOpt) {
console.log(conn.responseText);
var s = conn.responseText;
s = s.substring(6, (s.length - 2));
console.log(s);
s = s.replace(/\\/g, "");
console.log(s);
store.proxy = new Ext.ux.data.P
grid.store = store;
store.load();
grid.GetView().refresh();
}
})
}

}]
}
}


C# WebService:



[WebService(Namespace = "localhost")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class Director : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false, XmlSerializeString = false)]
public string getData()
{
Input data = JsonConvert.DeserializeObject<Input>(input);
int id = data.id;
string json = "";
if (id == 0)
{
json = "[{\"ID\":\"0\",\"NAME\":\"ALAN\"}]";
}
else if (id == 1)
{
json = "[{\"ID\":\"1\",\"NAME\":\"BLAKE\"}]";
}

return json;
}


public class Input
{
public int id {get; set;}
}
}

cmeans
10 Jun 2014, 6:00 PM
I'm wondering where the C# variable "input" is declared...I only see it used...but whatever, it has nothing to do with the problem :)

I also don't see the "name" property in your C# Input class...but whatever, it also has nothing to do with the problem :)

I assume you're using a recent version of .NET (3.5 or better)...

You should just be able to do the following (I say "you should", because I did it all the time...we've now moved onto WCF):

FYI: I'm typing this directly in, so there may be lots of mistakes etc., but you should be able to get the idea.



[Serializable]
public class Input
{
public int id { get; set; }
public string name { get; set; }
}

[WebMethod]
[ScriptMethod]
public Input getData(Input input)
{
if (input != null)
{
if (input.id == 0)
{
input.name = "ALAN";
}
else if (input.id == 1)
{
input.name = "BLAKE";
}
}

// Send the (maybe) modified object back.
return input;
}


So long as the classes (and any inner classes) you're passing around are flagged as [Serializable], .NET should have no problem marshalling data in and out for you in the WebService. DataContract is used in WCF (and lets you provide DataMember names so that you can use more natural property naming conventions client-side).

Client-side, your AJAX request can then just be something like:



function handleResult(responseInputValue)
{
// expect "id" and "name" properties for responseInputValue.
}

var value = { id: '0' };

transId = Ext.Ajax.request(
{
url: '/Director.asmx/getData (http://Director.asmx/getData)',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
jsonData:
{
input: value
},
method: 'POST',
success: function(result, options)
{
transId = 0;

handleResult(Ext.decode(result.responseText).d);
},
scope: this
});


Hope this helps. Let me know if you need more clarification.

-Chris

MikeandIke
10 Jun 2014, 8:28 PM
This appears, to work, those variables that you mentioned up above were due to the other testing I was doing as well as an attempt to define the object that was being sent in.

I think I got the idea, and based off of the code you sent me it should work. I have since then found an alternate method to achieve what I wanted, and the environment for me to retest this no longer exists. However this is the answer to this question.

Thanks for your input.