【问题标题】:Returning JSON from ASMX, and handling it correctly in Javascript从 ASMX 返回 JSON,并在 Javascript 中正确处理
【发布时间】:2011-03-12 21:55:10
【问题描述】:

我意识到这里已经有大量类似的问题,但我无法弄清楚这一点。

我有一个 Web 服务(C#、.net 3.5)。您需要了解的基本代码如下:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class WSMember : System.Web.Services.WebService {

    public WSMember () {   
    }


    [WebMethod]
    [ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
    public string GetMember(string IdMember)
    {
        //Ignore the parameter for now... I will be looking up a database with it... 
        //For now just return a minimal object:
        Member m = new Member();
        m.Surname = "Smith";
        m.FirstName = "John";
        return new JavaScriptSerializer().Serialize(m);
    }

另外,在 web.config 中,我添加了以下内容(我刚刚在其他帖子中看到...这正常/安全吗?)

  <webServices>
      <protocols>
        <add name="HttpGet" />
        <add name="HttpPost" />
      </protocols>
    </webServices>

然后在 Default.aspx 中,我的两个关键引用...

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<script type="text/javascript" src="jquery.json-2.2.min.js"  ></script>

jquery.json-2.2.min.js 是从google代码下载的

这里是 Javascript:

<script type="text/javascript">
         $(document).ready(function() {
             $("#button1").click(function(event) {
                 var myData = { IdMember: "2" };
                 var encoded = $.toJSON(myData);

                 alert(encoded);

                 $.ajax({
                     type: "POST",
                     url: "WSMember.asmx/GetMember",
                     data: encoded,
                     contentType: "application/json; charset=utf-8",
                     dataType: "json",
                     success: function(msg) {
                         alert("worked" + msg.d);
                         //$("#sidebar").append(msg);
                     },
                     error: function(msg) {
                         alert(msg.d);
                         //$("#sidebar").append(msg);
                     }
                 });
             });
         });

    </script>

当我执行它时,编码后的 json 会按预期出现在消息框中...即带有双引号:

{ "IdMember":"2" }

但是,它总是失败。即使对于没有传入数据的最基本的 Hello World,它也会失败。我不断收到消息数据的“未定义”。

如果我只使用 alert(msg),它会显示 [object XMLHttpRequest]

有人知道我的数据在哪里丢失了吗?

还有一个问题……我所做的事情有什么根本错误吗?

非常感谢。

编辑:

感谢大家的回复。我已经尝试了以下...

UseHttpGet = true 现在更改为 false。 (再次 - 我在某处看到它,所以我尝试了它......但我知道它不可能是正确的:-/)

假设 Web 服务现在返回一个字符串。我按如下方式构建字符串(似乎有点疯狂......序列化它做了完全相同的事情......)

    StringBuilder sb = new StringBuilder();
    sb.Append("{");
    sb.Append("\"Surname\":");
    sb.Append("\"");
    sb.Append(m.Surname);
    sb.Append("\"");

    sb.Append(",\"FirstName\":");
    sb.Append("\"");
    sb.Append(m.FirstName);
    sb.Append("\"");

    sb.Append("}");

    return sb.ToString();

此代码返回如下内容:

{"Surname":"Smith","FirstName":"John"}

我仍然得到完全相同的错误......

我也尝试过返回对象“Member”之类的方法,因此代码变为:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public Member GetMember(string IdMember)
{
    Member m = new Member();
    m.Surname = "Smith";
    m.FirstName = "John";

    return m;
}

这也会引发同样的错误。

很抱歉让您感到痛苦...我已经阅读了这两个链接以及其他链接。只是看不出这有什么不同。

是否有任何额外的配置设置我需要注意??

非常感谢您的回复。

更新: 问题已解决。上述代码的主要错误是:

[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]

应该是

[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

另外,在表单上,​​当使用按钮调用 javascript 时,我错误地设置了输入类型...

<input id="button1" type="submit" value="Just a test" />

当它应该说:

<input id="button1" type="button" value="Just a test" />

非常感谢所有帮助过的人。

【问题讨论】:

    标签: asp.net jquery ajax json asmx


    【解决方案1】:

    如果您要返回任何复杂对象(带有外键的关系对象),您有两种选择:

    1. 使用 DTO 对象
    2. 编写您自己的特定序列化转换器

    【讨论】:

      【解决方案2】:

      我的英语不好,但这是一个解决方案

      -- WSMember.asmx ------

      [WebService(Namespace = "http://tempuri.org/")]
      [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
      [System.Web.Script.Services.ScriptService]
      public class WSMember : System.Web.Services.WebService {
      
           public WSMember () {   
           }
      
           [WebMethod]
           [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
           public string GetMember(int IdMember)
           {
               Member m = new Member();//Get Member from DB, exam Linq to Sql
               m.Surname = "Smith";
               m.FirstName = "John";
               return string.Format("{{ \"Surname\":\"{0}\",\"FirstName\":\"{1}\" }}",m.Surname,m.FirstName);
           }
      }
      

      ---- Default.aspx ----

      <a href="#" id="button1">Just a test</a>
      <script type="text/javascript">
          $("#button1").click(function (event) {
              event.preventDefault();
              $.ajax({
                  type: "POST",
                  url: "WSMember.asmx/GetMember",
                  data: "{IdMember: 2 }",
                  contentType: "application/json; charset=utf-8",
                  dataType: "json",
                  success: function (msg) {
                      if (msg.hasOwnProperty('d')) {
                          msg = msg.d;
                      }
                      var json = JSON.parse(msg);
                      console.log(json.Surname);
                      console.log(json.FirstName);
                  },
                  error: function (xhr, status, error) {
                      //console.log(xhr);
                      //console.log(status);
                      //console.log(error);
                  }
              });
          });
      </script>
      

      【讨论】:

        【解决方案3】:

        在我看来,您尝试手动使用JavaScriptSerializer().Serialize 而不是返回对象的主要问题。来自 Web 服务的响应将采用双 JSON 编码。

        你是对的!有很多很接近的问题。看看这里Can I return JSON from an .asmx Web Service if the ContentType is not JSON? 和Can't get jQuery Ajax to parse JSON webservice result,你会(我希望)找到答案。

        已更新:抱歉,您有一个小错误,您没有发布。为了解决这个问题,我用旧版本的 Visual Studio (VS2008) 创建了一个小项目,它几乎完全符合您的代码并且可以工作。我把它放在http://www.ok-soft-gmbh.com/jQuery/WSMember.zip。您可以下载、编译并验证它是否有效。然后您可以将您的代码与我的代码进行比较并找到您的错误。

        最好的问候

        【讨论】:

        • Oleg,关于稍微不同的主题,强烈建议将这些服务更改为 WCF REST 吗?你似乎在这里全力以赴......! stackoverflow.com/questions/3189653/…
        • 人们不赞成我这么说,但我不建议将 WCF 用于简单的 AJAX 回调。 WCF 功能要强大得多,但如果您不使用这种功能,它并不会真正带来太多好处。事实上,在日期和枚举方面,ASMX 的 JavaScriptSerializer 实际上比 WCF 的 DataContractJsonSerializer 更灵活。在这种情况下很难证明 WCF 增加的复杂性是合理的(尽管他们正在努力)。
        • Oleg,您的示例将我的注意力吸引到了修复它的一行代码上。非常感谢。代码实际上没问题。对于你有 type="button" 的按钮。我有类型=“提交”。我刚刚采用了一个旧表格并对其进行了编辑……没有注意到按钮的类型。此外,为了更新,我将 jquery 引用更新为 1.4.2(我仍然指的是 1.3.2)。我也使用您的“字符串化”建议,尽管 $.toJSON(myData) 也可以。戴夫——也非常感谢您的 cmets。很有帮助。
        • @Dave:我同意你的观点,对于他们完全需要的特殊情况引入了不同的技术。我主要使用 WCF,但我同意 JavaScriptSerializer 有一些不错的功能,我也错过了 DataContractJsonSerializer。在所有情况下,如果有人在他的问题中询问有关 ASMX 的问题并且他的问题很简单,那么我不建议他切换到 WCF。在大多数情况下,这两种技术都足够好。
        【解决方案4】:

        是的,绝对不要手动序列化对象。如果您返回 Member 类型,框架将为您处理 JSON 序列化。

        当您看到 [object XMLHttpRequest] 警报时,这听起来像是在您的 $.ajax() 调用中进入错误处理程序,其中响应将其 XHR 对象作为第一个参数传递。您可能在服务器上收到 500 错误。

        这里是an example of decoding the ASP.NET AJAX error response in jQuery。最简单的是,将您的错误处理程序更改为:

        error: function(xhr, status, error) {
          var err = eval("(" + xhr.responseText + ")");
        
          alert(err.Message);
        }
        

        这将使您了解具体的错误是什么。

        【讨论】:

          【解决方案5】:

          如果您要发布数据,为什么要定义 UseHttpGet = true?这不应该是错误的以匹配您请求中的响应类型吗?此外,在 ws 调用中放置一个断点以查看序列化程序返回的确切内容也会有所帮助......如果返回值是字符串,我认为它不应该返回 JSON 对象。

          HTH。

          【讨论】:

          • 正确!这是程序中的另一个错误。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-26
          • 1970-01-01
          • 1970-01-01
          • 2018-05-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多