ASP.NET WebService 正在用 XML 标记包装我的 JSON 响应

Posted

技术标签:

【中文标题】ASP.NET WebService 正在用 XML 标记包装我的 JSON 响应【英文标题】:ASP.NET WebService is Wrapping my JSON response with XML tags 【发布时间】:2011-01-04 17:35:23 【问题描述】:

我不确定我错过了什么。

我正在构建一个 ASP.NET 2.0(在 .Net 3.5 框架上)Web 应用程序,并且包含一个 Web 服务。请注意,这不是一个 MVC 项目。我希望公开一个返回 JSON 字符串的方法;格式化以提供 jqGrid jQuery 插件。

这是我在服务中实现的初步测试方法:感谢 (Phil Haack's Guide for MVC)

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string getData()

    javascriptSerializer ser = new JavaScriptSerializer();

    var jsonData = new
    
        total = 1, // we'll implement later 
        page = 1,
        records = 3, // implement later 
        rows = new[]
          new id = 1, cell = new[] "1", "-7", "Is this a good question?", "yay",
          new id = 2, cell = new[] "2", "15", "Is this a blatant ripoff?", "yay",
          new id = 3, cell = new[] "3", "23", "Why is the sky blue?", "yay"
        
    ;

    return ser.Serialize(jsonData); //products.ToString();

调用时返回(为清晰起见格式化):

<?xml version="1.0" encoding="utf-8" ?> 
<string  mlns="http://tempuri.org/">

  "total":1,
  "page":1,
  "records":3,
  "rows":
    [
      "id":1,"cell":["1","-7","Is this a good question?","yay"],
      "id":2,"cell":["2","15","Is this a blatant ripoff?","yay"],
      "id":3,"cell":["3","23","Why is the sky blue?","yay"]
    ]

</string> 

没有 xml 包装如何实现上述响应?

【问题讨论】:

【参考方案1】:

你可能不会做的三件事:

将方法标记为静态 执行 POST 为 jQuery 中的数据处理一个空的“ ”。

可能有一种方法可以使用 GET 调用该方法,我只使用过 POST。我能够让您的示例与此一起使用:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script>
    // In your javascript block
    $(document).ready(function()
    
        $.ajax(
            url: "/Default.aspx/Tester",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: "",
            success: done
        );
    );

    function done(data)
    
        // Include http://www.json.org/json2.js if your browser doesn't support JSON natively
        var data = JSON.parse(data.d);
        alert(data.total);
    
</script>

后面的代码(你不需要创建webservice,你可以把这个放在你的default.aspx中):

[WebMethod]
public static string Tester()

    JavaScriptSerializer ser = new JavaScriptSerializer();

    var jsonData = new
    
        total = 1, // we'll implement later 
        page = 1,
        records = 3, // implement later 
        rows = new[]
              new id = 1, cell = new[] "1", "-7", "Is this a good question?", "yay",
              new id = 2, cell = new[] "2", "15", "Is this a blatant ripoff?", "yay",
              new id = 3, cell = new[] "3", "23", "Why is the sky blue?", "yay"
            
        ;

    return ser.Serialize(jsonData); //products.ToString();

结果:

"d":"\"total\":1,\"page\":1,\"records\":3,\"rows\":[\"id\":1,\"cell\":[\"1\",\"-7\",\"Is this a good question?\",\"yay\"],\"id\":2,\"cell\":[\"2\",\"15\",\"Is this a blatant ripoff?\",\"yay\"],\"id\":3,\"cell\":[\"3\",\"23\",\"Why is the sky blue?\",\"yay\"]]"

更详细的解释是here

【讨论】:

你是如何得到你的结果的。当我按照你的方式实施时,我似乎只能得到“[object Object]”。这对 JSON 来说可能是幼稚的,但我似乎无法让它工作。 我在 Firefox 中使用 firebug 来查看来自网络面板的响应 - 单击该请求的响应选项卡。 你知道为什么数据被包装在变量“d”中吗? “d”不是 jQuery 添加的,而是 .NET 3.5 作为安全措施添加的。【参考方案2】:

在您的代码中,不要“返回”json。改为使用:

Context.Response.Write(ser.Serialize(jsonData));

那你就好了。

常规返回命令帮助您输入更合适的服务格式。有人会说使用这种格式会更好,并从这种格式在客户端上解开您的 json。我说,你想怎么用就直接吐了!

【讨论】:

如果您导航到 .aspx 页面然后按照链接进行调用,这似乎有效。不幸的是,如果我尝试导航到“GridDataRequest.asmx/getData”,我会收到一个黄屏死机“请求格式无法识别,因为 URL 意外以 '/getData' 结尾。” +1 这个方便的代码宝石。然而,我选择了另一种更适合我们模型的解决方案。 是的,最好使用 json.parse,只要您仍然使用 jquery。更合适。【参考方案3】:

当您将服务标记为 ScriptService 时,它​​会自动处理 JSON 序列化。您不应该手动序列化响应。 有关详细信息,请参阅this 堆栈溢出条目。

【讨论】:

正确。除非您想使用不同的序列化器,例如 Newtonsoft,否则让 asmx 按设计工作要好得多——这包括为您处理序列化。不在响应中获取 XML 的关键是确保 IIS 知道 JSON 是必需的。然后只需返回 C# 对象并自动序列化为 JSON:***.com/a/16335022/397817【参考方案4】:

我在以下方面做得更好:

[WebMethod]
public static void GetDocuments()

    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject(repository.GetDocuments()));
    HttpContext.Current.Response.End();

正确设置内容类型并将 JSON 直接写入响应非常重要,然后结束响应,这样就不会发送更多数据来破坏您的响应。这种架构的一个优点是你可以使用任何你想要的序列化器,你不限于内置的 JSON 序列化器。在这种情况下,我使用了Json.NET。

我意识到这是在滥用架构(我个人不喜欢为应该返回数据的东西使用 void 返回类型),但这是我发现的唯一真正可靠的方法。

另一方面,您应该切换到 WCF 或 Web API,原因是 John Saunders 描述了 here。特别是 Web API 非常易于使用,并且允许客户端和服务器之间的内容类型协商。

【讨论】:

【参考方案5】:
    将返回类型设为 void 把你的对象放到^_^
[WebMethod]
public static void GetDocuments()

    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject( ^_^ ));
    HttpContext.Current.Response.End();

【讨论】:

【参考方案6】:

如果您请求 JSON,并且包含 [ScriptService] 属性,ASP.NET 将自动将响应序列化为 JSON。您看到 XML 表明这两个先决条件之一没有得到满足。 手动序列化为 JSON 的建议是错误的,除非您希望使用其他序列化器,例如 Newtonsoft。

这是一个启用 JSON 的 ASMX Web 服务的简单工作示例:

<%@ WebService Language="C#" Class="WebService" %>
using System;
using System.Collections.Generic;
using System.Web.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService 
    [WebMethod]
    public MyClass Example()
    
        return new MyClass();
    

    public class MyClass
    
        public string Message  get  return "Hi";  
        public int Number  get  return 123;  
        public List<string> List  get  return new List<string>  "Item1", "Item2", "Item3" ;  
    

JavaScript 请求它并处理响应(我们将简单地弹出一个带有来自 MyClass.Message 的消息的 JS 警报):

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Test</title>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.4.js" type="text/javascript"></script>  
</head>
<body>
    <script type="text/javascript">
        $.ajax(
            type: "POST",
            url: "WebService.asmx/Example",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: " ",
            error: function (XMLHttpRequest, textStatus, errorThrown)  alert(langError + " " + textStatus); ,
            success: function (msg) 
                alert(msg.d.Message);
            
        );
    </script>
</body>
</html>

Http请求:

POST http://HOST.com/WebService.asmx/Example HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: http://HOST.com/Test.aspx
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Connection: Keep-Alive
Content-Length: 3
Host: HOST.com

 

HTTP 响应:

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 08 Oct 2013 08:36:12 GMT
Content-Length: 98

"d":"__type":"WebService+MyClass","Message":"Hi","Number":123,"List":["Item1","Item2","Item3"]

结果:

“Hi”显示在 JS 弹出窗口中。

另见:

https://***.com/a/16335022/397817

https://***.com/a/3839649/397817

【讨论】:

以上是关于ASP.NET WebService 正在用 XML 标记包装我的 JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章

使用 jquery 从 asp.net webservice 解析简单的 xml

asp.net webservice cookie 保存后NAME有值,Value却没有值 代码如下:

asp.net webservice jquery 文本框自动完成

ASP.net jQuery调用webservice返回json数据的一些问题

ASP.net JSON Webservice 响应类型的问题

ASP.NET Membership - 当您在同一个 WebApp 中调用 WebService 时,经过身份验证的用户会丢失