Friday, October 21, 2016

Forcing Workflow on the Components | Things you should know

We implemented workflow using bundles with Tridion version 2013 SP1 HR1. Customer really liked the overall functionality but when a component updated outside of the workflow or a new component created, component was set to approval status 'undefined'. With this 'undefined' approval status there was no restriction on publishing those components at all, means the content which was yet to be approved by workflow process could be published. Certainly we didn't want this as this takes away one of the main purposes 'Content Auditing' of having the workflow.

So we needed some way to mitigate this risk and force the workflow on the items before they are set to publish.

Tridion provides a OOB option to force workflow on items, for this use the checkbox “Any changes made to a Component based on this Schema require approval by a Bundle Workflow Process” in the Component Schema as shown below:

enter image description here

How does it work in concept 

If the check box is checked in the schema, components based on the Schema cannot be checked-in except by workflow. The process would be, you add the items to a Bundle and when you are ready for all of the items inside to go through workflow then Start Workflow on that Bundle.
If someone updates/creates components outside of workflow, Instead of being checked-in, the components will be "Waiting for Workflow" before you add it to a Bundle and start the workflow on it. Components could be unlocked, so other people can continue editing it, with the condition that they need to take over all previous changes too (so if they Undo Checkout, they throw away all changes, not just their own). The CME and Experience Manager will prompt you to "take ownership" when you attempt to edit such a component, The workflow doesn’t give that prompt and assign the previous changes to the current user of the activity.

Porting content using Content Porter tool:

The content porting remains the same in principal with this workflow enforcement, below are few points worth highlighting:
a. Components could be updated/created outside of workflow for the first time, a  minor version will be created with the updates and then components will be locked and waiting for workflow. (Further updates to the components are possible manually but not with the content porter. In manual case user will have to “Take Ownership” of the previous updates).

b. Subsequent updates could only be made If the components are in workflow, the workflow activity is assigned to the user doing the porting. OR once the items have gone through the workflow (components have latest major versions).


We are supporting translation inside workflow and we faced a issue related to translation after enabling the workflow enforcement as asked here.

So we had a “Send For Translation” workflow activity to send the content for translation. This activity creates a translation job of type “Push” and sends components for translation. when the translation job is sent, the component is localized and checked-out in target publications. When the translation is retrieved by the translation management system it's checked back in. (This works like this when we don't force the workflow in the components).
But after forcing Bundle Workflow Process on Components using the checkbox in the schema, Once translation is complete, the components are NOT localized with the local content in the target publication.

I guess, this could be because when TMS tries to localize and update the component, it can’t because Tridion expects the component to be locked by a “Bundle Workflow Process”. And so the component is not localized and remains untranslated.

This issue is with 2013 sp1 and as it mentioned in one of the answers, there is a a hotfix for this issue "TT88491".
But there are workaround for this issue without this hotfix.
  1. Localize the schema at local publication level and uncheck the checkbox.
  2. Disable workflow for local Publication.
I've not tested it but expert says that this issue is fixed in web 8.

That's it chaps, it's really a cool feature do try it.

Friday, September 23, 2016

Items Panel Search Alchemy Plugin

Here is another Alchemy plugin called Items Panel Search, which is now available on Alchemy Web Store. It is inspired by another plugin called Publication Panel Search, publication panel search plugin operates on publications list but this plugin on items list in the right panel. It places a search box over items list to search or filter items. User types some text and the items list gets filtered on every key press and shows the items containing the string.

Also, the plugin preserves the search value and the search results if user open an item from the list or does the sorting. User can reset the search by clicking the refresh button at the top of the list.

Other than search for a particular item in a long item list, this plugin could be useful in situations when someone wants to operate on a set of items having a common string in title of the items. As shown in below image, all the items having “Articles” in titles are filtered.

This plugin gives users two search options, titles only and all information presented in the list. By default it searches on the titles of the items, if user want to search for all information shown, he can enable it going to plugin configuration and set the value for “SearchAllInformation” to true.

In technical term it is a GUI extension of type Resource Extension Group added to the Dashboard View. It simply contains a JS file as a resource, that is responsible to put the search box on the top of FilteredListControl and all the functionality included.

To see the plugin code please visit this Github link.

Feel free to contact if you have any questions or suggestions regarding this plugin.

Sunday, May 29, 2016

Title Translator | Alchemy Plugin for Tridion

I worked on a Tridion implementation for a client managing huge local content for their websites. One could imagine that local content is hardly anything to do with a developer, but he could be wrong. So at that client, with the content inside the localized components, the title of the items were also in local languages (at many places), specifically they had tons of local taxonomies with the local language titles. Now if any issues reported for a localized website, it was a nightmare for the developers to dig in to the content while investigating that issue because we developers knew only English language.

Few weeks ago, while looking at some of old work for that client that I remembered those days and that issue. So I decided to create a Alchemy Plugin called called Title Translator to address that issue, you can follow the link to Alchemy Web Store and download it from there.
This is really a simple plugin which uses SDL Translation API in background, all you need to do is get a SDL Translation API key, set the key in Plugin Configuration and you are ready to go. In the coming versions, I will try to include the support for Microsoft and Google translation as well.

To use the plugin, simply right click on a title in your CMS Filtered Item list or left-hand​ navigation panel and select 'Translate Title'. The updated title will show in the notification bar.

On the Technical side, This plugin is created using Alchemy Framework. The idea was pretty simple, create a context menu extension and on clicking it fire a command to show the translated title in notification bar.

The Code for the Plugin can be found here on Github. This basically have following building blocks:

  • TranslatorContextMenuExtension: This class holds information about your context menu extension. Other than specifying name and id, below are the important pieces of info it has:  
    • The order of your extension in the context menu.
    • Associated command to the context menu extension.
    • Dependent resource groups.
    • Which view, the extension applies to, In this extesnsion it applies to "DashboardView".
  • TranslatorCommandSet: The class is all about creating a command set from the commands specified in the JS files. We have only one command called "translate" and it is add to the commandset.
  • TranslatorResourceGroup: This class is used to tell alchemy, which resources (files/CommandSets) are you using in your extension. We have just one JS file named "TranslatorCommand.js" and one command set, so adding those in there.
  • TranslatorCommand.js file: This file holds the command code, which fires once "Translate Title" in context menu is clicked. The code basically sends the request to the SDL Machine Translation Service and gets back the translated title as an response and shows it in notification bar.
That's it chaps, go use it. And yeah, feel free to leave comments, questions, report bugs, improvements, pretty much anything related to it.


Wednesday, January 6, 2016

Tridion Custom Tools Example Projects – Event Handler

In the blogpost series of Tridion Custom Tools Example Projects, this blog covers the Event Handler Extension. The Example Code Project could be found here on GIT. I've also shared the Visual Studio Extension here, If you want to install the project template in visual studio for event handler.

An Event Handler is a piece of functionality that is triggered when a certain type of event happens to a certain Content Manager item, for example when a Component being saved.

In Technical terms, It is a .NET assembly that uses the Event System to hook into events occurring in the Content Manager.The Event System is part of the TOM.NET (.NET Tridion Object Model) API. 

To create an Event Handler, create a class that extends Tridion.ContentManager.Extensibility.TcmExtension. You then need to compile your Event Handler into an assembly (DLL) and register it.

Procedure (Copied From SDL Documentation)

  1. In Visual Studio, create a class that extends Tridion.ContentManager.Extensibility.TcmExtension. This class must have a unique class attribute, say,[TcmExtension("MyUniqueEventHandlerExtension")].
  2. In the constructor of this class, execute code that subscribes to one or more events using the following methods:
Subscribe asynchronously to an event. Select this method if your Event Handler code does not affect the data being handled in the Content Manager. For example, if your Event Handler saves data to a backup system or a log file, you can select this method.
Subscribe synchronously to an event. Select this method if your Event Handler code changes the data being handled. For example, if your Event Handler analyzes a Component and then adds metadata to it, ensure that you select this method.
Both methods have the following signatures:
Subscribe<TSubject, TEvent>(TcmEventHandler<TSubject, TEvent> eventHandler, EventPhases phases, EventSubscriptionOrder order)
SubscribeAsync<TSubject, TEvent>(TcmEventHandler<TSubject, TEvent> eventHandler, EventPhases phases, EventSubscriptionOrder order)
where the parameters mean the following:
TSubject (type parameter)
This is the type(s) of the object you are checking events for. This can be any item of class Tridion.ContentManager.IdentifiableObject or any of its subclasses, which includes any kind of content item (such as Component, Schema or Target Group), organizational item (such as Folder or Structure Group) or system-wide object (such as User or Group).
TEvent (type parameter)
This indicates the type(s) of event that trigger this code if applied to an item of the object type specified in TSubject. This can be any event of classTridion.ContentManager.Extensibility.TcmEventArgs or any of its subclasses.
TcmEventHandler<TSubject, TEvent> eventHandler
The name of the method that contains the code you want to be triggered when the event occurs. This method should be contained in the same class and should have parameters that are the same as the type parameters of this Subscribe or SubscribeAsync method.
EventPhases phases
The exact moment during the event at which the event code should be triggered. Note that this parameter is an enum with FlagsAttribute, meaning that you can select multiple moments, which in turn means that a single event could trigger the same code multiple times.
EventSubscriptionOrder order
This optional parameter specifies when the event code should be executed if the same event triggers multiple Event Handlers.
  1. Now, in the same class, implement your event code in a method with the name specified in the eventHandler parameter of the Subscribe or SubscribeAsync method. In this method, you can perform any action you wish, including any type of querying, modification or other manipulation of items in the Content Manager. Include any namespace you need to access these items.
When you write this code, note the following:
    • You can make changes to the members of the TEvent parameter (the members are different depending on the event type) by exchanging information between Event Handlers.
    • When executed, the code you write may result in other event code being triggered.
    • From your event handling method, you can identify the specific user who triggered the event through the Session property of your first parameter of type <TSubject>. For example, if your method has a signature HandlerForSave(Component subject, SaveEventArgs args, EventPhases phase), get the name of the user by checking subject.Session.User.Title.
  1. Once you are satisfied with your code, shut down the following services on your Content Manager server:
    • IIS
    • Any Tridion-related COM+ services
    • If your code is related to publishing, the Publisher service of SDL Tridion
  2. Compile your class to a .NET assembly.
Note: If your event code contains a bug that raises an exception, it can cause the event that triggered it to hang. Especially if your event code is likely to be triggered very often, this can easily cause the system to freeze. Always test your event code before deploying it.
  1. Open the configuration file called Tridion.ContentManager.config, located in the config/ subfolder of %TRIDION_HOME% (defaults to C:\Program Files (x86)\Tridion\), in a plain-text or XML editor. Find the extensions element in this file. If the element is empty (that is, if it reads <extensions/>), replace it with<extensions></extensions>. Then add a line of the following format:
<add assemblyFileName="C:\Projects\Events\MyCustomEventHandlerExample\bin\Debug\MyCustomEventHandler.dll" />
where MyCustomEventHandler.dll is the full path and name of your compiled class. If the element was empty, the fragment should now read:
  <add assemblyFileName="C:\Projects\Events\MyCustomEventHandlerExample\bin\Debug\MyCustomEventHandler.dll" />
  1. Save and close Tridion.ContentManager.config.
  2. Restart the services you stopped.

Tuesday, January 5, 2016

Tridion Custom Tools Example Projects – Core Service (.NET)

In the series of blog posts for Tridion Custom Tools Example Projects, in this blog I am explaining to set up a simple core service project and sharing the Example Code. Also you can install a visual studio project template for the same, the VSIX file can be found here

The Core Service is a Web service that allows applications to interact with the Content Manager. For example, Content Manager clients such as Experience Manager and Content Manager Explorer interact with the Content Manager through the Core Service, and you can use the Core Service to integrate external systems with SDL Tridion.

Setting up the project (Using the built-in .NET client)

1. Open Visual Studio and create a project (Console or Web according to your need) .

2. Copy the  Tridion.ContentManager.CoreService.Client assembly from bin\client subdirectory of %TRIDION_HOME% (defaults to C:\Program Files (x86)\Tridion\) to a location.

3. Add a reference to the Tridion.ContentManager.CoreService.Client assembly in the project from the copy location.

4. Add references to System.ServiceModel and System.Runtime.Serialization assemblies.

5. In the same folder, find the file Tridion.ContentManager.CoreService.Client.config and copy the WCF endpoint configuration you find in that file into your application's configuration file.

6. Use Tridion.ContentManager.CoreService.Client namespace to create CoreServiceClient object.

Alternatively, one can also create a proxy client creating a service reference in to the project.

Creating the core service client object:

To interact with CM, we need a core service client object and to create it, Endpoints (defined in applications config file) are used. In WCF terms, an Endpoint is simple collection of Address, Binding and Contract.

There are three default bindings:  BasicHttpBinding (SOAP), WSHttpBinding (WCF) and NetTcpBinding (network). These are used to connect to the Core Service from your SOAP, WCF or network client. You can find more about the default bindings here.

Different types of core service clients are listed here, which are used for different purposes. In this code example I am using SessionAwareCoreServiceClient to interect with Tridion Content Manager. 

Once the core service client object is created, it can be used to interact with Tridion CM. Have a look at the example code here.

Monday, January 4, 2016

Tridion Custom Tools Example Projects – Custom Resolver

I noticed many questions on Tridion SE, where new developers face issues with setting up projects for Tridion Custom Tools. So in this series of blog posts I am sharing some code examples and extensions for the same.

To start with, I am explaining to set up the Custom Resolver. I've set up a simple Example Code Project and could be found here , I've also shared the the Visual Studio Extension for it, if anyone wants to install a project template for custom resolver it could be found here.

Setting up the project:

1. Create a library project in Visual studio.

2. Add the following dlls as reference:

  • Tridion.Common
  • Tridion.ContentManager
  • Tridion.ContentManager.Common
  • Tridion.ContentManager.Publishing
3. Create a class say “MyCustomResolver” by extending from interface “IResolver”, which is found in “Tridion.ContentManager.Publishing.Resolving” namespace.

4. Implement the method public void Resolve(IdentifiableObject item, ResolveInstruction instruction, PublishContext context, Tridion.Collections.ISet<ResolvedItem> resolvedItems)

5. Sign the Assembly with a Strong Name.

6. Build and add the assembly to GAC on CMS and Publisher Servers, In case you have a separate publisher server.

Installation Process (To be done on CMS and Publisher Boxes):

1. Copy the assembly “ExampleTridionCustomResolver.dll” in to the server.

2. Add the assembly to the GAC.

3. Open “Tridion.ContentManager.config” file from the path “%TridionInstall% \config”.

4. Locate xml element <add itemType="Tridion.ContentManager.ContentManagement.Component"> inside element <resolving> ---> <mappings>. Since we only want to override resolving behavior for components in this example.

5. Inside the child element <resolvers>, add element <add type=" ExampleTridionCustomResolver.MyCustomResolver" assembly=" ExampleTridionCustomResolver, Version=, Culture=neutral, PublicKeyToken={PublicKeyToken}" /> as a LAST child.

6. Finally, save and close the Tridion.ContentManager.config file and from your list of Windows Services, restart all Windows services that start with Tridion Content Manager. Also restart IIS and the SDL Tridion Content Manager COM+ application. This applies your changes.

Sunday, November 29, 2015

Custom Resolver – Why it's important to deploy it on both CMS and Publisher Servers ?

Recently, We developed a Custom Resolver which deletes the dependent pages from the package, while publishing a component dynamically. 
The Custom Resolver actually overrides the default OOB resolver, more details could be found here.
Basically resolving is a process in which publisher identifies the dependent items, which are supposed to publish with the published item. It is a part of overall publishing process and happens before rendering sub-process. 
Since we are overriding the resolving process, it's obvious to deploy the Custom Resolver on the server where publisher runs. 

In our case, we had a separate publishing server, so we deployed the custom resolver to the publisher server. And it started working as expected by not including the dependent pages while publishing the components.

But then we noticed one issue, On publishing a component, in the publishing dialog on clicking “Show Items to Publish” button the dependent pages were still showing. 

And it was confusing content editors that dependent pages are being published and resolver is not working. Though it was working actually and it's just the dependent pages were listed in the publish dialog.

The issue occurred because the “Show Items to Publish” button uses resolver on CMS server not on Publisher server. And since we didn't deploy our custom resolver to CMS server the default resolver was running there.

So to fix the issue, we needed to deploy our custom resolver on CMS server as well so that it overrides the default behavior of the resolver. 
And once we deployed the custom resolver to CMS server, the issue was resolved.