"Не удается выполнить это действие" при попытке подготовить экземпляр списка с сайтом TaxonomyField
Справедливое предупреждение: постановка этого вопроса длинная, так что наберитесь терпения и оставайтесь со мной.
У меня есть две функции в моем пакете решений. Первый - это набор полей сайта и типов контента; давайте назовем это особенность А. Среди полей есть поле типа "TaxonomyFieldType" и связанное поле типа "Примечание" ( пояснение поля примечания).
<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): не удается выполнить это действие. Пожалуйста, повторите попытку] Microsoft.SharePoint.Library.SPRequestInternalClass.UpdateField(String bstrUrl, Строка bstrListName, строка bstrXML) +0 Microsoft.SharePoint.Library.SPRequest.UpdateField(String bstrUrl Строковый bstrListName, String bstrXML) +134 [SPException.: Не удается выполнить это действие. Повторите попытку.], Boolean fForce) +197 Microsoft.SharePoint.SPFeature.Activate(SPSite siteParent, SPWeb webParent, SPFeaturePropertyCollection реквизиты, Boolean fForce) +25437263 Microsoft.SharePoint.SPFeatureCollection.AddInternal(свойства версии SPFeatureDeflement, SPFeleFleleFlentFlectionFleleFlentFlectionFleleFlentFlectionFleleFlentFlectionFleleFleleFlentFlectionFleleFlectionFlectionFleceFlectionFleceFleN)) +27496735 Microsoft.SharePoint.SPFeatureCollection.AddInternalWithName(Guid featureId, String featureName, версия версии, свойства SPFeaturePropertyCollection, логическая сила, логическое значение fMarkOnly, SPFeatureDefinitionScope featdefScope) +150 Microsoft.ShareCollection.Fid.IourDelection Guid.Fid.IourDelection. сила, SPFeatureDefinitionScope featdefScope) +83 Microsoft.SharePoint.WebControls.FeatureActivator.ActivateFeature(Guid featid, SPFeatureDefinitionScope featdefScope) +699 Майкрософт.SharePoint.WebControls.FeatureAectiveTyBject.WeGenTigSignEgsTigStategSignEgsTigStegs.GateSject WebControls.Button.OnClick(EventArgs e) +115 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +140 System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String event.Arg).UI.Page.ProcessRequestMain(логическое значение includeStagesBeforeAsyncPoint, логическое значение includeStagesAfterAsyncPoint) +2981
Я совершенно уверен, что что-то не так с тем, как я настраиваю TaxonomyField
в функции A; его связь с экземпляром списка во время инициализации является причиной ошибки (я определил это, комментируя фрагменты и развертывая снова и снова). Там, кажется, очень мало документации, или даже опыт блоггера, с TaxonomyFields
и предоставляя их в списках экземпляров, так что я немного растерялся. Кто-нибудь имеет представление о том, что происходит не так?
3 ответа
Я следовал инструкциям Wictor Wilén " Как подготовить столбцы управляемых метаданных SharePoint 2010" и смог получить что-то подобное (не забудьте также внести изменения в этот комментарий).
Я закончил тем, что открыл инцидент поддержки с Microsoft, чтобы выяснить это. В конце концов, их сервисный представитель отследил это до установки свойства DisallowContentTypes="FALSE"
в шаблоне списка и EnableContentTypes="TRUE"
в схеме списка. Это решило мою проблему с обеспечением.
Тем не менее, у меня все еще есть проблема с возможностью создания элементов во вновь подготовленных списках, связанные с полем скрытого текста, которое должно сопровождать поле таксономии (grrr). Я подготовил поле примечания на сайте, и я сослался на него в своем шаблоне списка, и я установил для свойства TextField идентификатор этого поля примечания как в определении столбца сайта, так и в определении поля.
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 / sites / mysite / Lists / Entries
Я получаю ту же ошибку при активации изолированной функции, которая содержит элементы ListInstance для изолированного пользовательского шаблона списка, который содержит пользовательский ContentTypeRef. Список создан, но при создании ошибки произошла ошибка. Кроме того, список содержит автоматически сгенерированный тип содержимого, а не тот, который указан в определении списка. Если вы продолжаете пытаться активировать функцию до тех пор, пока не будут созданы все списки, функция, наконец, активируется.
Кроме того, я заметил, что не могу обновить свойства настраиваемых полей в изолированной программной среде в решениях SandBoxed в MOSS 2010. Я получаю сообщение об ошибке того же типа, указывающее, что не удается завершить действие, когда SPListItem.UpdateField вызывается в настраиваемом поле, определенном с помощью XML, в изолированной программной среде. решение.
Сейчас я пришел к выводу, что обновления в изолированной среде не поддерживаются в изолированных решениях для MOSS 2010.
Вместо того, чтобы программно обновлять поля из пользовательских типов содержимого в песочнице, вы должны полностью определить поле полностью в XML-определении поля XML и в поле шаблона списка.
Чтобы получить в своем списке возможность использовать свой пользовательский тип контента и активировать его, не вызывая ошибку "Не удается выполнить это действие", выполните следующие действия.
1) Используйте 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, то вышеупомянутая функция может не работать без возникновения ошибки в изолированном решении.
Для Типа события я использовал Тип содержимого события по умолчанию и запустил код, чтобы настроить список (добавляя столбцы) по мере необходимости.