【问题标题】:Asmx web service returning xml instead of json, Trying to remove <string xmlns="http://tempuri.org/"> from service outputAsmx Web 服务返回 xml 而不是 json,试图从服务输出中删除 <string xmlns="http://tempuri.org/">
【发布时间】:2012-05-30 21:23:33
【问题描述】:

过去 3 小时我一直在寻找 100 个链接,例如将 scriptfactory 添加到 webconfig、3 个错误、设置内容类型等。

我无法弄清楚到底是什么错误。

环境: 在 .net 4.0 上运行的服务 在 .net 4.0 上运行的 Web 应用程序

要求: 我需要将 jqGrid 与 asmx Web 服务绑定,该服务将 json 作为字符串返回给我。 Web 服务文件包含以下代码。

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string GetJsonServerProcess()
    {
        int memory = 1;
        string json = string.Empty;
        var obj = (System.Diagnostics.Process.GetProcesses().Where(r => r.WorkingSet64 > memory).Select(p => new { p.ProcessName, p.WorkingSet64 }).ToArray());
        json = Lib.ToJSON(obj);
        return json;
    }
}

Javascript如下

<script type="text/javascript">
    $(document).ready(function () {
        jQuery("#jqgajax").jqGrid({
            ajaxGridOptions: { type: "POST", contentType: 'application/json; charset=utf-8'  },
            url:'http://localhost:1092/SampleService.asmx/GetJsonServerProcess',
            datatype: "json",
            data: "{}",
            colNames: ['ProcessName', 'WorkingSet64'],
            colModel: [
                        { name: 'ProcessName', index: 'ProcessName', width: 55 },
                        { name: 'WorkingSet64', index: 'WorkingSet64', width: 90 }
                    ],
            rowNum: 10,
            width: 700,
            rowList: [10, 20, 30],
            sortname: 'invdate',
            viewrecords: true,
            sortorder: "desc",
            caption: "New API Example"
        });
    });
</script>

HTML如下

<table id="jqgajax">
</table>
<div id="jqgajax">
</div>

单击调用按钮时的 Web 服务输出

<string xmlns="http://tempuri.org/">
[{"ProcessName":"Dropbox","WorkingSet64":22736896},
 {"ProcessName":"fdhost","WorkingSet64":1941504},
 {"ProcessName":"IntelliTrace","WorkingSet64":39276544}
]
</string>

请建议我缺少什么。 &lt;string xmlns="http://tempuri.org/"&gt; 标签让我很恼火。我假设这些标签不会让我的网格能够绑定。

更新:

ASMX 服务现在如下所示。

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public List<demo> GetJsonServerProcess()
    {
        List<demo> test = new List<demo>();

        for(int i=1;i<=10;i++)
            test.Add(new demo { ProcessName = string.Format("Sample {0}",i), WorkingSet64 = i });

        var re = test;
        return re;
    }
}

public class demo
{
    public string ProcessName { get; set; }
    public int WorkingSet64 { get; set; }
}

【问题讨论】:

  • 问题相似,但解决方案不同。在链接的解决方案中,修复是修改 web.config 文件,在此解决方案中,修复是修改 Content-Type 标头。不过,它们可能不是相互排斥的解决方案。

标签: jquery json jqgrid asmx


【解决方案1】:

单击 Invoke 按钮会返回 XML,因为请求未指定 contentType: 'application/json; charset=utf-8'。所以点击 Invoke 按钮的实验并没有真正的帮助。

您的代码中的主要问题是您在 web 方法中将数据转换为字符串。线

json = Lib.ToJSON(obj);

不需要。通常做的是返回对象。 GetJsonServerProcess 应该改为类似

[ScriptService]
public class SampleService : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public List<Process> GetJsonServerProcess()
    {
        int memory = 1;
        return System.Diagnostics.Process.GetProcesses()
                   .Where(r => r.WorkingSet64 > memory)
                   .Select(p => new { p.ProcessName, p.WorkingSet64 })
                   .ToList();
    }
}

下一个问题是等待 jqGrid 的默认输入格式是另一种(参见here)。因此,您需要指定描述数据格式的jsonReader。在您的情况下,它将类似于

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

此外,您不应该在 Ajax url 中使用 http://localhost:1092/ 前缀,因为出于安全原因,您只能从同一站点获取数据。 jqGrid 中的 data 参数与 jQuery 中的参数有不同的含义,因此您应该删除 data: "{}" 并将 type: "POST"ajaxGridOptions 移动到 mtype: "POST"。结果你会得到类似的东西

$(document).ready(function () {
    $("#jqgajax").jqGrid({
        mtype: "POST",
        ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
        url: '/SampleService.asmx/GetJsonServerProcess',
        postData: "{}", // remove all parameters which jqGrid send typically
        datatype: "json",
        colNames: ['ProcessName', 'WorkingSet64'],
        colModel: [
            { name: 'ProcessName', index: 'ProcessName', width: 155 },
            { name: 'WorkingSet64', index: 'WorkingSet64', width: 190 }
        ],
        jsonReader: {
            repeatitems: false,
            id: "ProcessName",
            root: function (obj) { return obj; },
            page: function () { return 1; },
            total: function () { return 1; },
            records: function (obj) { return obj.length; }
        },
        rowNum: 10,
        loadonce: true,
        gridview: true,
        height: 'auto',
        rowList: [10, 20, 30],
        viewrecords: true,
        sortorder: "desc",
        caption: "New API Example"
    });
});

我没有测试代码,但应该更接近你的需要。

更新:您应该通过更改jsonReader 来修复代码。您可以下载工作演示here。它显示网格

我在服务器端使用了代码

using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web.Services;

namespace jqGridWebASMX
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class SampleService : WebService
    {
        [WebMethod]
        public List<Demo> GetJsonServerProcess()
        {
            const int memory = 1;
            return Process.GetProcesses()
                .Where (r => r.WorkingSet64 > memory)
                .Select(p => new Demo {
                    Id = p.Id,
                    ProcessName = p.ProcessName,
                    WorkingSet64 = p.WorkingSet64
                })
                .ToList();
        }
    }

    public class Demo
    {
        public int Id { get; set; }
        public string ProcessName { get; set; }
        public long WorkingSet64 { get; set; }
    }
}

在客户端

$("#list").jqGrid({
    mtype: "POST",
    ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
    url: '/SampleService.asmx/GetJsonServerProcess',
    postData: "{}", // remove all parameters which jqGrid send typically
    datatype: "json",
    colNames: ['ProcessName', 'WorkingSet64'],
    colModel: [
        { name: 'ProcessName', index: 'ProcessName', width: 200 },
        { name: 'WorkingSet64', index: 'WorkingSet64', width: 120,
            formatter: 'integer', sorttype: 'int', align: 'right' }
    ],
    jsonReader: {
        repeatitems: false,
        id: "Id",
        root: function (obj) { return obj.d; },
        page: function () { return 1; },
        total: function () { return 1; },
        records: function (obj) { return obj.d.length; }
    },
    rowNum: 10,
    loadonce: true,
    gridview: true,
    height: 'auto',
    pager: '#pager',
    rowList: [10, 20, 30],
    rownumbers: true,
    viewrecords: true,
    sortorder: "desc",
    caption: "New API Example"
});
$("#pager_left").hide(); // hide unused part of the pager to have more space

【讨论】:

  • you should never use http://localhost:1092/ prefix in Ajax url 目前我已经创建了两种不同的解决方案,一种用于服务,另一种用于 Web 应用程序。到目前为止,我还没有在 IIS 上托管该服务,而是直接将此服务用于另一个应用程序以进行测试。我试图实现 jqGrid。因此,在这种情况下,如果我使用服务的完整路径,那行得通吗?在实时应用程序中,我将处理 url。我会尝试你所有的建议。但是到目前为止,运行它一直很困难。感谢您的支持。
  • @ShantanuGupta:这只是 Ajax 的常见限制。该限制的名称为same origin policy。因此,您无法访问另一个主机或另一个端口作为您发出请求的主机或端口。像http://localhost:1092/ 这样的前缀没有意义。如果您应该只在相同 Web 服务器上包含Web 服务和相应的HTML/ASPX 页面。或者,您可以使用 JSONP 代替 JSON,但在实现用户身份验证更复杂的情况下,因此主要将其用于公共 Web 服务。
  • 我还在为数据问题而苦苦挣扎。 Web 服务未返回 JSON。它在顶部添加 XML 标记。 &lt;string xmlns="http://tempuri.org/"&gt;
  • @ShantanuGupta:您现在使用哪个代码?你得到&lt;string xmlns="http://tempuri.org/"&gt;,因为你对 JSON 做了额外的序列化。所以首先你应该删除第二个序列化并发布修改后的代码。
  • @ShantanuGupta:我更新了我的答案。主要原因是,必须在jsonReader 中使用root: function (obj) { return obj.d; }, records: function (obj) { return obj.d.length; }。您可以从here 下载完整的工作演示项目。
【解决方案2】:

好的,我遇到了同样的错误,经过大量试验和错误,这是我的“快速而肮脏”的解决方案;

$.get(url, {var1: parameter1, var2: parameter2}, function(data){
    data = JSON.parse($(data).find("string").text());
    alert("data.source: " + data.source);
});

【讨论】:

    【解决方案3】:

    下面的代码应该可以解决问题:

    this.Context.Response.ContentType = "application/json; charset=utf-8";
    this.Context.Response.Write(json);
    

    【讨论】:

      【解决方案4】:

      这段代码完美运行

      SqlDataAdapter sda = new SqlDataAdapter(strsql, ConfigurationManager.ConnectionStrings["BTConString"].ToString());
      DataSet das = new DataSet();
      sda.Fill(das);
      Context.Response.Output.Write(JsonConvert.SerializeObject(das, Newtonsoft.Json.Formatting.Indented));
      Context.Response.End();
      
      return string.Empty;
      

      【讨论】:

      • 这对一个 5 年前的问题有什么帮助? ....不是很多...
      【解决方案5】:
        response = await client.GetAsync(RequestUrl, HttpCompletionOption.ResponseContentRead);
                      if (response.IsSuccessStatusCode)
                      {
                          _data = await response.Content.ReadAsStringAsync();
                          try
                          {
                              XmlDocument _doc = new XmlDocument();
                              _doc.LoadXml(_data);
                              return Request.CreateResponse(HttpStatusCode.OK, JObject.Parse(_doc.InnerText));
                          }
                          catch (Exception jex)
                          {
                              return Request.CreateResponse(HttpStatusCode.BadRequest, jex.Message);
                          }
                      }
                      else
                          return Task.FromResult<HttpResponseMessage>(Request.CreateResponse(HttpStatusCode.NotFound)).Result;
      

      【讨论】:

        【解决方案6】:

        在函数开始之前放下面

        [System.Web.Services.WebMethod(EnableSession = true)]
        [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
        

        将函数设为 void

        函数结束时放在行下

        this.Context.Response.ContentType = "application/json; charset=utf-8";
        this.Context.Response.Write(json);
        

        示例程序

                [System.Web.Services.WebMethod(EnableSession = true)]
                [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
                public void testJson()
                {
                    string json = "{}";
                    this.Context.Response.ContentType = "";
                    this.Context.Response.Write(json);
                }
        

        【讨论】:

          【解决方案7】:

          您可以将您的网址放在邮递员中并使用响应

          像这样我正在使用 php

          <?php
          
          $curl = curl_init();
          
          curl_setopt_array($curl, array( CURLOPT_URL => 'your url', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', ));
          
          $response = curl_exec($curl);
          
          curl_close($curl); echo $response;
          
          ?>
          

          【讨论】:

            【解决方案8】:

            对于有效的 JSON 响应,请使用此代码..

            [WebService(Namespace = "http://tempuri.org/")]
            [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
            [System.ComponentModel.ToolboxItem(false)]
            [ScriptService]
            public class SampleService : System.Web.Services.WebService
            {
                [WebMethod]
                [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
                public void GetJsonServerProcess()
                {
                    int memory = 1;
                    string json = string.Empty;
                    var obj = (System.Diagnostics.Process.GetProcesses().Where(r => r.WorkingSet64 > memory).Select(p => new { p.ProcessName, p.WorkingSet64 }).ToArray());
                    json = Lib.ToJSON(obj);
                   this.Context.Response.ContentType = "application/json; charset=utf-8";
                        this.Context.Response.Write(json);
            
                }
            }
            

            【讨论】:

            • 请写下你做了什么,以及它对解决问题有什么用处。
            猜你喜欢
            • 1970-01-01
            • 2012-06-20
            • 2020-06-02
            • 1970-01-01
            • 2011-02-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多