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

13

我不确定我在哪里出错或者我漏掉了什么。

我正在构建一个 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包装的情况下实现上述响应?

6个回答

11

在您的代码中,不要“返回”json。请改用以下方法:

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

这样你就会做得很好了。

常规的"return"命令通过以更合适的服务格式插入内容来帮助您。有些人认为最好使用此方法,并从此格式取消包装您的json。我认为,只需将内容直接输出为所需格式即可!


1
如果您导航到.aspx页面,然后跟随链接调用,似乎可以正常工作。但是,如果我尝试导航到"GridDataRequest.asmx/getData",我会得到一个黄色的死亡屏幕,上面显示"请求格式不被识别,URL意外地以'/getData'结束。" - Mike
1
这段代码真是太方便了,点个赞。不过我已经选择了另一个解决方案,更适合我们的模型。 - Mike
是的,最好使用json.parse,只要你已经在使用jquery了。更加规范。 - Patrick Karcher

10

你可能没有做到以下三件事:

  • 将方法标记为静态的
  • 执行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>

后台代码(您不需要创建Web服务,可以将其放在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\"]}]}"}

这里有一个更详细的解释:点击这里


你是怎么得到结果的?当我按照你的实现方式进行时,似乎只会返回"[object Object]"。这可能是对JSON的无知,但我似乎无法让它正常工作。 - Mike
我在Firefox中使用Firebug查看Net面板的响应 - 单击该请求的响应选项卡。 - Chris S
你知道为什么数据被包装在变量“d”中吗? - Mike
2
“d”并非由jQuery添加,而是.NET 3.5作为一项安全措施添加的。 - Chris S

3
  1. 将返回类型改为void
  2. 把你的对象放到^_^上
[WebMethod]
public static void GetDocuments()
{
    HttpContext.Current.Response.ContentType = "application/json";
    HttpContext.Current.Response.Write(JsonConvert.SerializeObject( ^_^ ));
    HttpContext.Current.Response.End();
}

2
我做以下事情的运气更好:
[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返回类型用于应该返回数据的内容),但这是我找到的唯一真正可靠的方法。

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


2

当您将服务标记为ScriptService时,它会自动处理JSON序列化。您不应手动序列化响应。 请参阅堆栈溢出条目以获取更多详细信息。


正确。除非您想使用其他序列化程序,如Newtonsoft,否则最好让asmx按设计工作-包括为您处理序列化。不在响应中获取XML的关键是确保IIS知道需要JSON。然后只需返回C#对象,自动进行JSON序列化:https://dev59.com/wG7Xa4cB1Zd3GeqPr6HO#16335022 - Stephen Kennedy

1
如果您请求JSON,并且包括[ScriptService]属性,ASP.NET将自动将响应序列化为JSON。您看到XML表明这两个前提条件中的一个没有得到满足。除非您想使用不同的序列化程序(例如Newtonsoft),否则手动序列化为JSON的建议是错误的。
以下是启用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用于发送请求并处理响应(我们将简单地使用一个JS警报弹出来自MyClass.Message的消息):
<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"]}}

结果:

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

另请参阅:

https://dev59.com/wG7Xa4cB1Zd3GeqPr6HO#16335022

https://dev59.com/c3RB5IYBdhLWcg3wbGtB#3839649


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接