从沙盒解决方案到 SharePoint 2013 网站的 REST 调用与 JSOM 调用

问题描述

我有一个 Angular 2+ 应用程序,它可以通过 REST API 愉快地执行对托管在不同服务器中的 SharePoint 2013 的调用。它工作得很好,但不幸的是,对于非常特殊的需求(讨论板),这还不够。这是我在做什么:

async addMessageREST(callback,siteUrl,discussionBoardName,parentItemId,newMessageBody) {

    const requestOptions = {
      withCredentials: true,crossDomain: true
    };

    var messagePayload = {
      // '__Metadata': { "type": "SP.Data.discussionsListItem" },'Body': newMessageBody,'ParentItemID': parentItemId,//unfortunately will be ignored
      'FileSystemObjectType': 0,'ContentTypeId': '0x0107008822E9328717EB48B3B665EE2266388E'
    };

    // retrieve the contextinfo
    let contextinfo = await this._http
    .post(
          siteUrl + '/_api/contextinfo',null,requestOptions
    )
    .toPromise();

    // finally post the request
    const requestOptionsAddMessage = {
    withCredentials: true,crossDomain: true,headers: new HttpHeaders().set('X-RequestDigest',contextinfo["FormDigestValue"]).set("Accept","application/json;odata=verbose")
    };

    let request = "/_api/web/Lists/GetByTitle('" + discussionBoardName + "')/items";


    let discussionItem = await this._http
    .post(
    siteUrl + request,messagePayload,requestOptionsAllMessages
  )
  .toPromise();

callback(discussionItem);
}

从技术上讲,这很好用,但不幸的是,这还不够,因为您可能知道 REST API 不提供管理讨论项目的特定功能。对于这个 JSOM 提供了很好的方法,但不幸的是我无法与它建立连接(我收到 401 错误)。这是我在做什么:

addMessageJSOM(callback,parentTopicId,newMessageBody) {

    let clientContext = new SP.ClientContext(siteUrl);

    let list = clientContext.get_web().get_lists().getByTitle(discussionBoardName);
    
    let discussionItem = list.getItemById(parentTopicId);

    let properties = {
       'Body': newMessageBody
    };

    let messageItem = SP.Utilities.Utility.createNewdiscussionReply(clientContext,discussionItem);

    for (var propName in properties) {
      messageItem.set_item(propName,properties[propName])
    }
    messageItem.update();

    clientContext.executeQueryAsync(() => {
      callback(messageItem);
    },(error: any) => {
        console.log('Request Failed',error);
    });

}

一切正常,直到涉及到 executeQueryAsync,我收到了上述 401 错误。我想这是因为不知何故我没有传递我在 REST 调用中通过 HTTP 传递的摘要/选项。 知道如何通过 JSOM 传递这些选项吗? 或者,有没有一种方法可以通过 HTTP 调用 JSOM 端点而不依赖于 SP 库?

在此之前感谢您的阅读!

解决方法

你能不能在下面的行中改变这一点,以便父项 ID 不会被忽略

let request = "/_api/web/Lists/GetByTitle('" + discussionBoardName + "')/items(" + parentItemId + ")" ;
,

JSOM 必须依赖于 SP 库。如果您想通过 Rest API 创建讨论项,您可以参考以下演示:

function executeJson(options) {
    var headers = options.headers || {};
    var method = options.method || "GET";
    headers["Accept"] = "application/json;odata=verbose";
    if (options.method == "POST") {
        headers["X-RequestDigest"] = $("#__REQUESTDIGEST").val();
    }

    var ajaxOptions =
    {
        url: options.url,type: method,contentType: "application/json;odata=verbose",headers: headers
    };
    if ("data" in options) {
        ajaxOptions.data = JSON.stringify(options.data);
    }

    return $.ajax(ajaxOptions);
}


function createListItem(webUrl,listTitle,payload) {
    var url = webUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/items";
    return executeJson({
        "url": url,"method": 'POST',"data": payload
    });
}

function moveListItem(webUrl,itemId,folderUrl) {
    var url = webUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/getItemById(" + itemId + ")?$select=FileDirRef,FileRef";
    return executeJson({
        "url": url
    })
        .then(function (result) {
            var fileUrl = result.d.FileRef;
            var fileDirRef = result.d.FileDirRef;
            var moveFileUrl = fileUrl.replace(fileDirRef,folderUrl);
            var url = webUrl + "/_api/web/getfilebyserverrelativeurl('" + fileUrl + "')/moveto(newurl='" + moveFileUrl + "',flags=1)";
            return executeJson({
                "url": url,"method": 'POST'
            });
        });
}


function getParentTopic(webUrl,itemId) {
    var url = webUrl + "/_api/web/lists/getbytitle('" + listTitle + "')/getItemById(" + itemId + ")/Folder";
    return executeJson({
        "url": url,});
}


function createNewDiscussionReply(webUrl,messagePayload) {
    var topicUrl = null;
    return getParentTopic(webUrl,messagePayload.ParentItemID)
        .then(function (result) {
            topicUrl = result.d.ServerRelativeUrl;
            return createListItem(webUrl,messagePayload);
        })
        .then(function (result) {
            var itemId = result.d.Id;
            return moveListItem(webUrl,topicUrl);
        });
}

$(function () {
    // Handler for .ready() called.

    var listTitle = "discuss";
    var webUrl = _spPageContextInfo.webAbsoluteUrl;
    var messagePayload = {
        '__metadata': { "type": "SP.Data.DiscussListItem" },//set DiscussionBoard entity type name
        'Body': "Thanks for the information",//message Body
        'FileSystemObjectType': 0,//setto 0 to make sure Mesage Item
        'ContentTypeId': '0x0107008822E9328717EB48B3B665EE2266388E',//set Message content type
        'ParentItemID': 1  //set Discussion (topic) Id
    };

    createNewDiscussionReply(webUrl,messagePayload)
        .done(function (item) {
            console.log('Message(reply) has been sent');
        })
        .fail(function (error) {
            console.log(JSON.stringify(error));
        });

});

更多参考:

BR

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...