使用 STA 线程修改 SharePoint 页面时检测到 DisconnectedContext

DisconnectedContext detected when using STA thread to modify SharePoint page

背景信息:我在 SharePoint 2010 中使用 ItemCheckedIn 接收器,目标是 .NET 3.5 Framework。接收者的目标是:

  1. 确保页面的属性(列)与页面上内容编辑器 Web 部件中的数据相匹配,以便可以在使用筛选器 Web 部件的搜索中找到该页面。这些页面是自动生成的,因此除非有任何错误,否则它们保证符合预期的格式。
  2. 如果不匹配,请签出页面,修复属性,然后重新签入。

我一直在防止接收器陷入无限 check-in/check-out 循环,尽管现在我正在努力解决这个问题,但它非常笨拙。但是,现在我无法处理它,因为每当我点击 UpdatePage 函数时都会收到 DisconnectedContext 错误:

public override void ItemCheckedIn(SPItemEventProperties properties)
{
    // If the main page or machine information is being checked in, do nothing
    if (properties.AfterUrl.Contains("home") || properties.AfterUrl.Contains("machines")) return;

    // Otherwise make sure that the page properties reflect any changes that may have been made
    using (SPSite site = new SPSite("http://san1web.net.jbtc.com/sites/depts/VPC/"))
    using (SPWeb web = site.OpenWeb())
    {
        SPFile page = web.GetFile(properties.AfterUrl);

        // Make sure the event receiver doesn't get called infinitely by checking version history
        ...

        UpdatePage(page);
    }
}

private static void UpdatePage(SPFile page)
{
    bool checkOut = false;

    var th = new Thread(() =>
    {
        using (WebBrowser wb = new WebBrowser())
        using (SPLimitedWebPartManager manager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
        {
            // Get web part's contents into HtmlDocument
            ContentEditorWebPart cewp = (ContentEditorWebPart)manager.WebParts[0];

            HtmlDocument htmlDoc;
            wb.Navigate("about:blank");
            htmlDoc = wb.Document;
            htmlDoc.OpenNew(true);
            htmlDoc.Write(cewp.Content.InnerText);

            foreach (var prop in props)
            {
                // Check that each property matches the information on the page
                string element;
                try
                {
                    element = htmlDoc.GetElementById(prop).InnerText;
                }
                catch (NullReferenceException)
                {
                    break;
                }

                if (!element.Equals(page.GetProperty(prop).ToString()))
                {
                    if (!prop.Contains("Request"))
                    {
                        checkOut = true;
                        break;
                    }
                    else if (!element.Equals(page.GetProperty(prop).ToString().Split(' ')[0]))
                    {
                        checkOut = true;
                        break;
                    }
                }
            }

            if (!checkOut) return;

            // If there was a mismatch, check the page out and fix the properties
            page.CheckOut();
            foreach (var prop in props)
            {
                page.SetProperty(prop, htmlDoc.GetElementById(prop).InnerText);
                page.Item[prop] = htmlDoc.GetElementById(prop).InnerText;

                try
                {
                    page.Update();
                }
                catch
                {
                    page.SetProperty(prop, Convert.ToDateTime(htmlDoc.GetElementById(prop).InnerText).AddDays(1));
                    page.Item[prop] = Convert.ToDateTime(htmlDoc.GetElementById(prop).InnerText).AddDays(1);
                    page.Update();
                }
            }

            page.CheckIn("");
        }
    });
    th.SetApartmentState(ApartmentState.STA);
    th.Start();
}

据我所知,使用 WebBrowser 是在此版本的 .NET 中填充 HtmlDocument 的唯一方法,因此这就是我必须使用此线程的原因。

此外,我已经阅读了一些资料,看起来 DisconnectedContext 错误与线程和 COM 有关,我对这些主题几乎一无所知。我该如何处理 prevent/fix 这个错误?

编辑

正如@Yevgeniy.Chernobrivets 在评论中指出的那样,我可以插入一个绑定到页面列的 editable 字段,而不用担心解析任何 html,但是因为当前页面布局在内容编辑器 WebPart 中使用 HTML table,这种字段无法正常工作,我需要制作新的页面布局并从下到上重建我的解决方案,我真的宁愿避免。

我还想避免下载任何东西,因为我工作的公司通常不允许使用未经批准的软件。

您不应该使用 WebBrowser class 进行 html 解析,它是 Windows Forms 的一部分,不适合网络以及纯 html 解析.尝试使用一些 html 解析器,例如 HtmlAgilityPack