$ .ajax для dojo.xhr для использования в веб-сервисах sharepoint не работает - PullRequest
0 голосов
/ 13 сентября 2011

Эта функция использует библиотеки jquery и Dojo для получения информации из Sharepoint.Я хочу использовать только Dojo.Как я могу перенести часть jquery в Dojo?

Если быть точным, вызов $ .ajax необходимо преобразовать в dojo.xhrPost

$.ajax({
  url: url,
  type: "POST",
  async: false,
  dataType: "xml",
  data: getSOAPEnvelope(fields, guid),
  complete: function (xData, status) {//parse xml to json},
  contentType: "text/xml"
})

Это моя попытка:

dojo.xhrPost({
  url: url,
  sync:true,                            //in jquery, sync     => async
  handleAs:"xml",                       //in jquery, handleAs => dataType
  content:getSOAPEnvelope(fields, guid),//in jquery, content  => data
  load: (fn from 1.1 section goes here) //in jquery, load     => complete
  headers: {Content-Type:"text/xml"}    //in jquery is contentType:"text/xml"
  }
});

И этополная оригинальная (не перенесенная) функция:

    /*
    Returns a json object from a sharepoint list 
    url and guid arguments are strings (without the {})
    fields is an optional array of fileds to be output. this will reduce teh size of the response.
    uniqueFields is an optional array of fileds to be filtered. For example: 
    if the list has
    row,fruit,color,size
    1,banana,green,small
    2,banana,yellow,small
    3,apple,yellow,medium
    4,apple,green,small
    5,apple,red,small
    for a list of fruits, you put: getJsonItems(url,guid,true,['row',fruit','color'],['fruit']) -> returns rows 1 and 3 
    for a list of fruit sizes, do: getJsonItems(url,guid,true,false,['fruit','size']) -> returns all columsn for items (1,3,4)
    */
    dojo.require("dojox.xml.parser");
    function getJsonItems(url, guid, fields, uniqueFields) {

        //prepare the SOAP envelope

        var jsonItems = []
        var pkHash = []
        //1. fetch xml data from server and parses into json
        $.ajax({
            url: url,
            type: "POST",
            async: false,
            dataType: "xml",
            data: getSOAPEnvelope(fields, guid),
            complete:
            //1.1 when data is received from the server, parse it to json
                function (xData, status) {

                    //1.1.1 convert xml to DOM for easier manipulation
                    var dom = dojox.xml.parser.parse(xData.responseXML.xml)

                    //1.1.2 get xml rows
                    var rows = dom.getElementsByTagName("z:row")

                    //1.1.3 parse each xml row and add it to jsonItems array
                    dojo.forEach(rows, function (row, i) {
                        var jsonItem = {};
                        var uniqueKey = "";
                        //1.1.3.1 parse each xml row into json object. (It removes the ";#" prefix and other MS junk for lookup values or values with spaces)
                        for (var j = 0; j < row.attributes.length; j++) {

                            //1.1.3.1.1 parse the col name by removing ows_, replacing hex numbers (x_00xx_) and trimming spaces
                            var col = row.attributes[j].nodeName.replace("ows_", "").replace(/_x([A-F\d]{4})_/gi, function (str, hexNum) { return eval("\"\\u" + hexNum + "\"") }).replace(/^\s+|\s+$/g, "$1")

                            var val = row.attributes[j].nodeTypedValue.replace(/\d+;#/, "")

                            //1.1.3.2 add property to jsonItem
                            if (dojo.indexOf(fields?fields:[col], col) >= 0) jsonItem[col] = val;

                            //1.1.3.3 filter duplicates based on uniqueFields
                            if (dojo.indexOf(uniqueFields?uniqueFields:[col], col) >= 0) uniqueKey += col + val;
                        }

                        //1.1.3.3 add to uniqueKey to pkHash
                        if (dojo.indexOf(pkHash, uniqueKey) < 0) {
                            pkHash.push(uniqueKey);
                            jsonItems.push(jsonItem)
                        }

                    })
                },
            contentType: "text/xml"
        })

        //2. return parsed xml to json ojbect
        return jsonItems
    }


    function getSOAPEnvelope(fields,guid){

        //prepare ViewFields element
        var viewFields = "";
        if (fields) {
            viewFields = "<viewFields><ViewFields Properties='True'>"
            dojo.forEach(fields, function (e) {viewFields += "<FieldRef Name='"+e+"'/>"});
            viewFields += "</ViewFields></viewFields>";
        }

        var envelope = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \
                        <soapenv:Body> \
                            <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
                                <listName>{" + guid + "}</listName>\
                                " + viewFields + " \
                            </GetListItems> \
                        </soapenv:Body> \
                     </soapenv:Envelope>";

        return envelope;
    }

Ответы [ 3 ]

4 голосов
/ 14 сентября 2011

Если вы используете content в dojo.xhr, Dojo будет обрабатывать content как объект JSON и преобразовывать его, используя кодирование формы.Например, если вы передадите {a : 1, b : 2} как content, фактические данные, отправленные на сервер, будут a=1&b=2.

Ваша функция getSOAPEnvelope фактически возвращает простую строку, поэтому вы не можете использовать content.Просто удалите content и используйте postData.Например,

dojo.xhrPost({
  url: url,
  sync:true,                            //in jquery, sync     => async
  handleAs:"xml",                       //in jquery, handleAs => dataType
  postData:getSOAPEnvelope(fields, guid),//in jquery, content  => data
  load: (fn from 1.1 section goes here) //in jquery, load     => complete
  headers: {Content-Type:"text/xml"}    //in jquery is contentType:"text/xml"
}
});
0 голосов
/ 17 сентября 2011

Я думаю, что нашел проблему. Я упростил до минимума и dojo.xhr отлично работает. Есть небольшие отличия:

$.ajax({
    url: url,
    type: "POST",
    async: false,
    dataType: "xml",
    data: soap,
    complete: function (xData, status) {
        alert(xData.responseXML.xml)
    },
    contentType: "text/xml; charset=utf-8"
})


dojo.xhrPost({
    url: url,
    sync: true,
    handleAs: "xml",
    postData: soap,
    load: function (xData, status) {
        alert(xData.xml )
    },
    headers: { "Content-Type": "text/xml; charset=utf-8;" }
})

Вот полный код. Вы можете скопировать, вставить этот скрипт и запустить его со своего рабочего стола, потому что все cdn и библиотека sharepoint, которую я использую для тестирования, общедоступна

<code>    <html>
     <head>
      <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/dojo/1.6/dojo/dojo.xd.js.uncompressed.js" djConfig="parseOnLoad: true"></script>


         <script>

              var url = "http://msftplayground.com/_vti_bin/lists.asmx";  //this is a public sharepoint site, so you don't have to change anything
              var soap = '<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><GetListCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/" /></soap:Body></soap:Envelope>';

              function jqueryAjax() {
                    dojo.byId("xmlResp").value = "response from $.ajax: ";
                    $.ajax({
                              url: url,
                              type: "POST",
                              async: false,
                              dataType: "xml",
                              data: soap,
                              complete: function (xData, status) { dojo.byId('xmlResp').value += xData.responseXML.xml },
                              contentType: "text/xml; charset=utf-8"
                    })
              }

              function dojoXhr() {
                    dojo.byId("xmlResp").value = "response from dojo.xhrPost: ";
                    dojo.xhrPost({
                         url: url,
                         sync: true,
                         handleAs: "xml",
                         postData: soap,
                         load: function (xData, status) {
                              dojo.byId('xmlResp').value += xData.xml 
                         },
                         headers: { "Content-Type": "text/xml; charset=utf-8;" }
                    })
         }

         </script>

    </head>
    <body>
    <pre>
    <button onclick="jqueryAjax()">test jquery</button>
    <button onclick="dojoXhr()">test dojo</button>
    Response:
    <textarea id="xmlResp" style="height:500px;width:99%;overflow:auto"></textarea>
    
0 голосов
/ 16 сентября 2011

Хотел бы я использовать Firebug, но мне нужно использовать fiddler, потому что FF не будет SSO на Sharepoint.Я использую VS 2010 для отладки, и он ломается, когда в диалоговом окне IE «access denied error» отображается функция xhr.open.Это препятствует тому, чтобы что-либо было отправлено, даже если я игнорирую или продолжаю ошибку.Это происходит в строке 11208 dojo.xd.js.uncompressed ver 1.6 от gdd cdn:

    // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
    // workaround for IE6's apply() "issues"
    xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
    if(args.headers){
        for(var hdr in args.headers){
            if(hdr.toLowerCase() === "content-type" && !args.contentType){
                args.contentType = args.headers[hdr];
            }else if(args.headers[hdr]){
                //Only add header if it has a value. This allows for instnace, skipping
                //insertion of X-Requested-With by specifying empty value.
                xhr.setRequestHeader(hdr, args.headers[hdr]);
            }
        }
    }

Передаваемые значения аргументов:

    method:POST, 
    ioArgs.url:*my sharepoint url*, 
    args.user:*undefined*, 
    args.password:*undefined*

У меня такое ощущение, что этоимя пользователя / pwd.Просто чего-то не хватает в параметрах dojo.XHRPost или просто мне нужно использовать другую функцию dojo (например, dojo.io.iframe)

Теперь, если вы хотите сравнить ответы XHR, с jquery я получаю:

  1. Окно подтверждения от IE, в котором говорится, что «страница обращается к информации, которая не находится под ее контролем с угрозой безопасности»
  2. Первая попытка запросить информацию у _vti_bin / lists.asmxс 401 несанкционированным ответом
  3. Вторая успешная попытка запросить то же самое

Вот подробности:

1-й запрос с jquery:

POST https://a101.sharing.***.com/sites/HOU000169/_vti_bin/lists.asmx HTTP/1.1
Accept: application/xml, text/xml, */*
Accept-Language: en-us
x-requested-with: XMLHttpRequest
Content-Type: text/xml; charset=utf-8
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C; .NET4.0E; MS-RTC LM 8)
Host: a101.sharing.***.com
Content-Length: 0
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: WSS_KeepSessionAuthenticated=80
Authorization: NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAHEXAAAADw==

1-й ответ

HTTP/1.1 401 Unauthorized
Content-Length: 1539
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: NTLM TlRMTVNTUAACAAAAEAAQADgAAAAFgomioKDRqMorlxAAAAAAAAAAALQAtABIAAAABQLODgAAAA9BAE0ARQBSAEkAQwBBAFMAAgAQAEEATQBFAFIASQBDAEEAUwABABgASABPAFUASQBDAC0AUwAtADYAMAA3ADgABAAkAGEAbQBlAHIAaQBjAGEAcwAuAHMAaABlAGwAbAAuAGMAbwBtAAMAPgBoAG8AdQBpAGMALQBzAC0ANgAwADcAOAAuAGEAbQBlAHIAaQBjAGEAcwAuAHMAaABlAGwAbAAuAGMAbwBtAAUAEgBzAGgAZQBsAGwALgBjAG8AbQAAAAAA
MicrosoftSharePointTeamServices: 12.0.0.6219
X-Powered-By: ASP.NET
Date: Fri, 16 Sep 2011 16:49:31 GMT
Proxy-Support: Session-Based-Authentication

2-я попытка

POST https://a101.sharing.***.com/sites/HOU000169/_vti_bin/lists.asmx HTTP/1.1
Accept: application/xml, text/xml, */*
Accept-Language: en-us
x-requested-with: XMLHttpRequest
Content-Type: text/xml; charset=utf-8
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C; .NET4.0E; MS-RTC LM 8)
Host: a101.sharing.***.com
Content-Length: 433
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: WSS_KeepSessionAuthenticated=80
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAKYAAABmAWYBvgAAABAAEABYAAAAJAAkAGgAAAAaABoAjAAAAAAAAAAkAgAABYKIogYAcRcAAAAPpsehFcQrqLsci4ksbHmc0kEATQBFAFIASQBDAEEAUwBKAG8AcwBlAC4ATAAuAEwAZQB2AGkAYQBnAHUAaQByAHIAZQBIAE8AVQBCAFQAQwAtAEQALQA2ADkANgAxAAFMM6NEtmJORCTtsBAnHHWRUNRPM01quP7zKT4VD35T2Y4glT4PV6YBAQAAAAAAAFFUfpuQdMwBkVDUTzNNargAAAAAAgAQAEEATQBFAFIASQBDAEEAUwABABgASABPAFUASQBDAC0AUwAtADYAMAA3ADgABAAkAGEAbQBlAHIAaQBjAGEAcwAuAHMAaABlAGwAbAAuAGMAbwBtAAMAPgBoAG8AdQBpAGMALQBzAC0ANgAwADcAOAAuAGEAbQBlAHIAaQBjAGEAcwAuAHMAaABlAGwAbAAuAGMAbwBtAAUAEgBzAGgAZQBsAGwALgBjAG8AbQAIADAAMAAAAAAAAAABAAAAACAAAMzqw8jpvzbRjHmde0Fhp8Dw6btoC9d5sGE8/LukEd0PCgAQAOq5JkugZHw/GB0+NrLsKCMJADYASABUAFQAUAAvAGEAMQAwADEALgBzAGgAYQByAGkAbgBnAC4AcwBoAGUAbABsAC4AYwBvAG0AAAAAAAAAAAA=

<soapenv...the hole soap envelope

2-й ответ

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Length: 103794
Content-Type: text/xml; charset=utf-8
Server: Microsoft-IIS/6.0
MicrosoftSharePointTeamServices: 12.0.0.6219
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Set-Cookie: WSS_KeepSessionAuthenticated=80; path=/
Set-Cookie: MSOWebPartPage_AnonymousAccessCookie=80; expires=Fri, 16-Sep-2011 17:19:31 GMT; path=/
Date: Fri, 16 Sep 2011 16:49:31 GMT

<?xml version...and the rest of my xml response that I'll later on parse to json

Помните, что jquery отлично работает с рабочего стола после принятия угрозы безопасности, но не работает с dojo.Если я перемещаю файл на сам сервер, он работает нормально.

Итоговый вопрос

В заключение, моя главная проблема в том, почему jquery может обойти междоменную защиту, но не с помощью dojo?Может быть, с dojo.io.iframe, но пока не повезло!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...