PDA

View Full Version : [Solved] JsonStore and asp.net web service



mohaaron
14 Jul 2009, 7:39 AM
Hello all,

I have been reading through this thread http://extjs.com/forum/showthread.php?t=59903 as an example to get my web service working and not matter what I've tried I cannot get it to work. I've been working on this for a while now and have finally given in to asking for help.

Can anyone tell me what's wrong with my code? I'm using .net 3.5, webforms, ExtJs 3.0 Final.

I can now say for sure that even though I am using the aspNetJsonReader it's never being fired. I have tried setting a break point in the read function and I can also see that the line console.log('aspNetJsonReader.read()'); is never executed. I don't know why it's not firing and could use some help understanding this as well.

The reason that I'm passing the json back from the service as a string is so I can custom format it with totalRows and rows properties.

ASPX


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JobsGrid.aspx.cs" Inherits="Tests_JobsGrid" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" type="text/css" href="../Common/JavaScript/ext-3.0.0/resources/css/ext-all.css" />
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/ext-all-debug.js"></script>
<script src="../Common/JavaScript/jobsGrid.js" type="text/javascript"></script>
<script type="text/javascript">
Ext.onReady(function() {

Ext.ux.aspNetJsonReader = Ext.extend(Ext.data.JsonReader,{
read : function(response){
console.log('aspNetJsonReader.read()');
var json = response.responseText;
var o = eval("("+json+")");
o = Ext.decode(o.d);
if(!o) {
throw {message: "JsonReader.read: Json object not found"};
}
return this.readRecords(o);
}
});

var grid = new Ext.grid.GridPanel({
id: 'grid',
store: new Ext.data.JsonStore({
id: 'gridStore',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetJobs'
,jsonData: {}
,method: 'post'
, headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.ux.aspNetJsonReader({
root: 'rows'
,totalProperty: 'totalRows'
//,idProperty: 'JobId'
,id: 'JobId'
}),
fields: [
{ name: 'JobId' },
{ name: 'BerthFromCode' },
{ name: 'BerthToCode' },
{ name: 'JobTypeName' },
{ name: 'TugName' }
]
}),
columns: [
{ header: 'JobId', width: 90, sortable: true, dataIndex: 'JobId' },
{ header: 'BerthFromCode', width: 90, sortable: true, dataIndex: 'BerthFromCode' },
{ header: 'BerthToCode', width: 90, sortable: true, dataIndex: 'BerthToCode' },
{ header: 'JobTypeName', width: 90, sortable: true, dataIndex: 'JobTypeName' },
{ header: 'TugName', width: 90, sortable: true, dataIndex: 'TugName' }
],
viewConfig: {
forceFit: true
},
renderTo: 'content',
title: 'My First Grid',
width: 500,
autoHeight: true,
frame: true,
listeners: {
render: function(grid) {
console.log('grid.getStore().load()');
grid.getStore().load();
grid.getStore().on('load', function(store, records, options) {
console.log('grid.getStore().on(load, function()');
grid.getView().focusEl.focus();
grid.getSelectionModel().selectFirstRow();
});
}
}
});
});
</script>
</head>
<body>

<div id="content" />

</body>
</html>
Web Service


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using BayDelta.AppServices;
using BayDelta.LLBLGen.EntityClasses;
using BayDelta.LLBLGen.HelperClasses;
using LLBLGenExtensions.EntityExtensions.JSon;
using LLBLGenExtensions.ExtensionMethods;

/// <summary>
/// Summary description for JobsWebService
/// </summary>
[WebService(Namespace = "http://localhost/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class JobsWebService : System.Web.Services.WebService
{

public JobsWebService()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
//[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public string GetJobs()
{
EntityCollection<JobEntity> jobs = ServiceManager.GetJobManager().GetJobs("2009, 6, 12", "2009, 6, 13");
int count = jobs.Count;
string json = jobs.ToJSon(
JobFields.JobId,
JobFields.BerthFromCode,
JobFields.BerthToCode,
JobFields.JobTypeName,
JobFields.TugName
);

string jresult = "{" + (char)(34) + "totalRows" + (char)(34) + ":" + count + "," + (char)(34) + "rows" + (char)(34) + ":" + json + "}";

return jresult;
//return jobs;
}
}
RESPONSE JSON (from Firebug)


{"d":"{\"totalRows\":18,\"rows\":[{\"JobId\":703,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"ROD 8
\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":704,\"BerthFromCode\":\"STREAM
\",\"BerthToCode\":\"ROD 8\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":705
,\"BerthFromCode\":\"ROD 8\",\"BerthToCode\":\"ROD 8\",\"JobTypeName\":\"Standby\",\"TugName\":\"DELTA
LINDA\"},{\"JobId\":706,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"OAK 22\",\"JobTypeName\":\"Docking
\",\"TugName\":\"AMNAV LIBERTY\"},{\"JobId\":707,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"SFO 35S
\",\"JobTypeName\":\"Docking\",\"TugName\":\"GOLIAH\"},{\"JobId\":708,\"BerthFromCode\":\"STREAM\",\"BerthToCode
\":\"SFO 35S\",\"JobTypeName\":\"Docking\",\"TugName\":\"FOSS AMERICA\"},{\"JobId\":709,\"BerthFromCode
\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"STARLIGHT Z-4\"
},{\"JobId\":710,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking
\",\"TugName\":\"FOSS LYNN MARIE\"},{\"JobId\":693,\"BerthFromCode\":\"MRZ 3\",\"BerthToCode\":\"STREAM
\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":694,\"BerthFromCode\":\"MRZ
8\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId
\":695,\"BerthFromCode\":\"MRZ 8\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName
\":\"GOLIAH\"},{\"JobId\":696,\"BerthFromCode\":\"MRZ 8\",\"BerthToCode\":\"SFO Z1\",\"JobTypeName\"
:\"Escort\",\"TugName\":\"GOLIAH\"},{\"JobId\":697,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM
\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":698,\"BerthFromCode\":\"OAK
30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"AMNAV\"},{\"JobId\":699
,\"BerthFromCode\":\"SFO Z1\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Escort\",\"TugName\":\"DELTA
LINDA\"},{\"JobId\":700,\"BerthFromCode\":\"SFO Z6\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Escort
\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":701,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"MRZ 5
\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":702,\"BerthFromCode\":\"STREAM
\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA LINDA\"}]}"}

tryanDLS
14 Jul 2009, 9:14 AM
Go back and read http://extjs.com/learn/Ext_FAQ_Grid

Attaching a load handler after load has executed has no effect.

mohaaron
14 Jul 2009, 9:33 AM
OK, I just realized that the line I had that said // THIS NEVER FIRES was incorrect. The store load function does fire, I just don't get any data in the grid.

mohaaron
14 Jul 2009, 9:36 AM
Here is a screen shot of what I have so far.

tryanDLS
14 Jul 2009, 11:32 AM
Look at the Net tab and see what your JSON response looks like. Also I don't why you're extending JsonReader to do this - assuming you send the response in the correct format, that processing is done for you.

Add a handler for the exception event too and see if you get there.

mohaaron
14 Jul 2009, 1:10 PM
The json response in Firebug Net is the same as the json response from the Firebug Console which I have in my first post. Is there something I don't understand about your question? The json is valid, I have tested it. The JsonReader was extended to deal with the additional d{} wrapper that .NET web services add to the response.

I'll go ahead and add the exception event and get post the results that I get.

thanks for the help.

Animal
14 Jul 2009, 1:17 PM
JsonReader can handle that:



reader: new Ext.ux.aspNetJsonReader({
root: 'd.rows'
,totalProperty: 'd.totalRows'
,idProperty: 'JobId'
}),

mohaaron
14 Jul 2009, 1:37 PM
Hello Animal,

Yes, I have tried your suggestion with no change. I have also now added the exception handler. The exception handler is not being fired so it seems there is no exception. What else can I check to figure this out?



<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JobsGrid.aspx.cs" Inherits="Tests_JobsGrid" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" type="text/css" href="../Common/JavaScript/ext-3.0.0/resources/css/ext-all.css" />
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/ext-all-debug.js"></script>
<script src="../Common/JavaScript/jobsGrid.js" type="text/javascript"></script>
<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>
<script type="text/javascript">
Ext.onReady(function() {

Ext.ux.aspNetJsonReader = Ext.extend(Ext.data.JsonReader,{
read : function(response){
console.log('aspNetJsonReader.read()');
var json = response.responseText;
var o = eval("("+json+")");
o = Ext.decode(o.d);
if(!o) {
throw {message: "JsonReader.read: Json object not found"};
}
return this.readRecords(o);
}
});

var grid = new Ext.grid.GridPanel({
id: 'grid',
store: new Ext.data.JsonStore({
id: 'gridStore',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetJobs'
,jsonData: {}
,method: 'post'
, headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.ux.aspNetJsonReader({
root: 'rows'
,totalProperty: 'totalRows'
//,idProperty: 'JobId'
,id: 'JobId'
}),
fields: [
{ name: 'JobId' },
{ name: 'BerthFromCode' },
{ name: 'BerthToCode' },
{ name: 'JobTypeName' },
{ name: 'TugName' }
],
listeners: {
exception: function(misc) {
console.log('exception');
}
}
}),
columns: [
{ header: 'JobId', width: 90, sortable: true, dataIndex: 'JobId' },
{ header: 'BerthFromCode', width: 90, sortable: true, dataIndex: 'BerthFromCode' },
{ header: 'BerthToCode', width: 90, sortable: true, dataIndex: 'BerthToCode' },
{ header: 'JobTypeName', width: 90, sortable: true, dataIndex: 'JobTypeName' },
{ header: 'TugName', width: 90, sortable: true, dataIndex: 'TugName' }
],
viewConfig: {
forceFit: true
},
renderTo: 'content',
title: 'My First Grid',
width: 500,
autoHeight: true,
frame: true,
listeners: {
render: function(grid) {
console.log('grid.getStore().load()');
grid.getStore().load();
grid.getStore().on('load', function(store, records, options) {
console.log('grid.getStore().on(load, function()');
grid.getView().focusEl.focus();
grid.getSelectionModel().selectFirstRow();
});
}
}
});
});
</script>
</head>
<body>

<div id="content" />

</body>
</html>

mohaaron
14 Jul 2009, 1:49 PM
I also don't understand why the aspNetJsonReader.read event is never being fired. Why is this not happening?

I have also tried setting a break point in the store.load event and see that the stores reader contains the json data in store.reader.jsonData.d as you can see in the attachment. So it seems to be there but is not being loaded into the grid.

tryanDLS
14 Jul 2009, 2:21 PM
Maybe give you grid a height?

mohaaron
14 Jul 2009, 2:36 PM
OK, I gave is a height and commented out autoHeight. Still the same thing, now I have a taller empty grid. Screen shot attached.

Updated with height.


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="JobsGrid.aspx.cs" Inherits="Tests_JobsGrid" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link rel="stylesheet" type="text/css" href="../Common/JavaScript/ext-3.0.0/resources/css/ext-all.css" />
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../Common/JavaScript/ext-3.0.0/ext-all-debug.js"></script>
<script src="../Common/JavaScript/jobsGrid.js" type="text/javascript"></script>
<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>
<script type="text/javascript">
Ext.onReady(function() {

Ext.ux.aspNetJsonReader = Ext.extend(Ext.data.JsonReader,{
read : function(response){
console.log('aspNetJsonReader.read()');
var json = response.responseText;
var o = eval("("+json+")");
o = Ext.decode(o.d);
if(!o) {
throw {message: "JsonReader.read: Json object not found"};
}
return this.readRecords(o);
}
});

var grid = new Ext.grid.GridPanel({
id: 'grid',
store: new Ext.data.JsonStore({
id: 'gridStore',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetJobs'
,jsonData: {}
,method: 'post'
, headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.ux.aspNetJsonReader({
root: 'rows'
,totalProperty: 'totalRows'
//,idProperty: 'JobId'
,id: 'JobId'
}),
fields: [
{ name: 'JobId' },
{ name: 'BerthFromCode' },
{ name: 'BerthToCode' },
{ name: 'JobTypeName' },
{ name: 'TugName' }
],
listeners: {
exception: function(misc) {
console.log('exception');
}
}
}),
columns: [
{ header: 'JobId', width: 90, sortable: true, dataIndex: 'JobId' },
{ header: 'BerthFromCode', width: 90, sortable: true, dataIndex: 'BerthFromCode' },
{ header: 'BerthToCode', width: 90, sortable: true, dataIndex: 'BerthToCode' },
{ header: 'JobTypeName', width: 90, sortable: true, dataIndex: 'JobTypeName' },
{ header: 'TugName', width: 90, sortable: true, dataIndex: 'TugName' }
],
viewConfig: {
forceFit: true
},
renderTo: 'content',
title: 'My First Grid',
width: 600,
height: 200,
//autoHeight: true,
frame: true,
listeners: {
render: function(grid) {
console.log('grid.getStore().load()');
grid.getStore().load();
grid.getStore().on('load', function(store, records, options) {
console.log('grid.getStore().on(load, function()');
grid.getView().focusEl.focus();
grid.getSelectionModel().selectFirstRow();
});
}
}
});
});
</script>
</head>
<body>

<div id="content" />

</body>
</html>

mohaaron
14 Jul 2009, 2:49 PM
I just commented out the the usage of aspNetJsonReader in the grid and now get an exception event. I now get the error "root is undefined". What's wrong with using d.rows?

Attached is a pic of the debug window in the exception event showing the responseText.



var grid = new Ext.grid.GridPanel({
id: 'grid',
store: new Ext.data.JsonStore({
id: 'gridStore',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetJobs'
,jsonData: {}
,method: 'post'
, headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
//reader: new Ext.ux.aspNetJsonReader({
root: 'd.rows'
,totalProperty: 'd.totalRows'
//,idProperty: 'JobId'
,id: 'JobId'
//})
,fields: [
{ name: 'JobId' },
{ name: 'BerthFromCode' },
{ name: 'BerthToCode' },
{ name: 'JobTypeName' },
{ name: 'TugName' }
],
listeners: {
exception: function(misc) {
console.log('exception');
}
}
}),

Animal
14 Jul 2009, 11:34 PM
So go back through the call stack and see who threw the exception and why. It's a VERY simple job.

mohaaron
16 Jul 2009, 12:48 PM
I've found where in ext-all-debug.js the exception is being thrown but I don't understand why.

Line: 33358
var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;

When "var root = this.getRoot(o)" executes it runs the this function which returns null.

function anonymous(obj) {
return obj.d.rows;
}

When "c = root.length" executes root is undefined and throws "'length' is null or not an object".

I can see what's happening but I don't know how to fix it.

andycramb
16 Jul 2009, 2:20 PM
@mohaaron

You are correct you do not need the aspNetJsonReader.
I did it to correct my original attempt at returning JSON from the web service where I was incorretly serializing an object twice resulting in JSON being returned like this.


"{"d:": "{myJson object}"}"I don't know if you got to the last post in the first page. I attempted to explain that the aspNetJsonReader was no longer required and to use a JSON reader as follows:


, reader: new Ext.data.JsonReader({
root: 'd.Requests'
,totalProperty: 'd.TotalJars'....In your code below you no longer have any reader.
It is commented out
If you put it back in as follows and see what happens


reader: new Ext.data.JsonReader({
root: 'd.rows'
,totalProperty: 'd.totalRows'
,id: 'JobId'
})
If you look at the correct way to do it(grid at the bottom left of the page on the example site) you can see that I use the following code.
Note that Ext.ux.aspNetJsonReader is commented out and not used


AF.myReqStore = new Ext.data.Store({
id: 'searchReqResultsStore'
, proxy: new Ext.data.HttpProxy({
// url: 'WebService1.asmx/getAFJsonString'
url: url
, jsonData: {}//for FF
, method: 'post'
, headers: { 'Content-Type': 'application/json;charset=utf-8' }
})
//, reader: new Ext.ux.aspNetJsonReader({
, reader: new Ext.data.JsonReader({
root: 'd.Requests'
, totalProperty: 'd.TotalJars'
}, [
{ name: 'RequestName', mapping: 'RequestName' }
, { name: 'RequestType', mapping: 'RequestType' }
, { name: 'Status', mapping: 'Status' }
, { name: 'WFID', mapping: 'WFID', type: 'float' }
, { name: 'WorkFlows', mapping: 'WorkFlows', type: 'float' }
//,{name:'lastname',mapping:'lastname'}
])
})This handles this JSON


{"d":{"ParentRequestID":1,"TotalJars":8,"Pending":1,"Opened":7,"Status":"All Tasks Complete","WFID":123456
,"Requests":[{"RequestType":"Mortgage"

mohaaron
2 Aug 2009, 1:26 PM
andycramb,

Here is my attempt at making this work the way you have. When I run the code (below) I get a "Record is undefined" error at line 33354 of ext-all-debug.js. Can you tell me why this is happening?

html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="../Common/Scripts/ext-3.0.0/resources/css/ext-all.css" />
<!-- <script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script> -->
<script type="text/javascript" src="../Common/Scripts/ext-3.0.0/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../Common/Scripts/ext-3.0.0/ext-all-debug.js"></script>
<script src="../Common/Scripts/jobsGrid.js" type="text/javascript"></script>
<script type="text/javascript">
Ext.onReady(function() {

var grid = new Ext.grid.GridPanel({
id: 'grid',
store: new Ext.data.JsonStore({
id: 'gridStore',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetJobs'
,method: 'post'
,jsonData: {}
,headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.data.JsonReader({
root: 'd.rows'
,totalProperty: 'd.totalRows'
,idProperty: 'JobId'
}, [
{ name: 'JobId' },
{ name: 'BerthFromCode' },
{ name: 'BerthToCode' },
{ name: 'JobTypeName' },
{ name: 'TugName' }
])
// ,listeners: {
// beforeload: function(gridStore, options) {
// console.log('beforeload: gridStore.count = ' + gridStore.getCount());
// //console.log(options);
// },
// load: function(gridStore, records, options) {
// console.log('load: ' + gridStore.getCount());
// //console.log(options);
// },
// exception: function(misc) {
// console.log('exception:');
// console.log(misc);
// }
// }
}),
columns: [
{ header: 'JobId', width: 90, sortable: true, dataIndex: 'JobId' },
{ header: 'BerthFromCode', width: 90, sortable: true, dataIndex: 'BerthFromCode' },
{ header: 'BerthToCode', width: 90, sortable: true, dataIndex: 'BerthToCode' },
{ header: 'JobTypeName', width: 90, sortable: true, dataIndex: 'JobTypeName' },
{ header: 'TugName', width: 90, sortable: true, dataIndex: 'TugName' }
],
viewConfig: {
forceFit: true
},
renderTo: 'content',
title: 'My First Grid',
width: 600,
height: 200,
frame: true,
listeners: {
render: function(grid) {
console.log('grid.render');
grid.getStore().load();
grid.getStore().on('load', function(grid, records, options) {
console.log('grid.getStore().on(load, function()');
grid.getSelectionModel().selectFirstRow();
grid.getView().focusEl.focus();
});
}
}
});
});
</script>
</head>
<body>

<div id="content" />

</body>
</html>
json


{"d":"{\"totalRows\":18,\"rows\":[{\"JobId\":703,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"ROD 8\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":704,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"ROD 8\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":705,\"BerthFromCode\":\"ROD 8\",\"BerthToCode\":\"ROD 8\",\"JobTypeName\":\"Standby\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":706,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"OAK 22\",\"JobTypeName\":\"Docking\",\"TugName\":\"AMNAV LIBERTY\"},{\"JobId\":707,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"SFO 35S\",\"JobTypeName\":\"Docking\",\"TugName\":\"GOLIAH\"},{\"JobId\":708,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"SFO 35S\",\"JobTypeName\":\"Docking\",\"TugName\":\"FOSS AMERICA\"},{\"JobId\":709,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"STARLIGHT Z-4\"},{\"JobId\":710,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"FOSS LYNN MARIE\"},{\"JobId\":693,\"BerthFromCode\":\"MRZ 3\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":694,\"BerthFromCode\":\"MRZ 8\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":695,\"BerthFromCode\":\"MRZ 8\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"GOLIAH\"},{\"JobId\":696,\"BerthFromCode\":\"MRZ 8\",\"BerthToCode\":\"SFO Z1\",\"JobTypeName\":\"Escort\",\"TugName\":\"GOLIAH\"},{\"JobId\":697,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":698,\"BerthFromCode\":\"OAK 30\",\"BerthToCode\":\"STREAM\",\"JobTypeName\":\"Undocking\",\"TugName\":\"AMNAV\"},{\"JobId\":699,\"BerthFromCode\":\"SFO Z1\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Escort\",\"TugName\":\"DELTA LINDA\"},{\"JobId\":700,\"BerthFromCode\":\"SFO Z6\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Escort\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":701,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA BILLIE\"},{\"JobId\":702,\"BerthFromCode\":\"STREAM\",\"BerthToCode\":\"MRZ 5\",\"JobTypeName\":\"Docking\",\"TugName\":\"DELTA LINDA\"}]}"}

andycramb
2 Aug 2009, 2:30 PM
Do you have firebug up and running, preferably the version with the JSON tab in the XHR response.
Do you see that your d property is set to a string and not an object.

It should be like this:


{"d":{"rows":[{"id":"1"},{},{}]}}

You have this:


{"d":"{\"totalRows\":18,\"rows\":[{\"JobId\":703,\"....

I think this is where the problem lies

mohaaron
2 Aug 2009, 4:29 PM
How do I fix this. I'm return the json as a string from the web service and the web service is adding the d and the double quotes. How can I fix this?

andycramb
3 Aug 2009, 1:19 AM
Lets have a look at your .NET code that returns the JSON

mohaaron
4 Aug 2009, 10:11 AM
Here are two different methods that I have tried that both give the same "Record is undefined" error.



[WebMethod]
//[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public string GetJobs()
{
EntityCollection<JobEntity> jobs = ServiceManager.GetJobManager().GetJobs("2009, 6, 12", "2009, 6, 13");
int count = jobs.Count;
string json = jobs.ToJSon(
JobFields.JobId,
JobFields.BerthFromCode,
JobFields.BerthToCode,
JobFields.JobTypeName,
JobFields.TugName,
JobOrderFields.ShipName
);

string jresult = "{" + (char)(34) + "totalRows" + (char)(34) + ":" + count + "," + (char)(34) + "rows" + (char)(34) + ":" + json + "}";

return jresult;
}

[WebMethod]
public string GetShips()
{
System.Text.StringBuilder json = new System.Text.StringBuilder();
EntityCollection<ShipEntity> ships = ServiceManager.GetMiscDataManager().GetShips();

json.Append("{rows:[");
foreach (ShipEntity ship in ships)
{
json.Append("{ShipId:" + ship.ShipId + ", ShipName:\"" + ship.ShipName + "\"}");
}
json.Append("]}");

return json.ToString();
}

andycramb
4 Aug 2009, 12:31 PM
Ok here is the approach I now take to send json back from .NET whether its MVC or a web service.
I tend to build an anonymous object to provide the EXT JS required data structure around a list of objects and let the framework do the serialization. MVC example:


[AcceptVerbs(HttpVerbs.Get)]
public JsonResult List()
{
try
{
var allConversations = conversationRepositry.FindJustAllConversations();
// this works -- return Json(allConversations);
return Json(new { rows = allConversations, success = true });
}
catch (Exception e)
{
string error = "{'success': 'false', 'error': 'there has been an error'}";
return Json(error);

}
}A good example (http://encosia.com/2009/02/10/a-breaking-change-between-versions-of-aspnet-ajax/)of explaining this is done by Dave Ward. He also points out that there is no need to serialize your response.

My code would look like the code below. I helped some guy with this before and there is an example of it on my site (http://www.cramb.org.uk/webservice1/default1.aspx). This is a lot cleaner to my mind and more performant.

Web service code for this example is:



[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Person getPerson(Person myPerson)
{
// this one is slightly different as .NET realises that I have sent back a person object(form attributes match on the UI)
// I change the lastName property to Smith
//sorry your last name is definitely Smith
myPerson.LastName = "Smith";

return myPerson;
}

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<Person> getTreeData(string node)
{
List<Person> people = new List<Person>()
{
new Person { FirstName="Andy", LastName="Todd", Age=21, Height=221 },
new Person { FirstName="Dave", LastName="Nelson", Age=1, Height=1 },
new Person { FirstName="Lil", LastName="Edgar", Age=24, Height=121 },
new Person { FirstName="Ian", LastName="Davis", Age=11, Height=190 }
};

return people;
}

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<Tree> getTreeData1(string node)
{
List<Tree> trees = new List<Tree>()
{
new Tree{ id=1, text="Fred", leaf=true, cls="file"},
new Tree{ id=2, text="Dave", leaf=true, cls="file"},
new Tree{ id=3, text="Lil", leaf=true, cls="file"},
new Tree{ id=4, text="Ian", leaf=true, cls="file"},
};

return trees;
}

mohaaron
4 Aug 2009, 1:17 PM
In your web service example your not passing back the collections with properties to use for "root" and "totalProperty"? How do you call this using a reader?

What does your AllConversations class look like? Is there some way I can do the MVC way in the web service?

I also have a little problem with the method your showing me when a datetime property is part of the entity. Ext does not work well with the .net datetime type.

andycramb
4 Aug 2009, 1:57 PM
In your web service example your not passing back the collections with
properties to use for "root" and "totalProperty"? How do you call this
using a reader?In the reader:
Your root will be d.rows
Yout totalProperty will be d.totalProperty


[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
// public List<Person> getTreeData(string node)
public Object getTreeData()
{
List<Person> people = new List<Person>()
{
new Person { FirstName="Andy", LastName="Todd", Age=21, Height=221 },
new Person { FirstName="Dave", LastName="Nelson", Age=1, Height=1 },
new Person { FirstName="Lil", LastName="Edgar", Age=24, Height=121 },
new Person { FirstName="Ian", LastName="Davis", Age=11, Height=190 }
};

var data = new { rows = people, success = true, totalProperty = people.Count};

return data;
}

Is there some way I can do the MVC way in the web service?Nope try the above


I also have a little problem with the method your showing me when a
datetime property is part of the entity. Ext does not work well withYeah I have heard that it is slightly tricky
I have not used it yet but I believe there are quite a few posts around on how to handle it
the .net datetime type.

mohaaron
4 Aug 2009, 2:02 PM
I found that the json.net library works really well for fixing the datetime problem. I'm asking the question because I'm now thinking about how to mix it into the problem we're discussing here.

andycramb
4 Aug 2009, 2:14 PM
Would love to give you a qualified answer on this but not had a chance to bump in to this one yet.

Seen some stuff on the forums (http://extjs.com/forum/showthread.php?p=30648) though so you may have to use a custom parser to deal with the formatting

mohaaron
4 Aug 2009, 2:18 PM
I've updated my code to match yours and the json looks more correct but I still get the same "Record is undefined error". Earlier I was trying to solve this problem using a grid which never worked. I have now moved to trying to do this in a combobox using the shipStore.

UPDATED: The json I posted was not up to date.

ext


var shipStore = new Ext.data.JsonStore({
id: 'ShipId',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetShips'
,method: 'post'
,jsonData: {}
,headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.data.JsonReader({
root: 'd.rows',
totalProperty: 'd.totalRows',
idProperty: 'ShipId'
}, [
{ name: 'ShipId' },
{ name: 'ShipName' }
])
,listeners: {
beforeload: function(store, options) {
console.log('beforeload');
//console.dir(store);
//console.log(options);
},
load: function(store, records, options) {
console.log('load');
//console.dir(store);
//console.log(options);
},
exception: function(dataProxy, type, action, options, response, args) {
console.log('exception');
console.dir(args);
}
}
});
shipStore.load();
web service


public object GetShips()
{
EntityCollection<ShipEntity> ships = ServiceManager.GetMiscDataManager().GetShips();

List<Ship> list = new List<Ship>();
for(int i = 0; i < ships.Count; i++)
{
ShipEntity shipentity = ships[i];
Ship ship = new Ship();
ship.ShipId = shipentity.ShipId;
ship.ShipName = shipentity.ShipName;
list.Add(ship);
}

var data = new { success = true, totalRows = list.Count, rows = list };

return data;
}
json


{"d":{"success":true,"totalRows":20,"rows":[{"ShipId":2218,"ShipName":"AZTEC"},{"ShipId":2219,"ShipName":"BRO ARTHUR"},{"ShipId":2220,"ShipName":"BRO CHARLOTTE"},{"ShipId":2221,"ShipName":"BRO PRIORITY"},{"ShipId":2222,"ShipName":"BT ALASKA"},{"ShipId":2223,"ShipName":"BT NAVIGATOR"},{"ShipId":2224,"ShipName":"BT NIMROD"},{"ShipId":2225,"ShipName":"BU YI HE"},{"ShipId":2226,"ShipName":"BUJIN"},{"ShipId":2227,"ShipName":"BULWARK/101"},{"ShipId":2228,"ShipName":"BUM CHIN"},{"ShipId":2229,"ShipName":"BUM DONG"},{"ShipId":2230,"ShipName":"BUM EUN"},{"ShipId":2231,"ShipName":"BUM SHIN"},{"ShipId":2232,"ShipName":"BUN CHIN"},{"ShipId":2233,"ShipName":"BUNGA KANTAN DUA"},{"ShipId":2234,"ShipName":"BUSAN EXPRESS"},{"ShipId":2235,"ShipName":"BW LENA"},{"ShipId":2236,"ShipName":"C. COLUMBUS"},{"ShipId":2237,"ShipName":"C. F. CAMPBELL/JOVALAN"}]}}

andycramb
4 Aug 2009, 2:27 PM
d.totalRows should it not be d.totalProperty

mohaaron
4 Aug 2009, 2:30 PM
Sorry, I just didn't update the json text in here. It is actually correct. I'll update the post to show the correct json now.

andycramb
4 Aug 2009, 2:39 PM
just looking at the Ext stuff

Just for the time being change your store to a normal store as the JsonStore is a helper class for dealing with JSON and has the proxy and the reader "built in"

So if you go with the store and then see how it goes

mohaaron
4 Aug 2009, 2:48 PM
I thought that I had to use the HttpProxy so I could pass the header specifying the response as json? When I just us a plain JsonStore with the built in proxy and reader I get "Content-Type text/plain; charset=utf-8" as the response type and then the Firebug response looks like junk, it's a bunch if funny characters.

andycramb
4 Aug 2009, 2:50 PM
Yes I believe you are correct but just use a normal Store


var shipStore = new Ext.data.Store({
id: 'ShipId',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetShips'
,method: 'post'
,jsonData: {}
,headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
reader: new Ext.data.JsonReader({
root: 'd.rows',
totalProperty: 'd.totalRows',
idProperty: 'ShipId'
}, [
{ name: 'ShipId' },
{ name: 'ShipName' }
])

mohaaron
4 Aug 2009, 2:51 PM
Yeah! No I've got something. Thinking about what you said I decided to try and just remove the reader and leave the proxy. This works.



var shipStore = new Ext.data.JsonStore({
id: 'ShipId',
proxy: new Ext.data.HttpProxy({
url: '../WebServices/JobsWebService.asmx/GetShips'
,method: 'post'
,jsonData: {}
,headers: { 'Content-Type': 'application/json; charset=utf-8;' }
}),
root: 'd.rows',
totalProperty: 'd.totalRows',
idProperty: 'ShipId',
fields: ['ShipId', 'ShipName']
});
shipStore.load();

andycramb
4 Aug 2009, 2:56 PM
Yes you beauty :D

You could leave the reader and change the store

var shipStore = new Ext.data.JsonStore({

to


var shipStore = new Ext.data.Store({

mohaaron
4 Aug 2009, 3:02 PM
I think for now I'm going to leave this alone. That felt like it took a lot of time. I'm so happy to have it working I'm not touching it for a while. I think I can now use this example to get other JsonStore's working using web services.

userofit
3 Mar 2011, 7:05 AM
Ext.onReady(function() {
Ext.Ajax.request({
url: '/Default.aspx/ClientCallHandler',
success: function(res) {
jsonString = res.responseText;
showData(jsonString);
},
failure: function() { alert('failure getting new data'); },
jsonData: '{action: "GetData", month: 1}',
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
});
});
function showData(jsonString) {
var json = Ext.decode(jsonString);
json = Ext.decode(json.d);
var store = new Ext.data.JsonStore({
proxy: new Ext.data.MemoryProxy(json),
totalProperty: 'totalCount',
root: 'rows',
idProperty: 'ID',
fields: [{ name: 'ID' }, { name: 'Image' }, { name: 'Clarity' }, { name: 'Colour' },
{ name: 'Cut' }, { name: 'Size' }, { name: 'WholeSalePrice' }, { name: 'inStock' },{ name: 'Name' }
]
});
store.load();

////other stuff ...
}