【问题标题】:SharePoint CSOM not throwing expected exceptions on ExecuteQuerySharePoint CSOM 未在 ExecuteQuery 上引发预期异常
【发布时间】:2020-10-05 19:57:22
【问题描述】:

基本上就是标题所说的,无论出于何种原因,当我调用 clientContext.ExecuteQuery(); 时,例如数据进入的列表中缺少一列,我没有遇到异常,它实际上只是按预期运行,我有去调查可能导致数据不显示的原因。

我使用的 NuGet 包是 Microsoft.SharePoint2016.CSOM 版本 16.0.4690.1000

任何提示或建议指出我正确的方向表示赞赏。完全有可能我在这里有点昏暗。

这是我用于更新列表项的完整代码块:

public override object UpdateEntity(object entity)
{
    if (entity == null)
    {
        // if the definition is null throw argument null exception.
        throw new ArgumentNullException(nameof(SharePointDefinition));
    }

    // check for incorrect type being passed in that we can still handle
    if (entity is List<SharePointDefinition> definitions)
    {
        return UpdateEntities(definitions);
    }

    ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
    ExceptionHandlingScope exceptionScopeSubmit = new ExceptionHandlingScope(clientContext);

    // run single definition submit to SP.
    if (entity is SharePointDefinition definition)
    {
        // variables.
        IntegrationEventLog log = new IntegrationEventLog();
        EventInformation ei = new EventInformation();
        List list = null;
        ListItemCollection listItemCol = null;

        using (exceptionScopeFetch.StartScope())
        {
            using (exceptionScopeFetch.StartTry())
            {
                // get the required list
                list = clientContext.Web.Lists.GetByTitle(definition.ListName);

                // create query
                listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());

                // set these items for retrieval.
                clientContext.Load(listItemCol);
            }

            using (exceptionScopeFetch.StartCatch())
            {
                // Assume that if there's an exception, it can only be 
                // because there is no list with the specified title, so report this back.
                if (exceptionScopeFetch.HasException)
                {
                    ei = new EventInformation()
                    {
                        LoggingEventType = LoggingEventType.DataSentFailure,
                        LoggingSeverity = LoggingSeverity.HighSeverity,
                        SerialisedMessage = JsonConvert.SerializeObject(definition),
                        ServiceMessage = $"Hit SharePoint exception handler during list and data pull: Message: {exceptionScopeFetch.ErrorMessage}",
                        StackTrace = exceptionScopeFetch.ServerStackTrace,
                        TimeGenerated = DateTime.Now,
                        TimeWritten = DateTime.Now,
                    };

                    log.EventLogEntryType = EventLogEntryType.Error;
                    log.EventID = LoggingSeverity.HighSeverity;
                    log.Message = JsonConvert.SerializeObject(ei);
                    AddToLog(log);
                }
            }

            using (exceptionScopeFetch.StartFinally())
            {
                //
            }
        }

        // get item instances first
        try
        {
            clientContext.ExecuteQuery();
        }
        catch (Exception genEx)
        {
            // return failure log.
            ei = new EventInformation()
            {
                LoggingEventType = LoggingEventType.DataSentFailure,
                LoggingSeverity = LoggingSeverity.HighSeverity,
                SerialisedMessage = JsonConvert.SerializeObject(definition),
                ServiceMessage = "Errored trying to get data from SharePoint list ready for update operation; see stacktrace for more information.",
                StackTrace = genEx.StackTrace,
                TimeGenerated = DateTime.Now,
                TimeWritten = DateTime.Now,
            };

            log.EventLogEntryType = EventLogEntryType.Error;
            log.EventID = LoggingSeverity.HighSeverity;
            log.Message = JsonConvert.SerializeObject(ei);
            AddToLog(log);

            return false;
        }

        // this is the column we want to overwrite.
        var comparisonColumn = definition.UpdateIdentifier ?? "";

        //List col to dict
        var listItems = listItemCol.Cast<ListItem>().ToList();

        // Now we know if we were able to retrieve existing data, perform submit.
        using (exceptionScopeSubmit.StartScope())
        {
            using (exceptionScopeSubmit.StartTry())
            {
                // loop through our rows
                foreach (var row in definition.RowData)
                {
                    int existingItemIndex = -1;
                    // see if the row exists already
                    if (!string.IsNullOrEmpty(comparisonColumn) && listItems.Count != 0)
                    {
                        existingItemIndex = listItems.FindIndex(x => x[comparisonColumn].ToString() == row[comparisonColumn]);
                    }

                    if (existingItemIndex != -1 && listItems.Count != 0)
                    {
                        // item exists - loop through our row columns
                        foreach (var keyValuePair in row)
                        {
                            // they key relates to a column, the Value to the rows colum Value.
                            listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
                        }

                        // update this item
                        listItems[existingItemIndex].Update();
                    }
                    else
                    {
                        ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
                        ListItem newItem = list.AddItem(itemCreateInfo);

                        // loop through our row columns
                        foreach (var keyValuePair in row)
                        {
                            // they key relates to a column, the Value to the rows colum Value.
                            newItem[keyValuePair.Key] = keyValuePair.Value;
                        }
                        newItem.Update();
                    }
                }
            }

            using (exceptionScopeSubmit.StartCatch())
            {
                // Assume that if there's an exception, it can only be 
                // because there is no list with the specified title, so report this back.
                if (exceptionScopeFetch.HasException)
                {
                    ei = new EventInformation()
                    {
                        LoggingEventType = LoggingEventType.DataSentFailure,
                        LoggingSeverity = LoggingSeverity.HighSeverity,
                        SerialisedMessage = JsonConvert.SerializeObject(definition),
                        ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
                        StackTrace = exceptionScopeFetch.ServerStackTrace,
                        TimeGenerated = DateTime.Now,
                        TimeWritten = DateTime.Now,
                    };

                    log.EventLogEntryType = EventLogEntryType.Error;
                    log.EventID = LoggingSeverity.HighSeverity;
                    log.Message = JsonConvert.SerializeObject(ei);
                    AddToLog(log);
                }
            }

            using (exceptionScopeSubmit.StartFinally())
            {
                //
            }
        }

        // try to execute submit.
        try
        {
            clientContext.ExecuteQuery();

            ei = new EventInformation()
            {
                LoggingEventType = LoggingEventType.DataSentSuccess,
                LoggingSeverity = LoggingSeverity.Information,
                SerialisedMessage = JsonConvert.SerializeObject(definition),
                ServiceMessage = "No exceptions were thrown from the Execution process.",
                StackTrace = "",
                TimeGenerated = DateTime.Now,
                TimeWritten = DateTime.Now,
            };

            log.EventLogEntryType = EventLogEntryType.Information;
            log.EventID = LoggingSeverity.Information;
            log.Message = JsonConvert.SerializeObject(ei);
        }
        catch (Exception genEx)
        {
            ei = new EventInformation()
            {
                LoggingEventType = LoggingEventType.DataSentFailure,
                LoggingSeverity = LoggingSeverity.HighSeverity,
                SerialisedMessage = JsonConvert.SerializeObject(definition),
                ServiceMessage = $"Data failed to be updated within SharePoint - {genEx.Message} - see stacktrace for more information.",
                StackTrace = genEx.StackTrace,
                TimeGenerated = DateTime.Now,
                TimeWritten = DateTime.Now,
            };

            log.EventLogEntryType = EventLogEntryType.Error;
            log.EventID = LoggingSeverity.HighSeverity;
            log.Message = JsonConvert.SerializeObject(ei);
            AddToLog(log);

            return false;
        }

        AddToLog(log);
        return true;
    }
    else
    {
        // If a different definition type is passed in throw an appropriate exception. 
        // This should be caught at runtime only.
        throw new TypeLoadException(nameof(SharePointDefinition));
    }
}

【问题讨论】:

    标签: c# sharepoint csom sharepoint-2016


    【解决方案1】:

    我检查了您发布的代码,发现您正在更新对象列表,在您的情况下是 listItems,而不是在 ListItemCollection 中的 ListItem,在您的情况下listItemCol。 为了更清楚,我相信您可以尝试将 listItems 替换为 listItemCol。 例如,而不是:

    listItems[existingItemIndex].ParseAndSetFieldValue(keyValuePair.Key, keyValuePair.Value);
    

    使用

    listItemCol[existingItemIndex][keyValuePair.Key] = keyValuePair.Value;
    

    【讨论】:

    • 我实际上都试过了,更新代码实际上是双向的,但即使我设置了一些我知道应该抛出错误的东西,它也永远不会遇到 catch 子句。更新问题是因为我传递了 SharePoint 不允许我分配的 ID 列的值。它应该告诉我的,但它没有
    【解决方案2】:

    所以我离开并重新阅读了大量文档并查看了一些示例,我想知道为什么异常处理程序从未返回错误,即使很明显正在执行的查询存在问题。如果您查看 Microsoft 文档及其示例 here,您会发现它们没有向您展示如何使用异常范围对象的 exceptionScopeSubmit.HasException 组件。这导致了我的一个非常愚蠢的假设。事实证明,异常块在 SharePoint 服务器上运行,应该用于修复您在查询中的预期异常期间可能导致的问题。

    不仅如此,在使用异常作用域时,将 ExecuteQuery 包装在 try catch 中也是多余的,因为这意味着该方法将不再抛出异常。实际上,您必须在执行后评估 exceptionScopeSubmit.HasException,以获取有关 SharePoint 服务器端执行查询报告的错误的更多详细信息。

    所以现在我如下使用它,我可以获得详细的错误信息,而无需进行一些愚蠢的手动调试,这很容易让我花费数小时来追踪愚蠢的问题。因此,如果有人偶然发现有同样的问题,我希望它会有所帮助。

    ExceptionHandlingScope exceptionScopeFetch = new ExceptionHandlingScope(clientContext);
    
    // variables.
    IntegrationEventLog log = new IntegrationEventLog();
    EventInformation ei = new EventInformation();
    List list = null;
    ListItemCollection listItemCol = null;
    
    using (exceptionScopeFetch.StartScope())
    {
        using (exceptionScopeFetch.StartTry())
        {
            // get the required list
            list = clientContext.Web.Lists.GetByTitle(definition.ListName);
    
            // create query
            listItemCol = list.GetItems(CamlQuery.CreateAllItemsQuery());
    
            // set these items for retrieval.
            clientContext.Load(listItemCol);
        }
    
        using (exceptionScopeFetch.StartCatch())
        {
            //
        }
    
        using (exceptionScopeFetch.StartFinally())
        {
            //
        }
    }
    
    // get item instances first
    clientContext.ExecuteQuery();
        
    if (exceptionScopeSubmit.HasException)
    {
        ei = new EventInformation()
        {
            LoggingEventType = LoggingEventType.DataSentFailure,
            LoggingSeverity = LoggingSeverity.HighSeverity,
            SerialisedMessage = JsonConvert.SerializeObject(definition),
            ServiceMessage = $"Error at SharePoint exception handler during submit to list: Message: {exceptionScopeFetch.ErrorMessage}",
            StackTrace = exceptionScopeFetch.ServerStackTrace,
            TimeGenerated = DateTime.Now,
            TimeWritten = DateTime.Now,
        };
    
        log.EventLogEntryType = EventLogEntryType.Error;
        log.EventID = LoggingSeverity.HighSeverity;
        log.Message = JsonConvert.SerializeObject(ei);
        AddToLog(log);
    }
    

    【讨论】:

      猜你喜欢
      • 2015-06-09
      • 1970-01-01
      • 2023-02-12
      • 2017-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 1970-01-01
      相关资源
      最近更新 更多