How to jsonify "Add" post/parameters for jqGrid
Asked Answered
V

1

0

This one's killing me. I've read through a lot of Oleg's comments, and through the documentation, but I think I'm overlooking something really simple.

I have a jqGrid populated by calling a webmethod that returns JSON. We're good there. I'm using the Navigator for my "Add" button, and using onSelectRow w/ jqGrid.editRow() for my editing.

I get the dialog box when clicking the "Add" button, and can fill everything in. However, I get a error Status: 'Internal Server Error'. Error code: 500 return message after clicking the Submit button. Using Firebug, the Response is {"Message":"Invalid JSON primitive: FileType.","StackTrace":..... and the Post is FileType=3&ExportDate=12%2F29%2F2010&oper=add&id=_empty.

Obviously, my post is not getting "jsonified". I have tried using serializeEditData, and beforeSubmit in an attempt to manually return JSON.stringify(eparams);, but nothing has worked. Please see my code below.

Webmethod

<WebMethod()> _
<ScriptMethod()> _
Public Sub ModifyFileLog(ByVal FileType As String, _
  ByVal ExportDate As Nullable(Of Date), _
  ByVal oper As String, ByVal id As String)
    Try
        ' blah
    Catch ex As Exception
        Throw New Exception(ex.Message)
    End Try
End Sub

JS - Globals

jQuery.extend(
    jQuery.jgrid.defaults, {
        type: "POST",
        mtype: "POST",
        datatype: "json",
        ajaxGridOptions: { contentType: "application/json" },
        ajaxRowOptions: { contentType: "application/json" },
        rowNum: 10,
        rowList: [10, 20, 30],
        serializeGridData: function(data) {
            return JSON.stringify(data);
        },
        gridview: true,
        viewrecords: true,
        sortorder: "asc"
    },
    jQuery.jgrid.edit, {
        ajaxEditOptions: { contentType: "application/json" },
        recreateForm: true,
        serializeEditData: function(postData) {
            return JSON.stringify(postData);
        }
    }
);

JS - jqGrid

var tblName = "tblFiles";
var pager1 = '#pagerFiles';
var grid = $("#" + tblName);
grid.jqGrid({
    url: 'WebService.asmx/GetFileLog',
    colNames: ['ID', 'File Type', 'Report Date', 'Export Date', 'EE Count'],
    ajaxGridOptions: {
        success: function(data, textStatus) {
            if (textStatus == "success") {
                ReceivedClientData(JSON.parse(getMain(data)).rows, grid);  // populates grid
                endGridRequest(tblName);    // hides the loading panel
            }
        },
        error: function(data, textStatus) {
            alert(textStatus);
            alert('An error has occured retrieving data!');
        }
    },
    editurl: "WebService.asmx/ModifyFileLog",
    serializeEditData: function(postData) {
        return JSON.stringify(postData);
    },
    recreateForm: true,
    pager: pager1,
    ...
}); // end .jqGrid()
grid.jqGrid('navGrid', pager1, { add: true, del: false, edit: true, view: false, refresh: true, search: false },
    {}, // use default settings for edit
    {
        //beforeSubmit: submitAddFileLog,
        closeAfterAdd: false,
        closeAfterEdit: true
    }, // use default settings for add
    {},  // delete instead that del:false we need this
    {multipleSearch: false }, // enable the advanced searching
    {closeOnEscape: true} /* allow the view dialog to be closed when user press ESC key*/
); // end grid/jqGrid('navGrid')

NOTE: I started out populating by using $.ajax() by way of datatype: function(data), but thought I would return to the simplest example to get this to work. If you care to offer your thoughts on the advantages of using $.ajax() over simply using grid.jqGrid({ url: blah });, I'd love to learn more. Otherwise, please let me know if it would be more appropriate to post it as a separate question.

Also, please let me know if I'm just flat out doing this the wrong way. I'm not locked in to any one way of getting this done. I would prefer to be wrong and to learn how to do this the right way, than to be "right" in my own mind and continue to hack my way through it.

Any help, along w/ examples, would be hugely appreciated.

Valdis answered 29/12, 2010 at 21:13 Comment(0)
C
2

In my opinion your main problem is in JS - Globals. You use jQuery.extend function in a wrong way. You should replace one call

jQuery.extend(
    jQuery.jgrid.defaults, {
        // ...
    },
    jQuery.jgrid.edit, {
        // ...
    }
);

to two separate calls:

jQuery.extend(
    jQuery.jgrid.defaults, {
        // ...
    }
);
jQuery.extend(
    jQuery.jgrid.edit, {
        // ...
    }
);

After that the edit request to the server will be {"FileType":3,"ExportDate"="12/29/2010","oper":"add","id":"_empty"} instead of FileType=3&ExportDate=12%2F29%2F2010&oper=add&id=_empty.

Next, I am not sure that you can use ExportDate as a Date (DateTime ???) type. Probably you should start with String type and then convert the input data to the datatype which you need.

Next remark. Be sure that ModifyFileLog return JSON data. For example you can use <ScriptMethod(ResponseFormat:=ResponseFormat.Xml)> instead of <ScriptMethod()>. If you use .NET 4.0 you can achieve the same in many other ways.

One more thing. The ModifyFileLog should be Function instead of Sub and return the Id of new added object. In case of edit or del operations the return value will be ignored.

Because ModifyFileLog Function will be returned JSON data you have to decode/parse it. You can do this almost in the same way which I described here. In case of ASMX web service you can do about following:

jQuery.extend(
    jQuery.jgrid.edit, {
        ajaxEditOptions: { contentType: "application/json" },
        recreateForm: true,
        serializeEditData: function(postData) {
            return JSON.stringify(postData);
        },
        afterSubmit: function (response, postdata) {
            var res = jQuery.parseJSON(response.responseText);
            return [true, "", res.d];
        }
    }
);
Cajolery answered 29/12, 2010 at 23:20 Comment(4)
is my hero, like he has been for so many other questions; thanks, Oleg. I have a follow-up question to one of your comments ( please let me know if I should start another question). 1) Would I need to use ResponseFormat.Json if I return a JSON object (using NewtonSoft)? 2) Would I need to run afterSubmit if I have reloadAfterSubmit: true? Also, using VB.NET 2.0, my function accepted ExportDate as Nullable(Of DateTime).Valdis
@mmengel: You welcome! I am glad to here, that I could help you. About your questions. 1) If you use Json.NET library of Newtonsoft you can better use WCF as ASMX web services (see #3119004 and #3078897). In WCF you can declare method which retutn Stream and return any data type with custom serializer, so you can any use NewtonSoft instead of standard ResponseFormat.Json.Cajolery
@mmengel: afterSubmit and reloadAfterSubmit:true do absolutely different things. If you can not return Id of the new row you must use reloadAfterSubmit:true of cause. If you have many sorted and paged items and you want to see new added item in the correct sorted order, you should use reloadAfterSubmit:true. In other situations reloadAfterSubmit:false can be OK. The user see the item which he just added and he like it. I prefer return new Id and use afterSubmit if needed always to be conform to jqGrid interface and be more sure that in new jqGrid version my program works OK.Cajolery
@mmengel: If usage of ExportDate as Nullable(Of DateTime) work fine in case of your locale than you can use it of cause. I don't reproduced your program and was not sure that all will work. I personally prefer to use language independent formats for the data transfer, but it is not mandatory in real world.Cajolery

© 2022 - 2024 — McMap. All rights reserved.