1

公平警告:这个问题的设置很长,所以请耐心等待我。

我的解决方案包中有两个功能。第一个是一组站点字段和内容类型;我们称之为Feature A。这些字段中有一个“TaxonomyFieldType”类型的字段和一个“Note”类型的关联字段(注释字段的解释)。

<Elements ...>  
<Field ID="{956a1078-ec35-4c04-83c4-0a3742119496}" 
        Name="TaxonomyTextField" 
        Type="Note" DisplayName="Tags_0" 
        ShowInViewForms="FALSE" 
        Required="FALSE"
        Group="MyGroup"
        Hidden="TRUE"/>

<Field ID="{92BC866B-0415-45F0-B431-D4DF69C421CC}"
        Name="Tags"
        DisplayName="Custom Tags"
        Type="TaxonomyFieldType"
        ShowField="Term1033"
        Required="FALSE"
        Group="MyGroup"
        >
  <Customization>
    <ArrayOfProperty>
      <Property>
        <Name>IsPathRendered</Name>
        <Value xmlns:q7="http://www.w3.org/2001/XMLSchema" p4:type="q7:boolean" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">true</Value>
      </Property>
      <Property>
        <Name>TextField</Name>
        <Value xmlns:q6="http://www.w3.org/2001/XMLSchema" p4:type="q6:string" xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{956a1078-ec35-4c04-83c4-0a3742119496}</Value>
      </Property>
    </ArrayOfProperty>
  </Customization>
</Field>
</Elements>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <!-- Parent ContentType: Item (0x01) -->
  <ContentType ID="0x0100b61c774f4c0e4a89bf230cbb44cd4f75"
               Name="MyContent"
               Group="MyGroup"
               Description="Description of My Content Type"
               Inherits="FALSE"
               Overwrite="TRUE"
               Version="0">
    <FieldRefs>
      <FieldRef ID="{52578fc3-1f01-4f4d-b016-94ccbcf428cf}" DisplayName="Comments" Name="Comments" Required="FALSE"/>
      <FieldRef ID="{956a1078-ec35-4c04-83c4-0a3742119496}" Name="TimeTrackerTaxonomyTextField"/>
      <FieldRef ID="{92BC866B-0415-45F0-B431-D4DF69C421CC}" DisplayName="Tags" Name="Tags" Required="FALSE"/>
    </FieldRefs>
  </ContentType>
</Elements>

在第一个特征的特征接收器(我们称之为特征 A)中,我以编程方式检索它TaxonomyField并确保它被配置为从预定术语集中检索术语:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    SPWeb web = GetWebObj(properties.Feature.Parent);
    Guid fieldId = new Guid("92BC866B-0415-45F0-B431-D4DF69C421CC");
    TaxonomyField field = web.Fields[fieldId] as TaxonomyField;
    string groupName = properties.Feature.Properties["TaxonomyGroupName"].Value;
    string termSetName = properties.Feature.Properties["TermSetName"].Value;
    DiagnosticService logger = DiagnosticService.Local;

    TermSet set = null;
    TaxonomySession session = new TaxonomySession(web.Site);
    TermSetCollection termSets = session.GetTermSets(termSetName, System.Threading.Thread.CurrentThread.CurrentUICulture.LCID);
    if (termSets == null || termSets.Count == 0)
    {
        logger.WriteTrace(1, logger[CategoryId.Deployment], TraceSeverity.Medium,
            "Activity Tags term set not found.  Ensuring '{0}' group and '{1}' term set.", groupName, termSetName);
        // create the term set in the default store
        var store = session.DefaultSiteCollectionTermStore;
        var group = store.EnsureGroup(groupName);
        set = group.EnsureTermSet(termSetName);

        store.CommitAll();
        logger.WriteTrace(1, logger[CategoryId.Provisioning], TraceSeverity.Verbose, "created taxonomy group '{0}' and term set '{1}'", group, set);
    }
    else
    {
        logger.WriteTrace(1, logger[CategoryId.Deployment], TraceSeverity.Verbose, "term set found.");
        // need to make sure we grab the one in the right group, or it might be someone else's term set.                
        foreach (var termSet in termSets)
        {
            if (String.Equals(termSet.Group.Name,groupName))
            {
                if (set == null)
                {
                    set = termSet;
                }
                else
                {
                    logger.WriteTrace(1, logger[CategoryId.Deployment], TraceSeverity.Unexpected,
                        "Multiple term sets named '{0}' found in more than one taxonomy group.", termSetName);
                    throw new SPException(String.Format("Multiple term sets named '{0}' found in more than one taxonomy group.  "+
                                                        "Was there a previous installation that was not removed properly?", termSetName));
                }
            }
        }

        if (set == null)
        {
            // term set found, but in an unrecognized group.  leave it alone and do like above
            logger.WriteTrace(1, logger[CategoryId.Deployment], TraceSeverity.Verbose,
                "Term set '{0}' found, but in unrecognized group.  Provisioning new group and term set as configured.", termSetName);
            var store = session.DefaultSiteCollectionTermStore;
            var group = store.EnsureGroup(groupName);
            set = group.EnsureTermSet(termSetName);

            store.CommitAll();
            logger.WriteTrace(1, logger[CategoryId.Provisioning], TraceSeverity.Verbose, "created taxonomy group '{0}' and term set '{1}'", group, set);
        }
    }

    // set termSets to the newly created term set                
    field.SspId = set.TermStore.Id;
    field.TermSetId = set.Id;
    field.TargetTemplate = String.Empty;
    field.AnchorId = Guid.Empty;
    field.Open = true;
    field.AllowMultipleValues = true;
    field.Update();
}

第二个特性包含列表模板和实例,其中一个使用上述内容类型;让我们将此功能称为Feature B

这是配置时爆炸的列表的列表架构(ListInstance未显示元素):

<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" Title="My List" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/MyList" BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/">
  <MetaData>
    <ContentTypes>      
      <ContentTypeRef ID="0x0100b61c774f4c0e4a89bf230cbb44cd4f75"></ContentTypeRef>
    </ContentTypes>

    <Fields> 
      <Field ID="{956a1078-ec35-4c04-83c4-0a3742119496}" Name="TaxonomyTextField" Type="Note"/>      
      <Field ID="{92bc866b-0415-45f0-b431-d4df69c421cc}" Name="Tags" Type="TaxonomyFieldType"/>
      <Field ID="{52578FC3-1F01-4f4d-B016-94CCBCF428CF}" Name="_Comments" Type="Note"/>      
    </Fields>
    <Views>
      <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
        <Toolbar Type="Standard" />
        <XslLink Default="TRUE">main.xsl</XslLink>
        <RowLimit Paged="TRUE">30</RowLimit>
        <ViewFields>
          <!-- <FieldRef Name="Tags"></FieldRef> -->
          <FieldRef Name="_Comments"></FieldRef>
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="ID">
            </FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
          <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
        </ParameterBindings>
      </View>
    </Views>
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>

解决方案部署后,我可以毫无问题地激活功能 A。创建网站栏和内容类型。当我尝试激活Feature B时,功能激活调用堆栈会爆炸并导致错误页面出现以下堆栈跟踪:

[COMException (0x80004005):无法完成此操作。

请再试一次。]
   Microsoft.SharePoint.Library.SPRequestInternalClass.UpdateField(字符串 bstrUrl,字符串 bstrListName,字符串 bstrXML)+0
   Microsoft.SharePoint.Library.SPRequest.UpdateField(字符串 bstrUrl,字符串 bstrListName,字符串 bstrXML)+134

[SPException:无法完成此操作。

请再试一次。]
   Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionListInstances(SPFeaturePropertyCollection 道具,SPSite 站点,SPWeb 网站,布尔 fForce)+23649702
   Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionElements(SPFeaturePropertyCollection 道具,SPWebApplication webapp,SPSite 站点,SPWeb web,布尔 fForce)+197
   Microsoft.SharePoint.SPFeature.Activate(SPSite siteParent,SPWeb webParent,SPFeaturePropertyCollection 道具,布尔 fForce)+25437263
   Microsoft.SharePoint.SPFeatureCollection.AddInternal(SPFeatureDefinition featdef,版本版本,SPFeaturePropertyCollection 属性,布尔力,布尔 fMarkOnly)+27496735
   Microsoft.SharePoint.SPFeatureCollection.AddInternalWithName(Guid featureId,字符串 featureName,版本版本,SPFeaturePropertyCollection 属性,布尔力,布尔 fMarkOnly,SPFeatureDefinitionScope featdefScope)+150
   Microsoft.SharePoint.SPFeatureCollection.Add(Guid featureId,布尔力,SPFeatureDefinitionScope featdefScope)+83
   Microsoft.SharePoint.WebControls.FeatureActivator.ActivateFeature(Guid featid,SPFeatureDefinitionScope featdefScope)+699
   Microsoft.SharePoint.WebControls.FeatureActivatorItem.BtnActivateFeature_Click(对象 objSender,EventArgs evtargs)+140
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +115
   System.Web.UI.WebControls.Button.RaisePostBackEvent(字符串 eventArgument)+140
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +29
   System.Web.UI.Page.ProcessRequestMain(布尔 includeStagesBeforeAsyncPoint,布尔 includeStagesAfterAsyncPoint)+2981

我相当确定我TaxonomyFieldFeature A中配置的方式有问题;它在配置时与列表实例的关联是导致错误的原因(我通过注释掉片段并一遍又一遍地部署来确定这一点)。似乎很少有文档,甚至是博主经验,TaxonomyFields在列表实例中使用和配置它们,所以我有点不知所措。有人知道出了什么问题吗?

4

3 回答 3

1

我遵循了 Wictor Wilén 的How to Provision SharePoint 2010 Managed Metadata 列,并且能够得到类似的工作(请务必也从这个评论中进行修改)。

于 2011-03-08T20:34:33.887 回答
0

我最终打开了与微软的支持事件来解决这个问题。最终,他们的服务代表跟踪到DisallowContentTypes="FALSE"在列表模板和EnableContentTypes="TRUE"列表架构上设置属性。这解决了我的配置问题。

但是,我仍然无法在新配置的列表上实际创建项目,这与必须伴随分类字段 (grrr) 的隐藏文本字段有关。我在站点中提供了一个注释字段,并在我的列表模板中引用了它,并且我在站点列定义和字段定义中都将 TextField 属性设置为该注释字段的 ID。

Wictor 提到了这一点(如果我记得阅读他的帖子),但这里还有更多内容:http: //www.sharepointconfig.com/2011/03/the-complete-guide-to-provisioning-sharepoint-2010-managed-元数据字段/

我目前被困在项目创建时引发的异常上,说:

无法从“托管元数据”字段类型控件中获取“标签”列的值。请参阅日志中的详细信息。异常消息:无效的字段名称。{956a1078-ec35-4c04-83c4-0a3742119496} http://server/sites/mysite /sites/mysite/Lists/Entries

于 2011-03-08T22:30:42.003 回答
0

在为包含自定义 ContentTypeRef 的沙盒自定义列表模板激活包含 ListInstance 元素的沙盒功能时,我遇到了同样的错误。列表已创建,但功能在创建时出错。此外,列表包含自动生成的内容类型,而不是列表定义中指定的内容类型。如果您在创建所有列表之前一直尝试激活该功能,则该功能将最终激活。

此外,我注意到我无法从 MOSS 2010 中的沙盒解决方案更新沙盒自定义字段属性。我收到相同类型的错误,表明当在沙盒中通过 XML 定义的自定义字段调用 SPListItem.UpdateField 时它无法完成操作解决方案。

我现在得出结论,MOSS 2010 的沙盒解决方案不支持沙盒字段更新。

您应该在 XML 字段定义和列表模板字段 XML 元素中完全定义字段,而不是以编程方式从沙盒自定义内容类型更新字段。

让您的列表使用您的自定义内容类型并激活而不导致“无法完成此操作”错误的方法如下:

1)在您的列表定义中使用 Default ContentTypeRef,而不是您创建的自定义。

https://msdn.microsoft.com/en-us/library/office/ms452896(v=office.14).aspx

例如:0x01 默认项目内容类型

0x0101 默认文档内容类型

在 List Schema.xml 文件中,如果您的内容类型基于默认项内容类型,您可以将其更改为:

<ContentTypes>
    <ContentTypeRef ID="0x01"></ContentTypeRef>
</ContentTypes>

2) 将功能激活事件接收器添加到运行代码以配置列表内容类型的功能。

我编写了一个函数,它基本上设置了列表的内容类型,并摆脱了与列表关联的任何其他内容类型。您的功能激活事件接收器可以运行此功能并将列表的内容类型设置为应有的类型。下面的函数假定您的内容类型是唯一命名的。如果需要,您也可以添加对内容类型组名称的检查。

       public static string ConfigureCustomListForCustomContentType(SPWeb web, string strListName, string strCustomContentTypeName)
    {
        StringBuilder sbOutput = new StringBuilder();
        try
        {
            SPList customlist = web.Lists[strListName];

            SPContentType CustomContentType = null;
            //Validate Content Types
            //1) Find the Content Type in the Content Type list
            foreach (SPContentType spct in web.Site.RootWeb.ContentTypes)
            {
                if (spct.Name == strCustomContentTypeName)
                {
                    CustomContentType = spct;
                    break;
                }
            }

            if (CustomContentType == null)
            {
                sbOutput.Append("<div class='error'>Unable to find custom content type named " + strCustomContentTypeName +".</div>");
                return sbOutput.ToString();
            }
            sbOutput.Append("Found content Type "+CustomContentType.Name+"...<br />");

            Boolean bFoundContentType = false;


            customlist.ContentTypesEnabled = true;

            List<SPContentTypeId> RemoveContentTypeList = new List<SPContentTypeId>();
            //Remove all other content types
            foreach (SPContentType spct in customlist.ContentTypes)
            {
                if (spct.Name == strCustomContentTypeName)
                {
                    bFoundContentType = true;
                }
                else
                {
                    RemoveContentTypeList.Add(spct.Id);
                }

            }


        if (!bFoundContentType)
            {
                sbOutput.Append("Adding [" + strCustomContentTypeName + "] to List " + customlist.Title + "<br />");
                customlist.ContentTypes.Add(CustomContentType);
            }
            else
            {
                sbOutput.Append("[" + strCustomContentTypeName + "] already in List " + customlist.Title + ".<br />");
            }

            for (int i = 0; i < RemoveContentTypeList.Count; i++)
            {

                sbOutput.Append("Removing extra content type: " + customlist.ContentTypes[RemoveContentTypeList[i]].Name + "<br />");
                customlist.ContentTypes[RemoveContentTypeList[i]].Delete();
            }


        }
        catch (Exception ex)
        {
            sbOutput.Append("<div class='error'>Error occurred configuring "+strListName+": " + ex.ToString() + "<br /></div>");
        }

        return sbOutput.ToString();

    }

这应该允许您实例化您的列表并将内容类型设置为您的自定义内容类型。

如果您的列表基于事件类型 0x0102,则上述功能可能无法正常工作,而不会在沙盒解决方案中导致错误。

对于事件类型,我使用默认的事件内容类型并运行代码来根据需要自定义列表(添加列)。

于 2015-10-16T09:14:05.133 回答