【问题标题】:The remote server returned an error: (401) Unauthorized - CSOM - OAuth - after specific time远程服务器返回错误:(401) Unauthorized - CSOM - OAuth - after specific time
【发布时间】:2018-05-11 07:19:08
【问题描述】:

我正在尝试使用控制台应用程序中的 csom 从文档库中获取分配给每个文档的权限。控制台应用程序运行良好近一个小时,并发布我收到错误消息:“远程服务器返回错误:(401)未经授权。”

我在 SharePoint 中注册了一个应用程序,我正在使用客户端 ID 和客户端密钥来生成客户端上下文。这是获取客户端上下文的代码

public static ClientContext getClientContext()
    {
        ClientContext ctx = null;
        try
        {
            ctx = new AuthenticationManager().GetAppOnlyAuthenticatedContext(SiteUrl, ClientId, ClientSecret);
            ctx.RequestTimeout = 6000000;

            ctx.ExecutingWebRequest += delegate (object sender, WebRequestEventArgs e)
            {
                e.WebRequestExecutor.WebRequest.UserAgent = "NONISV|Contoso|GovernanceCheck/1.0";
            };
        }
        catch (Exception ex)
        {
            WriteLog("Method-getClientContext, Error - " + ex.Message);
        }
        return ctx;
    }

这是获取分配给文档库中文档的所有分配的代码。

static StringBuilder excelData = new StringBuilder();            
static void ProcessWebnLists()
    {
        try
        {
            string[] lists = { "ABC", "XYZ", "DEF", "GHI"};

            foreach (string strList in lists)
            {
                using (var ctx = getClientContext())
                {
                    if (ctx != null)
                    {
                        Web web = ctx.Site.RootWeb;
                        ListCollection listCollection = web.Lists;
                        ctx.Load(web);
                        ctx.Load(listCollection);
                        ctx.ExecuteQuery();

                        List list = web.Lists.GetByTitle(strList);
                        ctx.Load(list);
                        ctx.ExecuteQuery();

                        Console.WriteLine("List Name:{0}", list.Title);

                        var query = new CamlQuery { ViewXml = "<View/>" };

                        var items = list.GetItems(query);
                        ctx.Load(items);
                        ctx.ExecuteQuery();

                        foreach (var item in items)
                        {
                            var itemAssignments = item.RoleAssignments;
                            ctx.Load(item, i => i.DisplayName);
                            ctx.Load(itemAssignments);
                            ctx.ExecuteQuery();
                            Console.WriteLine(item.DisplayName);
                            string groupNames = "";
                            foreach (var assignment in itemAssignments)
                            {
                                try
                                {
                                    ctx.Load(assignment.Member);
                                    ctx.ExecuteQuery();
                                    groupNames += "[" + assignment.Member.Title.Replace(",", " ") + "] ";
                                    Console.WriteLine($"--> {assignment.Member.Title}");
                                }
                                catch (Exception e)
                                {
                                    WriteLog("Method-ProcessWebnLists, List-" + list.Title + ", Document Title - " + item.DisplayName + ", Error : " + e.Message);
                                    WriteLog("Method-ProcessWebnLists, StackTrace : " + e.StackTrace);
                                }
                            }
                            excelData.AppendFormat("{0},{1},ITEM,{2}", list.Title, (item.DisplayName).Replace(",", " "), groupNames);
                            excelData.AppendLine();
                        }
                    }
                    excelData.AppendLine();
                }
            }
        }
        catch (Exception ex)
        {
            WriteLog("Method-ProcessWebnLists, Error : " + ex.Message);
            WriteLog("Method-ProcessWebnLists, StackTrace : " + ex.StackTrace.ToString());
        }
    }

谁能建议我在这方面还缺少什么或我需要进行哪些更改以避免此错误?

该过程花费了太多时间,因此我希望我的应用程序继续运行几个小时。

提前致谢!

【问题讨论】:

    标签: sharepoint console-application office365 csom


    【解决方案1】:

    getClientContext() 在 foreach 循环内有什么原因吗?

    我之前遇到过这个错误。 我添加了这个来解决我的问题。

    public static void ExecuteQueryWithIncrementalRetry(this ClientContext context, int retryCount, int delay)
    {
        int retryAttempts = 0;
        int backoffInterval = delay;
        if (retryCount <= 0)
            throw new ArgumentException("Provide a retry count greater than zero.");
       if (delay <= 0)
            throw new ArgumentException("Provide a delay greater than zero.");
       while (retryAttempts < retryCount)
        {
            try
            {
                context.ExecuteQuery();
                return;
            }
            catch (WebException wex)
            {
                var response = wex.Response as HttpWebResponse;
                if (response != null &amp;&amp; response.StatusCode == (HttpStatusCode)429)
                {
                    Console.WriteLine(string.Format("CSOM request exceeded usage limits. Sleeping for {0} seconds before retrying.", backoffInterval));
                    //Add delay.
                    System.Threading.Thread.Sleep(backoffInterval);
                    //Add to retry count and increase delay.
                    retryAttempts++;
                    backoffInterval = backoffInterval * 2;
                }
                else
                {
                    throw;
                }
            }
        }
        throw new MaximumRetryAttemptedException(string.Format("Maximum retry attempts {0}, have been attempted.", retryCount));
    }
    

    基本上,此代码会在执行另一个查询之前回退一段时间/间隔,以防止节流。

    所以不要使用ctx.ExecuteQuery(),而是使用ctx.ExecuteQueryWithIncrementalRetry(5, 1000);

    这里有更多解释 https://docs.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online

    【讨论】:

      猜你喜欢
      • 2011-09-10
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多