Ссылка компонента Tridion не разрешается в представлении динамического компонента
В настоящее время я реализую функциональность в Tridion 2009 с пакетом обновления 1 (SP1), где пользователь может использовать фильтр, который, в свою очередь, запрашивает у брокера критерии соответствия, а затем возвращает представления компонентов на страницу. Каждый возвращенный элемент содержит ссылку на компонент.
Первоначально динамические CP хранились в БД брокера в виде фрагментов HTML, но было обнаружено, что при таком хранении CP Tridion удаляет ссылку на компонент из содержимого и оставляет пустое место в HTML.
Затем я переключил настройку так, чтобы динамические CP теперь сохранялись в хранилище файлов как элементы управления ascx. Когда этот параметр используется, <tridion:ComponentLink ... />
успешно сохраняется в файле ascx.
Тем не менее, когда я прихожу, чтобы представить результаты на экран, ссылка на компонент не разрешается, и я остаюсь с <tridion:ComponentLink ... />
в моем полученном источнике.
В настоящее время я использую GetComponentPresentation
метод для возврата содержимого CP, которое затем добавляется в список перед привязкой к репитеру для отображения.
Обобщенный код ниже:
ComponentPresentationFactory CPFactory = new ComponentPresentationFactory();
List<string> componentPresentations = new List<string>();
for (int i = 0; i < tbl.Rows.Count; i++)
{
ComponentPresentation cp = CPFactory.GetComponentPresentation(
tbl.Rows[i][0].ToString(),
strComponentTemplate.ToString());
if (cp != null)
{
componentPresentations.Add(cp.Content);
}
}
Этот список связан с ретранслятором обычным способом:
rptOffer.DataSource = componentPresentations;
rptOffer.DataBind();
Кто-нибудь знает, как я могу принудительно разрешить компонентную ссылку и почему GetComponentPresentation
функция не делает это для меня?
Есть ли что-то, что я должен делать по-другому, или это просто невозможно в том смысле, как я это реализую?
Я подтвердил, что tridion
tagprefix правильно зарегистрирован в web.config.
Я довольно новичок в Tridion, поэтому любая помощь очень ценится!
ОБНОВИТЬ
Я попытался реализовать предложение Уилла, так как оно кажется наиболее подходящим решением для моего сценария, но я получаю (довольно мягкую) ошибку, когда пытаюсь использовать предложение Уилла с моим кодом ниже:
ComponentPresentationAssembler cpa = new ComponentPresentationAssembler("tcm:35-62652-64");
string content = cpa.GetContent(tbl.Rows[i][0].ToString(), strComponentTemplate.ToString());
На самом деле есть 2 ошибки, которые происходят (на первый взгляд) случайно, но всегда на cpa.GetContent(...)
вызов. Ошибки:
Exception occurred during configuration callback
OR
com.tridion.dcp.ComponentPresentationFactory
Кажется, я не могу понять, почему ошибка меняется между запусками кода. Ошибка изменяется, даже если код не был изменен.
Кто-нибудь знает, что мне здесь не хватает? Я предположил, что это будет проблема с подключением к хранилищу брокера и т. Д., Но потом я вспомнил, что эта часть работала, когда я использовал ComponentPresentationFactory
учебный класс.
Если это помогает, DCP, который хранится в хранилище файлов в виде ascx, содержит следующий HTML:
<div class="content-list-item offer redesign noImage">
<h2><span>Mike Offer 01/06 - 10/06 & 20/06 - 10/07</span> Exp May 20th</h2>
<div class="content-list-item-text">
<p>Body Text</p>
<div class="input-btn burgundy">
<tridion:ComponentLink runat="server" PageURI="tcm:0-0-0" ComponentURI="tcm:35-31685" TemplateURI="tcm:0-0-0" AddAnchor="false" LinkText="Button Text<span class="rm">: Button Text</span>" LinkAttributes=" alt="Button Text" target="_self" " TextOnFail="true"/>
</div>
<p>Sub Title</p>
</div>
<div class="offers-list">
<ul>
<li>Offer ends: 20 May 2012</li>
<li>Offer available at all hotels</li>
</ul>
</div>
<div class="back-to-top">
<a href="#content">Back to top</a>
</div>
ОБНОВЛЕНИЕ 2
Благодаря Райану, я обнаружил, что мои файлы DCP (ASCX) не публиковались в папке приложения в папке wwwroot, что решило проблему вывода <tridion:ComponentLink ... />
тег непосредственно к источнику. Сейчас он отображается, но ссылка все еще не разрешена. <a ... />
теги не выводятся. Это где ассемблер, надеюсь, войдет - как только я смогу заставить это работать.
Я реализовал больше логов и проверок и получил больше информации об ошибке, которая предполагает, что я могу пропустить файл JAR или иметь неправильную версию:
Exception Details: Java.Lang.ClassNotFoundException: com.tridion.dcp.ComponentPresentationFactory
Интересно, когда я использую ComponentPresentationFactory
класс, он работает (без разрешения внутренней ссылки), но как только я использую Ассемблер, он выдает вышеупомянутую ошибку.
Я также попытался добавить страницу в конструктор, как это предложил Элвин, но результат тот же.
4 ответа
Как уже обсуждалось, для решения вашей проблемы вам нужно использовать ComponentPresentationAssembler
класс, а не ComponentPresentationFactory
класс, но вы должны убедиться, что вы используете ComponentPresentationAssembler
класс внутри Tridion.ContentDelivery.WAI
Пространство имен:
Tridion.ContentDelivery.WAI.ComponentPresentationAssembler presentationAssembler = new Tridion.ContentDelivery.WAI.ComponentPresentationAssembler("tcm:5-44410-64",this.Page);
Response.Write(presentationAssembler.GetContent("tcm:5-62700", "tcm:5-62627-32"));
Вам также необходимо обеспечить:
Ваши ASCX-файлы публикуются в файловой системе. Это задается в файле cd_broker_conf.xml внутри
<Bindings>
раздел, например<Binding Name="ASPComponentPresentation" Class="com.tridion.broker.componentpresentations.FSASCXComponentPresentationHome"/>
Ваши ASCX-файлы публикуются в веб-приложении.Net. Это установлено в файле cd_broker_conf.xml внутри
<Publications>
раздел, например<Publication Id="5" DocumentRoot="C:/Inetpub/wwwroot/website1" DataRoot="C:/Inetpub/wwwroot/website1/dcp"> <Dcp> <Asp Location="C:/Inetpub/wwwroot/website1/dcp"/> </Dcp> </Publication>
Помните, что места, которые вы видите выше, чувствительны к регистру
Чтобы выполнить DCP, а не просто получить опубликованный контент, вам нужно использовать ComponentPresentationAssembler
класс, а не ComponentPresentationFactory
учебный класс.
Простой пример ниже:
ComponentPresentationAssembler cpa =
new ComponentPresentationAssembler("tcm:69-6212-64",this.Page);
Response.Write(cpa.GetContent("tcm:69-2882", "tcm:69-6339-32"));
Обратите внимание, что если вы публикуете много (то есть сотни) презентаций компонентов (и публикуете их часто), не рекомендуется использовать ascx - у вас могут возникнуть проблемы с производительностью, если пакетная обработка ASP.NET перекомпилирует папку, содержащую их все, или запуск приложения перезапускается.
Безопаснее опубликовать их как (X) фрагменты HTML в базе данных и опубликовать ссылки, как упоминает Марк.
Как упоминает Фрэнк в 2011 SP1, вы можете использовать REL для этой постобработки. Смотрите эту статью для получения дополнительной информации
Ответ Марка уже охватывает наиболее важную часть вашей версии Tridion: вы должны опубликовать файлы ASCX на диск, чтобы tridion:CompontentLink
элементы управления, которые будут выполняться ASP.NET.
В качестве альтернативного решения Tridion 2011 представил REL. При использовании REL вы просто снова публикуете фрагменты HTML и tcdl:ComponentLink
будет храниться в базе данных как есть (поэтому не преобразуется в tridion:ComponentLink
после развертывания). Затем, когда вы получаете содержимое (через ComponentPresentationTransformer
или через новый веб-сервис OData доставки контента) tcdl:ComponentLink
(и другие tcdl:*
теги), и вы получите желаемый результат.
Вы загружаете содержимое представления динамического компонента в виде строки, а не выполняете строку, как, скажем, пользовательский элемент управления.
Для решения вашей проблемы вы можете использовать одно из двух решений:
1) Используйте регулярное выражение на cp.Content
обрабатывать ссылки через Tridion API.
2) Опубликуйте свой динамический контент в файловой системе в качестве пользовательских элементов управления и загрузите этот элемент управления на свою страницу / пользовательский элемент управления, таким образом выполняя его
using (var cpf = new ComponentPresentationFactory(publicationId))
{
var cp = cpf.GetComponentPresentation(componentId, componentTemplateId);
fileLocation = cp.FileLocation;
}
if (!String.IsNullOrEmpty(fileLocation))
{
var crtl = this.LoadControl(MapPathReverse(fileLocation));
phldControls.Controls.Add(crtl);
}