tag:blogger.com,1999:blog-25232179014041414572024-02-19T06:44:00.057-08:00Andrew EddyThoughts and code snippets focused on Ektron development.Anonymoushttp://www.blogger.com/profile/13866716929310867212noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-2523217901404141457.post-9795693761851992772012-04-24T07:48:00.000-07:002012-04-24T07:48:06.143-07:00Hi All, I just want to assure you that I have indeed NOT forgotten about this little site, and that in the upcoming couple months we'll be seeing lots of new content from what I've been working on at Ektron posted here as well as ektron.com. :) I think you'll like it!Anonymoushttp://www.blogger.com/profile/13866716929310867212noreply@blogger.com0tag:blogger.com,1999:blog-2523217901404141457.post-39600722449155219012012-01-31T06:28:00.000-08:002012-02-03T07:00:01.947-08:00Custom Data Lists in SmartForms<br />
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;">Intro</span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Ektron Smartforms are one of the key content types that all
Ektron customers take advantage of in one way or another. They are reusable,
extendable, provide a great way of structuring data, and provide your content
authors with easy to input forms for content entry. But out of the box, the Ektron smartforms
aren’t customized to fit with <i>YOUR</i>
information architecture. Yes, we’ve
made great recent improvements especially regarding the Resource Selector which
allows you to associate content, folder, and taxonomy items to your content
item. But what if you want to associate other organizational items or custom
types not defined within the selector? The following guide will provide you
with code and instructions on extending your SmartForms to allow for custom
list types in an easy to extend class that uses our newest Framework API
functionality.<o:p></o:p></span></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;">Getting Ready<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">To get ready there’s a few things you’ll need to make this
easier:<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Visual Studio 2010 (Express will work)<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Write access to: \Workarea\ContentDesigner\DataListSpec.xml<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Write access to: \Workarea\ContentDesigner\Resources\DataListSpec[.*].resx<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;">First Step<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Alright, to get started I have created a fairly
straightforward ashx file that is really at the heart of all this. What this
file does, is provide a XML structured string to your SmartForm select field
with your list data. I have created the
following basic lists and hopefully have made it easy enough to extend for you
to further customize for your own site architecture:<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Content List<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Folder List<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Taxonomy List<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpMiddle" style="mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Collection List<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpLast" style="mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="font-family: Arial, Helvetica, sans-serif;">·<span style="font: normal normal normal 7pt/normal 'Times New Roman';">
</span>Menu List<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Copy the following code and paste it in a new .ASHX file in
your site root or somewhere that makes sense within your site architecture:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<pre class="brush: csharp">
<%@ WebHandler Language="C#" Class="CustomList" %>
using System;
using System.Web;
using System.Collections.Generic;
using System.Text;
using Ektron.Cms.Content;
public class CustomList : IHttpHandler {
public void ProcessRequest (HttpContext context) {
string type = context.Request.QueryString["type"] ?? "ContentList";
long parentId = QueryString("parentId", 0, context);
context.Response.ContentType = "text/xml";
context.Response.Write("<select>");
string results = string.Empty;
EktLists el = new EktLists(parentId);
switch (type)
{
case "ContentList": results=el.ContentList(); break;
case "FolderList": results = el.FolderList(); break;
case "TaxonomyList": results = el.TaxonomyList(); break;
case "CollectionList": results = el.CollectionList(); break;
case "MenuList": results = el.MenuList(); break;
}
context.Response.Write(results);
context.Response.Write("</select>");
}
public bool IsReusable {
get {
return false;
}
}
public static long QueryString(string paramName, int defaultValue, HttpContext context)
{
long value;
if (!long.TryParse(context.Request.QueryString[paramName], out value))
return defaultValue;
return value;
}
}
public class EktLists
{
long _parentId;
public EktLists(long parentId)
{
_parentId = parentId;
}
public string ContentList()
{
StringBuilder options = new StringBuilder();
Ektron.Cms.Framework.Content.ContentManager cm = new Ektron.Cms.Framework.Content.ContentManager();
ContentCriteria criteria = new ContentCriteria(Ektron.Cms.Common.ContentProperty.Id, Ektron.Cms.Common.EkEnumeration.OrderByDirection.Ascending);
criteria.AddFilter(Ektron.Cms.Common.ContentProperty.FolderId, Ektron.Cms.Common.CriteriaFilterOperator.EqualTo, _parentId);
List<ektron.cms.contentdata> list = cm.GetList(criteria);
foreach (Ektron.Cms.ContentData item in list)
{
options.AppendFormat("<option value="\"{0}\"">{1}</option>", item.Id, item.Title);
}
return options.ToString();
}
public string FolderList()
{
StringBuilder options = new StringBuilder();
Ektron.Cms.Framework.Organization.FolderManager fm = new Ektron.Cms.Framework.Organization.FolderManager();
Ektron.Cms.FolderCriteria criteria = new Ektron.Cms.FolderCriteria(Ektron.Cms.Common.FolderProperty.Id, Ektron.Cms.Common.EkEnumeration.OrderByDirection.Ascending);
criteria.AddFilter(Ektron.Cms.Common.FolderProperty.Id, Ektron.Cms.Common.CriteriaFilterOperator.EqualTo, _parentId);
List<ektron.cms.folderdata> list = fm.GetList(criteria);
foreach (Ektron.Cms.FolderData item in list)
{
options.AppendFormat("<option value="\"{0}\"">{1}</option>", item.Id, item.Name);
}
return options.ToString();
}
public string TaxonomyList()
{
StringBuilder options = new StringBuilder();
Ektron.Cms.Framework.Organization.TaxonomyManager tm = new Ektron.Cms.Framework.Organization.TaxonomyManager();
Ektron.Cms.Organization.TaxonomyCriteria criteria = new Ektron.Cms.Organization.TaxonomyCriteria(Ektron.Cms.Organization.TaxonomyProperty.Name, Ektron.Cms.Common.EkEnumeration.OrderByDirection.Ascending);
criteria.AddFilter(Ektron.Cms.Organization.TaxonomyProperty.Id, Ektron.Cms.Common.CriteriaFilterOperator.EqualTo, _parentId);
List<ektron.cms.taxonomydata> list = tm.GetList(criteria);
foreach (Ektron.Cms.TaxonomyData item in list)
{
options.AppendFormat("<option value="\"{0}\"">{1}</option>", item.Id, item.Name);
}
return options.ToString();
}
public string CollectionList()
{
StringBuilder options = new StringBuilder();
Ektron.Cms.Framework.Organization.CollectionManager cm = new Ektron.Cms.Framework.Organization.CollectionManager();
Ektron.Cms.CollectionCriteria criteria = new Ektron.Cms.CollectionCriteria(Ektron.Cms.Common.ContentCollectionProperty.Title, Ektron.Cms.Common.EkEnumeration.OrderByDirection.Ascending);
criteria.AddFilter(Ektron.Cms.Common.ContentCollectionProperty.Id, Ektron.Cms.Common.CriteriaFilterOperator.EqualTo, _parentId);
List<ektron.cms.organization.contentcollectiondata> list = cm.GetList(criteria);
foreach (Ektron.Cms.Organization.ContentCollectionData item in list)
{
options.AppendFormat("<option value="\"{0}\"">{1}</option>", item.Id, item.Title);
}
return options.ToString();
}
public string MenuList()
{
StringBuilder options = new StringBuilder();
Ektron.Cms.Framework.Organization.MenuManager mm = new Ektron.Cms.Framework.Organization.MenuManager();
Ektron.Cms.Organization.MenuData list = mm.GetTree(_parentId);
foreach (Ektron.Cms.Organization.MenuItemData item in list.Items)
{
options.AppendFormat("<option value="\"{0}\"">{1}</option>", item.Id, item.Text);
}
return options.ToString();
}
</pre>
</div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Now that you’ve pasted this in, let’s go over it a
little. You’ll notice the first Class,
“CustomList” is simply a generic ashx handler, which looks at two arguments,
nothing too special:<o:p></o:p></span></div>
<div class="MsoNormal" style="text-indent: .5in;">
<span style="font-family: Arial, Helvetica, sans-serif;"><b>string Type</b>: Used to define the type of list being loaded, current
acceptable values are ContentList, FolderList, TaxonomyList, CollectionList,
and MenuList.<o:p></o:p></span></div>
<div class="MsoNormal" style="text-indent: .5in;">
<span style="font-family: Arial, Helvetica, sans-serif;"><b>long parentId</b>: Used to define the containing organizational
identifier. E.g. A parent folder id.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">The second class “<b>EkLists</b>”
however is where all the action happens. This class is instantiated right above
the switch case and given the parentId for the container your list will be
in. The proper method which fills the
list is then called. Your resulting string which is received by the editor will
look a lot like:<o:p></o:p></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-size: 10pt;"><span style="font-family: Arial, Helvetica, sans-serif;"><select><o:p></o:p></span></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-size: 10pt;"><span style="font-family: Arial, Helvetica, sans-serif;"><option value="30">Sample
Content Block</option><o:p></o:p></span></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-size: 10pt;"><span style="font-family: Arial, Helvetica, sans-serif;"><option value="32">testing</option><o:p></o:p></span></span></div>
<div class="MsoNormal" style="margin-bottom: 0.0001pt;">
<span style="font-size: 10pt;"><span style="font-family: Arial, Helvetica, sans-serif;"></select><o:p></o:p></span></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;">But we still need to
tell the editor about our lists!<o:p></o:p></span></b></div>
<div class="MsoNormal">
<b><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></b></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">So now that we have our new super ektlist class outputting
all the xml lists we can imagine, the editor still has no idea this file or our
cool lists exist. The good news is, all
our list information is read in from a configuration file called <b>DataListSpec.xml </b>located in \Workarea\ContentDesigner\.
<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Open this file, and right before the ending
</datalists> paste:<o:p></o:p></span></div>
<pre style="background: white;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="color: blue;"> <</span><span style="color: #a31515;">datalist</span><span style="color: blue;"> </span><span style="color: red;">name</span><span style="color: blue;">=</span>"<span style="color: blue;">ContentList</span>"<span style="color: blue;"> </span><span style="color: red;">localeRef</span><span style="color: blue;">=</span>"<span style="color: blue;">ContentList</span>"<span style="color: blue;"> </span><span style="color: red;">src</span><span style="color: blue;">=</span>"[path]<span style="color: blue;">/CustomList.ashx?type=ContentList</span><span style="color: red;">&amp;</span><span style="color: blue;">parentId=0</span>"<span style="color: blue;"> </span><span style="color: red;">cache</span><span style="color: blue;">=</span>"<span style="color: blue;">false</span>"<span style="color: blue;"> </span><span style="color: red;">select</span><span style="color: blue;">=</span>"<span style="color: blue;">/select/option</span>"<span style="color: blue;"> </span><span style="color: red;">captionxpath</span><span style="color: blue;">=</span>"<span style="color: blue;">.</span>"<span style="color: blue;"> </span><span style="color: red;">valuexpath</span><span style="color: blue;">=</span>"<span style="color: blue;">@value</span>"<span style="color: blue;"> </span><span style="color: red;">validation</span><span style="color: blue;">=</span>"<span style="color: blue;">select-req</span>"<span style="color: blue;">></span><o:p></o:p></span></pre>
<pre style="background: white;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="color: blue;"> <</span><span style="color: #a31515;">item</span><span style="color: blue;"> </span><span style="color: red;">value</span><span style="color: blue;">=</span>""<span style="color: blue;"> </span><span style="color: red;">localeRef</span><span style="color: blue;">=</span>"<span style="color: blue;">sSel</span>"<span style="color: blue;">/></span><o:p></o:p></span></pre>
<pre style="background: white;"><span style="font-family: Arial, Helvetica, sans-serif;"><span style="color: blue;"> </</span><span style="color: #a31515;">datalist</span><span style="color: blue;">></span><o:p></o:p></span></pre>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">If you read the above statement, there are a few key parts:<o:p></o:p></span></div>
<div class="MsoListParagraphCxSpFirst" style="mso-list: l2 level1 lfo3; text-indent: -.25in;">
</div>
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;"><span style="font: normal normal normal 7pt/normal 'Times New Roman';"> </span>Name: Can be whatever you’d like </span><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;">localeRef: Name Key referenced in DataListSpec[.*].res</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;">src: “[path]/CustomList.ashx” Location to file
you imported earlier</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;">type: Defaults to ContentList, can be modified
to any list type defined.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;">parentId: Containing element of list items</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif; text-indent: -0.25in;">validation: Default is select-req, which makes
this field required</span></li>
</ul>
<br />
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">And that’s it; the rest of the values will normally not
change. </span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">The only piece left is adding the reference into the resx file and
we’re ready to start viewing our list(s). <o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Open “\Workarea\ContentDesigner\Resources\DataListSpec[.*].resx”
which is a two column spreadsheet of a Name/Value pair. Create a new entry for
any datalists you defined, where the Name equals “localeRef” and the Value can
be whatever you’d like. For the above configuration I entered:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Name: ContentList, Value: ContentList(FolderID 0)<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">OK! If everything was put in the right spot, when we go into
the SmartForm data designer we should now be able to see our new list for a
“Choices Field” option.<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha7dCIU1sfwCVdkcLOO7x7ofv7AN77w7Rwr5PpCLXdKpAjvvDX-IF-45Yq9uQTNs6s7CjtX_PgdnNZQfV7pcDpcJ4Af4Mcvf3hISwdGgMwU5e2JHRQmBRxlYvpO2kQEhCW7XiGIQnEJmSd/s1600/ss_choices.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha7dCIU1sfwCVdkcLOO7x7ofv7AN77w7Rwr5PpCLXdKpAjvvDX-IF-45Yq9uQTNs6s7CjtX_PgdnNZQfV7pcDpcJ4Af4Mcvf3hISwdGgMwU5e2JHRQmBRxlYvpO2kQEhCW7XiGIQnEJmSd/s320/ss_choices.png" width="250" /></a></div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Thanks for reading, please leave comments below for ideas or
extensions on this. Also feel free to talk with me on twitter @andrew_eddy
about this article or Ektron in general!</span><o:p></o:p></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoListParagraph">
<br /></div>Anonymoushttp://www.blogger.com/profile/13866716929310867212noreply@blogger.com1tag:blogger.com,1999:blog-2523217901404141457.post-79636034916781495942012-01-10T06:56:00.000-08:002012-01-10T06:56:40.615-08:00Expiring Content from the v8.5 Cache Framework<br />
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
We in Ektron Engineering have been spending the past several years making our APIs and developer framework more user friendly and powerful with every release (see a webinar <a href="http://www.ektron.com/Resources/Webinars/Framework-API/" style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #286db2; font-family: inherit; font-style: inherit; font-weight: 700; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; vertical-align: baseline;">Framework API:Consistency, Discoverability, and Simplicity</a>). We are extremely excited about the release of 8.5, and are working on anew era of development tools to complement our existing product set.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
In v8.5, a transparent caching layer has been implemented. Thisnew caching layer sits below the Framework API and caches frequently accessed objects (see related webinar: <a href="http://www.ektron.com/Resources-And-Tools/Webinars/Screencasts/Developer/Optimize-Site-Performance-through-Caching/" style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #286db2; font-family: inherit; font-style: inherit; font-weight: 700; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-decoration: none; vertical-align: baseline;">v8.5 &Caching Best Practices</a>). One common question is: "<em style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">How do Invalidate the cache of a content object upon publish or update?</em>"</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
Using Ektron CMS Extensions (plug-ins) you can modify the publish process to invalidate the framework cache. For those of you not familiar with either concept, allow me to provide a brief rundown on what this functionality can do.</div>
<h3 style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 12px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 7px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; width: 280px;">
CMS Extensions and the Strategy Pattern</h3>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
Strategy Pattern is an design pattern that lets you select an implementation at runtime. For Ektron, CMS Extensions are a piece of code that is executed when a certain event fires, for example if you want to append a date to the title of your content, you could tie code to do this on the OnBeforePublish event. Now every time content is published it is executed through the strategy and a date will be appended.</div>
<h3 style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 12px; margin-bottom: 10px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 7px; padding-right: 0px; padding-top: 0px; vertical-align: baseline; width: 280px;">
The Framework API</h3>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
Ektron's newest API that exposes the majority of feature sets in a straight forward way with the ability to use criteria to pull data, perform impersonation, integrate with WCF, and more.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
With the most recent improvements to the Framework API, we have implemented an entire caching strategy to specify which objects we would like to automatically be stored in cache, and for how long.By doing this we greatly increase the framework performance by avoiding database hits until the cache is expired. Now this is all well and good, until we run into an instance where we need something to display immediately. Currently there are limited options to expire the cache in this scenario, you would either need a script that expires the cache entirely or by key (which would be difficult to discover), or (YIKES!) have to reset the IISapplication pool to see your content change immediately.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
With the introduction of Unity into our Framework, we expose some extremely advanced caching options that solve this. The following is a step by step tutorial on creating a strategy that expires an individual cache based on content changes making cache keys dependent on changes, rather than time elapsed.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
To get started let's make sure we have the necessary requirements setup within our CMS400 instance:</div>
<ul style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; list-style-image: initial; list-style-position: initial; list-style-type: none; margin-bottom: 16px; margin-left: 40px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
<li style="background-attachment: initial; background-clip: initial; background-image: url(http://www.ektron.com/images/sub/bullet-gold.jpg); background-origin: initial; background-position: 0px 6px; background-repeat: no-repeat no-repeat; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; margin-bottom: 8px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 11px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">CMS400 version 8.5</li>
<li style="background-attachment: initial; background-clip: initial; background-image: url(http://www.ektron.com/images/sub/bullet-gold.jpg); background-origin: initial; background-position: 0px 6px; background-repeat: no-repeat no-repeat; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; margin-bottom: 8px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 11px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Folder in workarea with more than one piece of content</li>
<li style="background-attachment: initial; background-clip: initial; background-image: url(http://www.ektron.com/images/sub/bullet-gold.jpg); background-origin: initial; background-position: 0px 6px; background-repeat: no-repeat no-repeat; border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; font-family: inherit; font-style: inherit; margin-bottom: 8px; margin-left: 0px; margin-right: 0px; margin-top: 0px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 11px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">Framework Caching turned on</li>
</ul>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
While the first two steps are straight forward, the third step implies a little additional help. To turn on framework caching within your 8.5 I'll introduce you to a new config file in the root of your site, "ektron.cms.framework.unity.config". Upon opening this file you'll notice a few things, a list of framework class definitions, and 3 sections that define WCF, Cache, andDefault. Right now we're focused on using the Cache definition, since we're looking to cache our Framework functions. To turn on the framework caching, there should be a section in your web.config that looks like:</div>
<pre style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: inherit; font-size: 14px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"> <ektron.framework.services>
<unity configSource="ektron.cms.framework.unity.config" />
<framework defaultContainer="Default" childContainer="BusinessObjects" />
</ektron.framework.services>
</pre>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
By simply changing the defaultContainer to "Cache" we have enabled it. You're framework api calls should now all be caching!You can set the timeouts individually on items by looking back inektron.cms.framework.unity.config, but the default should be okay for now.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
So we have our framework caching now which is all well and good, but if we go back to our earlier scenario, we don't want to publish an item and wait around for the cache to expire, or have to expire the cache ourselves which could drastically hurt your site performance if the cache is emptied at once. With 8.5 fear no more, we can now expire the cache of items pulled through the framework api individually! We accomplish this by setting up a strategy, and for those of you that have done this before it's easier than ever in 8.5.</div>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
You can get an Ektron strategy up and running faster than ever ,you no longer need to compile the code, or use a utility to add it to your site. In a few painless steps you'll have as many hooks into your CMS system as you need. We'll start by creating anew Class file under your App_Code\CSCode, copy the code below replacing all text in the newly created CS file:</div>
<pre style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: inherit; font-size: 14px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ektron.Cms;
using Ektron.Cms.Common;
using Ektron.Cms.Instrumentation;
using Ektron.Cms.Extensibility;
using Ektron.Cms.Extensibility.Content;
namespace Cms.Extensions.Custom
{
public class InvalidateFrameworkCache : ContentStrategy
{
public override void OnAfterPublishContent(ContentData contentData, CmsEventArgs eventArgs)
{
//Cache manager class to access Framework Cache
Ektron.Cms.BusinessObjects.Caching.CacheManager cmanager =
new Ektron.Cms.BusinessObjects.Caching.CacheManager();
//Fill cachekey in
string CackeKey = string.Format("Ektron:content:{0}", contentData.Id);
//Remove key from cache
cmanager.Remove(CackeKey);
//Write results to log
Log.WriteInfo(string.Format("InvalidateFrameworkCache.OnAfterAddContent: {0}::{0}",
contentData.Id, contentData.Title));
}
}
}
</pre>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
Looking at the above code we immediately can see how simple this task is using our API's. The other thing you'll probably notice is how the cache key is formatted, we follow a very simple naming convention: "Ektron:object:id". We follow this convention and use our API's to make this "smart" functionality.What I mean by that is that all the places in the cache where this object shows, are now removed. So in three lines of code, based on the piece of content we just published, it has been removed from all the caches it resided in, this includes any list caches the content was in as well. The final step is to register this extension in the object factory so that it knows to execute. To register the extension you simply need to openObjectFactory.config (also in the root of your website) and change the content section to look like the following assuming this is anew install:</div>
<pre style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: inherit; font-size: 14px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;"><add name="Content">
<strategies>
<add name="GoogleGeoCoder"
type="Cms.Extensions.GoogleGeoCoder.ContentStrategy, Cms.Extensions.GoogleGeoCoder"/>
<add name="InvalidateFrameworkCache" type="Cms.Extensions.Custom.InvalidateFrameworkCache" />
</strategies>
</add>
</pre>
<div style="border-bottom-width: 0px; border-color: initial; border-image: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; color: #666666; font-family: 'Century Gothic', 'Lucida Grande', Helvetica, Arial, Verdana, sans-serif; font-size: 14px; margin-bottom: 14px; margin-left: 8px; outline-color: initial; outline-style: initial; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; vertical-align: baseline;">
And there you have it! With a few very simple steps we have created a strategy to invalidate the cache of a content object upon publish. Hopefully by now your imagination is cooking up more ideas on how to improve your site performance and content delivery at the same time, please leave those ideas, or other questions in the comments below!</div>Anonymoushttp://www.blogger.com/profile/13866716929310867212noreply@blogger.com2