【问题标题】:SharePoint CSOM - Update document and list item property together?SharePoint CSOM - 一起更新文档和列表项属性?
【发布时间】:2015-03-09 10:16:05
【问题描述】:

当远程事件接收器更改文档列表项时,我需要处理它。远程事件接收器连接到 itemupdated 事件。这有一个明显的问题,如果我在 itemupdated 事件中更新项目,我将陷入无限循环。

为了避免这种无限循环,并且在没有像旧式 SharePoint 开发中使用的 EventFiringEnabled 之类的东西的情况下,我考虑在列表项上添加一个“已处理”标志以指示文档已被处理。

然后逻辑流程如下所示。

  • 文档已添加到库中 - 这里没什么特别的
  • 已在列表项上填写元数据 - 触发 ItemUpdated 事件
  • 远程事件接收器应运而生。检查“已处理”标志。如果是真的,什么都不做,如果是假的,继续。使用文档上的元数据,它“处理”它。文档已更新,列表项“已处理”标志设置为 true。

我遇到的麻烦是在单个事务中更新文档和列表项。

我的 SaveFile 方法如下所示:

    private void SaveFile(List list, string url, MemoryStream memoryStream)
    {
        var newFile = new FileCreationInformation
        {
            ContentStream = memoryStream,
            Url = url,
            Overwrite = true
        };

        File updatedFile = list.RootFolder.Files.Add(newFile);
        ListItem item = updatedFile.ListItemAllFields;
        item["Processed"] = true;
        item.Update();

        _clientContext.ExecuteQuery();
    }

但这表现为两个更新。文件被更新,然后列表项被更新。有谁知道我是否可以将其强制为单个更新?

【问题讨论】:

  • 如果您不想获取新项目,则无需调用 Load() 方法,这从您当前的 sn-p 中可以看出。我认为,@Vadim 正确地指出它仍然是从客户端机器发送的单个请求。

标签: sharepoint csom sharepoint-online


【解决方案1】:

事实上,在指定的例子中,只有一个单个请求被提交给服务器(当ClientContext.ExecuteQuery方法被调用时)。可以使用Fiddler等网络监控工具进行验证。

这里是原始示例的稍加修改的版本,带有 cmets:

private static void SaveFile(List list, string url, Stream contentStream,IDictionary<string,object> itemProperties)
{
    var ctx = list.Context;
    var fileInfo = new FileCreationInformation
    {
        ContentStream = contentStream,
        Url = url,
        Overwrite = true
    };
    var file = list.RootFolder.Files.Add(fileInfo); //1. prepare to add file
    var item = file.ListItemAllFields;
    foreach (var p in itemProperties)
       item[p.Key] = p.Value;
    item.Update();  //2. prepare list item to update
    ctx.ExecuteQuery();  //3. submit request to the server that includes adding the file and updading the associated list item properties. 
}

更新

使用具有以下签名的ListItem.ValidateUpdateListItem method

public IList<ListItemFormUpdateValue> ValidateUpdateListItem(
    IList<ListItemFormUpdateValue> formValues,
    bool bNewDocumentUpdate,
    string checkInComment
)

此方法类似于UpdateOverwriteVersion 方法 在服务器 API 上可用。 ValidateUpdateListItem 设置元数据 如果 bNewDocumentUpdate 参数设置为 true 将调用 UpdateOverwriteVersion 方法将在不增加的情况下更新 版本

private static void SaveFile(List list, string url, Stream contentStream,List<ListItemFormUpdateValue> itemProperties)
{
        var ctx = list.Context;
        var fileInfo = new FileCreationInformation
        {
            ContentStream = contentStream,
            Url = url,
            Overwrite = true
        };

        var file = list.RootFolder.Files.Add(fileInfo);
        var item = file.ListItemAllFields;
        item.ValidateUpdateListItem(itemProperties, true, string.Empty);
        ctx.ExecuteQuery();
}

用法:

var list = ctx.Web.Lists.GetByTitle(listTitle);
using (var stream = System.IO.File.OpenRead(filePath))
{
    var itemProperties = new List<ListItemFormUpdateValue>();
    itemProperties.Add(new ListItemFormUpdateValue() { FieldName = "Processed", FieldValue = "true" });
    SaveFile(list, pageUrl, stream,itemProperties);    
}

【讨论】:

  • 您好 Vadim,感谢您抽出宝贵时间回复。我已按照您的建议从代码中删除了 Load 行,但这仍然会在执行时产生两个版本的列表项 - 一个用于新文件,一个用于新字段值:(
  • 您好 Vadim,再次感谢您的持续帮助。这个解决方案几乎就在那里,因为版本历史只显示了一次更新,但问题是 ItemUpdated 事件被触发了两次——一次用于文件更新,一次用于更新的项目属性。这意味着文档的更新在我的已处理标志设置为 true 之前触发,并且它被一次又一次地处理!有什么想法吗?
  • 在进一步调查中,我认为我的标志在文件更新时被覆盖。我正在更新文档的内容(word open xml),但 sharepoint 列的值(我相信)也存储在文档的 customxml 部分中。你知道我如何通过 OpenXML 更新它吗?
猜你喜欢
  • 1970-01-01
  • 2019-07-07
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 2015-03-28
  • 2015-10-15
相关资源
最近更新 更多