Blog post Technical, Tridion

Leveling up Aprimo and Tridion Integration series (Part 4: Reference Aprimo DAM record in Tridion component as an ECL item)

In our previous blog posts, we covered the process of uploading media files to the Aprimo upload service, obtaining the token, and creating an Aprimo record. This final post in the series will delve into utilizing the record ID to generate an ECL item and integrating it into Tridion Components.

Initial considerations

The first order of business is to retrieve the Aprimo record ID, which is automatically generated upon record creation. For detailed instructions on this step, please refer to the earlier posts in this seriesEnter Content Here

RecordEntity record = GetRecord(AuthenticationEntity.Token, recordId, new List<Tuple<string, string>>() {
new Tuple<string, string>("Select-Record", "masterFile"),
new Tuple<string, string>("Select-Record", "Title"),
new Tuple<string, string>("Select-Record", "fields"),
new Tuple<string, string>("Select-Record", "files"),
new Tuple<string, string>("Select-Record", "masterFileLatestVersion"),
new Tuple<string, string>("Select-File", "latestversion")});

return new AprimoTridionECL()
{
    AprimoId = record.MasterFile.Id,
    Title = record.Title
};

The code demonstrates the retrieval of the record containing the essential values required later in the code, namely:

  • record.MasterFile.Id: The ID of the master file. Normally, the value is something like this: “79b065e74d504d48a74fb06d00a5d810”
  • record.Title: The title of the Aprimo Record.

Both these values play a crucial role in constructing the source code of the Tridion Component with an ECL item. For example, a relevant section of the source code for my Article Component might resemble the following:

<Video xlink:type="simple" xlink:href="ecl:6-aprimo-1f93ced9f8dc4b50903bada000d82afd!2D;1-AprimoFile-file" xlink:title="Demo Video Title" xmlns:xlink="http://www.w3.org/1999/xlink"></Video>

Upon considering these two aspects together, one might assume that record.MasterFile.Id and record.Title correspond directly to the xlink:href and xlink:title properties in the Component source, respectively. However, this assumption would be incorrect. The issue is slightly more intricate, and the workflow in Tridion involves specific processing steps:

  1. Utilize the master file ID to construct the ECL ID.
  2. Use the ECL ID to generate the Tridion Stub ID.
  3. Incorporate the Tridion Stub ID and record Title in the source of the Tridion Component during its saving process via the Core Service.

The necessity of this process stems from Tridion's distinct handling of ECL links compared to regular links. Tridion mandates that all Components created via the Core Service contain Tridion Stub IDs in multimedia links. This requires the XML source code of a Component created via the Core Service to include something akin to the following:

<Video xlink:type="simple" xlink:href="tcm:6-246568" xlink:title="Demo Video Title" xmlns:xlink="http://www.w3.org/1999/xlink"></Video>

Upon saving and inspecting the Component in CME, you'll notice a difference in the source tab from the initial xml fragment:

<Video xlink:type="simple" xlink:href="ecl:6-aprimo-1f93ced9f8dc4b50903bada000d82afd!2D;1-AprimoFile-file" xlink:title="Demo Video Title" xmlns:xlink="http://www.w3.org/1999/xlink"></Video>

Here, the xlink:href property changes from the Tridion Stub ID to the ECL ID.

The scenario varies when utilizing the Tridion UI, as all these actions occur within the UI's underlying engine. However, working with the Core Service necessitates additional processing. Hence, when employing the Core Service, the steps above become a must.

Moreover, you might wonder: "How do I obtain the Tridion Stub ID from the ECL ID?"

Stub IDs (or TCM IDs) can be generated by invoking the GenerateStubId() method of the ECL service. We will elaborate on this later. For now, let's commence with using the masterFile ID to construct the ECL ID.

Using masterFile ID to construct ECL ID

The ECL id is constructed out of masterFile ID in the following pattern:

$"ecl:{ContentPublication.Id)}-aprimo-{masterFileID}!2D;1-AprimoFile-file"

Here, ContentPublication.Id denotes the Publication ID in which the Component should be generated, and masterFileID has been obtained in the preceding step.

Using ECL ID to generate Tridion Stub ID

Once we obtain an ECL ID, we can initiate the procedure for generating the Tridion Stub ID. To accomplish this, we must establish a connection to the ECL service.

TIP:

By default, ECL is not accessible as a public web service. This implies that you can only connect to it via the net.TCP protocol, and solely on localhost. However, starting from version 9.5, you have the option to install the hotfix ECL_9.5.0.29149_1, which allows you to connect to ECL over HTTP, much like to the Core Service.

There are a few prerequisites to connecting to the ECL service:

  1. Installing hotfix ECL_9.5.0.29149_1 on Tridion Sites 9.5 and later
  2. Obtaining and importing Tridion.ExternalContentLibrary.V2.dll
  3. Obtaining and importing Tridion.ExternalContentLibrary.Service.Client.dll
  4. Obtaining and importing Tridion.ExternalContentLibrary.Data.dll

To see details of the ECL_9.5.0.29149_1 hotfix please visit the following webpage You can download it from RWS FTP server or by contacting the customer support.

To retrieve Tridion.ExternalContentLibrary.V2.dll from the CM server, locate it in the \Tridion Home\bin\client\ folder.

To retrieve Tridion.ExternalContentLibrary.Service.Client.dll from the CM server, you can find it in the \Tridion Home\web\WebUI\WebRoot\bin\Components\ExternalContentLibrary\ folder.

Please note that Tridion.ExternalContentLibrary.Data.dll is not directly available, as it is in the Global Assembly Cache (GAC), making retrieval a bit more complex. First, verify that the GAC contains the DLL. You can use the gacutil.exe tool to list all DLLs in the GAC with the following command (for example, in PowerShell):

.\gacutil.exe -l > all_dlls.txt

Open the all_dlls.txt file and search for the following entry:

Once you verified that it’s indeed there, you can find it at:

C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Tridion.ExternalContentLibrary.Data\v4.0_9.6.0.0__ddfc895746e5ee6b

TIP:

While Tridion.ExternalContentLibrary.Data.dll may not be directly utilized in the solution, it still needs to be referenced because it is utilized by Tridion.ExternalContentLibrary.Service.Client.dll. Omitting this reference would result in the code throwing an exception during runtime.

After that you can configure the endpoint as follows in web.config:

<endpoint name="wsHttp_2012" address="https://my-tridion-cm-instance/webservices/ECL/EclService2012.svc" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="Tridion.ExternalContentLibrary.Service.Client.ISessionAwareEclService">
  <identity>
    <dns value="VALUEOFDNS" />
  </identity>
</endpoint>

In the same file configure the bindings as well:

<wsHttpBinding>
  <binding name="wsHttp" openTimeout="00:30:00" closeTimeout="00:30:00" sendTimeout="00:30:00" receiveTimeout="00:30:00" maxBufferPoolSize="2147483646" maxReceivedMessageSize="2147483646">
    <readerQuotas maxStringContentLength="2147483646" maxArrayLength="2147483646" />
    <security mode="TransportWithMessageCredential">
      <message clientCredentialType="UserName" />
    </security>
    <reliableSession enabled="true" />
  </binding>
</wsHttpBinding>

Once web.config is configured, you can proceed to utilize the following code sample to retrieve the stub URI by supplying the ECL URI:

public class ECLServiceHelper
{
    private string endpoint = ConfigurationManager.AppSettings["EclServiceEndpoint"];
    private string eclServiceUser = ConfigurationManager.AppSettings["Username"];
    private string eclServicePass = ConfigurationManager.AppSettings["Password"];
    private static ILog log = LogManager.GetLogger("RollingFileAppender");

    public Dictionary<string, string> GenerateStubId(string[] eclUri)
    {
        using (ChannelFactory<ISessionAwareEclService> channelFactory = new ChannelFactory<ISessionAwareEclService>(endpoint))
        {
            channelFactory.Credentials.UserName.UserName = eclServiceUser;
            channelFactory.Credentials.UserName.Password = eclServicePass;

            ISessionAwareEclService sessionAwareEclService = channelFactory.CreateChannel();
            try
            {
                Dictionary<string, string> stubUri = sessionAwareEclService.CreateOrGetStubUris(eclUri);

                return stubUri;
            }
            catch (Exception ex)
            {
                log.Error($"failed to create stub uri! {ex.Message}");
            }

            return null;
        }
    }
}

As you can observe, the code is quite straightforward. Upon retrieving the Dictionary, you can readily utilize it within the source code of the Component. It's important to note that the Dictionary<string, string> stubUri comprises pairs of mapped ECL URI and STUB URI.

TIP:

Based on my experience, establishing a connection to the ECL service and invoking it can be resource-intensive operations. Therefore, if you're dealing with multiple ECL stub URIs for which you need to retrieve Stub URIs, I recommend consolidating them into a single call. The CreateOrGetStubUris() method facilitates this by allowing you to send an array of items.

Conclusion

Once you've successfully navigated through these steps, along with the previous posts in the series, you can consider yourself proficient in Tridion and Aprimo integrations. As a result, you can streamline content generation tools, simplify content management for Editors, and automate a significant portion of content generation tasks.

If you have any queries or wish to gain firsthand insights into Aprimo and/or Tridion integrations from us, feel free to reach out. We're here to assist you every step of the way.

Contact us to discuss your project.
We're ready to work with you.
Let's talk