【问题标题】:JQ Grid web service call with parameters doesn't work, does with Ajax带参数的 JQ Grid Web 服务调用不起作用,对 Ajax 起作用
【发布时间】:2012-06-02 12:30:45
【问题描述】:

我能够将表单数据从 ajax 脚本传递到 ASP.Net Web 服务并接收 JSON 对象作为响应,效果很好。当我在 JQ Grid 中使用相同的参数进行相同的调用时,我会收到“无效的 Web 服务调用”或“无效的 JSON 原语”作为响应。

我相信这与以下帖子非常接近,我已经应用了这些建议(以及许多其他帖子中的建议),但没有成功。 JQGrid - Cannot call ASP.NET WebMethod but can with Ajax

以下 Ajax 代码成功,它将表单参数传递给 Web 服务并以 JSON 格式检索结果。

Ajax Javascript 代码: 此代码有效问题出在 JQ Grid(在下方)

<script language="JavaScript">
    function populateResults() {
    var arForm = $("#searchForm").serializeArray();

    $.ajax({
      type: "POST",
      url: "./WebService/Service.asmx/doSearch",
      data: JSON.stringify({ formVars: arForm }),
      contentType: "application/json",
      dataFilter: function(data) {
        var msg = eval('(' + data + ')');
        if (msg.hasOwnProperty('d'))
          return msg.d;
        else
          return msg;
      },
      success: function(msg) {
        // This will now output the same thing 
        //  across any current version of .NET.
        //console.log(msg.foo);
      }
    });
    };

    </script>

网络服务:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string doSearch(NameValue[] formVars)
{...

问题: 以下是我失败的 JQ Grid 代码:

<script type="text/javascript">
    function populateResults() {
        var arForm = $("#searchForm").serializeArray(); 
        var searchParams = JSON.stringify({ formVars: arForm });

        var grid = $("#tblResults");
        grid.jqGrid({
            url: "./WebService/Service.asmx/doSearch",
            ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
            data: searchParams,
            dataType: 'json',
            dataFilter: function(data) {
                var msg = eval('(' + data + ')');
                alert(msg.d);

                if (msg.hasOwnProperty('d'))
                  return msg.d;
                else
                  return msg;
            },
            mtype: 'POST',
            colNames:['Exam Date','Type','Name','UR Number','Pathology Type','Result Date','Modality', 'Results'],
            colModel:[
                {name:'resExamDate',index:'resExamDate', editable:false, width:120},
                {name:'resType',index:'resType', editable:false, width:60},
                {name:'name',index:'name', editable:false, width:120},
                {name:'urnumber',index:'urnumber', width:65, sorttype:'int'},
                {name:'resPathologyType',index:'resPathologyType', editable:false, width:120},
                {name:'resResultDate',index:'resResultDate', editable:false, width:120},
                {name:'resModality',index:'resModality', editable:false, width:170, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal;"'}},
                {name:'results',index:'results', editable:false, width:240, cellattr: function (rowId, tv, rawObject, cm, rdata) { return 'style="white-space: normal;"'}}
            ],
            rowNum:10,
            rowList:[5,10,20],
            pager: '#pager',
            sortname: 'surname',
            viewrecords: true,
            sortorder: "desc",
            height: "100%",
            processData: false,  //jquery will stringify again apparently: https://stackoverflow.com/questions/6471759/invalid-web-service-call-missing-value-for-parameter
            serializeGridData: function (postData) { return JSON.stringify(postData);   },
            jsonReader: { 
                total: "total",
                page: "page",
                records: "records",
                root: "rows",
                id: "id",
                cell: "cell",
                repeatitems: false
            }
        });
    }
    </script>

在 Firebug 中我收到:

Post
{"_search":false,"nd":1338180778103,"rows":10,"page":1,"sidx":"surname","sord":"desc"}

Response
{"Message":"Invalid web service call, missing value for parameter: \u0027formVars\u0027.","StackTrace":"   at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters)\r\n

或者,如果我注释掉“serializeGridData:”行(我想我将它序列化两次或其他什么,所以我尝试注释掉它),我得到:

Post:
    _search=false&nd=1338180203206&rows=10&page=1&sidx=surname&sord=desc

Response:
    {"Message":"Invalid JSON primitive: _search.","StackTrace":"   at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n ......

关于为什么它不起作用的任何可靠的想法?我花了几天的时间试图让它以这种方式工作。虽然我可以通过执行 Ajax 调用并将数据存储在变量中并将其设置为 JQ Grid 来使其工作,但我需要来自 JQ GRid 的直接 Web 服务调用才能用于过滤和其他事情......

提前谢谢:)

编辑: - 使用 JQ Grid v4.3.2 - 发送到 Web 服务的 JSON 数据已使用 http://jsonlint.com/ 验证(这是上面 javascript 代码中的变量“searchParams”)

【问题讨论】:

    标签: jquery asp.net ajax web-services jqgrid


    【解决方案1】:

    你在调用的{}(见/*here*/)里面使用了什么

    grid.jqGrid({/*here*/});
    

    jqGrid 参数jqGrid options。在这里使用dataFilter 是错误的,因为jqGrid 会忽略该选项。同样,jqGrid 不知道dataType 选项,它会忽略dataType: 'json'datatype(注意字母大小写)的默认值为'xml'。因为来自服务器的 JSON 响应是错误的 XML 文件,所以您会收到错误消息。

    以同样的方式data jqGrid 的参数将被以另一种方式使用。您应该改用postData 参数。重要的是要了解您应该使用grid.jqGrid({/*here*/}); once 之类的代码创建 jqGrid。因此,如果您希望在分页、排序或过滤数据时 当前 表单中的值 "#searchForm" 将发送到服务器,您应该将 formVars 定义为 function .有关详细信息,请参阅the answer。如果您使用mtype: 'POST',那么在serializeGridData 回调中添加formVars 属性可能会很容易。

    因此,您应该将当前代码重写为以下内容:

    $(function () {
        var grid = $("#tblResults");
        grid.jqGrid({
            url: "./WebService/Service.asmx/doSearch",
            ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
            serializeGridData: function (postData) {
                // extend the parameter which will be send to the server
                postData.formVars = $("#searchForm").serializeArray();
                // serialize the parameters as JSON string
                return JSON.stringify(postData);
            },
            datatype: 'json',
            mtype: 'POST',
            colNames:['Exam Date','Type','Name','UR Number','Pathology Type','Result Date','Modality', 'Results'],
            colModel:[
                {name:'resExamDate',index:'resExamDate', width:120},
                {name:'resType',index:'resType', width:60},
                {name:'name',index:'name', width:120},
                {name:'urnumber',index:'urnumber', width:65},
                {name:'resPathologyType',index:'resPathologyType', width:120},
                {name:'resResultDate',index:'resResultDate', width:120},
                {name:'resModality',index:'resModality', width:170,
                    cellattr: function () {
                        return ' style="white-space: normal;"'
                    }},
                {name:'results',index:'results', width:240,
                    cellattr: function () {
                        return ' style="white-space: normal;"'
                    }}
            ],
            rowNum: 10,
            rowList: [5, 10, 20],
            pager: '#pager',
            sortname: 'surname',
            viewrecords: true,
            sortorder: "desc",
            height: "100%",
            jsonReader: {
                root: function (obj) { return obj.d; },
                page: function () { return 1; },
                total: function () { return 1; },
                records: function (obj) { return obj.d.length; }
            }
        });
    });
    

    此外,您的服务器部分似乎没有实现数据分页。如果它忽略了所有标准 jqGrid 参数(rows,page,sidx,sord),您应该将rowNum 的值增加到rowNum: 10000,例如,删除rowList 和其他寻呼机信息(见the documentation):pgbuttons: false, pginput: false。此外,您可以使用

    serializeGridData: function () {
        return JSON.stringify({formVars: $("#searchForm").serializeArray()});
    }
    

    如果 jqGrid 将只发送formVars 到服务器。

    【讨论】:

    • 非常感谢 Oleg 的回复,它成功了! :) 我现在可以看到来自网络服务的 POST 数据和响应,非常感谢 :)。我将在这里发布我的完整代码,以便它也可以帮助其他人。
    • 我仍然有 1 个问题,数据没有显示在网格上,我认为这是来自不正确的 jsonReader 配置。返回 obj.d 返回 'undefined',obj 的警报返回:{"total":"1","page":"1","re​​cords":"15","rows":[{ "id":"1","cell":["21-Nov-2011 12:57","Radiology","LASTNAME, Firstname","12345","text","22-Nov-2011 08: 58","X-Ray Finger Left","text"]},{"id":"2","cell":[".... 在 Firebug 中 web 服务返回: {"d":"{\"total\":\"1\",\"page\":\"1\",\"records\":\"15\",\"rows\":[ {\"id\":\"1\",\"cell\":[\"21-Nov-2011 12:57\",\"Radiology\"...
    • 我尝试过使用 jsonReader 参数,例如 root: "rows"root: "d.rows"root:函数 (obj) { 返回 obj.d; } 但没有一个成功,你有什么想法吗?
    • @xander:只有以{"d":... 开头的响应才会显示真实数据。可以看出您在 Web 服务中犯了一个典型错误。必须从网络方法返回 object。 .NET Framework 将对 JSON 本身进行序列化。我想你包括了一些手动调用 JavaScriptSerializer 这是错误的。您可以像beforeProcessing: function (data) {data.d = $.parseJSON(data.d);} 一样修复beforeProcessing 内部的问题,但最好修改您的服务器代码。然后你可以使用jsonReader: { root: "d.rows", page: "d.page", total: "d.total", ...}
    • 顺便说一下,鉴于响应 JSON 的格式,我一直在使用 repeatitems: true
    【解决方案2】:

    您需要包含 Web 服务的预期参数名称,例如

    var grid = $("#tblResults");
            grid.jqGrid({
                url: "./WebService/Service.asmx/doSearch",
                ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
                data:{u0027formVars: searchParams},
    

    之前的代码是成功的,因为其中包含了输入参数名称

    【讨论】:

    • 谢谢约翰,不幸的是这不起作用。我相信当 JSON 对象在 'var searchParams = JSON.stringify({ formVars: arForm });' 行中被字符串化时包含该参数。
    • JSON 对象(在变量 searchParams 中)以 {"formVars":[{"name":"txtSearchKeywords","value":""},{"name": "radio","value":"and"},..... 等等,所以它肯定包含 formVars 参数。
    【解决方案3】:

    你需要像这样传递数据:

    function populateResults() {
    var arForm = $("#searchForm").serializeArray();
    var formvars = JSON.stringify(arForm);
    
    $.ajax({
      type: "POST",
      url: "./WebService/Service.asmx/doSearch",
      data: "{'formVars':'" + formvars + "'}",
      contentType: "application/json",
      dataFilter: function(data) {
        var msg = eval('(' + data + ')');
        if (msg.hasOwnProperty('d'))
          return msg.d;
        else
          return msg;
      },
      success: function(msg) {
        // This will now output the same thing 
        //  across any current version of .NET.
        //console.log(msg.foo);
      }
    });
    };
    

    【讨论】:

    • 感谢 GeekYouNeed,我已经尝试过了,但仍然失败,并在响应中显示 “无效的 Web 服务调用,参数缺失值:\u0027formVars\u0027.”。我相信调用 JSON.stringify({ formVars: arForm }) 与 data: "{'formVars':'" + formvars + "'}" 做同样的事情
    • formvars 的值是多少?你能把它放到一个警报窗口中并放在这里吗?
    • var searchParams = JSON.stringify({ formVars: arForm }); 搜索参数提醒: {"formVars":[{"name":"txtSearchKeywords","value":""},{"name":"radio","value":"和"},{"name":"txtStartDate","value":""},{"name":"txtEndDate","value":""},{"name":"txtPatientFirstName","value" :""},{"name":"txtPatientSurname","value":""},{"name":"txtURNumber","value":""},{"name":"ageMin","value ":"0"},{"name":"ageMax","value":"120"},{"name":"sex","value":"both"},{"name":"txtDrFirstName ","value":""},{"name":"txtDrSurname","value":""},{"name":"txtRequestingLocation","value":""}...评论的最大字符数到达
    • 是否将内容类型更改为 contentType: "application/json; charset=utf-8", help ?
    • 也将此添加到您的 ajax 调用 dataType: "json",
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多