December 31, 2014

Different API and Extension points in Tridion CM

Sdl Tridion can be customized at various levels as it provides very rich APIs to extend it. Tridion has different extension points for CM and CD. i will try to cover maximum extension points below.

Content Management

APIs

1) Tom.net: Tom.net is .net based API, it runs and CM machine. it allows to you to interact from CM machine only.  Tom.net provides various methods to be used for Templating, Event System. This is Read/Write API, but write operations are by default off in config.

2) Core Service - Core service is WCF service which expose various APIs to interact with CM system. it provide CRUD methods to operate on various CMS Objects. Main use-case of core-service is when you need to interact with CM machine from different machine other than CM or if you want to integrated CM with some third party system. It was introduced in Tridion 2011 (to replace existing COM based APIs) and still in use. It is also used in Workflows
e.g:  you need to read some Xml and create components in Tridion CM.

3) Anguilla: It is used to extend Content Manager Explorer(CME) user interface. eg. you want to introduce new buttons and new functionality in CME. e.g Custom spell checker, custom publishing, extend paste functionality. It was introduced in Tridion 2011 and still in use.

4) ECL : External Content Library was introduced in Tridion 2013, its very useful and awesome API available in Tridion. It allows to list/integrate external content repositories  third-party content/media in CMS and allow you to use it as native components with little exception. The access point looks just like a normal folder, making it easy to manage.
e.g . User want to see all images of DAM into CM system, want to view You tube or Dailymotion videos in CM interface to use in the components. 

Extension Points:

5) GUI Extensions - Its used to extend/customized the CMS UI. anguilla, JS and .net are used to create a GUI extension.

6) Events: Tridion provides Events as extension point where you can capture particular event and provide some customization. one of the most used use-case is validation of data. so when user save the component, save even can be captured and validate the data, log the data etc.

7) Custom Resolver: A resolver basically read an item from the publishing-queue and returns a list of items to be rendered. Tridion has kept it extensible so if you want to override default resolving behavior.
e.g when a component is resolved, by default all the component that links to this component are also resolved and so on. so it gives very long queue and impact the performance also, so if you want to resolve only this component or level 1 component this can be extended and registered in the TridionContentManager.config file.

8) Custom Page: Custom Pages can be used to perform operations in the Content Manager that are not supported by the default UI(user interface) . e.g, create a Custom Page that talks with the Core Service to automate Page creation. it can also be used to customize dashboard for users.

December 16, 2014

Anchor in Tridion Component links

In Tridion Link Anchor (jump to specific section of the page) is very tricky. there is an out of the box anchor option. let discuss that first.

Anchor OOTB : In component link there is an attribute "Add Anchor"

<tridion:ComponentLink runat="server" PageURI="tcm:85-159563-64" ComponentURI="tcm:85-159309" TemplateURI="tcm:0-0-0" AddAnchor="true" LinkText="internal link test" LinkAttributes=" title= &#34;alt text for link &#34;" TextOnFail="true"/>

when this AddAnchor = true is set. Tridion CD will create anchor for particular components as per their position of the page.

e.g following is a Tridion page sompage.aspx having three components Comp 1 and Comp 2 and Comp 3

------------
Comp 1
---------
Comp 2
---------
Comp 3
---------------

e.g you use comp2 as component link on another page. it will be resolved as somepage.aspx#1
so this is as per the position of the component on page.

another catch is you have to create <a id="1"> on somePage explicitly using your templates. this is not automated.

Custom solution:
As OOTB solution is base on numbers only. if you want to based it on some text e.g #Intro. you need some customization for it.

I have develop & tested this small solution for it.
------------------------------------------------------------------------------------------------------------
namespace  CD.Web.ComponentLink.Extensions
{
    public class ComponentLink : Tridion.ContentDelivery.Web.UI.ComponentLink
    {
        [DefaultValue("None")]
        [Bindable(true)]
        [Category("Appearance")]
        public string AnchorName { get; set; }


        protected override void Render(HtmlTextWriter writer)
        {
            if (HttpContext.Current == null || HttpContext.Current.Application == null)
                return;
            using (var compLink = new Tridion.ContentDelivery.Web.Linking.ComponentLink(new TcmUri(ComponentUri).PublicationId))
            {
             
                var link = compLink.GetLink(PageUri, ComponentUri, TemplateUri, LinkAttributes, LinkText, TextOnFail, AddAnchor);
                link.Anchor = AnchorName;
             
                string linkAsString = link.ToString();
                writer.Write(linkAsString);
                this.RenderChildren(writer);
            }
        }

    }

}
------------------------------------------------------------------------------------------------------


  • Register above custom control in your website's web.config 
  • Update schema to accept the Anchor from Editor
  • Update template code to pass this anchor name as mention below

<Rk:ComponentLink runat="server" PageURI="tcm:85-159563-64" ComponentURI="tcm:85-159309" TemplateURI="tcm:0-0-0" AnchorName="true" AddAnchor="false" LinkText="internal link test" LinkAttributes=" title= &#34;alt text for link &#34;" TextOnFail="true"/>

do post comments if you have any questions.

December 09, 2014

CXM: Customer Experience Managment-tridion


Customer Experience Management (CXM) is a strategy and practice for managing customer
experiences online and offline to acquire, retain, and turn customers into satisfied, loyal brand
advocates and ambassadors.(Wiki)

I heard this acronym around 1.5 year back in a discussion and then found lots of  information from Forrester and RealstoryGroup.

Some says" is nothing more than a feature arms race between companies that have latched onto a false "next big thing". These features were not developed in response to actual customer needs or requests. I never hear anyone talking about CXM except for CMS vendors and analysts."

As per my view, CXM Make sense in lots of context.

Following example describe a particular experience of an user. and how different type of module/systems enhance the experience of user.

Experience:
  1. Raj get to know of discount on newly launched restaurant in his Area via a Ad on search engine - Ads
  2. He browse the restaurant website on his Mobile. - Mobile Delivery
  3. Check few restaurant picture and details -  DAM/MAM
  4. Then Browse the reviews of restaurant on the website and yelp!! - Reviews, Ratings
  5. Raj also checks restaurant 's Facebook page for more reviews. - Social Share, Social Listening.
  6. He finally calls their customer care to book the restaurant. - Customer care

if we replace restaurant with a Mobile phone.

  1. Customer buy the phone from the Website. E-commerce
  2. Website also add some loyalty points for his buying which could be later on used for buying some other product. - Loyalty management 
  3. Share the review on website & his joy on Social media.
  4. On revisiting the website, website come up with accessories and other stuff related to his past browsing and buying experience.  Personalization. 
  5. Vendor sends him various coupons/products information or email on his mobile/mail - Coupon management, Campaigning
CXM Technology Ecosystem

   IMAGE Courtesy:  rEALsTORY gROUP

SDL Tridion as CXM Capabilities.


Recently SDL launched new offering SDL Customer Experience Cloud which is an SaaS based solution and provide provide most of the features from above pictures on cloud in integrated mode. It seems very promising and give a leg-up to SDL in very competitive CMS world. 

November 25, 2014

Tridion: Image handling in Responsive design.

In responsive websites, we usually keep different breakpoints for different devices & different breakpoints require different image sizes. There are different ways to use images in responsive layouts.
  • Same image on all Devices
  • Manual upload of device specific Image
  • Generate images on Fly.
  • Tridion CID
Same image on all devices: This is simplest of all as point of development, let user upload single image and same image is published on delivery. But there are few points which needs to be taken care for this.

UI Designer has to maintain the aspect ratio in his designs across Desktop, tablet, mobile or whatever breakpoints you have. e.g

Desktop:  200  : 100
Tablet:      100 :  50
Mobile:     50:    25

so if you see the aspect ration has been maintained at 2:1.  so Maintaining aspect-ratio is very important as it can go haywire if the objects start scaling based on the screen dimension. To maintain aspect ratio of the objects, select Auto for either width or height of the object in the Primary view

Tridion side there is no special change is required. normal image publishing.

Cons: Mobile has to download the same big image, which could be bandwidth issue, also in sites where lots of images are used, this approach on tablet/mobile would not be considered best

Manual upload of device specific Image:  There are different reasons where device specific images are required:
  • Designers are not totally versed with it. so ratios are not maintained  across devices
  • Performance and bandwidth issue
  • For mobile instead of whole image only part of image is required for more cleared and focused view.
these images could be manually-generated or from some DAM System.

Tridion Implementation:

Create a category with Keywords having device information. 
Category : Device Type
Keywords - large, medium, small

Create a embedded schema "Responsive Multimedia" as shown below
ScreenSize refer above category.

For this we created a generic helper class in razor, it generate the Data-Interchange tags in images. We are using Foundation Framework for handle responsiveness of site  here. 

<img data-interchange="[@Publication.MultimediaUrl/@mobile, (default)], [@Publication.MultimediaUrl/@tablet, (medium)], [@desktop, (large)]"></img>

Now you can read the component and read the values of uploaded images and generate the image tag with data-interchange as shown above. 

Generate images on Fly  Other approach is to upload a single image and generate the rest of the device specific images on Fly using custom code. But design should maintain aspect ratio of the images. 

Tridion code: we have written a c# tbb to handle it, here is the code for it. you can customize it 

[TcmTemplateTitle("AddAssets")]
    public class AddAssets : TemplateBase
    {
        
        public override void Transform(Engine engine, Package package)
        {
            Initialize(engine, package);
            var items = m_Package.GetEntries();
            var dynamicbinaries = new Dictionary<string, string[]>();
            foreach (var i in items)
            {
                Logger.Info(i.Key + ":" + i.Value);

                if (i.Key != "GenerateDynamic") continue;
                Logger.Info("Generate Dynamic parsing:");

                var arr = i.Value.GetAsString();
                var binaries = arr.Split(',');

                dynamicbinaries.Add(binaries[0], binaries);
           }

            var allowedContentTypes = new Dictionary<ContentType, ImageFormat>()
                                   {
                                       {ContentType.Bmp, ImageFormat.Bmp},
                                       {ContentType.Jpeg, ImageFormat.Jpeg},
                                       {ContentType.Png, ImageFormat.Png},
                                       {ContentType.Gif, ImageFormat.Gif}
                                   };
            foreach (var contentType in allowedContentTypes.Keys)
            {
                foreach (var item in package.GetAllByType(contentType))
                {
                    if (dynamicbinaries.ContainsKey(item.Properties[Item.ItemPropertyTcmUri]))
                    {
                        InsertRelatedBinaries(item, allowedContentTypes[contentType], dynamicbinaries[item.Properties[Item.ItemPropertyTcmUri]]);
                    }
                }

            }
        }

        private void GenerateDeviceSpecificBinaries(Item item, ImageFormat imageFormat, string[] binary)
        {

            var mmc = new Component(new TcmUri(item.Properties[Item.ItemPropertyTcmUri]), m_Engine.GetSession());

            var binaryContent = mmc.BinaryContent;
            var binaryBytes = binaryContent.GetByteArray();
            using (var bitmap = new Bitmap(new MemoryStream(binaryBytes)))
            {
                var tabPercentage = Int32.Parse(m_Package.GetValue("TabPercentage"));
                var mobilePercentage = Int32.Parse(m_Package.GetValue("MobilePercentage"));
                var resizedBitmap = ResizeBitmap(bitmap, tabPercentage);
                AddBitmapAsBinary(item, imageFormat, mmc, binaryContent, resizedBitmap, "2", binary[2]);//Tablet Images

                resizedBitmap = ResizeBitmap(bitmap, mobilePercentage);

                AddBitmapAsBinary(item, imageFormat, mmc, binaryContent, resizedBitmap, "3", binary[1]); // Mobile Images
                resizedBitmap.Dispose();
            }
        }

        private void AddBitmapAsBinary(Item item, ImageFormat format, Component mmc, BinaryContent binaryContent, Bitmap resizedBitmap, string variant, string filename)
        {
            var resizedStream = new MemoryStream();
            resizedBitmap.Save(resizedStream, format);
            var binary = this.m_Engine.PublishingContext.RenderedItem.AddBinary(
                resizedStream, filename, variant, mmc,
                binaryContent.MultimediaType.MimeType);
            resizedStream.Dispose();
        }

        private Bitmap ResizeBitmap(Bitmap sourceBitmap, int per)
        {
          
                var sourceWidth = sourceBitmap.Width;
                var sourceHeight = sourceBitmap.Height;

                float nPercentW = per;
                float nPercentH = per;

                var  destWidth = (int)(sourceWidth * (nPercentW / 100));
                var  destHeight = (int)(sourceHeight * (nPercentH / 100));
           

            var resultBitmap = new Bitmap(destWidth, destHeight);
            var graphicsd = Graphics.FromImage(resultBitmap);
            graphicsd.InterpolationMode = InterpolationMode.HighQualityBicubic;

            graphicsd.DrawImage(sourceBitmap, 0, 0, destWidth, destHeight);
            graphicsd.Dispose();

            return resultBitmap;
        }

    }
}

Tridion CID  Contextual Image delivery  is a product from SDL which helps in transforming the images in various ways such as
  • Resize with Cropping
  • Resize without Cropping
  • Trim image
  • Change Image format
Please read this very good article for further explanation of this module. What Does Contextual Image Delivery Mean for SDL Tridion Images? 

September 14, 2014

Single Sign On Integration with SDL Tridion and CA Siteminder


In today’s world most of the products, be it a financial product like credit  card, media or electronics item,  do not come from just one vendor but from collaboration between different partner companies. All partners play  a unique role in marketing of such product and need access to related data.

Practically, it is not possible to provide access to all the partners to the Active Directory or LDAP and here comes SSO for the rescue which enables all the partners to use a common policy server to authenticate themselves.
SDL Tridion can be easily integrated with SSO servers like CA Siteminder and IBM Tivoli.

Following figures describes SSO flow till authentication.
Fig: Flow Chart of SSO Request

Installation & Configuration: Setting up SSO requires lots of configurationThe first step for configuring SSO for Tridion is installing Site Minder agent on CM server which intercepts all the request coming to Tridion CMS and authorize the user
The web agent interacts with Policy Server in order to authorize user based on the credential provided by user. Once authenticated, unique user id is set in header variable of each request which is then used by Tridion to identify the user if SSO is configured.
Authorization can be done at Tridion CMS security level where based on business requirement different access and permissions can be given to users on CMS items like publication etc.

Installing CA Siteminder agent on CMS server 
  1. Execute ca-wa-12.5-cr02-win64.exe.
  2. Follow the instructions according to installation wizard
  3. In the Host Registration dialog box, select ‘Yes’ to register a host and click Next.
  4. Complete the following fields in the Admin Registration dialog box, then click Next- Provide the required admin credentials
  5. Admin User Name
  6. Admin Password
  7. Confirm Admin Password 
  8. Enabled Shared Secret Rollover – Unchecked
  9. In the Trusted Host Name and Configuration Object dialog box, enter webserver name as trusted host name. 
  10. In the Policy Server IP Address dialog box enter the IP or  policy server VIP:
  11. Choose FIPS Compatibility Mode (Default) and click Next.
  12. Accept the default location of the host configuration file, SmHost.conf or click Choose to select a different location. Click Next.
  13. In the Select Web server(s) dialog box, select the option for the Microsoft IIS 7.5 and click Next.
  14. Select the virtual sites(SDL Tridion 2011) that need to be configured with this web agent and click Next.
  15. Enter the ACO name <webserver>_agent_config and click Next:
  16. In the WebAgent Enable Option, check the YES box and click Next.
  17. In the Web Server Configuration Summary dialog box. Confirm that the configuration settings are correct, then click Install.
  18. Click done when the installation is complete. The system restarts
Permission to user to modify encrypted configuration sections
  1. Open command prompt and go to where PSTools is located
  2. Run:    psexec -i -s cmd.exe
  3. This should open another new command prompt window
  4. In the new command prompt window, navigate to where aspnet_regiis is (should be in c:\Windows\Microsoft.Net\Framework64\v4.0.30319  
  5. Run:   aspnet_regiis -pa "TridionRsaKeyContainer" "Domain\UserName"
  6. Follow the same steps for user NT AUTHORITY\IUSR
Configuration Console:

Fig: SSO Configuration in CMS
Set header name which will be used to retrieve user name after authentication.

Some Useful links:

  • http://docs.sdl.com/LiveContent/content/en-US/SDL%20Tridion%202011%20SP1%20full%20documentation-v1/GUID-407B4F89-B8D0-4799-A16B-147D89B044F6
  • https://support.ca.com/cadocs/0/CA%20SiteMinder%20r6%200%20SP6-ENU/Bookshelf_Files/PDF/siteminder_wa_config_enu.pdf
Issues and Trouble shooting

In my previous experience with SSO the unique user GUID that is set by Siteminder in the header of response was not getting persisted and hence SSO was not working fine with Tridion. To resolve this issue one can try putting a custom HTTP Module in request pipeline and check if the GUID is getting persisted, and in case it is not you will have to explicitly set the header variable.
NOTE: One important point to take care of (especially in case you are making entries manually in web.config)  make sure that HTTP module entry in web.config for your custom http module comes after the entry of CA Siteminder.

<add name="CASiteMinderWebagentModule" preCondition="integratedMode,bitness64" />
<add name="customhttpmodule" type="<>, Version=1.1.0.0, Culture=neutral, PublicKeyToken=<>" />
Some point worth noting is that we were not able to run the Tridion Client applications like Template Builder and Content porting using SSO and hence it was explicitly set on windows authentication.

August 12, 2014

Paste From Word Plugin:UI Extension

In Tridion 2011 the paste-special feature doesn't work perfectly. The ask was to copy/paste articles directly from the Microsoft Word, as Tridion OOB feature was not working so client's whole process was impacted. 

so we come up with this plugin  Paste Special Cross Browser Extension  which helped them to copy paste from word without those problematic word tags. it was written on top of  excellent CKeditor (without reinventing :) )
Plugin Code Structure:


  • CKeditor
  • Client
  • Config

With this plugin it is possible to paste content from Microsoft Word and maintain original content formatting and also paste as a plain text. The plugin adds the Paste from Word and Paste as Text button which makes it possible to paste clipboard data. This Paste Special Cross Browser Extension removes the existing Paste Special Functionality from the CME/Experience Manager and replaces it with a cross browser solution.

CKeditor: Contains CKeditor’s java script, CSS and HTML files (PasteAsText and PasteFromWord)  

Client: Contains PasteSpecialFormatArea javascript file that is the main javascript file where we define the command for the UI extension buttons.

For e.g.

Extensions.PasteAsText.prototype.isAvailable = function PasteAsText$isAvailable(target){              
    return true;
};
Extensions.PasteAsText.prototype.isEnabled = function PasteAsText$isEnabled(target){
    return true;
};

Extensions.PasteAsText.prototype._execute = function
PasteAsText$_execute(target)
{
popUpData="";
var host = window.location.hostname;
var newwindow = window.open("http://"+host+"/WebUI/Editors/PasteSpecialFormatArea/ckeditor/PasteAsText.html",'FormatArea','height=356,width=750');
     
var unloadFunc = function () { setEditorData(); };
if (newwindow) { // null if a pop-up blocker does not create the window
if (newwindow.addEventListener) {
newwindow.addEventListener('unload', unloadFunc, false);
} else {
newwindow.attachEvent('onunload', unloadFunc);
}
}

function setEditorData()
{
if(popUpData != "")
{
target.editor.applyHTML(popUpData);
}
}
};

function setPopupText(data)
{
popUpData = data;
}


Config: Contains the config file that has the configuration for the UI extension button and also all the dependency files path.

Deployment
  
1.     Copy the plugin folder “BCGFormatArea” inside the Editor folder in the Tridion installation path “InstallationPath\Tridion\web\WebUI\Editors”.

2.     Now in IIS create a virtual directory with the name “BCGFormatArea” inside Editor Directory as shown in the below screen shot.


3.     Now open the “System.config” file in the path “C:\Program Files (x86)\Tridion\web\WebUI\WebRoot\Configuration” and add a new editor configuration setting inside the “<editors default="CME">” element tag 


Here is the configuration setting:

<editor name="BCGFormatArea" xmlns="http://www.sdltridion.com/2009/GUI/Configuration">
<installpath> InstallationPath\Tridion\web\WebUI\Editors\BCGFormatArea\</installpath>
<configuration>config\BCGFormatArea.config</configuration>
<vdir>BCGFormatArea</vdir>
</editor>
 Note: Make sure the virtual directory name in the editor setting <vdir> is matched with the created one.
4.     Now make the IIS reset and open the CMS you will see two new “Paste As Text” and “Paste From Word” buttons added in the component view as shown in the below screenshot.



5.     Click the button to open the popup.

How it works:

Most intersting methods to notice  are _execute, setEditorData, setPopupText.

_execute: It first trigger the popup "PasteAsText.html". which in turns intialize the ckEditor. 

so now when user enter the content in the text box and press ok, following code gets executed:

 function GetContents() {
                // Get the editor instance that you want to interact with.
                var editor = CKEDITOR.instances.editor1;                
window.opener.SetPopupText(editor.getData());
closeWin();
            }

if you notice it just set the text via calling formatArea's SetPopupText method. 
and closeWin(), which again triggers the unloadFunc method of FormatArea. which sets the data to the CME textbox.

July 24, 2014

Tridion CMIS connector for aDAM - External content Library

We had a requirement to connect aDam with Tridion 2013. I started the POC after reading docs, posts       ( from Eric & Bart).

External Content Library aka ECL was introduced in Tridion 2013 to connect external content/multimedia sources with Tridion Interface e.g youtube, vimeo, flicker, facebook, aDam, Media Manager. Its a great feature.
When content starts displaying in the CME, it looks like native components.

Prerequisite

Tridion: 
  • Assembly: Tridion.ExternalContentLibrary.V2
  • Admin Privilege
Terminologies:

Mount Point: Tridion folder which you mount to access external content. all external content is listed under this folder. 

ECL Stub Schema: When a provider is mounted in Tridion, it generates a Stub schema , and all stub components (from external sources) displayed in this mountPoint are type of this stub schema.(because you need a schema to represent a component in Tridion)

Interface: Interfaces in following figure are used in development.








aDam
  • aDam Studio installed
  • Rest Service to access its content - in aDam 5.0 there was no open API/oData etc were available. In current 5.0 version there is no official API comes with aDam installer. but aDam guys provided this Sample Rest Service which can be extended, as i discussed with them, API will be released in next versions.
Few Terminologies
  • Classification: its basically taxonomy of aDam, and content in CME would also categorized by classification. 
  • Record: Assets are called Record in aDam. 
Development.  
Lets move to development side, i will keep code short as possible with a view to brevity and clarity.

Here i am declaring that my connector will show two types of item in the interface, first one is a folder, which is collection of items, in aDam case its Classification. Rest methods are standard implementations.

AdamEclProvider : IContentLibrary 
it initialize the AddIn, this is the class which is configured in ExternalContentLibrary.xml.

[AddIn(
    "AdamProvider",
    Description = "Adam External Content Library Provider",
    Publisher = "Raj Future Technologies",
    Version = "1.0.0.0")]
    public class AdamEclProvider : IContentLibrary

    {
public IList<IDisplayType> DisplayTypes
        {
            get
            {
                return new[]
                    {
                        HostServices.CreateDisplayType( "clf", "Classification", EclItemTypes.Folder),
                        HostServices.CreateDisplayType( "ast", "Assets", EclItemTypes.File),
                    };
            }

        }

     }//Class end


AdamContext : IContentLibraryContext:

This call has code for connecting to external sources and retrieval of the content. 

internal class AdamContext : IContentLibraryContext

    {

/*this method is triggered when user click on MountPoint, its fetches the classifications from the Adam and show there
now when that particular folder is clicked, sub classicifations and assest are displayed. */

public IFolderContent GetFolderContent(IEclUri parentFolderUri, int pageIndex, EclItemTypes itemTypes)
        {
                       
            List<IContentLibraryListItem> result = new List<IContentLibraryListItem>();
            if (parentFolderUri.ItemType == EclItemTypes.MountPoint && itemTypes.HasFlag(EclItemTypes.Folder))
            {
//AdamHelper is kind of facade to get the information from service
                            var classifications = AdamHelper.GetClassifications();
                foreach (var classification in classifications)
                {
                    result.Add(new AdamListClassification(parentFolderUri.PublicationId, classification.id.ToString(), classification.Name));                
                
                }
                
           canSearch = true;
            }
            else if (parentFolderUri.ItemType == EclItemTypes.Folder && parentFolderUri.SubType == "clf" && itemTypes.HasFlag(EclItemTypes.File))
            {
               // throw new Exception("iam here");
                var records = AdamHelper.GetRecords(parentFolderUri.ItemId);
                
                result.AddRange()//
            }
                return AdamEclProvider.HostServices.CreateFolderContent(parentFolderUri, result, false, canSearch);


        }
//fetch particular item. 
public IContentLibraryItem GetItem(IEclUri eclUri)
        {
                       if (eclUri.ItemType == EclItemTypes.File && eclUri.SubType == "ast")
            {
                var record = AdamHelper.GetRecord(eclUri.ItemId);
                return new AdamAsset(eclUri.PublicationId, record, eclUri.ItemId);
            }
            throw new NotSupportedException();

        }
//fetch item list
 public IList<IContentLibraryItem> GetItems(IList<IEclUri> eclUris)
        {
///code goes here to call the aDam helper
}

} //Class end

//This class represent one type of asset, so if you have image, video you have to implement it for  each of the asset.

public class AdamAsset : IContentLibraryMultimediaItem
    {
public AdamAsset(int publicationId, RecordData record, string parentId)
        {
            _parentId = parentId;
            _record = record;
            _id = AdamEclProvider.HostServices.CreateEclUri(publicationId, AdamEclProvider.MountPointId, record.id.ToString(), "ast", EclItemTypes.File);

        }

public string DisplayTypeId
        {
            get { return "ast"; }

        }

}
}//Class end

//Represent a classification

public class AdamClassification : IContentLibraryListItem, IContentLibraryItem 

    {

    }

Note: You have to set WebReady property to "Yes" from Files tab to view the asset in Tridion.

with above code you will able to display the asset in CMS and will able to include it in the native Tridion components, for publishing those there would be additional template code. which i did not do as scope of my POC and different direction of the project.


Official Adam Connector: Official aDam connector is also available from SDL which is licensed Separately. You can check with SDL for it.

Let me know if you have any questions or need any help, feel free to comment below.

July 09, 2014

Content Porter - How it works

Content Porter(CP)  is integral part of SDL Tridion development to transfer content in DTAP environments. I have used it in various releases 5.3 sp1, 2009, 2011 etc. Its has been improved a lot in each of the releases. 2013 sp1 claims to be fastest CP ever.

Next set of lines i will explain some internals of content porter. 

Following tools/services are behind the import/export of a Content Porter package.
  • Content Porter Client
  • Import Export Service
  • Core Service
 1) Content Porter Client - this tools is generally downloaded on the client machine from the CM GUI interface. 
It acts as thin client for user, which send user selections/settings to server and show the progress of import/export.

 2) Import Export Service - It is installed after running Content Porter server setup. Here import/export happens. It basically groups and wraps different method of Core Service.

if you open: http://CMSURL/ImportExportService/ImportExportService.asmx. You will see some endpoints. and from their names you can figure out the use.

Another URL http://CMSURL/ImportExportService/UploadPackage.aspx:  its used to upload package from client to Server side.

 3) Core Service - Its is installed as part of Tridion CM installation. It is used by Import/Export service APIs to facilitate the import/export of content.

Export Process: 

  1. User selects content to be exported.
  2. and that selections are sent to Import/Export Service
  3. Import export service calls Core service APIs and complete Package is generated at server file-system
  4. Progress of that is shown to user on CP client
  5. at last exported package is sent back to User Machine via CP client.
Fig-1: Export Process

                                                               


Import Process

  1. User selects package to be imported
  2. Package is uploaded at server with help of client & import/export service
  3. Service extract the package to a temp folder
  4. Service read the package
  5. Then items are updated in the CM DB using coreservice



Fig-2: Import Process

So in both cases(export/import) most of the work is performed at server side,  so it does not matter much from where you actually trigger content porter.

April 25, 2014

Deployer Extension Secrets in SDL Tridion

While migrate from 5.3 to 2011, i found an issue in Deployer extension, My particular extension Module was  on top of  "deploy" action processor in  Tridion 5.3, but same did not work in 2011.

In 2011 Deployer works in transactions, so whatever i was updating initially it got updated in DB but it was  was not assumed as part of transaction and on final commit it was getting removed from database.

I get to know about an optional attribute "Phase" in Processor node. so i performed following steps to configure my extension

1) Copy paste existing Processor node with action deploy/undeploy  depending upon your requirement.

2) <Processor Action="Deploy" Class="com.tridion.deployer.Processor"  Phase="post-transaction"
>
            <!-- A Module is triggered by a Processor to process incoming instructions.
                    The 'Type' attribute needs to be unique within a Processor and serves
                    as a symbolic identifier. The 'Class' attribute defines the
                    implementation used for any type of Module. Replace or add modules to
                    implement custom Deployer behavior. -->
                                <Module Type="CustomDeploy" Class="com.tridion. portal. Deploy">
                       
                                                </Module>
        </Processor>
3) It would be activated only after the transaction has committed its results.

4) Now there would be 3 processor in cd_deployer.config file.

Possible values of Phase, I did not find  cd_deployer.schema to validate.
  • pre-processing
  • processing
  • post-processing
  • pre-transaction
  • post-transaction