jqGrid Not Loading Data

I'm sure this is something simple that I'm missing, but I just can't seem to find it. I have a simple jqGrid specified here:

$('#mainGrid').jqGrid({
    datatype: 'local',
    colNames: ['id', 'name'],
    colModel: [
        { name: 'id', index: 'id', width: 100 },
        { name: 'name', index: 'name', width: 300 }
    ],
    rowNum: 9999,
    sortname: 'name',
    viewrecords: true,
    sortorder: 'asc',
    data: [{"id":"924c18a4-cad6-4b6a-97ef-f9ca61614530","name":"Pathway 1"},{"id":"54897f40-49ab-4abd-acac-6047006c7cc7","name":"Pathway 2"},{"id":"61542c48-102f-4d8e-ba9f-c24c64a20d28","name":"Pathway 3"},{"id":"c4ca9575-7353-4c18-b38a-33b383fcd8b2","name":"Pathway 4"}]
});

This loads correctly. Simple proof of concept. Now I try to replace the local data with a call to a server resource:

$('#mainGrid').jqGrid({
    url: 'AJAXHandler.aspx',
    datatype: 'json',
    colNames: ['id', 'name'],
    colModel: [
        { name: 'id', index: 'id', width: 100 },
        { name: 'name', index: 'name', width: 300 }
    ],
    rowNum: 9999,
    sortname: 'name',
    viewrecords: true,
    sortorder: 'asc'
});

The server resource returns the same data. But the grid isn't loading the data. (At least, it's not showing any records.) I've confirmed with FireBug that the resource is indeed being called and is returning the expected data.

At first I thought that the content type in the resource's response should be changed to application/json, but that made no difference. Is there something else wrong with that response that's preventing the grid from loading the data?

Firebug output for the server resource:

Response Headers
  Cache-Control     private
  Content-Length    261
  Content-Type      text/html; charset=utf-8
  Server            Microsoft-IIS/6.0
  MicrosoftSharePointTeamSe...    12.0.0.6219
  X-Powered-By      ASP.NET
  X-AspNet-Version  2.0.50727
  Set-Cookie        WSS_KeepSessionAuthenticated=80; path=/
  Date              Sat, 23 Apr 2011 14:35:43 GMT

Request Headers
  Host              cyber0ne.com
  User-Agent        Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16
  Accept            application/json, text/javascript, */*; q=0.01
  Accept-Language   en-us,en;q=0.5
  Accept-Encoding   gzip,deflate
  Accept-Charset    ISO-8859-1,utf-8;q=0.7,*;q=0.7
  Keep-Alive        115
  Connection        keep-alive
  X-Requested-With  XMLHttpRequest
  Referer           http://cyber0ne.com/dovetail_pages/Member/Pathways.aspx?MemberID=b428e0a7-dd55-de11-8e97-0016cfe25fa3
  Cookie            WSS_KeepSessionAuthenticated=80

Params
  _search   false
  nd        1303569347783
  page      1
  rows      9999
  sidx      name
  sord      asc

Response
  [{"id":"4d4b8249-b5f9-4da6-aba2-bf3af588d560","name":"Pathway 1"},{"id":"230184e6-44cc-4274-97fd-b455440cd9c0","name":"Pathway 2"},{"id":"7f938218-b963-495f-9646-f3cfb1e63ea1","name":"Pathway 3"},{"id":"2b17f23e-5500-4b01-ac1c-df2de90dc511","name":"Pathway 4"}]

Update:

Per @Paul Creasey's answer below, the response content is now:

{"total":4,"page":1,"records":4,"rows":[{"id":"55132687-b0bd-4c89-97cb-122d127429eb","name":"Pathway 1"},{"id":"123ba476-1560-4148-ae96-968bdd10e190","name":"Pathway 2"},{"id":"43f5660b-141c-4ccc-848e-6b41667b399a","name":"Pathway 3"},{"id":"b0d21316-d07d-4b46-8011-89c3cb07a8f6","name":"Pathway 4"}]}

The behavior has changed slightly. The grid now says "Loading" but still doesn't load the data.


The answer of Paul is absolutely correct. You should just use jsonReader : {repeatitems: false}. I decide to write some more additional information only to clear why jqGrid could not read your original data at the beginning. I want additionally describe how jsonReader parameter can help to read JSON or XML data returned from the server.

First of all you can read almost any input JSON data in jqGrid. You should just define the jsonReader parameter which describe how the data should be read. For example the data in your original format do can be read by jqGrid with respect of the following jsonReader:

jsonReader: {
    repeatitems: false,
    page: function() { return 1; },
    root: function (obj) { return obj; },
    records: function (obj) { return obj.length; }
}

You can see on the demo that the way really works. You can read more about this in my old answer where I suggested to use functions as parameters of jsonReader in situations like youth.

Why is it needed at all to provide the data in so strange form in the server response? Why the jsonReader is needed? The reason is that jqGrid allows the server to implement sorting, paging and optionally filtering/searching. So the request to the server is not like "please get me the list of the users", but more like "please sort the users by the last name and get me the 5-th page of the data where the page consists of 10 rows". The page size (10 in the case) will be get from the combobox of the jwGrid pager. The rowList array parameter defines the list of possible values and the user can choose the page size which he/she prefer.

The returned data should contain not only up to 10 requested rows of the data, but tree additional parameters: "total", "page" and "records" which describes some fields which will be filled in the pager:

enter image description here

The data, which build the grid contain, are array of objects. Every array item hold the information about one grid row. The array item can be either the object with named properties like

{"id":"55132687-b0bd-4c89-97cb-122d127429eb","name":"Pathway 1"}

or the object like

{"id":"55132687-b0bd-4c89-97cb-122d127429eb",
 cell:["55132687-b0bd-4c89-97cb-122d127429eb","Pathway 1"]}

or the arrays like

["55132687-b0bd-4c89-97cb-122d127429eb","Pathway 1"]

To read data in the first format one should use jsonReader:{repeatitems:false}. The second format is default and to read the data one need not define any jsonReader. To read data in the last format we should define jsonReader:{cell:''} and additionally key:true for the id column. The last format in the most compact, but it can be used only if one from the column of jqGrid has unique data which can be interpret as the id. The id is important, because jqGrid build HTML table with <tr> element having exactly the id which one post back. No id duplicates inside one page are permitted corresponds to HTML specifications.

The final remark. If you don't can or don't want to implement paging and sorting on the server side you should return all data in the server response and use loadonce:true parameter of jqGrid. This will follow to changing the datatype parameter of jqGrid to 'local' after the first data load. After that, the sorting and paging of data will be done inside of JavaScript code of jqGrid.


According to the docs here, the expected json format is:

{ 
  "total": "xxx", 
  "page": "yyy", 
  "records": "zzz",
  "rows" : [
    {"id" :"1", "cell" :["cell11", "cell12", "cell13"]},
    {"id" :"2", "cell":["cell21", "cell22", "cell23"]},
      ...
  ]
}

Therefore you web service should be returning this:

{
    "total": "4",
    "page": "1",
    "records": "4",
    "rows" : [
        {
            "id": "4d4b8249-b5f9-4da6-aba2-bf3af588d560",
            "name": "Pathway 1" 
        },
        {
            "id": "230184e6-44cc-4274-97fd-b455440cd9c0",
            "name": "Pathway 2" 
        },
        {
            "id": "7f938218-b963-495f-9646-f3cfb1e63ea1",
            "name": "Pathway 3" 
        },
        {
            "id": "2b17f23e-5500-4b01-ac1c-df2de90dc511",
            "name": "Pathway 4" 
        } 
    ]
}

At the moment you only have the rows array.

You could implement your own function to read the json, but i've never done this, see the "jsonReader as Function" section of the link above.


Edit:

I was wrong initially, either you should set the repeatitems flag to false:

jsonReader : {
   repeatitems: false
},

and use the json above (i think!) or return data like this:

{
    "total": "4",
    "page": "1",
    "records": "4",
    "rows" : [
        {
            "id": "4d4b8249-b5f9-4da6-aba2-bf3af588d560",
            "cells" : ["Pathway 1"]
        },
        {
            "id": "230184e6-44cc-4274-97fd-b455440cd9c0",
            "cells" : ["Pathway 2"]
        },
        {
            "id": "7f938218-b963-495f-9646-f3cfb1e63ea1",
            "cells" : ["Pathway 3"]
        },
        {
            "id": "2b17f23e-5500-4b01-ac1c-df2de90dc511",
            "cells" : ["Pathway 4"] 
        } 
    ]
}

I've always done the latter, but i think the former is probably better!