Wednesday, February 6, 2013

Custom URL - Tridion

This example will discuss creating a Custom Page to assign to the "Custom Url" field of a schema field:

The purpose of the Custom URL field is to allow you to add a link to the description of a field to:
  • Allow for customized help for the field to content authors:
    • Providing a detailed explanation as to the purpose of this field
      • Screenshots
      • Description
      • Use cases
  • Allow field values on a Component to be filled through code:
    • Retrieve values
      • Current time
      • User’s e-mail address
      • Access external systems
        • Database
        • Web Service
        • Third Party Application

We will need to create the Custom Page:
  • Create a simple html page that will:
    • Contain a button with the text "Display alert box"

      • When the button is clicked it will open an alert box:
        • The first message is "Hello! I am an alert box!!"

        • The second message is the length of the field (number of values in the field object):

        • The third message reads the current value of the field and displays it:

        • After clicking "ok" on the last message above the page will close and prior to closing it will assign "Hello Tridion" to the field as its value:

Code for the Custom Page:
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
   <script type="text/javascript" language="javascript" src="/WebUI/Core/Controls/Popup/PopupInit.js"></script>
   <script type="text/javascript">
   
   var fields = window.dialogArguments.getFields();
   var valArray = new Array("Hello Tridion");
   var GeoData = "";

   function display_alert()
   {
     try{
     debugger;
     alert("Hello! I am an alert box!!");
     alert("Length is: " + fields.length);
     alert("Field Value is: " + fields[0].getValues());

     if (fields && fields.length > 0)
     {
       fields[0].setValues(valArray);
     }
     window.close();
     }
     catch (e){alert("Error: " + e.message);}
   }
   </script>
  </head>
  <body>
    <input type="button" onclick="display_alert()" value="Display alert box" />
  </body>
</html>

 
We will now place the Custom Page in the following location:
  • Tridion install path: (ex. "D:\Tridion\web\CustomUrls\CustomUrlSample.html")
Now that the Custom Page has been created and placed in the appropriate location, we will now need to add the reference to the Custom Page to the appropriate schema field in Tridion:

 
  • The path to the Custom Page will be as follows: "/CustomUrls/CustomUrlSample.html"
Now we can Create/Edit a component based on this schema:
  • The description will look like a hyperlink as seen in the screenshot below in the red box:
  •  Click on the description for the field to launch the Custom Page:

Thursday, January 24, 2013

Sorting Component Array - Tridion 2011

This example will discuss creating a component array which filters all component presentations on a page based on template title. The component array pushed to the package will then be retrieved from the package by a C# TBB that will then sort the component array and push to the package the sorted list of component presentations.

The Environment shown is the Electridion Training Environment and I helped describe how to complete an exercise to the group in a way that made sense to everyone and demonstrated a real world use case by making the following example during a recent .NET templating course.

Step One - Create a Component Array based on component template title and push to the package:
  • Create a parameter schema to pass the following parameters to the C# Template Building Block to create the Component Array:
    • Template Name
      • Single line text field
    • Item Name
      • Single line text field
 
 
  • Assign the Parameter Schema to the C# Template Building Block:
    • Navigate to the location in Tridion where the C# Template Building Block is located:
      • \200 Website Design\Building Blocks\System\Template Building Blocks\C# Examples\Components Array
    • Open the C# Template Building Block and assign the Parameter Schema to it:

  • Place the C# Template Building Block on a Compound Page Template and provide the values for the parameters:
    • Template Name value
      • summary
    • Item Name value
      • CP Array

  • Component Array Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Tridion.ContentManager;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
using comm = Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.ContentManagement.Fields;

namespace TrainingTemplates
{
    [TcmTemplateTitle("Components Array")]
    class ComponentsArray : ITemplate
    {
        public void Transform(Engine engine, Package package)
        {
            string templateName = package.GetValue("templateName"), itemName = package.GetValue("itemName");
            // Get the page object from the package
            Item pageItem = package.GetByType(ContentType.Page);
            // Get the TCMURI of the page
            comm.Page page = engine.GetObject(pageItem.GetAsSource().GetValue("ID")) as comm.Page;
            if (page != null)
            {
                ComponentPresentationList m_cpList = new ComponentPresentationList();

                foreach (comm.ComponentPresentation cp in page.ComponentPresentations)
                {
                    if (cp.ComponentTemplate.Title.ToLower().Contains(templateName))
                    {
                        m_cpList.Add(new ComponentPresentation(cp.Component.Id, cp.ComponentTemplate.Id));
                    }
                }
                package.PushItem(itemName, package.CreateStringItem(ContentType.ComponentArray, m_cpList.ToXml()));
            }
        }
    }
}

Step Two - Retrieve Component Array from Step One, sort and then push the Sorted Component Array to the package:
  • Create a parameter schema to pass the following parameters to the C# Template Building Block to sort the Component Array:
    • Component Sort Field
      • Single line text field
    • Name of Component Array
      • Single line text field




  • Assign the Parameter Schema to the C# Template Building Block:
    • Navigate to the location in Tridion where the C# Template Building Block is located:
      • \200 Website Design\Building Blocks\System\Template Building Blocks\C# Examples\Retrieve Components Array From Package
    • Open the C# Template Building Block and assign the Parameter Schema to it:


  • Place the C# Template Building Block on a Compound Page Template and provide the values for the parameters:
    • Component Sort Field
      • title
    • Name of Component Array
      • CP Array

  • Retrieve Array From Package Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Tridion.ContentManager;
using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
using comm = Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager.ContentManagement;
using Tridion.ContentManager.ContentManagement.Fields;
using System.Web;
using System.Xml;




namespace TrainingTemplates
{
    [TcmTemplateTitle("Retrieve Components Array From Package")]
    class RetrieveArrayFromPackage : ITemplate
    {
        public void Transform(Engine engine, Package package)
        {
            ComponentPresentationList m_cpList = new ComponentPresentationList();
            SortedList<string, ComponentPresentation> sortedList = new SortedList<string, ComponentPresentation>();
            XmlDocument xDoc = new XmlDocument();
            String arrayName = package.GetValue("ComponentArray");
            String sortField = package.GetValue("ComponentSortField");
            xDoc.LoadXml(package.GetValue(arrayName));
            XmlNode node = xDoc.ChildNodes[1];
 
            foreach (XmlNode n in node.ChildNodes)
            {
                Component comp = engine.GetObject(n["ComponentURI"].InnerText) as Component;
                TcmUri templateUri = new TcmUri(n["TemplateURI"].InnerText);
                sortedList.Add(comp.Content[sortField].InnerText, new ComponentPresentation(comp.Id, templateUri));
            }

            foreach (ComponentPresentation cp in sortedList.Values as IList<ComponentPresentation>)
            {
                m_cpList.Add(cp);
            }
            package.PushItem("Sorted CP Array", package.CreateStringItem(ContentType.ComponentArray, m_cpList.ToXml()));
        }
    }
}
 
Compare the two Component Array Lists to show the difference before and after sorting:

  • Original Component Array (no sorting):

  • New Component Array (sorted):

Wednesday, January 23, 2013

Tridion and .NET User Controls

These .NET user controls currently query a Database to retrieve content for the site (example: press releases). The controls will now need to pull content from Tridion using the Content Delivery API.

 
The following is an example of how to create a User Control that Queries Tridion via the Content Delivery API to fetch Data:
  • Using Visual Studio create a new project:

  • The project will need to be an “ASP.NET Web Application”:

  • Add a reference to the “Tridion.ContentDelivery.dll”:

  • Create a “Bin” folder and include all of the Delivery files in the Bin folder for your Deployer:

  • Create a new user control:
 
 

  • This control will contain an asp repeater to display the list of Component Presentations retrieved from Tridion based on a Keyword (Dynamic Component Presentations that have been tagged with the selected Keyword):
<asp:Repeater ID="cpRepeater" runat="server" OnItemDataBound="cpRepeater_ItemDataBound">
  <ItemTemplate>
    <div>
      <asp:Label ID="lblContent" runat="server"></asp:Label>
    </div>
  </ItemTemplate>
</asp:Repeater>
 
  • The code to retrieve the list of Component Presentations based on the desired Keyword is as follows:
           using System;
           using System.Collections.Generic;
           using System.Linq;
           using System.Web;
           using System.Web.UI;
           using System.Web.UI.WebControls;
           using Tridion.ContentDelivery.DynamicContent;
           using Tridion.ContentDelivery.Taxonomies;
           using Tridion.ContentDelivery.Web.UI;
           using Tridion.ContentDelivery.Web.Utilities;
          
           namespace TestUserControls
           {
               public partial class QueryTaxonomy : System.Web.UI.UserControl
               {
                  String DynamicTemplateURI = String.Empty;
                  String selectedURI = String.Empty;
                  /// <summary>
                  /// Paramter for the Query Taxonomy User Control
                  /// </summary>
                  /// <param name="Keyword">TCMURI of the taxonomy keyword</param>
                  /// <returns>Keyword instance</returns>

                  public virtual String Keyword
                  {
                     get
                     {
                        string s = (string)ViewState["Keyword"];
                        return (s == null ? String.Empty : s);
                      }

                      set
                      {
                         ViewState["Keyword"] = value;
                       }
                    }

                  protected void Page_Load(object sender, EventArgs e)
                  {
                     if (Request.QueryString["category"] != null)
                     {
                       selectedURI = "tcm:254-" + Request.QueryString["category"] + "-1024";
                     }
                     else
                     {
                       selectedURI = this.Keyword;
                     }

                     DynamicTemplateURI = "tcm:254-4219-32";
                     Keyword selected = GetKeywordFromURI(selectedURI);
                    
                     List<Tridion.ContentDelivery.DynamicContent.ComponentPresentation> references = new List<Tridion.ContentDelivery.DynamicContent.ComponentPresentation>();
                     references.AddRange(GetRelatedContent(selected));

                      // Assign the List of Component Presentations as the Datasource
                     cpRepeater.DataSource = references;
                     cpRepeater.DataBind(); // Bind the Datasource
                  }

                  /// <summary>
                  /// Gets the taxonomy keyword
                  /// </summary>
                  /// <param name="tcmuri">TCMURI of the taxonomy keyword</param>
                  /// <returns>Keyword instance</returns>

                  private Keyword GetKeywordFromURI(string tcmuri)
                  {
                     Keyword result = null;

                     if (!string.IsNullOrEmpty(tcmuri))
                     {
                        using (TaxonomyFactory tf = new TaxonomyFactory())
                        {
                           result = tf.GetTaxonomyKeyword(tcmuri);
                        }
                      }
                      return result;
                    } //private Keyword GetKeywordFromURI(string tcmuri)

                    private List<Tridion.ContentDelivery.DynamicContent.ComponentPresentation> GetRelatedContent(Keyword keyword)
                    {
                       List<Tridion.ContentDelivery.DynamicContent.ComponentPresentation> cps = new List<Tridion.ContentDelivery.DynamicContent.ComponentPresentation>();

                        if (keyword != null)
                        {
                           using (ComponentPresentationFactory cpf = new ComponentPresentationFactory(keyword.KeywordUri))
                           {
                              cps.AddRange(cpf.GetTaxonomyComponentPresentations(keyword, DynamicTemplateURI, true));
                           }
                         }
                         else
                         {
                            System.Diagnostics.Debug.WriteLine("No selected keyword found.");
                         }
                         return cps;
                      }

                      protected void cpRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
                      {
                         if (e.Item.ItemType == ListItemType.Item)
                         {
                            Label lblContent = (Label)e.Item.FindControl("lblContent");
                            lblContent.Text = ((Tridion.ContentDelivery.DynamicContent.ComponentPresentation)e.Item.DataItem).Content;
                          }
                       }
                     }
                   }

  • Compile the project:

  • Copy the User Control to your staging site:

  • Copy the compiled DLL from you project to the Staging Bin folder:

  • Locate your Page Design DWT in Tridion:

  • Open the Template Building Block:

  • Go to the source tab and insert the reference to you user control:

<%@ Page Title="Training Web Site" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" %>
 
<%@ Register TagPrefix="uc1" TagName="QueryTaxonomy" Src="~/UserControls/QueryTaxonomy.ascx" %>

<uc1:QueryTaxonomy ID="TaxControl1" runat="server" Keyword="tcm:254-4217-1024" />
 

    • Use this TBB in your Page Template
    • Create a page using the Page Template created Above:
 
 

  • Publish the Page to the Staging environment:
 
 

  • This test User Control as currently coded allows for the passing of a Keyword via a parameter as well as URL Query String:
    • If Query String is provided for category then the content will be presented using that Keyword:
    • If no Query String is provided the Keyword parameter is used:
    • If neither is provided no content is retrieved