公平警告:此问题的设置很长,请耐心等待并留在我身边。
我的解决方案包中有两个功能。第一个是一组站点字段和内容类型;让我们称之为功能A 。其中包括“TaxonomyFieldType”类型的字段和“Note”类型的关联字段(an explanation of the note field)。
<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();
}
第二个功能包含列表模板和实例,其中一个使用上述内容类型;我们将此功能称为功能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 。将创建站点列和内容类型。当我尝试激活功能B 时,功能激活调用堆栈会爆炸并导致出现错误页面,其中包含以下堆栈跟踪:
[COMException (0x80004005): Cannot complete this action. Please try again.] Microsoft.SharePoint.Library.SPRequestInternalClass.UpdateField(String bstrUrl, String bstrListName, String bstrXML) +0 Microsoft.SharePoint.Library.SPRequest.UpdateField(String bstrUrl, String bstrListName, String bstrXML) +134 [SPException: Cannot complete this action. Please try again.] Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionListInstances(SPFeaturePropertyCollection props, SPSite site, SPWeb web, Boolean fForce) +23649702 Microsoft.SharePoint.Administration.SPElementDefinitionCollection.ProvisionElements(SPFeaturePropertyCollection props, SPWebApplication webapp, SPSite site, SPWeb web, Boolean fForce) +197 Microsoft.SharePoint.SPFeature.Activate(SPSite siteParent, SPWeb webParent, SPFeaturePropertyCollection props, Boolean fForce) +25437263 Microsoft.SharePoint.SPFeatureCollection.AddInternal(SPFeatureDefinition featdef, Version version, SPFeaturePropertyCollection properties, Boolean force, Boolean fMarkOnly) +27496735 Microsoft.SharePoint.SPFeatureCollection.AddInternalWithName(Guid featureId, String featureName, Version version, SPFeaturePropertyCollection properties, Boolean force, Boolean fMarkOnly, SPFeatureDefinitionScope featdefScope) +150 Microsoft.SharePoint.SPFeatureCollection.Add(Guid featureId, Boolean force, SPFeatureDefinitionScope featdefScope) +83 Microsoft.SharePoint.WebControls.FeatureActivator.ActivateFeature(Guid featid, SPFeatureDefinitionScope featdefScope) +699 Microsoft.SharePoint.WebControls.FeatureActivatorItem.BtnActivateFeature_Click(Object objSender, EventArgs evtargs) +140 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +115 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +29 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2981
我很确定我在功能A 中配置TaxonomyField
的方式有问题;它在配置时与列表实例的关联是错误的原因(我通过注释掉片段并反复部署来确定这一点)。 TaxonomyFields
似乎只有很少的文档,甚至博客经验,并且在列表实例中配置它们,所以我有点不知所措。有人知道出了什么问题吗?
答案 0 :(得分:1)
我跟随WictorWilénHow to provision SharePoint 2010 Managed Metadata columns并且能够得到类似的工作(确保也可以从this comment进行修改。)
答案 1 :(得分:0)
我最终向微软公开了一个支持事件,以解决这个问题。最终,他们的服务代表将其跟踪到设置列表模板上的属性DisallowContentTypes="FALSE"
和列表架构上的EnableContentTypes="TRUE"
。这解决了我的配置问题。
但是,我仍然有一个问题,即能够在新配置的列表上实际创建项目,这与必须伴随分类字段(grrr)的隐藏文本字段有关。我在网站中配置了一个注释字段,我在列表模板中引用了它,并且我已将TextField属性设置为网站列定义和字段定义中此注释字段的ID。
Wictor提到了这一点(如果我从阅读他的帖子中回忆起来的话),但这里有更多内容:http://www.sharepointconfig.com/2011/03/the-complete-guide-to-provisioning-sharepoint-2010-managed-metadata-fields/
我目前停留在项目创建时抛出的异常,说:
无法获得“标签”的值 “托管元数据”中的列 场类型控制。详见 登录。异常消息:无效字段 名称。 {956a1078-ec35-4c04-83c4-0a3742119496} http://server/sites/mysite /位点/ mysite的/列表/个
答案 2 :(得分:0)
在为包含自定义ContentTypeRef的沙盒自定义列表模板激活包含ListInstance元素的沙盒功能时,我遇到了同样的错误。列表已创建,但创建时出现功能错误。此外,该列表包含自动生成的内容类型,而不是列表定义中指定的内容类型。如果您在创建所有列表之前一直尝试激活该功能,该功能将最终激活。
此外,我注意到我无法从MOSS 2010中的SandBoxed解决方案更新沙盒自定义字段属性。我得到相同类型的错误,表明在通过XML定义的自定义字段上调用SPListItem.UpdateField时无法完成操作在沙盒解决方案中。
我现在得出的结论是,MOSS 2010的沙盒解决方案不支持沙盒字段更新。
您应该在XML字段定义和列表模板字段XML元素中完全定义字段,而不是以编程方式更新沙盒自定义内容类型中的字段。
让您的列表使用自定义内容类型并激活而不会导致&#34;无法完成此操作的方法&#34;错误如下:
1)在列表定义中使用默认ContentTypeRef,而不是您创建的自定义ContentRef。
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,则上述函数可能无法在沙盒解决方案中导致错误。
对于事件类型,我使用默认的事件内容类型并运行代码以根据需要自定义列表(添加列)。