I eventually gave up on JSON (with ASP.NET) and just used XML. Then everything just works.
Make sure the return type from your asmx is XmlDocument
A good summary of everything you need to do to make it work (on the client side at least) can be found on the the JQGrid wiki
Look at their sample XML and make sure what your service returns a buffer (best to validate with Fiddler) that follows the same schema.
UPDATE - Some Code samples
Here is the client side script to create the grid
var mygrid = $("#list").jqGrid({
url: '../../webServices/callsGridService.asmx/getCallsGridDataXML?nd=' + new Date().getTime(),
datatype: 'xml',
mtype: 'POST',
contentType: "text/xml",
colNames: ['Call ID', 'Date / Time', 'Duration'],
colModel: [
{ name: 'callId', index: 'callId', align: "right", key: true },
{ name: 'callTime', index: 'callTime', sorttype: 'date' },
{ name: 'duration', index: 'duration', align: "right" }
],
pager: $('#pager'),
rowNum: 10,
rowList: [10, 25, 50, 100],
sortname: 'callTime',
viewrecords: true,
sortorder: "desc",
height: "100%",
multiselect: true,
rownumbers: true,
gridview: true,
autowidth: true,
caption: "Calls"
})
And here is the service code (VB.NET):
Public Function getCallsGridDataXML() As XmlDocument
Dim xmlRet As New XmlDocument
Dim ret As New StringBuilder
m_pageNum = CInt(HttpContext.Current.Request.Form.Item("page"))
If m_pageNum = Nothing OrElse m_pageNum = 0 Then
m_pageNum = 1
End If
m_pageSize = CInt(HttpContext.Current.Request.Form.Item("rows"))
If m_pageSize = Nothing OrElse m_pageSize = 0 Then
m_pageSize = 10
End If
m_sortItem = CStr(HttpContext.Current.Request.Form.Item("sidx"))
m_sortOrder = CStr(HttpContext.Current.Request.Form.Item("sord"))
Dim dt As DataTable
dt = Session(SESSION_CALLS_GRID_DATA)
Dim myView As DataView = dt.DefaultView
If m_sortItem IsNot Nothing AndAlso m_sortOrder IsNot Nothing Then
myView.Sort = m_sortItem & " " & m_sortOrder
End If
ret.Append("<?xml version='1.0' encoding='utf-8'?>")
ret.Append("<rows>")
ret.Append("<page>" & m_pageNum & "</page>")
ret.Append("<total>" & Math.Floor(dt.Rows.Count / m_pageSize) & "</total>")
ret.Append("<records>" & dt.Rows.Count & "</records>")
For i As Integer = (m_pageNum - 1) * m_pageSize To Math.Min(dt.Rows.Count - 1, m_pageNum * m_pageSize - 1)
ret.Append("<row>")
Dim cellCount As Integer = 0
ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callId")) & "</cell>")
ret.Append("<cell>" & Server.HtmlEncode(myView(i)("callTime")) & "</cell>")
ret.Append("<cell>" & Server.HtmlEncode(myView(i)("duration")) & "</cell>")
ret.Append("</row>")
Next
ret.Append("</rows>")
xmlRet.LoadXml(ret.ToString)
Return xmlRet
End Function
You can see I'm building the XML as a string and then loading it into the XMLDocumennt. I can't say I know this is the best way. You could build the XML DOM directly on the document.