PDA

View Full Version : Reading Json webservice IIS 7 dot net 3.5



michelk
21 Sep 2010, 12:46 PM
Hi,

After several hours spitting though the examples and forums I can’t get it to work. This should be so simple ….
I have created a C# dotnet 3.5 webservice what is returning json data.
I have created a sencha touch application that calls the webservice and gets the json results and put this in a store.
The webservice is working okay. Because when I do a Ext.Ajax.request and look at the responsetext I see the json data.
But when I do the same in the a Ext.data.Store with a ajax proxy , the store.getcount() is always 0.

The strange part is when I replace the webservice url to load directly a natve .json file that also on the iis site the data is loaded.

So I think IIS 7 is doing something with the json webservice output. ??? (and yes , I have set the root to ‘d’)

And when using the ajax proxy , how can I get the http responsetext to see if the http call was successful ? Since I can’t use the success and failure events as I can with the ext.ajax.request ??

See the code below. I think I’m not alone here and a good example will help a lot of sencha touch newbie’s ;-))

Thanks All for your time
Michel


Ext.setup({
fullscreen: true,
glossOnIcon: false,
onReady: function () {

// to test the call
Ext.Ajax.request({
url: './../scom_ipad/service1.asmx/GetAllAlerts',
method: 'GET',
jsonData: { "Alert": {} },
headers: { 'Content-Type': 'application/json;charset=utf-8' },

success: function (response, opts) {
alert(response.responseText);
},
failure: function (response, opts) {
alert(response.responseText);
}
})

// to load the store
var model = Ext.regModel('model', {
fields: [{ name: '__type', type: 'string' }, //added this because the responsetext was show this as “__type”:”Webservice1.Alert”. Is this needed???
{ name: 'Name', type: 'string' },
{ name: 'Description', type: 'string' },
{ name: 'ID', type: 'float' }
]
});

// load it
var store = new Ext.data.Store({
model: 'model',
autoLoad: true,
proxy: {
type: 'ajax',
url: './../scom_ipad/service1.asmx/GetAllAlerts',
// Ask for Json response
headers: { 'Content-Type': 'application/json;charset=utf-8' },
method: 'GET',
reader: {
type: 'json',
root: 'd'
}
}
});

// display the row count , but it is Always 0
alert('count ' + store.getCount());


var tpl = new Ext.XTemplate(
'<tpl for=".">',
'<div class="thumb-wrap" id="{ID}">',
'<div class="thumb"><img src="{Description}" title="{Name}"></div>',
'<span class="x-editable">{Name}</span></div>',
'</tpl>',
'<div class="x-clear"></div>'
);

// show the store row on the screen but nothing is shown.

var panel = new Ext.Panel({
id: 'images-view',
fullscreen: true,
dockedItems: [ // Added for effect
{
dock: 'top',
xtype: 'toolbar',
items: [{
text: 'btn top'
}]
},
{
dock: 'bottom',
xtype: 'toolbar',
items: [{
text: 'btn bottom'
}]
}
],
items: [new Ext.DataView({
store: store,
tpl: tpl,
autoHeight: true,
multiSelect: true,
overClass: 'x-view-over',
itemSelector: 'div.thumb-wrap',
emptyText: 'No images to display'
})]
});


}

});




-----------------------------------------------
---c# Webservice
-----------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml;
using System.Web.Script.Serialization;
using System.Web.Script.Services;

namespace WebService1
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json,UseHttpGet = true, XmlSerializeString = false)]
public Alert[] GetAlerts()
{
Alert[] p = new Alert[2];
p[0] = new Alert (1,"1aadd", "ddd");
p[1] = new Alert(2,"2aadd", "aaaa");
return (p);
}

}


public class Alert
{

public string Name { get; set; }
public string Description { get; set; }
public int ID { get; set; }


public Alert() { }

public Alert(int Key,string firstname, string lastname)
{
ID = Key;
Name = firstname;
Description = lastname;
}
}
}

evant
21 Sep 2010, 3:56 PM
You haven't provided enough information. It doesn't matter what your server side code looks like, the only thing that's relevant is the resulting data that is passed to the client.

michelk
21 Sep 2010, 10:22 PM
Hi Evant,

Thanks for replying.

When I call the webservice method in ms internet explorer i see: (don't know why this is a xml output?? i'm really sure i'm outputting json)


<?xml version="1.0" encoding="utf-8" ?>
<ArrayOfAlert xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<Alert>
<Name>1aadd</Name>
<Description>ddd</Description>
<ID>1</ID>
</Alert>
<Alert>
<Name>2aadd</Name>
<Description>aaaa</Description>
<ID>2</ID>
</Alert>
</ArrayOfAlert>


When I look on the IPAD what the result of the "// to test the call
Ext.Ajax.request({" is i get:


{"d":[{"__type":"Webservice1.Alert","Name":"1aadd","Description":"ddd","ID":1},{"__type":"Webservice1.Alert","Name":"2aadd","Description":"aaaa","ID":2}]}



Michel

michelk
22 Sep 2010, 10:56 AM
Okay I now having the output in IE as:


<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://abc.service/">[{"Name":"aadd","Description":"ddd","ID":1},{"Name":"aadd","Description":"aaaa","ID":2}]</string>
How do I get rit of the <string> tags

xnakxx
22 Sep 2010, 3:15 PM
can you post a link to your script?

merry andrew
22 Sep 2010, 3:21 PM
I've had success with JSON using only this header within Ext.Ajax.request:



headers: {
'Accept': 'application/json'
}

michelk
22 Sep 2010, 10:42 PM
I'm sure the cause of this is the IIS7 webservice response. I created a test file test.htm that contains:
{
"d": [
{
"Name": "dd",
"Description": "ddd",
"ID": 1
},
{
"Name": "aa",
"Description": "aaaa",
"ID": 2
}
]
}

In de code where 'store'proxy is loaded replaced the code :
url: './../scom_ipad/service1.asmx/GetAllAlerts',
to
url: './test.htm',

And now the store is loaded. So it must be the webservice reponse. I think this is because the webservice is still returing XML with a json string inside.


<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://abc.service/">[{"Name":"aadd","Description":"ddd","ID":1},{"Name":"aadd","Description":"aaaa","ID":2}]</string>


Any any help on this ????

2 more question:
1) why is the store.getcount() always 0 ? even when it cointains records ?
2) is there any way to see what the responsetext was that the store proxy is returning ? 'success: and failure: events don't seem to work.

michel

michelk
22 Sep 2010, 10:45 PM
I've had success with JSON using only this header within Ext.Ajax.request:



headers: {
'Accept': 'application/json'
}

Do you have any example code on this ? I tried it out but it didn't work.

michelk
22 Sep 2010, 10:46 PM
can you post a link to your script?

Hi see my first post ??

evant
22 Sep 2010, 10:57 PM
The above isn't valid JSON, there's nothing magic you can do to force it to parse. Sounds like a problem with the web service. You could write your own proxy that extends Ajax Proxy to strip out the xml before it comes back.



<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://abc.service/">[{"Name":"aadd","Description":"ddd","ID":1},{"Name":"aadd","Description":"aaaa","ID":2}]</string>


Why doesn't it just return raw json?

michelk
22 Sep 2010, 11:33 PM
The above isn't valid JSON, there's nothing magic you can do to force it to parse. Sounds like a problem with the web service. You could write your own proxy that extends Ajax Proxy to strip out the xml before it comes back.



<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://abc.service/">[{"Name":"aadd","Description":"ddd","ID":1},{"Name":"aadd","Description":"aaaa","ID":2}]</string>


Why doesn't it just return raw json?

Thanks, Yes you are correct on the non valid json. But now how do i get rit of it. I'm using the correct scripthandlers. I assume it a combination of iis7 and dot net 3.5

Do you have any simple example code on how this proxy should look like ?

AND for me even better any code on how to read a XML response in stead of json ?

Thanks,
Michel

merry andrew
23 Sep 2010, 8:03 AM
It pulls data from a SharePoint service (sorry, I don't have any available for test):


var processRequest = function(queryUrl) {
Ext.Ajax.request({
url: queryUrl,
method: 'GET',
headers: {
'Accept': 'application/json'
},
success: function(response, opts) {

var result = Ext.decode(response.responseText).d;
personStore.loadData(result.results, false);
},
failure: function() {
alert('lookUp failed');
}
});
};
When that header isn't included, the site responds with XML.

xnakxx
23 Sep 2010, 9:38 AM
LOL parse your XML response to extract and parse your JSON string....
hmmmmm
look what i found
http://forums.asp.net/t/1054378.aspx
google is your friend

michelk
23 Sep 2010, 10:12 AM
LOL parse your XML response to extract and parse your JSON string....
hmmmmm
look what i found
http://forums.asp.net/t/1054378.aspx
google is your friend

I know this post and checked everything. And the code / web config is good.

Any example how to read XML into the store I tried to change the type but this won't work.



// load it
var store = new Ext.data.Store({
model: 'model',
autoLoad: true,
proxy: {
type: 'ajax',
url: './../scom_ipad/service1.asmx/GetAllAlerts',
// Ask for Json response
headers: { 'Content-Type': 'application/json;charset=utf-8' },
method: 'GET',
reader: {
type: 'xml'}
}
});

xnakxx
23 Sep 2010, 10:24 AM
your content type is still set to application/json, not sure if that makes a difference.

it looks to have been discussed before also. Im not a seasoned ASP guy but there are a few suggestions here
http://www.sencha.com/forum/showthread.php?103679-Json-datastore-from-asp.net-webservice (http://www.sencha.com/showthread.php?103679-Json-datastore-from-asp.net-webservice)

mathieurene
23 Sep 2010, 11:35 AM
in my case i use http handler with a little json convert from Newtsoft : http://james.newtonking.com/

server side :


public class myHandlerJSONP : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}

public void ProcessRequest(HttpContext context)
{
String callbackDecorateur = context.Request.QueryString["callback"];
string champ = context.Request.QueryString["champ"];
//Do something

//objet Json
var obj = new { r = IsOk,property1= "ezkjekzje",property2=123 };
string r = JsonConvert.SerializeObject(obj);
//on retourne la chaine json
context.Response.Clear();
context.Response.ContentType = "text/json";
context.Response.Write(string.Format("{0}({1})", callbackDecorateur, r));
context.Response.End();
}
}
}client side:

Ext.util.JSONP.request({
url: '/myHandler.aspx',
callbackKey: 'callback',
params: {
param1: this.champ1.getValue()
},
callback: function(data) {
console.log(data.r);
if (data.r) {
//fait ce qu'il y a faire
}
}
});i hope it will be helpfull

sorry for my bad english

x33z
27 Oct 2010, 11:38 AM
michelk,

Did you ever figure this out? I'm having the exact same issue (Windows 7, IIS 7.5, C# Web Service) with the result always containing the XML response with the JSON encoded data (that I encode myself), even though I've set the web service to have:


[ScriptMethod(ResponseFormat = ResponseFormat.Json)]I've also tried every header type I can think of in the JS code, and I just can't seem to get the web service to force ONLY the JSON response back over.

I tried to create an iHTTPHndler, but that seemed to mess up my existing ASMX files, so that either does not work or I did not do it right...

I've ended up just removing the XML from the Ext.Ajax.request response (in the success function) and then converting the object for now. This is far from ideal though, so would like to figure it out "for real":



//remove XML from heading
var r = response.responseText.substr(response.responseText.indexOf("[{")).replace("</string>","");

//encode as JSON object
var result = Ext.decode(r); //no "d" header in this response, so don't need to include it
Thanks.

mathieurene
27 Oct 2010, 12:03 PM
in my case, i write my json directly in the output stream and i don't use asmx webservice.(*.json handler instead ).

x33z
27 Oct 2010, 1:03 PM
Ideally I'd like to keep it in the asmx file, as I'm already doing other SOAP-based requests from it. But if I can't figure it out, I may resort to separate services...

I have made progress though. Few things I'd like to share, as it's been a complete pain in getting this to work, and there is no reason for people to struggle through such a simple thing so much :-\

1) make sure IIS has HttpGet configured. Do this from the IIS Manager itself - the web.config for the web service didn't seem to take for whatever reason.

2) Web service. Make sure UseHttpGet is set to true. You will also need to manually encode your datatables/information into JSON format using a third party program or the .NET JSON serializer (which, ironically, won't work with DataTables/Sets at this point...)


[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public string Test()
{
string str = "[{\"username\":\"Admin\",\"first_name\":\"Admin\",\"last_name\":\"istrator\",\"initials\":\"ADM\"}]";
return str;
}
3) Actual client call.


function LoadRecord_AJAX() {
//status bar
Ext.getBody().mask(true, '<div class="demos-loading">Loading&hellip;</div>');

//make request
Ext.Ajax.request({
url: "http://192.168.1.2/webservice/service.asmx/Test",
method: 'GET',
headers: { 'Content-Type': 'application/json;charset=utf-8' },
success: function(response, opts) {
Ext.getBody().unmask();
//response.text is in JSON format:
//{"d":"[{\"username\":\"Admin\",\"first_name\":\"Admin\",\"last_name\":\"istrator\",\"initials\":\"ADM\"}]"}
//so the data has to be decoded twice
var myData = Ext.decode(Ext.decode(response.responseText).d);
//the results were only 1 record, so access it in array [0]
alert(myData[0].username);
},
failure: function() {
Ext.getBody().unmask();
alert('Error');
}
});
};
So it works with the Ajax request, but I can't get the raw header working in the Ext.util.JSON.request. Where would I put the header information for Content-Type in JSON.request???

Thanks in advance...

Riaz
19 Apr 2011, 10:39 PM
I have allmost similar issue. Could you look at bbelow thread

http://www.sencha.com/forum/showthread.php?130560-IIS7-.NET-MVC3-Sencha-Touch-Issue