Saturday, January 8, 2011

Making jqGrid work with a .NET Web Service

(Also see Part 2 of this blog entry for a full working example of the code.)

I tore my hair out trying to get jqGrid to display results from a .NET web service. I ended up creating a method (in c#) to convert a datatable to a JSON string appropriate for consumption by jqGrid. Here is what I did...

First, I wrote the following method to convert a datatable to a jqGrid-appropriate JSON string:

public static string GetJqgridJson(DataTable dt) {
            ///<summary>
            ///     This method converts a DataTable to a JSON string
suitable for jqGrid consumption.
            /// </summary>
            ///<param name="dt">
            ///     The DataTable to be processed.
            /// </param>
            ///<returns>
            ///     jqGrid-JSON string if dt parameter has rows, null if dt 
parameter has rows
            /// </returns>

            StringBuilder jsonString = new StringBuilder();
            if(dt != null && dt.Rows.Count > 0) {
                jsonString.Append("{");
                jsonString.Append("\"total\": \"1\",");  //set as 1 for example
                jsonString.Append("\"page\": \"1\",");   //set as 1 for example
                jsonString.Append("\"records\": \"" + dt.Rows.Count.ToString() + "\",");
                jsonString.Append("\"rows\":[");

                for(int i = 0; i < dt.Rows.Count; i++) {
                    jsonString.Append("{\"cell\" :[");
                    for(int j = 0; j < dt.Columns.Count; j++) {
                        if(j < dt.Columns.Count - 1) {
                            jsonString.Append("\"" + dt.Rows[i][j].ToString()
.Replace("\"", "\\\"") + "\",");
                        } else if(j == dt.Columns.Count - 1) {
                            jsonString.Append("\"" + dt.Rows[i][j].ToString()
.Replace("\"", "\\\"") + "\"");
                        }
                    }

                    if(i == dt.Rows.Count - 1) {
                        jsonString.Append("]} ");
                    } else {
                        jsonString.Append("]}, ");
                    }
                }

                jsonString.Append("]}");
                return jsonString.ToString();
            } else {
                //Return null if datatable has no rows.
                return null;
            }
        }

Next, I created a .Net WebMethod that uses the GetJqgridJson method. My WebMethod fetches data as a DataTable, uses the GetJqgridJson method to convert the DataTable to a JSON string, then returns the JSON string to the browser. (I wont include my WebMethod code here for sake of brevity.)

When you're creating your WebMethod, just be sure to include the following directive above your method to ensure you are sending a JSON and not an XML string back to the browser:
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

Finally
, I wrote my JavaScript code. Here is some sample code that can be used to set up a jqGrid and fetch the JSON string via AJAX. (Note: The following JavaScript code will not work out of the box. You'll need to update the portions surrounded with "**" to make it work within your project.)
$("**YOUR JQUERY SELECTOR HERE**").jqGrid({
                            datatype: 'jsonstring',
                            jsonReader: { root: "rows",
                                page: "page",
                                total: "total",
                                records: "records",
                                repeatitems: true,
                                cell: "cell"
                            },
                            gridview:true,
                            colNames: [**YOUR COLUMN NAMES HERE**],
                            colModel: [**YOUR COLMODEL HERE**],
                            viewrecords: true,
                            caption: '',
                            loadonce: false,
                            loadui: "enabled",
                            beforeSelectRow: function(rowid, e) {return false;},
                            hoverrows:false,
                            height:200,
                            scroll:1
                });
                $("**YOUR JQUERY SELECTOR HERE**").clearGridData();
                $.ajax({
                    type: "POST",
                    url: "**YOUR WEBMETHOD URL HERE**",
                    data: JSON.stringify(webservice_object),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (msg) {
                        var data = msg.d;
                        $("**YOUR JQUERY SELECTOR HERE**").jqGrid('setGridParam', 
                                        {datatype: 'jsonstring', datastr: data});
                        $("**YOUR JQUERY SELECTOR HERE**").trigger('reloadGrid');
                    }
            });

6 comments:

  1. where does webservice_object gets initialised.

    ReplyDelete
  2. That is a JS object I'm using to pass parameters to the AJAX call.

    As an example, you could initialize your object like this:

    webservice_object = new Object;
    webservice_object.id = 1;
    webservice_object.code = 123;

    ReplyDelete
  3. I shall be so glad and thankful if you could share with me the whole jqgrid. The webservice code, the script code and the aspx page which is calling the script.

    I am trying to implement it in such a way that for after each 20 records the jqgrid should make another call to the webservice. But i am not able to pass parameters( page,total etc
    to the web service. If possible share your code so that i can see whats going wrong here, or if u can point me whats going wrong in my code.

    Call to populate the Jqgrid from aspx page.

    function FillGrid(WebMethodString, GridName, PagerName, columnModel, columnNames, header)
    {
    // debugger;
    jQuery(GridName).GridUnload();
    jQuery.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    url: WebMethodString,
    data: '{}', //PageMethod Parametros de entrada
    datatype: "json",
    success: function(msg) {
    $('#dvWait').css('display', 'block');
    // Do interesting things here.
    // debugger;
    var mydata = jQuery.parseJSON(msg.d);
    //console.log(mydata);

    jQuery(GridName).jqGrid({
    datatype: "local",
    data: mydata,
    colNames: columnNames,
    colModel: columnModel,
    pager: jQuery(PagerName),
    rowNum: 25,
    mtype: "GET",
    pagination: true,
    scrollOffset: 0,
    rowList: [10, 20, 25],
    sortname: "WorkOrderID",
    scroll: 1,
    sortorder: "desc",
    multiselect: false,
    viewrecords: true,
    caption: header,
    autowidth: true,
    ignoreCase: true,
    height: 580,

    afterInsertRow: function(rowid, rowdata, rowelem) {
    jQuery(GridName).setCell(rowid, 'WorkOrderID', '', '', { title: '', onclick: 'DisappearPopup(event);' });
    jQuery(GridName).setCell(rowid, 'Requester', '', '', { title: '', onclick: 'DisappearPopup(event);' });
    jQuery(GridName).setCell(rowid, 'AssignedTo', '', '', { title: '', onclick: 'DisappearPopup(event);' });
    jQuery(GridName).setCell(rowid, 'SummaryText', '', '', { title: '', onclick: 'DisappearPopup(event);' });
    jQuery(GridName).setCell(rowid, 'CreationDate', '', '', { title: '', onclick: 'DisappearPopup(event);' });
    },
    gridComplete: function() {
    $('#dvMaintbl').css('visibility', 'visible');
    $('#dvWait').css('display', 'none');
    }

    })
    jQuery(GridName).jqGrid('navGrid', PagerName,
    {
    edit: false,
    add: false,
    del: false,
    searchtext: 'Search',
    refreshtext: 'Reload'
    });
    }
    });
    }

    ReplyDelete
  4. Webservice code which retrieves the json string:

    _
    _
    Public Function GetAllTroubleTickets() As String
    'Dim dsDatos As DataSet = oRequest.GetPendingDocuments(Employee)
    Dim strStatus As String = HttpContext.Current.Request.QueryString("status")
    Dim page As Integer = 1

    If HttpContext.Current.Request.Form("page") IsNot Nothing Then
    page = Integer.Parse(HttpContext.Current.Request.Form("page").ToString())
    End If
    Dim rp As Integer = 1
    If HttpContext.Current.Request.Form("rowNum") IsNot Nothing Then
    rp = Integer.Parse(HttpContext.Current.Request.Form("rowNum").ToString())
    End If
    Dim start As Integer = ((Page - 1) * rp)


    If (strStatus = Nothing) Then
    strStatus = "2"
    End If
    Dim dsDatos As DataSet = GetAllTroubleTicketsclass("", "WorkOrderID asc", "1", "4000", "", Convert.ToInt16(strStatus))

    Dim result As String = Jayrock.Json.Conversion.JsonConvert.ExportToString(dsDatos.Tables(0).Rows)
    Return result

    End Function

    ReplyDelete
  5. I attached a working Visual Studio example in a new post. Here is the link to the new post.
    http://www.hcicrossroads.com/2011/01/making-jqgrid-work-with-net-web-service.html

    ReplyDelete
  6. first of all than x for the wonderful article..
    i had tried to download your code but seems your link is dead ..please update your link

    ReplyDelete