您知道SharePoint 2016" Zombie ItemID缓存错误"?

时间:2018-05-18 10:14:54

标签: javascript ajax sharepoint

将各种SharePoint 2013 JavaScript应用程序迁移到SharePoint 2016后,我不得不关注SharePoint 2016 Rest API的一个奇怪现象:

假设您有2个ajax调用

  1. 上传文件 - >返回spFile
  2. 获取上传文件的列表项 - >返回spItem

    jQuery.ajax({
        url: "/sites/mysite/_api/web/getFolderByServerRelativeUrl('/sites/mySite/myLibrary')/files/add(overwrite=true, url='test1.txt')",
        type: "POST",
        data: params.arraybuffer,
        processData: false,
        headers: { "Accept": "application/json;odata=verbose", "X-RequestDigest": params.digest, "X-HTTP-Method": "POST","If-Match": "*" },
        success: function (file) {
            //get listItem for uploaded file
            jQuery.ajax({
                url: file.d.ListItemAllFields.__deferred.uri,
                type: "GET",
                headers: { "accept": "application/json;odata=verbose" },
                success: function (result) {
                    //after first upload: OK
                    var id = result.d.ID;
                }
            });
        }
    });
    
  3. 如果此URL下尚未存在该文件,则一切正常。 SharePoint会创建一个新的列表项,您将在第二次调用中获得具有正确ID的新项 - 假设我们获得ID 1。

    如果此URL下已存在具有相同名称的文件,并且稍后将其删除,则SharePoint将生成具有新ID的新项目。这是预期的。 但是:在这种情况下,SharePoint Rest API会返回错误的列表项。您将获得ID为1的旧已删除项目,而不是新创建的列表项(ID 2)。

    在SharePoint 2013中,不会发生此错误。在SharePoint 2016中 - 仅在ajax调用1和ajax调用2的相同浏览器上下文的情况下才会出现此错误。通常,您会受到此错误的影响,如果您在更新某些元值的同时上载文件。 / p>

    这似乎是SharePoint 2016中的一个错误。我想,MS已经实施了更严格的缓存算法并且越过了目标。

1 个答案:

答案 0 :(得分:0)

在MS修复此错误之前,我找到了一个解决方法:

  1. 以临时名称上传您的文件 - jQuery.Guid.New()+ myExtension
  2. 获取上传文件的新项目
  3. 发送呼叫以删除具有真实目标名称的可能存在的文件
  4. 将您上传的文件重命名为真实目标名称

                    var real_filename = 'test1.txt';
                    var temp_filename = jQuery.Guid.New() + '.txt';
                    // upload temp_filename instead real filename - fixes SharePoint 2016 ZombieId CacheBug
                    jQuery.ajax({
                        url: "/sites/mySite/_api/web/getFolderByServerRelativeUrl('/sites/mySite/myLibrary')/files/add(overwrite=true, url='" + temp_filename + "')",
                        type: "POST",
                        data: params.arraybuffer,
                        processData: false,
                        headers: { "Accept": "application/json;odata=verbose", "X-RequestDigest": params.digest, "X-HTTP-Method": "POST","If-Match": "*" },
                        success: function (file) {
                            //delete a possiblly existing file with real target name
                            jQuery.ajax({
                                url: "/sites/mySite/_api/web/GetFileByServerRelativeUrl('/sites/mySite/myLibrary/" + real_filename + "')",
                                type: "POST",
                                processData: false,
                                headers: { "Accept": "application/json;odata=verbose", "X-RequestDigest": params.digest, "X-HTTP-Method": "DELETE", "If-Match": "*" },
                                success: function () {
                                    //target file was existing
                                    finalize(file);
                                },
                                error: function () {
                                    //target file was not existing
                                    finalize(file);
                                }
                            });
                        }
                    });
                    function finalize(file) {
                        //get listItem for uploaded file
                        jQuery.ajax({
                            url: file.d.ListItemAllFields.__deferred.uri,
                            type: "GET",
                            headers: { "accept": "application/json;odata=verbose" },
                            success: function (result) {
                                var spItem = result.d;
                                //rename the uploaded file
                                jQuery.ajax({
                                    url: spItem.__metadata.uri,
                                    type: "POST",
                                    data: JSON.stringify({ __metadata: { 'type': spItem.__metadata.type }, FileLeafRef: real_filename }),
                                    headers: { "Accept": "application/json;odata=verbose", "X-RequestDigest": params.digest, "content-type": "application/json;odata=verbose", "X-HTTP-Method": "MERGE", "If-Match": "*" },
                                    success: function () {
                                        //file was renamed
                                        spItem.FileLeafRef = real_filename;
                                        defer.resolve(spItem);
                                    },
                                    error: function (e) {
                                        //something went wrong
                                        defer.resolve(null, e);
                                    }
                                });
                            }
                        });
                    }