【问题标题】:ASP.NET WebService is Wrapping my JSON response with XML tagsASP.NET WebService 正在用 XML 标记包装我的 JSON 响应
【发布时间】: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 包装如何实现上述响应?

【问题讨论】:

    标签: c# asp.net json web-services javascriptserializer


    【解决方案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:stackoverflow.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】:
      1. 将返回类型设为 void
      2. 把你的对象放到^_^
      [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://stackoverflow.com/a/16335022/397817

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          • 2014-10-18
          • 1970-01-01
          相关资源
          最近更新 更多