<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Paul&#039;s Sitecore Musings</title>
	<atom:link href="http://sitecorepm.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://sitecorepm.wordpress.com</link>
	<description>Just another Sitecore blog</description>
	<lastBuildDate>Thu, 19 Jan 2012 17:12:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='sitecorepm.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Paul&#039;s Sitecore Musings</title>
		<link>http://sitecorepm.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://sitecorepm.wordpress.com/osd.xml" title="Paul&#039;s Sitecore Musings" />
	<atom:link rel='hub' href='http://sitecorepm.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Setting the Folder in the sitecore TreeList control</title>
		<link>http://sitecorepm.wordpress.com/2011/08/08/setting-the-folder-in-the-sitecore-treelist-control/</link>
		<comments>http://sitecorepm.wordpress.com/2011/08/08/setting-the-folder-in-the-sitecore-treelist-control/#comments</comments>
		<pubDate>Mon, 08 Aug 2011 17:59:30 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Custom Component]]></category>
		<category><![CDATA[Field Types]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[TreeList]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=132</guid>
		<description><![CDATA[The TreeList field type allows you to specify many things through the &#8220;Source&#8221; property as detailed in Sitecore&#8217;s documentation (and here). However, one setting that (I feel) is missing is the ability to specify which tree node to start from. &#8230; <a href="http://sitecorepm.wordpress.com/2011/08/08/setting-the-folder-in-the-sitecore-treelist-control/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=132&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The TreeList field type allows you to specify many things through the &#8220;Source&#8221; property as detailed in Sitecore&#8217;s documentation (<a href="http://firebreaksice.com/tame-your-sitecore-treelists/">and here</a>). However, one setting that (I feel) is missing is the ability to specify which tree node to start from. By default, you can set the DataSource property which, behind the scenes, sets the root node from which to start the tree. The tree then gets rendered and displays just the root node and its immediate children&#8230; but there&#8217;s no way for me to do things like:</p>
<ol>
<li>Expand the first sub-folder that contains the an item of type XYZ</li>
<li>Perform a sitecore query to determine which decendant folder to expand to</li>
<li>Expand the tree to a particular node depending on some attribute of the context item that i&#8217;m editing.</li>
</ol>
<p>In my particular case, we had FacultyProfile items with a Department field (TreeList type). They wanted the Department field TreeList to be &#8220;context aware&#8221; and auto-expand to the appropriate part of the Department Lookup tree depending on the Site that the FacultyProfile item was in. My solution was to extend Sitecore&#8217;s TreeList type to add the necessary functionality as detailed below.</p>
<p><a href="http://sitecorepm.files.wordpress.com/2011/08/smarttreelist.png"><img class="alignnone size-full wp-image-148" title="SmartTreeList" src="http://sitecorepm.files.wordpress.com/2011/08/smarttreelist.png?w=640&#038;h=190" alt="" width="640" height="190" /></a></p>
<p>Taking a look at the inner workings of the TreeList type (thank you .NET Reflector), I found that the TreeList type uses the TreeviewEx control to render the tree. The TreeviewEx control uses a DataContext control to set the Root folder and the start Folder. After some more digging, trial &amp; error I came up with the following extended data type (<a href="http://sdn.sitecore.net/Articles/API/Creating%20a%20Composite%20Custom%20Field.aspx">how to create an extended data type</a>):</p>
<p><pre class="brush: csharp;">
namespace Drexel.CustomTypes
{
    public class SmartTreeList : TreeList
    {
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (this.ItemID != null)
            {
                var tree = (TreeviewEx)this.FindControl(this.ID + &quot;_all&quot;);
                var dc = FindDataContext(this);
                var item = Sitecore.Context.ContentDatabase.GetItem(this.ItemID);

                var pipeArgs = new PreRenderSmartTreeListArgs(item, dc);
                CorePipeline.Run(&quot;PreRenderSmartTreeList&quot;, pipeArgs);

                if (!string.IsNullOrEmpty(pipeArgs.DataContext.Folder))
                {
                    // 'Select' the Folder item in addition to expanding it...
                    var i = item.Database.GetItem(pipeArgs.DataContext.Folder);
                    if (i != null)
                        tree.SetSelectedItem(i);
                }
            }
        }

        private DataContext FindDataContext(System.Web.UI.Control c)
        {
            DataContext dc = null;

            if (c is DataContext)
                dc = (DataContext)c;
            else
            {
                foreach (System.Web.UI.Control ctl in c.Controls)
                {
                    dc = FindDataContext(ctl);
                    if (dc != null)
                        break;
                }
            }

            return dc;
        }
    }
}
</pre></p>
<p>I decided to use a custom Sitecore pipeline for my SmartTreeList type. Here&#8217;s a great synopsis of <a href="http://adeneys.wordpress.com/2008/08/27/creating-and-running-custom-pipelines-in-sitecore/">how to create a custom pipeline</a>. This allows me to apply different logic for determining the &#8220;Start Folder&#8221; depending on the context item. So, in the OnPreRender event, I find DataContext control and get a reference to the Context Item. Then I call my custom pipeline which only contains 1 pipeline processor: FacultyProfileDepartmentProcessor.</p>
<p>First, the pipeline code&#8230;</p>
<p><pre class="brush: csharp;">
    interface IPreRenderSmartTreeListProcessor
    {
        void Process(PreRenderSmartTreeListArgs args);
    }
</pre></p>
<p>&nbsp;</p>
<p><pre class="brush: csharp;">
    public class PreRenderSmartTreeListArgs : PipelineArgs
    {
        public PreRenderSmartTreeListArgs(Item item, DataContext dc)
        {
            this.Item = item;
            this.DataContext = dc;
        }

        public Item Item { get; set; }
        public DataContext DataContext { get; set; }
    }
</pre></p>
<p>&nbsp;</p>
<p><pre class="brush: csharp;">
    public class FacultyProfileDepartmentProcessor : IPreRenderSmartTreeListProcessor
    {
        public void Process(PreRenderSmartTreeListArgs args)
        {
            if (args.Item != null &amp;&amp; args.Item.TemplateName == &quot;FacultyProfile&quot;)
            {
                // My logic to determine the correct Department node to open...
                // ...
                // ...
                args.DataContext.Folder = pathOrItemIdOfDepartmentItem;
            }
        }
    }
</pre></p>
<p>Then, add the configuration for the pipeline:</p>
<p><pre class="brush: xml;">
   ...
      &lt;PreRenderSmartTreeList&gt;
        &lt;processor type=&quot;Drexel.Pipelines.PreRenderSmartTreeList.FacultyProfileDepartmentProcessor, Sitecore.Drexel.Pipelines&quot; /&gt;
      &lt;/PreRenderSmartTreeList&gt;
   ...
</pre></p>
<p>That&#8217;s it. Relatively simple&#8230; relatively extensible. Just the way I like it..</p>
<p> <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/132/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/132/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/132/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=132&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2011/08/08/setting-the-folder-in-the-sitecore-treelist-control/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2011/08/smarttreelist.png" medium="image">
			<media:title type="html">SmartTreeList</media:title>
		</media:content>
	</item>
		<item>
		<title>Sitecore Proxy Filter POC Implementation</title>
		<link>http://sitecorepm.wordpress.com/2011/06/30/sitecore-proxy-filter-poc-implementation/</link>
		<comments>http://sitecorepm.wordpress.com/2011/06/30/sitecore-proxy-filter-poc-implementation/#comments</comments>
		<pubDate>Thu, 30 Jun 2011 17:54:26 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Proxy Items]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=125</guid>
		<description><![CDATA[Here is my proof-of-concept code for the Sitecore Proxy Filter. We never ended up implementing it.  Disclaimer: I pull this code from an old SVN branch and haven&#8217;t verified that I have all the parts or that it works still. You &#8230; <a href="http://sitecorepm.wordpress.com/2011/06/30/sitecore-proxy-filter-poc-implementation/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=125&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here is my proof-of-concept code for the <a href="http://sitecorepm.wordpress.com/2010/05/27/sitecore-proxy-filter/">Sitecore Proxy Filter</a>. We never ended up implementing it.  Disclaimer: I pull this code from an old SVN branch and haven&#8217;t verified that I have all the parts or that it works still. You have been warned <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>1. Extend the &#8220;SqlProxyDataProvider&#8221; class</p>
<p><pre class="brush: csharp;">

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;

using Sitecore.Configuration;
using Sitecore.Data;
using Sitecore.Data.DataProviders.Sql;
using Sitecore.Data.Items;
using Sitecore.Data.Proxies;
using Sitecore.Data.SqlServer;

using BaseIDs = Drexel.FieldIDs.Base;
using Drexel.Extensions;

namespace Drexel.Data.SqlServer
{
public class SqlServerProxyDataProvider : SqlProxyDataProvider
{
private string _connectionString = string.Empty;
private Dictionary&lt;string, bool&gt; _validIdLookup = new Dictionary&lt;string, bool&gt;();

private Database _db;
private Database ContextDb
{
get
{
if (_db == null)
{
try
{
ConnectionStringSettings css = ConfigurationManager.ConnectionStrings
.Cast&lt;ConnectionStringSettings&gt;()
.SingleOrDefault(x =&gt; x.ConnectionString == _connectionString);
_db = Factory.GetDatabase(css.Name);
}
catch (Exception ex)
{
Drexel.Logging.Log.Error(&quot;Failed to resolve connection string&quot;, ex);
_db = Factory.GetDatabase(&quot;master&quot;); // Default to master DB
}
}
return _db;
}
}
private SqlServerDataApi API { get; set; }
public SqlServerProxyDataProvider(string connectionString)
: this(new SqlServerDataApi(connectionString), true)
{
_connectionString = connectionString;
}
private SqlServerProxyDataProvider(SqlServerDataApi api, bool foo)
: base(api)
{
this.API = api;
}
public override ID GetVirtualId(ID itemId, ID proxyId, bool generateIfNotFound)
{
ID proxySourceItemID;
string vcProxyFilterQuery;
bool valid = true;

if (!_validIdLookup.TryGetValue(itemId.ToString(), out valid))
{
valid = true; // if TryGetValue fails, it sets valid=false...
GetProxyFilterInfo(proxyId, out proxySourceItemID, out vcProxyFilterQuery);

if (!string.IsNullOrEmpty(vcProxyFilterQuery) &amp;&amp; !proxySourceItemID.IsNull)
{
using (new ProxyDisabler())
{
string[] validIds = GetValidProxyIds(proxyId, proxySourceItemID, vcProxyFilterQuery);
valid = validIds.Contains(itemId.ToString());
}
}

_validIdLookup.Add(itemId.ToString(), valid);
}

if (valid)
return base.GetVirtualId(itemId, proxyId, generateIfNotFound);
else
{
// See if this proxied item was already shadowed... if so, then remove it
ID shadowId = base.GetVirtualId(itemId, proxyId, false);
if (shadowId != (ID)null)
this.RemoveShadow(shadowId);
return ID.Null;
}

}

private string[] GetValidProxyIds(ID proxyId, ID proxySourceItemID, string vcProxyFilterQuery)
{
System.Web.Caching.Cache cache = System.Web.HttpContext.Current.Cache;
Item proxyItem = ContextDb.GetItem(proxyId);
string vcCacheKey = &quot;ValidProxyIdsFor-&quot; + proxySourceItemID.ToString() + &quot;-&quot; + GetItemTimestamp(proxyItem);

string[] list = (string[])cache[vcCacheKey];
if (list == null)
{
Item i = ContextDb.GetItem(proxySourceItemID);
list = i.Axes.SelectItems(vcProxyFilterQuery).Select&lt;Item, string&gt;(x =&gt; x.ID.ToString()).ToArray();
cache.Insert(vcCacheKey, list, null, DateTime.Now.AddMinutes(10.0), System.Web.Caching.Cache.NoSlidingExpiration);
}
return list;
}
private string GetItemTimestamp(Item i)
{
ID[] fields = new ID[] { Sitecore.FieldIDs.Updated, Sitecore.FieldIDs.Created };
return Sitecore.DateUtil.IsoDateToDateTime(i.FieldCoalesce(fields).Value, DateTime.MinValue).ToString(&quot;yyyyMMddHHmmss&quot;);
}
private void GetProxyFilterInfo(ID proxyId, out ID ProxySourceItemID, out string vcProxyFilterQuery)
{
ProxySourceItemID = ID.Null;
vcProxyFilterQuery = string.Empty;
string sql = @&quot;select f.{0}FieldID{1}, f.{0}Value{1} from {0}Items{1} i inner join {0}Fields{1} f on f.{0}ItemId{1} = i.{0}ID{1} &quot; +
@&quot;where i.{0}ID{1} = {2}proxyId{3} and f.{0}FieldID{1} in ({2}queryFieldId{3}, {2}proxySourceItemFieldId{3})&quot;;

object[] parameters = new object[] { &quot;proxyId&quot;, proxyId,
&quot;queryFieldId&quot;, BaseIDs.ProxyFilter.Query,
&quot;proxySourceItemFieldId&quot;, Sitecore.FieldIDs.ProxySourceItem };

using (DataProviderReader reader = this.API.CreateReader(sql, parameters))
{
while (reader.Read())
{
ID id = this.API.GetId(0, reader);
if (id == Sitecore.FieldIDs.ProxySourceItem)
ProxySourceItemID = ID.Parse(this.API.GetString(1, reader));
else if (id == BaseIDs.ProxyFilter.Query)
vcProxyFilterQuery = this.API.GetString(1, reader);
}
}
}

private void RemoveShadow(ID shadowId)
{
string sql = &quot; DELETE FROM {0}Shadows{1} WHERE {0}ShadowID{1} = {2}shadowId{3}&quot;;
this.API.Execute(sql, new object[] { &quot;shadowId&quot;, shadowId });
}

}
}

</pre></p>
<p>2. Extend &#8220;ItemProvider&#8221; class</p>
<p><pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using Sitecore;
using Sitecore.Collections;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Data.Proxies;
using Sitecore.Diagnostics;
using Sitecore.Globalization;
using Sitecore.Layouts;
using Sitecore.SecurityModel;
using Sitecore.StringExtensions;

namespace Drexel.Data.Managers
{
    public class ItemProvider : Sitecore.Data.Managers.ItemProvider
    {
        public ItemProvider() : base() { }

        public override ChildList GetChildren(Item item, SecurityCheck securityCheck)
        {
            Assert.ArgumentNotNull(item, &quot;item&quot;);
            ItemList children = this.GetChildren(item);
            this.InsertVirtualChildren(children, item);
            children.RemoveAll(x =&gt; x == null); // remove nulls
            return new ChildList(item, this.ApplySecurity(children, securityCheck));
        }
    }
}
</pre></p>
<p>3. web.config changes..</p>
<p><pre class="brush: csharp;">
    &lt;proxyDataProviders&gt;
      &lt;main type=&quot;Drexel.Data.$(database).$(database)ProxyDataProvider, Sitecore.Drexel&quot;&gt;
        &lt;param connectionStringName=&quot;$(1)&quot; /&gt;
        &lt;Name&gt;$(1)&lt;/Name&gt;
      &lt;/main&gt;
      &lt;!--&lt;main type=&quot;Sitecore.Data.$(database).$(database)ProxyDataProvider, Sitecore.Kernel&quot;&gt;
        &lt;param connectionStringName=&quot;$(1)&quot; /&gt;
        &lt;Name&gt;$(1)&lt;/Name&gt;
      &lt;/main&gt;--&gt;
    &lt;/proxyDataProviders&gt;
...
 &lt;itemManager defaultProvider=&quot;default&quot;&gt;
      &lt;providers&gt;
        &lt;clear /&gt;
        &lt;add name=&quot;default&quot; type=&quot;Drexel.Data.Managers.ItemProvider, Sitecore.Drexel&quot; /&gt;
        &lt;!--&lt;add name=&quot;default&quot; type=&quot;Sitecore.Data.Managers.ItemProvider, Sitecore.Kernel&quot; /&gt;--&gt;
      &lt;/providers&gt;
    &lt;/itemManager&gt;
</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/125/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/125/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/125/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=125&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2011/06/30/sitecore-proxy-filter-poc-implementation/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Using cross site links.. aka dynamic links (part 2)</title>
		<link>http://sitecorepm.wordpress.com/2011/06/15/using-cross-site-links-aka-dynamic-links-part-2/</link>
		<comments>http://sitecorepm.wordpress.com/2011/06/15/using-cross-site-links-aka-dynamic-links-part-2/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 15:33:12 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Dynamic Links]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=105</guid>
		<description><![CDATA[Recently, it came to my attention that dynamic links were STILL not working properly on our websites! So I cracked open the Sitecore.Kernel.dll again to investigate&#8230; How it works now&#8230; The LinkBuilder.ResolveTargetSite method is responsible for determining what host name &#8230; <a href="http://sitecorepm.wordpress.com/2011/06/15/using-cross-site-links-aka-dynamic-links-part-2/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=105&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Recently, it came to my attention that dynamic links were STILL not working properly on our websites! So I cracked open the Sitecore.Kernel.dll again to investigate&#8230;</p>
<p><span style="text-decoration:underline;"><strong>How it works now&#8230;</strong></span></p>
<p>The LinkBuilder.ResolveTargetSite method is responsible for determining what host name to use if the requested item is outside the scope of the context site. To do this, it builds a &#8220;SiteResolvingTable&#8221; which consists of Dictionary object where the key is:</p>
<p style="padding-left:30px;">Site.RootPath + Site.StartItem</p>
<p>RootPath and StartItem come from the attribute values for each site as defined in your &lt;sites&gt; web.config section. The next step is to take the fullpath to the requested item and recursively chop off the last part of the path and try to match it up to one of the sites in the SiteResolvingTable. Like this:</p>
<p style="padding-left:30px;">Requested item: /sitecore/content/home/mysite/path1/path2/path3/myitem</p>
<ol style="padding-left:30px;">
<li>No match? Ok try: /sitecore/content/home/mysite/path1/path2/path3</li>
<li>No match? Ok try: /sitecore/content/home/mysite/path1/path2</li>
<li>No match? Ok try: /sitecore/content/home/mysite/path1</li>
<li>etc&#8230;</li>
</ol>
<p>When/if it finds a match, it takes the &#8220;TargetHostName&#8221; attribute (or &#8220;HostName&#8221; if there are no &#8216;*&#8217; or &#8216;|&#8217; characters in it) and builds the URL: http://TargetHostName/{ItemPath}.</p>
<p><span style="text-decoration:underline;"><strong>The problem&#8230;</strong></span></p>
<p>From the web.config documentation:</p>
<p><pre class="brush: csharp;">
/*
  rootPath: The path to the root item of the site.
            The item path specified in the URL will be appended to this value to find the item.

  startItem: The path to the start item of the site.
             This is used as the default item path if no path is specified in the URL.
             It will be combined with rootPath to find the default item of the site.
*/
</pre></p>
<p>So <span style="text-decoration:underline;">why is StartItem included in the SiteResolvingTable key</span>? It makes no sense to me&#8230; it must be a bug. The key should just be RootPath. No problem! We configuring &#8220;/&#8221; as the StartItem. The problem here is that all keys in the SiteResolvingTable will then end with &#8220;/&#8221;. The ItemPath logic above chops off the trailing slashes when recursing up the item path and so we&#8217;d never resolve any of our sites.</p>
<p><span style="text-decoration:underline;"><strong>UPDATE</strong></span>: I contacted Sitecore support about this issue and they are aware of the issue and have it registered as a bug. Read <a href="http://sdn.sitecore.net/Articles/Administration/Configuring%20Multiple%20Sites/Adding%20New%20Site/Internal%20Links.aspx">more about it here</a>. Still, if their suggested work-arounds do not work for you, read on&#8230;</p>
<p><span style="text-decoration:underline;"><strong>UPDATE 2</strong></span>: Sitecore support has informed me that  <em>&#8220;The issue is fixed in Sitecore 6.4.1 rev.110928. You can find the following entry in the <a href="http://sdn.sitecore.net/Products/Sitecore%20V5/Sitecore%20CMS%206/ReleaseNotes/ChangeLog/Release%20History%20SC64.aspx">Release Notes</a>.&#8221;</em></p>
<p>In the end, we decided to override Sitecore&#8217;s logic to build the SiteResolvingTable. I hate overriding things like this because eventually the overridden code will change (with new versions) and you start missing out on bug fixes. So hopefully they fix it and I can remove this. Here&#8217;s the custom LinkProvider we built:</p>
<p><pre class="brush: csharp;">
    ///
&lt;summary&gt; /// Extensions for the Sitecore.Links.LinkProvider class
 /// &lt;/summary&gt;
    public class LinkProvider : Sitecore.Links.LinkProvider
    {
        private delegate string KeyGetter(SiteInfo siteInfo);

        public override string GetItemUrl(Item item, UrlOptions options)
        {
            string itemUrl;

            options.SiteResolving = Sitecore.Configuration.Settings.Rendering.SiteResolving;

            // Use our custom LinkBuilder that fixes the SiteResolvingTable...
            var builder = new LinkBuilder(options);
            itemUrl = builder.GetItemUrl(item);

            return itemUrl;
        }

        private static string GetTargetHostName(SiteInfo siteInfo)
        {
            if (!siteInfo.TargetHostName.IsNullOrEmpty())
                return siteInfo.TargetHostName;

            string hostName = siteInfo.HostName;
            if (hostName.IndexOfAny(new char[] { '*', '|' }) &lt; 0)
                return hostName;

            return string.Empty;
        }

        public new class LinkBuilder : Sitecore.Links.LinkProvider.LinkBuilder
        {
            // Fields
            private readonly UrlOptions _options;
            private static Dictionary _siteResolvingTable;
            private static List _sites;
            private static readonly object _syncRoot;

            static LinkBuilder() { _syncRoot = new object(); }
            public LinkBuilder(UrlOptions options) : base(options) { _options = options; }

            protected override SiteInfo ResolveTargetSite(Item item)
            {
                SiteContext site = Context.Site;
                SiteContext context2 = this._options.Site ?? site;
                SiteInfo info = (context2 != null) ? context2.SiteInfo : null;
                if (!this._options.SiteResolving || (item.Database.Name == &quot;core&quot;))
                {
                    return info;
                }
                if ((this._options.Site != null) &amp;&amp; ((site == null) || (this._options.Site.Name != site.Name)))
                {
                    return info;
                }
                if ((context2 != null) &amp;&amp; item.Paths.FullPath.StartsWith(context2.StartPath))
                {
                    return info;
                }
                Dictionary siteResolvingTable = GetSiteResolvingTable();
                string key = item.Paths.FullPath.ToLower();
            Label_00AE:
                if (siteResolvingTable.ContainsKey(key))
                {
                    return siteResolvingTable[key];
                }
                int length = key.LastIndexOf(&quot;/&quot;);
                if (length &gt; 1)
                {
                    key = key.Substring(0, length);
                    goto Label_00AE;
                }
                return info;
            }

            private static Dictionary GetSiteResolvingTable()
            {
                List sites = SiteContextFactory.Sites;
                if (!object.ReferenceEquals(_sites, sites))
                {
                    lock (_syncRoot)
                    {
                        if (!object.ReferenceEquals(_sites, sites))
                        {
                            _sites = sites;
                            _siteResolvingTable = null;
                        }
                    }
                }
                if (_siteResolvingTable == null)
                {
                    lock (_syncRoot)
                    {
                        if (_siteResolvingTable == null)
                        {
                            _siteResolvingTable = BuildSiteResolvingTable(_sites);
                        }
                    }
                }
                return _siteResolvingTable;
            }

            private static Dictionary BuildSiteResolvingTable(IEnumerable sites)
            {
                Dictionary dictionary = new Dictionary();
                List list = new List();
                //KeyGetter[] getterArray = new KeyGetter[] { info =&gt; FileUtil.MakePath(info.RootPath, info.StartItem).ToLower() };
                KeyGetter[] getterArray = new KeyGetter[] { info =&gt; info.RootPath.ToLower() };
                foreach (KeyGetter getter in getterArray)
                {
                    foreach (SiteInfo info in sites)
                    {
                        if (!string.IsNullOrEmpty(info.HostName) &amp;&amp; string.IsNullOrEmpty(GetTargetHostName(info)))
                        {
                            Sitecore.Diagnostics.Log.Warn(&quot;LinkBuilder. Site '{0}' should have defined 'targethostname' property in order to take participation in site resolving process.&quot;.FormatWith(new object[] { info.Name }), typeof(LinkProvider.LinkBuilder));
                        }
                        //else if ((!string.IsNullOrEmpty(GetTargetHostName(info)) &amp;&amp; !string.IsNullOrEmpty(info.RootPath)) &amp;&amp; !string.IsNullOrEmpty(info.StartItem))
                        else if (!string.IsNullOrEmpty(GetTargetHostName(info)) &amp;&amp; !string.IsNullOrEmpty(info.RootPath))
                        {
                            string key = getter(info);
                            if (!list.Exists(new Predicate(key.StartsWith)))
                            {
                                dictionary.Add(key, info);
                                list.Add(key);
                            }
                        }
                    }
                }

                return dictionary;
            }
        }
    }
</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/105/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/105/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/105/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=105&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2011/06/15/using-cross-site-links-aka-dynamic-links-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Adding custom parameters to the log</title>
		<link>http://sitecorepm.wordpress.com/2011/02/17/adding-custom-parameters-to-the-log/</link>
		<comments>http://sitecorepm.wordpress.com/2011/02/17/adding-custom-parameters-to-the-log/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 16:25:35 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Log4Net]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=99</guid>
		<description><![CDATA[Sometimes it is difficult to troubleshoot errors in Sitecore&#8217;s standard log file due to the lack of some key pieces of information&#8230; namely: context user, context item id and the raw requested url. However, since Sitecore uses Log4Net, we can &#8230; <a href="http://sitecorepm.wordpress.com/2011/02/17/adding-custom-parameters-to-the-log/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=99&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Sometimes it is difficult to troubleshoot errors in Sitecore&#8217;s standard log file due to the lack of some key pieces of information&#8230; namely: context user, context item id and the raw requested url. However, since Sitecore uses Log4Net, we can easily inject this information into our log entries. <a href="http://sitecoreblog.alexshyba.com/2010/07/sitecore-logging-part-3-adding-custom.html">Alex Shyba has a great post</a> that details exactly how to get this information into your logs&#8230; IF you are logging to a SQL database that is.</p>
<p>In my case, I wanted to just add this information into the existing (default) LogFileAppender. To do this, I extended Sitecore&#8217;s &#8220;SitecoreLogFileAppender&#8221; class as follows:</p>
<p><pre class="brush: csharp;">
public class SitecoreLogFileAppenderEx : log4net.Appender.SitecoreLogFileAppender
{
    protected override void Append(LoggingEvent loggingEvent)
    {
        var properties = loggingEvent.Properties;

        properties[&quot;scuser&quot;] = string.Empty;
        properties[&quot;scitemid&quot;] = string.Empty;
        properties[&quot;rawurl&quot;] = string.Empty;

        // Only log ERRORS or higher level events
        if (Sitecore.Context.Site != null &amp;&amp; loggingEvent.Level &gt;= Level.ERROR)
        {
            if (Sitecore.Context.User != null)
                try { properties[&quot;scuser&quot;] = Sitecore.Context.User.Name; }
                catch { }
            if (Sitecore.Context.Item != null)
                try { properties[&quot;scitemid&quot;] = Sitecore.Context.Item.ID.ToString(); }
                catch { }

            try { properties[&quot;rawurl&quot;] = Sitecore.Web.WebUtil.GetServerUrl() + Sitecore.Web.WebUtil.GetRawUrl(); }
            catch { }
        }
        base.Append(loggingEvent);
    }
}
</pre></p>
<p>Then i modified the web.config log4net configuration to use my appender and added the custom properties to the PatternLayout as follows.:</p>
<p><pre class="brush: xml;">
		&lt;appender name=&quot;LogFileAppender&quot; type=&quot;log4net.Appender.SitecoreLogFileAppenderEx, Sitecore.Drexel.Logging&quot;&gt;
			&lt;file value=&quot;$(dataFolder)/logs/log.{date}.txt&quot;/&gt;
			&lt;appendToFile value=&quot;true&quot;/&gt;
			&lt;layout type=&quot;log4net.Layout.PatternLayout&quot;&gt;
				&lt;conversionPattern value=&quot;%4t %d{ABSOLUTE} %-5p %c [%P{scuser} %P{scitemid} %P{rawurl}] %m%n&quot;/&gt;
			&lt;/layout&gt;
		&lt;/appender&gt;
</pre></p>
<p>It is important to note that when specifying the parameters in the PatternLayout, you must use a capital &#8220;P&#8221;.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/99/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/99/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/99/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=99&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2011/02/17/adding-custom-parameters-to-the-log/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Dealing with multiple iFrame fields</title>
		<link>http://sitecorepm.wordpress.com/2011/01/05/dealing-with-multiple-iframe-fields/</link>
		<comments>http://sitecorepm.wordpress.com/2011/01/05/dealing-with-multiple-iframe-fields/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 19:07:55 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Drexel]]></category>
		<category><![CDATA[Field Types]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=92</guid>
		<description><![CDATA[The iFrame field type allows you to create your own GUI for a particular sitecore field. You create a UserControl and reference it with your iFrame field. Good so far! By default, Sitecore will pass some parameters to your UserControl &#8230; <a href="http://sitecorepm.wordpress.com/2011/01/05/dealing-with-multiple-iframe-fields/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=92&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>The iFrame field type allows you to create your own GUI for a particular sitecore field. You create a UserControl and reference it with your iFrame field.</p>
<p>Good so far! By default, Sitecore will pass some parameters to your UserControl page (taken right from the <a href="http://sdn.sitecore.net/Reference/Sitecore%206/Client%20Configuration%20Cookbook.aspx"> sitecore documentation</a>):</p>
<ul>
<li>id &#8211; The GUID of the item selected by the user.</li>
<li>la &#8211; The language code selected by the user.</li>
<li>vs &#8211; The version number selected by the user.</li>
</ul>
<p>Super! What if i have multiple iFrame fields on my item that point to the same UserControl though? What&#8217;s missing? How about what field am I supposed to be loading from.</p>
<p>This isn&#8217;t really a big deal though because the iFrame field type also allows you to specify extra parameters when you set the URL to your UserControl in the field data source. I pass an extra &#8220;?field=my-field-name&#8221; parameter to the end of my iFrame data source when necessary to avoid this issue. Then in the Page_Load of my UserControl I can use it like so:</p>
<p><pre class="brush: csharp;">

if (!IsPostBack)
{
Database db = Factory.GetDatabase(&quot;master&quot;);
Item myItem = db.GetItem(Request.Params[&quot;id&quot;]);
string fieldvalue = myItem[Request.Params[&quot;field&quot;]];

// ...
// code to load my control with &quot;fieldvalue&quot;
// ...

}

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/92/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/92/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/92/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=92&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2011/01/05/dealing-with-multiple-iframe-fields/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Datasets and DatasetRenderers</title>
		<link>http://sitecorepm.wordpress.com/2010/12/08/datasets-and-datasetrenderers/</link>
		<comments>http://sitecorepm.wordpress.com/2010/12/08/datasets-and-datasetrenderers/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 13:11:14 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Custom Component]]></category>
		<category><![CDATA[DatasetRenderer]]></category>
		<category><![CDATA[Datasets]]></category>
		<category><![CDATA[Drexel]]></category>
		<category><![CDATA[Sharepoint]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=75</guid>
		<description><![CDATA[In my experience, a good portion of custom Sitecore component requests are for components that display a &#8220;set of data&#8221; on a page. The set of data could be a manually selected list of sitecore items or perhaps the result &#8230; <a href="http://sitecorepm.wordpress.com/2010/12/08/datasets-and-datasetrenderers/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=75&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In my experience, a good portion of custom Sitecore component requests are for components that display a &#8220;set of data&#8221; on a page. The set of data could be a manually selected list of sitecore items or perhaps the result set of a sitecore query, or even data set from an external system. No matter the source, a custom component is usually needed to build that data set and then render it to the page in some custom fashion.</p>
<p>Having dealt with many requests for this type of component, I decided it would be worth the time to try coming up with a more generic solution. What I came up with was the concept of &#8220;Datasets&#8221; and &#8220;DatasetRenderers&#8221;. What follows in this post is a super-high-level-overview of what &#8220;Datasets&#8221; and &#8220;DatasetRenderers&#8221; have become&#8230;</p>
<p>In the typical custom component scenario you have a custom control and possibly a specific item type for storing extra rendering information. In a &#8220;Dataset&#8221; scenario there are always 3 pieces: the Dataset item, the DatasetRenderer item, and the DatasetRenderer control.</p>
<p>The “Dataset item&#8221; is used to specify the set of data we are working with, but NOT how that data gets rendered. There are currently 4 types of Datasets:</p>
<ul>
<li>ItemsQuery – sitecore query</li>
<li>StaticItemSet – manually choose sitecore items (TreelistEx)</li>
<li>DatabaseQuery – SQL query against an external data source</li>
<li>SharepointQuery – web services query against a Sharepoint list or view</li>
</ul>
<p>The “DatasetRenderer item&#8221; contains all the rendering information necessary to display data for the parent Dataset. A DatasetRenderer item is always the child of a Dataset item. A Dataset item may have more than one child DatasetRenderer.</p>
<p>The &#8220;DatasetRenderer control&#8221; is a server control that points to a DatasetRenderer item as it&#8217;s data source. It understands how to interpret the rendering information on the DatasetRenderer Item and apply it to the data from the Dataset.</p>
<p>At this point, I&#8217;m sure this is clear as mud&#8230; so how about a sample. A real, working, live sample in fact, from: <a href="http://drexel.edu/irt/help/workshops/">http://drexel.edu/irt/help/workshops/</a></p>
<p><a href="http://sitecorepm.files.wordpress.com/2010/12/sampledatasetusage.jpg"><img class="alignnone size-full wp-image-81" title="SampleDatasetUsage" src="http://sitecorepm.files.wordpress.com/2010/12/sampledatasetusage.jpg?w=640&#038;h=407" alt="" width="640" height="407" /></a></p>
<p>This page on Drexel&#8217;s website is used to provide information about upcoming workshops, demos, and training. Each of the tables on the page are dynamically populated with data from a single Sharepoint list. In the &#8220;Presentation Details&#8221; for the /irt/help/workshops item there are several DatasetRenderer controls (one for each table) each pointing to a DatasetRenderer item.</p>
<p><a href="http://sitecorepm.files.wordpress.com/2010/11/sharepointquery.jpg"><img class="alignnone size-full wp-image-79" title="SharepointQuery" src="http://sitecorepm.files.wordpress.com/2010/11/sharepointquery.jpg?w=640&#038;h=640" alt="" width="640" height="640" /></a></p>
<p>The &#8220;WorkshopsList&#8221; is a SharepointQuery dataset with several child DatasetRenderer items. I&#8217;m not going to go into any detail about the parameters in this post but you can see there are several parameters for a SharepointQuery dataset. Next, let&#8217;s take a look at what the &#8220;BbVista&#8221; datasetrenderer item looks like&#8230;</p>
<p><a href="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrenderer.jpg"><img class="alignnone size-full wp-image-82" title="WorkshoplistDatasetRenderer" src="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrenderer.jpg?w=640&#038;h=454" alt="" width="640" height="454" /></a></p>
<p><a href="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrenderer.jpg"></a>There are many more options than can be easily captured in a single screen shot so the above image only shows the most important fields.</p>
<ul>
<li>&#8220;List Item Fields&#8221; &#8211; contains all the available fields in the underlying dataset.</li>
<li>&#8220;List Item Template&#8221; &#8211; defines what HTML is output for each row in the dataset</li>
<li>&#8220;Alternating List Item Template&#8221; &#8211; allows you to define different output for alternating rows</li>
</ul>
<p>When the DatasetRenderer above was first created, all the fields except &#8220;List Item Fields&#8221; were empty. The user decided they wanted to output the contents of the dataset into a HTML table. They entered the HTML in the fields as shown using the &#8220;List Item Fields&#8221; field as a reference to choose fields to place in the &#8220;List Item Template&#8221; field with the syntax [fieldname], such as the [Start Date] field. There is quite a bit more functionality available in the template fields (like the @formatdate function) but that&#8217;s for another post.</p>
<p><span style="font-family:Georgia, 'Bitstream Charter', serif;line-height:24px;font-size:16px;">At this point you might ask&#8230; &#8220;Isn&#8217;t it a bad idea to allow the end user direct access to the output HTML?&#8221; Yes, but no more dangerous than a native Sitecore RichText field. Ultimately, if end users want to abuse the system&#8230; they find a way.</span></p>
<p>The extra tabs available at the top, Dataset (preview) and Output (preview) are particular useful for users. The Dataset (preview) tab shows a no frills asp.net datagrid of the raw data in the dataset.</p>
<p><span style="font-family:Georgia, 'Bitstream Charter', serif;line-height:24px;font-size:16px;"><a href="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendererdspreview.jpg"><img class="alignnone size-full wp-image-83" title="WorkshoplistDatasetRendererdsPreview" src="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendererdspreview.jpg?w=640&#038;h=152" alt="" width="640" height="152" /></a><br />
</span></p>
<p><span style="font-family:Georgia, 'Bitstream Charter', serif;line-height:24px;font-size:16px;">The Output (preview) table shows the html output of the DatasetRenderer.</span></p>
<p><span style="font-family:Georgia, 'Bitstream Charter', serif;line-height:24px;font-size:16px;"><a href="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendereroutputpreview.jpg"><img class="alignnone size-full wp-image-84" title="WorkshoplistDatasetRendererOutputPreview" src="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendereroutputpreview.jpg?w=640&#038;h=403" alt="" width="640" height="403" /></a></span></p>
<p>I think this is a fine place to stop with the high level overview of what Datasets &amp; DatasetRenderers are. There is really too much information (caching, @functions, renderer fields, etc&#8230;) for me to try covering in a single post and I&#8217;d rather wait to see if there are any interested Sitecore enthusiasts out there before posting more or perhaps even turning this into a Shared Source project (of course I&#8217;d need to get approval from &#8220;powers that be&#8221; before that could happen).</p>
<p>Happy coding!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/75/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/75/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/75/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=75&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2010/12/08/datasets-and-datasetrenderers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/12/sampledatasetusage.jpg" medium="image">
			<media:title type="html">SampleDatasetUsage</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/11/sharepointquery.jpg" medium="image">
			<media:title type="html">SharepointQuery</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrenderer.jpg" medium="image">
			<media:title type="html">WorkshoplistDatasetRenderer</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendererdspreview.jpg" medium="image">
			<media:title type="html">WorkshoplistDatasetRendererdsPreview</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/12/workshoplistdatasetrendereroutputpreview.jpg" medium="image">
			<media:title type="html">WorkshoplistDatasetRendererOutputPreview</media:title>
		</media:content>
	</item>
		<item>
		<title>Using Webdev.WebServer.exe instead of IIS</title>
		<link>http://sitecorepm.wordpress.com/2010/09/28/using-webdev-webserver-exe-instead-of-iis/</link>
		<comments>http://sitecorepm.wordpress.com/2010/09/28/using-webdev-webserver-exe-instead-of-iis/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 14:42:10 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=69</guid>
		<description><![CDATA[I use my development machine for other ASP.NET projects besides just Sitecore components, so going with the standard &#8220;make Sitecore your default IIS site&#8221; was sort of a pain when i needed IIS for other things. So, I decided to &#8230; <a href="http://sitecorepm.wordpress.com/2010/09/28/using-webdev-webserver-exe-instead-of-iis/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=69&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I use my development machine for other ASP.NET projects besides just Sitecore components, so going with the standard &#8220;make Sitecore your default IIS site&#8221; was sort of a pain when i needed IIS for other things. So, I decided to make it run with Visual Studios web server (Webdev.WebServer.exe). I put together a little batch file to do all the fun stuff for me&#8230;</p>
<p><pre class="brush: powershell;">

taskkill /f /im Webdev.WebServer.exe
cmd /c start /D&quot;C:\Program Files\Common Files\microsoft shared\DevServer\9.0\&quot; Webdev.WebServer.exe /port:81 /path:&quot;c:\&lt;path-to-your-sitecore-website&gt;\WebSite&quot;
ping 127.0.0.1 -n 3 -w 1000 &gt; nul
cmd /c start /D&quot;C:\Program Files\Internet Explorer\&quot; iexplore.exe http://localhost:81/sitecore

</pre></p>
<p>This script does the following:</p>
<ol>
<li>Kills any running Dev webserver instances</li>
<li>Starts a new Dev webserver instance running your sitecore website</li>
<li>Waits a few seconds (for the webserver to spin up)</li>
<li>Opens Internet Explorer to the sitecore website</li>
</ol>
<p>So after I run this batch file, I then attach to the WebDev.WebServer process and start debugging (actually, i use a VS macro for this). That&#8217;s it!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/69/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/69/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/69/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=69&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2010/09/28/using-webdev-webserver-exe-instead-of-iis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Using cross site links.. aka dynamic links (part 1)</title>
		<link>http://sitecorepm.wordpress.com/2010/08/04/using-cross-site-links-dynamic-links/</link>
		<comments>http://sitecorepm.wordpress.com/2010/08/04/using-cross-site-links-dynamic-links/#comments</comments>
		<pubDate>Wed, 04 Aug 2010 15:49:43 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Dynamic Links]]></category>
		<category><![CDATA[LinkManager]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=53</guid>
		<description><![CDATA[When you have multiple sites defined in Sitecore and you use LinkManager to get the URL to items in your site, all is well. Trouble arises however when you want a link to an item outside of the context site. &#8230; <a href="http://sitecorepm.wordpress.com/2010/08/04/using-cross-site-links-dynamic-links/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=53&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>When you have multiple sites defined in Sitecore and you use LinkManager to get the URL to items in your site, all is well. Trouble arises however when you want a link to an item outside of the context site. For example, if you have a sitecore content tree and site config like:</p>
<ul>
<li>/sitecore/content/Home
<ul>
<li>SiteA
<ul>
<li>ItemA1</li>
</ul>
</li>
<li>SiteB
<ul>
<li>ItemB1</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>If you had a custom control on SiteA that used LinkManager.GetItemURL(ItemB1), the return URL would be something like:</p>
<p style="padding-left:30px;"><a href="http://www.SiteA.com/sitecore/content/home/SiteB/ItemB1">www.SiteA.com/sitecore/content/home/SiteB/ItemB1</a></p>
<p>when what you really want is:</p>
<p style="padding-left:30px;"><a href="http://www.SiteB.com/ItemB1">www.SiteB.com/ItemB1</a></p>
<p>Several people in my group searched high and low for a Sitecore configuration that would result in exactly that. After much research, it seemed that the undocumented &#8220;SiteResolving&#8221; setting is what we needed.</p>
<p>To get SiteResolving to work, you need to:</p>
<ol>
<li>Set the targetHostName on the desired site config entries</li>
<li>When calling LinkManager.GetItemUrl, pass in UrlOptions with UrlOptions.SiteResolving=true.</li>
</ol>
<p>It seems that if targetHostName is set and UrlOptions.SiteResolving=true, then when a GetItemUrl request is made to the LinkProvider it will check whether the requested item is a descendant of the context site. If not, then the SiteResolving logic kicks in. This logic takes the requested item path and recursively chops off the last part of the path until a match is found. The match is against the site config’s RootPath+StartItem. If a match is found, that site’s targetHostName is used when generating the URL.</p>
<p>However, the trickiness is really setting UrlOptions.SiteResolving to true, unless you are going to remember to explicitly set this each time you call LinkManager.GetItemUrl. You would think adding the following web.config setting would do the trick:</p>
<p>&lt;setting name=&#8221;Rendering.SiteResolving&#8221; value=&#8221;true&#8221; /&gt;</p>
<p>But the neither the LinkProvider code nor the default UrlOptions seem to use this. So, in order to get this to work, I just added the following code to my custom LinkProvider:</p>
<p><pre class="brush: csharp;">

public class LinkProvider : Sitecore.Links.LinkProvider

{

public override string GetItemUrl(Item item, UrlOptions options)

{

string itemUrl;

//other code

options.SiteResolving = Sitecore.Configuration.Settings.Rendering.SiteResolving;

itemUrl = base.GetItemUrl(item, options);

//other code

return itemUrl;

}

}

}

</pre></p>
<p>Thanks to <a href="http://mikecaseycms.blogspot.com/">Mike Casey</a> for helping find this solution.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/53/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/53/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/53/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=53&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2010/08/04/using-cross-site-links-dynamic-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Build a FieldIDs class for your own template fields</title>
		<link>http://sitecorepm.wordpress.com/2010/06/02/build-a-fieldids-class-for-your-own-template-fields/</link>
		<comments>http://sitecorepm.wordpress.com/2010/06/02/build-a-fieldids-class-for-your-own-template-fields/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 14:02:35 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[FieldIDs]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=39</guid>
		<description><![CDATA[A while back I posted on the SDN forums about some code I pieced together which dynamically builds a FieldIDs class from your own custom templates. So now that I&#8217;m a &#8220;blogger&#8221;, I&#8217;m just reposting it here &#8230; I built &#8230; <a href="http://sitecorepm.wordpress.com/2010/06/02/build-a-fieldids-class-for-your-own-template-fields/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=39&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A while back I <a href="http://sdn.sitecore.net/forum//ShowPost.aspx?PostID=13084">posted on the SDN forums</a> about some code I pieced together which dynamically builds a FieldIDs class from your own custom templates. So now that I&#8217;m a &#8220;blogger&#8221;, I&#8217;m just reposting it here <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>&#8230;</p>
<p>I built a Sitecore command (usable from the &#8220;MyToolbar&#8221; in Content Editor) that dynamically builds a DLL containing my sites template field IDs (just like Sitecore.FieldIDs in the Sitecore.Kernel) mapped to string constants.</p>
<p>Why? Well the reason for creating the DLL can be found in <a href="http://sdn.sitecore.net/forum//ShowPost.aspx?PostID=12924">this post</a> and I made it dynamic so I wouldn&#8217;t have to maintain this library every time we decided to change a template&#8230;. and just to see if i could.</p>
<p>Code at the end of this post contains the class that does the creation/compiling. Beyond that, there are a few steps to get it up as a command. There may be some extra or unnecessary steps (let me know), but this is what I did.</p>
<p>1. Put the class code in and build your own class library (sitecore.foo.dll)<br />
2. In Commands.config for your Sitecore installation, add an entry that references this DLL</p>
<p>&lt;command name=&#8221;foo:buildfieldids&#8221; type=&#8221;MyNamespace.Commands.FieldIDsGenerator,sitecore.foo&#8221; /&gt;</p>
<p>3. Now we need to add the ribbon button. Go into the Sitecore Core Database content editor.<br />
4. Create a new chunk item (for this example called: MyChunk) in /sitecore/content/Applications/Content Editor/Ribbons/Chunks<br />
5. In MyChunk create a button item. Choose the header: &#8220;Generate FieldIDs DLL&#8221; and icon. In &#8220;Click&#8221; put &#8220;foo:buildfieldids&#8221;.<br />
6. Right click on the ribbon in content editor. Enable &#8220;My Toolbar&#8221; and choose &#8220;Customize&#8221;<br />
7. Find your MyChunk and add the new button to the toolbar<br />
8. Finally, in web.config for the Sitecore installation add these appSettings:<br />
    &lt;add key=&#8221;FieldIDsGenerator.DLLName&#8221; value=&#8221;Sitecore.MyNamespace.FieldIDs&#8221;/&gt;<br />
    &lt;add key=&#8221;FieldIDsGenerator.Namespace&#8221; value=&#8221;MyNamespace.FieldIDs&#8221;/&gt;<br />
    &lt;add key=&#8221;FieldIDsGenerator.RootTemplateQuery&#8221; value=&#8221;/sitecore/Templates/MyTemplates/*&#8221;/&gt;</p>
<p>Done. Try clicking the new button and take a look at the generated code.</p>
<p>Sample usage:</p>
<p><pre class="brush: csharp;">
using IDs = MyNamespace.FieldIDs;

public partial class Generic_Page : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Page.Title = Sitecore.Context.Item[IDs.TemplateName.FieldName];
    }
}
</pre></p>
<p>Hope this helps.<br />
Feel free to suggest improvements and/or ridicule me as you see fit <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>The code&#8230;</p>
<p><pre class="brush: csharp;">using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Text.RegularExpressions;
using Sitecore.Collections;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Data.Fields;
using Sitecore.Shell.Framework.Commands;
using Sitecore.Diagnostics;
using System.Linq;

namespace YourCompany.Commands
{
    /// &lt;summary&gt;
    /// Command that dynamically builds &amp; compiles the Sitecore.YourCompany.FieldIDs.dll
    /// and places it in the bin of the current sitecore installation.
    /// &lt;/summary&gt;
    [Serializable]
    public class FieldIDsGenerator : Command
    {
        Regex _rgxCleanName = new Regex(@&quot;[\W]*&quot;);

        // Methods
        public override void Execute(CommandContext context)
        {
            try
            {
                BuildFieldIDsDLL();
                Sitecore.Context.ClientPage.ClientResponse.Alert(&quot;Successfully rebuilt DLL&quot;);
            }
            catch (Exception ex)
            {
                Sitecore.Context.ClientPage.ClientResponse.Alert(&quot;Error: &quot; + ex.Message);
            }
        }

        public override CommandState QueryState(CommandContext context)
        {
            Error.AssertObject(context, &quot;context&quot;);
            if (!Sitecore.Context.IsAdministrator)
            {
                return CommandState.Disabled;
            }
            return base.QueryState(context);
        }

        private void BuildFieldIDsDLL()
        {
            string dllName = ConfigurationManager.AppSettings[&quot;FieldIDsGenerator.DLLName&quot;];
            string baseNamespace = ConfigurationManager.AppSettings[&quot;FieldIDsGenerator.Namespace&quot;];
            string templateQuery = ConfigurationManager.AppSettings[&quot;FieldIDsGenerator.RootTemplateQuery&quot;];

            // Create the DLL in the Sitecore/bin directory
            Directory.SetCurrentDirectory(Sitecore.Install.Files.PathUtils.MapPath(&quot;/bin&quot;));

            // Creates a text file to store the new class
            using (StreamWriter sr = File.CreateText(dllName + &quot;.cs&quot;))
            {
                sr.WriteLine(&quot;using System;&quot;);
                sr.WriteLine(&quot;using Sitecore.Data;&quot;);
                sr.WriteLine(&quot;&quot;);
                sr.WriteLine(&quot;namespace &quot; + baseNamespace);
                sr.WriteLine(&quot;{&quot;);
                Item[] items = Sitecore.Context.ContentDatabase.SelectItems(templateQuery);
                foreach (Item item in items)
                {
                    BuildTemplateFieldIDClass(sr, item);
                }

                sr.WriteLine(&quot;}&quot;);
            }

            // Create C# compiler
            CSharpCodeProvider csc = new CSharpCodeProvider();
            ICodeCompiler icc = csc.CreateCompiler();

            // input params for the compiler
            CompilerParameters co = new CompilerParameters();
            co.OutputAssembly = dllName + &quot;.dll&quot;;
            co.ReferencedAssemblies.Add(&quot;system.dll&quot;);
            co.ReferencedAssemblies.Add(&quot;Sitecore.Kernel.dll&quot;);

            // generate a DLL
            co.GenerateExecutable = false;

            // Run the compiler
            icc.CompileAssemblyFromFile(co, dllName + &quot;.cs&quot;);
        }

        private void BuildTemplateFieldIDClass(StreamWriter sr, Item item)
        {

            string className = _rgxCleanName.Replace(item.Name, &quot;&quot;);
            string memberName = null;

            switch (item.Template.Name)
            {
                case &quot;Template Folder&quot;:

                    // Write the namespace...
                    sr.WriteLine(&quot;namespace &quot; + className);
                    sr.WriteLine(&quot;{&quot;);

                    // Build base template classes
                    ChildList children = item.GetChildren();
                    foreach (Item child in children)
                    {
                        BuildTemplateFieldIDClass(sr, child);
                    }

                    // End the namespace...
                    sr.WriteLine(&quot;}&quot;);

                    break;

                // Check if class has already been created and it has it's own fields
                case &quot;Template&quot;:

                    TemplateItem ti = (TemplateItem)item;

                    if (ti.OwnFields.Length &gt; 0)
                    {
                        // Write the class...
                        sr.WriteLine(&quot;public static class &quot; + className);
                        sr.WriteLine(&quot;{&quot;);

                        // Write the class members...
                        foreach (TemplateFieldItem tfi in ti.OwnFields)
                        {
                            sr.Write(&quot;\tpublic static ID &quot;);

                            memberName = _rgxCleanName.Replace(tfi.Name, &quot;&quot;);
                            if (className == memberName) memberName = &quot;_&quot; + memberName;

                            sr.Write(memberName);
                            sr.Write(&quot; = new ID(\&quot;&quot;);
                            sr.Write(tfi.ID.ToString());
                            sr.Write(&quot;\&quot;);\n&quot;);
                        }

                        // End the class...
                        sr.WriteLine(&quot;}&quot;);

                    }
                    break;
            }
        }
    }
}

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/39/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=39&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2010/06/02/build-a-fieldids-class-for-your-own-template-fields/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>
	</item>
		<item>
		<title>Sitecore Proxy Filter</title>
		<link>http://sitecorepm.wordpress.com/2010/05/27/sitecore-proxy-filter/</link>
		<comments>http://sitecorepm.wordpress.com/2010/05/27/sitecore-proxy-filter/#comments</comments>
		<pubDate>Thu, 27 May 2010 14:53:22 +0000</pubDate>
		<dc:creator>Paul Martin</dc:creator>
				<category><![CDATA[Proxy Items]]></category>
		<category><![CDATA[Sitecore]]></category>

		<guid isPermaLink="false">http://sitecorepm.wordpress.com/?p=30</guid>
		<description><![CDATA[Let me just preface this with the fact that this idea/solution was really just a proof of concept. Additionally, the next major release of Sitecore (MASSIVE&#8230; yes, i&#8217;m pretty sure it has to be all caps) will have a much &#8230; <a href="http://sitecorepm.wordpress.com/2010/05/27/sitecore-proxy-filter/">Continue reading <span class="meta-nav">&#8594;</span></a><img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=30&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Let me just preface this with the fact that this idea/solution was really just a proof of concept. Additionally, the next major release of Sitecore (MASSIVE&#8230; yes, i&#8217;m pretty sure it has to be all caps) will have a much more flexible way to deal with virtual items.</p>
<p>But until then&#8230;</p>
<p>Proxy Items in Sitecore would be really useful if there was more flexibility as to which Items are &#8220;proxied&#8221;. With the current design, there are only a few options regarding which items to shadow: 1 item, all the children of a target item, or all descendants under a target item. That&#8217;s great and all, but it would be more useful (at least for the cases I need it) if you could somehow specify a subset of items under a target item. With this need in mind, I pieced together ProxyFilter.</p>
<p style="text-align:center;"> <a href="http://sitecorepm.files.wordpress.com/2010/05/proxyfilter.jpg"><img class="size-full wp-image-31 aligncenter" title="proxyfilter" src="http://sitecorepm.files.wordpress.com/2010/05/proxyfilter.jpg?w=640&#038;h=380" alt="" width="640" height="380" /></a></p>
<p>I added the ProxyFilter section to the Proxy template with a field called “Query”. In this field, you enter a sitecore query you would like used to filter the virtual items that the proxy points to. This all works by extending the “SqlServerProxyDataProvider” class… along with a small extension to “ItemProvider”.  I&#8217;m not going to go into <a href="http://sitecorepm.wordpress.com/2011/06/30/sitecore-proxy-filter-poc-implementation/">the code</a> here unless someone actually wants it because as I said above, this was more a proof of concept and it will most likely become unnessary with Sitecore&#8217;s MASSIVE release.</p>
<p>ProxyFilter in action&#8230; On the left, is the set of virtual items you get setting up a regular Proxy item. On the right, is the filtered subset of virtual items created as a result of the ProxyFilter settings in the screenshot above.</p>
<p style="padding-left:180px;"> </p>
<p style="text-align:center;"><a href="http://sitecorepm.files.wordpress.com/2010/05/proxyfiltersample.jpg"><img class="size-full wp-image-34 aligncenter" title="proxyfiltersample" src="http://sitecorepm.files.wordpress.com/2010/05/proxyfiltersample.jpg?w=640" alt=""   /></a></p>
<p>One issue I did notice was that the ProxyProvider contains a ProxyCache object which among other things stores VirtualIds. But it seems to store them indefinitely. The reason this is bad is that when I update the Proxy item.. say to point to a different source item, it doesn’t update the virtual items until the cache is cleared.</p>
<p>And there you have it&#8230; ProxyFilter.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/sitecorepm.wordpress.com/30/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/sitecorepm.wordpress.com/30/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/sitecorepm.wordpress.com/30/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=sitecorepm.wordpress.com&amp;blog=13377405&amp;post=30&amp;subd=sitecorepm&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://sitecorepm.wordpress.com/2010/05/27/sitecore-proxy-filter/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/719d731d424af9b2fa60d0c53d15d060?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">sitecorepm</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/05/proxyfilter.jpg" medium="image">
			<media:title type="html">proxyfilter</media:title>
		</media:content>

		<media:content url="http://sitecorepm.files.wordpress.com/2010/05/proxyfiltersample.jpg" medium="image">
			<media:title type="html">proxyfiltersample</media:title>
		</media:content>
	</item>
	</channel>
</rss>
