从ASMX返回JSON,并在Javascript中正确处理它

时间:2010-07-07 15:58:59

标签: asp.net jquery ajax json asmx

我意识到这里已经有很多类似的问题,但我无法想出这个问题。

我有一个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是从谷歌代码下载的

以下是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" />

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

5 个答案:

答案 0 :(得分: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上。您可以下载它,编译并验证它是否有效。然后,您可以将您的代码与我的代码进行比较,并找到您的错误。

祝你好运

答案 1 :(得分:1)

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

HTH。

答案 2 :(得分:1)

是的,绝对不要手动序列化对象。如果返回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);
}

这将使您对特定错误的具体信息有所了解。

答案 3 :(得分:0)

如果要返回任何复杂对象(带有外键的关系对象),则有2个选项:

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

答案 4 :(得分:-1)

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

----- 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>