在.net中的jquery + jstree - webservice responseformat?

时间:2010-10-19 14:09:39

标签: c# asp.net jquery json jstree

我第一次使用c#.net玩jstree(1.0rc2)+ jquery(1.4.2),尽管我已经开始工作了,但我还是有几件事我不了解数据如何由我用来填充树的webservice提供给树(使用ajax和json_data插件)。我希望有更多使用jstree经验的人可以提供一些见解。

jstree配置如下所示:

 "json_data": {
                "ajax": {
                    "url": "GetTree.asmx/GetChildren",
                    "type": "POST",
                    "contentType": "application/json; charset=utf-8",
                    "dataType": "json",
                    "data": function(n) {
                        var result = "{'id':'" + (n.attr ? n.attr("id").replace("node_", "") : "0") + "'}";
                        return (result);
                    }
                }
            }

GetTree.asmx GetChildren方法:

   [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Xml )]
    public string GetChildren(string id)
    {
        List<jsTreeNode> jsTree = new List<jsTreeNode>();
        //... (build the tree as needed)

        JavaScriptSerializer serializer = new JavaScriptSerializer();
        return(serializer.Serialize(jsTree)); 
    }

问题1:所以一切都很好,所以有什么问题?问题是“ResponseFormat = ResponseFormat.Xml”。我挣扎了一段时间才能使它工作,因为当它设置为ResponseFormat.Json时它不起作用,这是我所期望的。在这种情况下,在解析json响应时,Web服务或jQuery不会报告任何错误,但树将呈现为空。

在查看Web服务的HTML输出时,我发现无论哪种方式呈现的内容都没有区别。我希望有人可以解释为什么这样做(违反直觉)以及为什么它不适用于ResponseFormat.Json,如果这表明我可能做错了其他事情。

问题2:通常,网络服务或网络处理程序?

使用通用Web处理程序(ashx)是否会更有效地执行此操作?标准Web服务与通用Web处理程序所需的开销是否存在实质性差异?因为我的目标基本上是控制输出的确切内容(并且在Web服务中使用json数据格式似乎并不像我想要的那样工作)我不确定有什么好处,如果有的话,那就是在这里使用Web服务而不是完全剥离它。另一方面,这现在有效,所以也许我应该留下足够好的。

3 个答案:

答案 0 :(得分:4)

看到这个问题有近600个观点,没有答案,我想我会自己回答(因为我早就认识到了)。

使用ScriptMethod实际上不是与jQuery ajax通信的正确方法。虽然可以这样做,但您会注意到我上面所做的是返回一个string,其中包含我使用JavascriptSerializer.

将自己编码为JSON的数据

但是,使用ScriptMethod自动合并序列化/反序列化,旨在与Microsoft的AJAX框架进行通信。由于序列化没有对象包装器的纯字符串通常会产生相同的字符串(无论我是返回XML还是JSON格式),它基本上都有效,但内部真正发生的事情是它被序列化两次

所以我应该做的至少是:

public List<jsTreeNode> GetChildren(string id)

也就是说,返回类型应该是实际的数据类型,而不是一串序列化数据。

然而,这仍然不完全正确,因为Microsoft的方法将返回值包装在对象d中。我仍然可以在Javascript中提取它来获取内部数据。但是,如果像jsTree这样的东西期望以预定义的格式生成数据,那么这可能是行不通的。

最佳解决方案是不使用Web服务,而是使用通用处理程序(ashx)。这使您可以完全控制输入和输出的格式和处理。为自己设置一个不错的框架可能需要做一些工作,但是无法跳过你不需要的部分WebService处理的挫败感使它非常值得。

答案 1 :(得分:1)

很抱歉,我不同意你的回答3.5框架对Json序列化和Web服务有很好的支持(对于2.0你可以使用Newtonsoft.Json)。请参阅http://code.zyky.com/jsTreeView/Default.aspxhttp://asp-net-elephant.blogspot.com/2012/01/how-to-use-jstree-in-aspnet-web-forms.html上的JsTree ASP.NET Web控件演示,以获取两者的示例。希望这会有所帮助。

答案 2 :(得分:0)

关于问题1(我不能和Q2说话),我已经获得了一个Web服务来将JSON反馈给jsTree插件。虽然我认识到WCF和REST是更新的方法,但从长远来看无疑更好,我们仍然使用asmx Web服务,他们确实完成了工作。但这并不容易:我花了一些时间试图在JS中使用确切的语法,以便jsTree从ASP.NET Web服务获取其数据对象。正如OP在他的解决方案中暗示的那样,问题不在于我的JS和插件的连接,而在于我的Web服务返回了不稳定的JSON数据。它看起来像JSON,但它是简化的JSON对象的字符串表示。

要修复它,我必须反序列化并序列化我的json字符串(我从https://stackoverflow.com/a/20080495/1129926得到了一个关于此的线索)并且生成的对象被jsTree愉快地消耗了。这是我的网络服务:

Imports System.Web.Script.Serialization

Public Function GetJsonData() As String
    Dim jss As JavaScriptSerializer = New JavaScriptSerializer
    ' IMPORTANT: do not use single quotes ' in JSON string, use ""
    Dim jsonData As String = "" & _
    "{ ""text"": ""CONTACTS"", ""children"": [ { ""text"": ""CUSTOMER"", ""column"": ""CLASS"", ""children"": [ { ""text"": ""Excelo Communications"", ""column"": ""COMPANY"", ""children"": [{ ""text"": ""Fred Shorts"", ""column"": ""CONTACT"" }] } ] }, { ""text"": ""USER"", ""column"": ""CLASS"" } ] }"
    Dim o As Object = Nothing
    Try
        ' deserialize the JSON into an Object,
        ' shout out to: https://stackoverflow.com/a/20080495/1129926
        o = jss.Deserialize(Of Object)(jsonData)
        o = jss.Serialize(o)
        Context.Response.Clear()
        Context.Response.ContentType = "application/json; charset=utf-8"
    Catch ex As Exception
        // log something
    End Try

    Return o

End Function

在客户端上,我在脚本块中初始化了jsTree,如下所示:

$(document).ready(function () {
    var sURL = "../dataIO.asmx/GetJsonData";
    var dataIn = "";
    $.ajax({
        async: true,
        type: "POST",
        url: sURL,
        dataType: "json",
        data: dataIn,
        contentType: "application/json; charset=utf-8",
        success: function (data) {
            console.log("data obj:" + data);
            createJSTrees(data);
        },
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            console.log(XMLHttpRequest.statusText + "(status=" + XMLHttpRequest.status + "): " + XMLHttpRequest.responseText);
        }
    });
});
function createJSTrees(jsonData) {
    $("#jstree_dataNav").jstree({
        "core": {
            "data": jsonData
        }
    });
    $("#jstree_dataNav").on("changed.jstree", function (e, data) {
        console.log(data.selected);
    });
}

<div id="jstree_dataNav"></div>

jsTree有一个不同的替代语法,而你在core.data部分调用web服务,但我无法让它工作。相反,我通过ajax调用我的Web服务,然后将JSON数据对象传递给初始化jsTree插件的函数,而jsTree只使用在数据中传入的对象:。