<?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/"
	>

<channel>
	<title>Rohland de Charmoy</title>
	<atom:link href="http://www.rohland.co.za/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rohland.co.za</link>
	<description>Pushing buttons...</description>
	<lastBuildDate>Mon, 16 Aug 2010 07:22:57 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ordering pizza online &#8211; baking the code that made it happen</title>
		<link>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/</link>
		<comments>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 14:13:37 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Spark]]></category>
		<category><![CDATA[Workflow 4]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=217</guid>
		<description><![CDATA[For the past 2-3 months <a href="http://www.clyral.com/web/pages/team" target="_blank">we</a> have been working hard to deliver (no pun intended) an online ordering system for Debonairs. Basically, we we were tasked to produce a <a href="http://www.debonairs.co.za" target="_blank">website</a> and <a href="http://debonairs.mobi" target="_blank">mobi site</a> which would enable Debonairs' customers to order a pizza using their favourite internet browser. The sites went live a few weeks ago and  I thought it would be useful to put together a short blog post describing the solution from a technical perspective.]]></description>
			<content:encoded><![CDATA[<p>For the past 2-3 months <a href="http://www.clyral.com/web/pages/team" target="_blank">we</a> have been working hard to deliver (no pun intended) an online ordering system for Debonairs. Basically, we we were tasked to produce a <a href="http://www.debonairs.co.za" target="_blank">website</a> and <a href="http://debonairs.mobi" target="_blank">mobi site</a> which would enable Debonairs&#8217;s customers to order a pizza using their favourite internet browser. The sites went live a few weeks ago and  I thought it would be useful to put together a short blog post describing the solution from a technical perspective.</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/08/Debonairs.png"><img src="http://www.rohland.co.za/wp-content/uploads/2010/08/Debonairs.png" alt="Debonairs Pizza" title="Debonairs Pizza" width="550" height="94" class="aligncenter size-full wp-image-273" /></a></p>
<p>Both the website and mobi site were developed using Microsoft&#8217;s <a href="http://www.asp.net/mvc" target="_blank">ASP .NET MVC 2.0</a> framework with some slight modifications to the vanilla setup. We chose to use <a href="http://www.sparkviewengine.com/" target="_blank">Spark</a> as our view engine. Spark&#8217;s syntax is declarative and resembles HTML which enables us to integrate code seamlessly (i.e. our views don&#8217;t evolve into <a href="http://en.wikipedia.org/wiki/Spaghetti_code" target="_blank">spaghetti code</a>). This is not the sole advantage of using Spark, I would recommend taking a read through the <a href="http://www.sparkviewengine.com/book" target="_blank">documentation</a> to realise the more important benefits. This is not the first project we&#8217;ve integrated Spark with, and we continue to enjoy working with it. </p>
<p>In terms of client side scripting, we used <a href="http://jquery.com/" target="_blank">jQuery</a> as our JavaScript library. <a href="http://combres.codeplex.com/" target="_blank">Combres</a> (an open source project hosted on Codeplex) was implemented at the backend to ensure that resources such as JavaScript and CSS were minified and compressed before being served to a customer&#8217;s browser. Furthermore, Combres enables us to easily update our JavaScript/CSS references which ensures that the latest version of the relevant resources are always loaded.</p>
<p>For the mobi site, we stuck with MVC but ensured that the markup produced by the server was XHTML-MP compliant. Given the nature of the mobile landscape, we were required to support a large number of internet enabled devices ranging from smart phones (such as the iPhone) to the hugely popular Samsung E250. For <a href="http://www.populi.net/mobileresearcher/" target="_blank">Mobile Researcher</a> we use a library called <a href="http://deviceatlas.com/" target="_blank">Device Atlas</a> which enables us to detect the type of device accessing the site and provide information regarding key capabilities. Given our experience with the product we used the same library on the Debonair&#8217;s mobi site. Images are automatically scaled and cached for devices accessing the site which ensures the site&#8217;s look and feel remains consistent no matter what resolution the relevant device sports. In time, we may begin enchancing the site for specific devices such as iPhones and Blackberrys.</p>
<p>For persistence we chose <a href="http://www.microsoft.com/sqlserver/2008/en/us/web.aspx" target="_blank">SQL Server 2008 R2 Web Edition</a>. We have extensive experience working with both Microsoft SQL Server and MySql, however, we wanted to utilise Windows Workflow 4.0 as part of the solution and we didn&#8217;t have time to look at writing a custom MySql persistence service for the workflow engine. In any event, our selected ORM (<a href="http://www.llblgen.com" target="_blank">LLBLGEN</a>) enables us to target any number of database technologies so theoretically, we could switch over to MySql in the long term without too much work. From a code perspective, we implemented the repository pattern using <a href="http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/" target="_blank">custom LLBLGEN templates</a>. At the repository level, queries were developed using LLBLGEN&#8217;s LINQ engine.</p>
<p><a href="http://msdn.microsoft.com/en-us/netframework/aa663328.aspx" target="_blank">Windows Workflow 4.0</a> was used to handle longer running processes such as those invoked when placing an order. Once an order is validated, the order is serialised into XML and posted to a third party POS gateway which performs further validation and propagates the order down to the relevant store. There are number of failure points involved in this process hence the use of Windows Workflow. If the order is not successful (whether it reached the third party gateway or not) an SMS is sent to the relevant customer informing them of the failure. As you can imagine, there are a number of issues that could cause this to happen including network connectivity failures to the the third party gateway, connectivity problems between the stores and the gateway etc. We wrote a custom Workflow Application Manager that manages persistence and execution of Workflows which means the system is resilient against system reboots etc. </p>
<p>A Windows Service was developed to host the workflow runtime and provides the host for workflow execution. Besides order processing, the service handles menu synchronisation, store connectivity tracking and communication (email/SMS) services. To facilitate communication between the web and mobi-site, we used <a href="http://nservicebus.com/" target="_blank">NServiceBus</a> which leverages MSMQ. NServiceBus enables us to deliver messages to the Windows Service in a transactional context which is obviously critical.</p>
<p>As far as unit testing goes, we used a number of frameworks and libraries to facilitate the unit testing process. For the core testing framework, we used <a href="http://www.nunit.org/" target="_blank">NUnit</a>. For our mocking library we chose <a href="http://code.google.com/p/moq/" target="_blank">Moq</a>. Moq simplifies the mocking process considerably as it exposes a fluent API. If you haven&#8217;t heard of Moq I seriously recommend checking it out.</p>
<p>Right now both sites are humming away on IIS 7.5. There is a lot more to come with a number of key features still in development/testing, the main being the ability to pay for an order using your credit card. All in all, the<br />
implementation process has has been an exciting experience which has allowed us to leverage a number of new and useful technologies. Without resorting to butchering the idiom &#8216;the proof is in the pudding&#8217;, please think about placing your next order for a Pizza using one of the sites mentioned &#8211; we would really appreciate your feedback. </p>
<p>If you have any questions, comments or suggestions please free to give me a shout.</p>
<p>Cheers,<br />
Rohland</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/08/14/ordering-pizza-online-baking-the-code-that-made-it-happen/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Workflow 4.0 &#8211; Custom activities not appearing in the VS2010 toolbox</title>
		<link>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/</link>
		<comments>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 20:24:56 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[llblgen]]></category>
		<category><![CDATA[vs2010]]></category>
		<category><![CDATA[workflow4]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=207</guid>
		<description><![CDATA[I thought this particular issue warranted a blog post because it took me a good couple of hours to track down the problem. Essentially as the title suggests, my custom Workflow 4.0 activities were not appearing in the Workflow 4.0 toolbox on a few projects I am working on.
If I created a new Workflow 4.0 [...]]]></description>
			<content:encoded><![CDATA[<p>I thought this particular issue warranted a blog post because it took me a good couple of hours to track down the problem. Essentially as the title suggests, my custom Workflow 4.0 activities were not appearing in the Workflow 4.0 toolbox on a few projects I am working on.</p>
<p>If I created a new Workflow 4.0 project in Visual Studio 2010, everything worked as it should. However, if I integrated Workflow 4.0 with an existing project I ran into problems. After numerous Google/Bing searches I found a few examples of <a target="_blank" href="http://social.msdn.microsoft.com/Forums/en/wfprerelease/thread/178a2b83-9dc4-46ed-8275-ea6851979d7f">forum</a>/<a target="_blank" href="http://stackoverflow.com/questions/1626210/windows-workflow-4-0-activities-not-being-added-to-the-toolbox">stackoverflow</a> posts about the problem but usually in the VS2010 Beta context.</p>
<p>It tuned out that the problem in my case is that I had two projects in my solution where the project files (*.csproj) were in the same directory. VS2010 did not like that for some reason. After moving the two projects into separate folders, everything worked! Absolutely bizarre. </p>
<p>If you are interested, the reason I had two project files in a single directory was because it&#8217;s the default configuration when using <a href="http://www.llblgen.com/" target="_blank">LLBLGEN</a> (adapter mode). It generates two projects, one database specific and the other generic. It is possible to get LLBLGEN to generate the projects in separate folders, you can find the instructions <a href="http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=8871&#038;StartAtMessage=0&#49181" target="_blank">here</a>.</p>
<p>Feel free to play the <a href="http://www.sadtrombone.com/" target="_blank">sad trombone</a> if you wasted as much time as I did.</p>
<p>Cheers,<br />
Roh</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/06/08/workflow-4-0-custom-activities-not-appearing-in-the-vs2010-toolbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backup your Subversion repository offsite (Windows Guide)</title>
		<link>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/</link>
		<comments>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 17:59:34 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[offsitebackup]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=166</guid>
		<description><![CDATA[If you work in a development environment, theres a good chance you are using Subversion as your code repository of choice. If thats the case, the usual suggestion for backing up is to dump the repositories onto a DVD or external drive to be stored offsite. We have been doing this for a while and [...]]]></description>
			<content:encoded><![CDATA[<p>If you work in a development environment, theres a good chance you are using <a href="http://subversion.tigris.org/" target="_blank">Subversion</a> as your code repository of choice. If thats the case, the usual suggestion for backing up is to dump the repositories onto a DVD or external drive to be stored offsite. <a href="http://www.clyral.com" target="_blank">We</a> have been doing this for a while and have found the process painfull (to say the least!). If you run subversion and don&#8217;t have your data backed up frequently offsite, you might find yourself pushing <a href="http://www.nooooooooooooooo.com/" target="_blank">this button</a> sooner or later! </p>
<p>Near the end of last year I started looking at offsite backup options that didn&#8217;t require user intervention and was very excited to discover the <a href="http://svnbook.red-bean.com/en/1.5/svn.ref.svnsync.html" target="_blank">svnsync</a> command. The benefit of svnsync is that only new revisions are mirrored and not the full repository each time. This is absolutely critical if you have a repository that is quite active. Needless to say, I decided to forge ahead and try my hand at implementing automated scripts to take care of backing up our repositories online utilising the svnsync tool. As a reference I have posted the setup process here.</p>
<p>Its important to note that this guide assumes you are working in a Windows environment and that you have access to a server offsite. I have referenced a few articles and other blog posts I discovered along the way to help you if you are working in a Linux environment.</p>
<div style="padding-left:30px">
<p><strong>Step 1 &#8211; Setup Subversion on your remote server</strong></p>
<p>Create a Windows user account on your remote server which you will use to remotely access the backup repository from your main Subversion server. Take note of the account name and password you use. Once you have created the account, install <a href="http://www.visualsvn.com/server/download/" target="_blank">Visual SVN</a> on the server where you want to host your mirrored repositories. Ensure you select Windows Authentication on the security dialog during the installation process. Once completed, ensure that Subversion is running correctly on the remote machine by opening the VisualSVN manager and clicking on the repository address displayed. Now ensure you can access the repository from your host Subversion server. If your backup server&#8217;s name is not addressable from your host server, use the remote servers IP address or simply add an entry to your DNS server or Windows <a href="http://en.wikipedia.org/wiki/Hosts_file" target="_blank">host file</a>. If you opted for setting up a DNS entry, you should be able to ping your backup server using the server&#8217;s name. Try access the repository again. When prompted for username and password use the credentials setup for the user account you created.</p>
<p><strong>Step 2 &#8211; Configure permissions</strong></p>
<p>Before setting up the repositories etc. we need to define which users have access writes to the backup repository. To configure this, open VisualSVN manager on the remote server and right click on the Repositories folder, choose Properties from the drop down menu. Revoke all access for the BUILTIN\Users role and then add the user account you setup in Step 1. Ensure this user has full Read/Write access.</p>
<p><strong>Step 3 &#8211; Create the destination repository</strong></p>
<p>Now that you have full configured the Subversion server hosted on your remote server we can start the process of setting up the synchronisation process. To do this we need to ensure that we have a destination repository to mirror your existing repository to (if you have more than one you need to create a destination repository for each repository you want to mirror). To keep things simple, I gave the destination repository the same name as the source repository. Take note that any repository you create on the destination server should be empty (i.e. do not tick the &#8220;Create default structure&#8221; checkbox when creating the repository.</p>
<p><strong>Step 4 &#8211; Configure the repository</strong></p>
<p>The next step involves setting the Pre-revision Property Change Hook. This is an important step. Right click on the repository you created on the destination server and select All Tasks > Manage Hooks. Click on the &#8220;Pre-revision property change hook&#8221; entry and click Edit. Enter a few blank lines and click OK and Apply.</p>
<p><strong>Step 5 &#8211; Configure SSL</strong></p>
<p>We need to configure the client server to accept the SSL certificate generated by the VisualSVN installer. If you wish to use a properly signed certificate or already have one, follow this <a href="http://www.visualsvn.com/support/topic/00034/" target="_blank">guide</a> and ignore the rest of this step. If you want to continue using the auto generated certificate, follow Mark Wilson&#8217;s <a href="http://www.markwilson.co.uk/blog/2008/11/trusting-a-self-signed-certificate-in-windows.htm" target="_blank">guide</a> on how to trust the default certificate.</p>
<p><strong>Step 6 &#8211; Initialise your repositories for synchronisation</strong></p>
<p>Before you can synchronise your repository, you need to initialise it. To do this, you need to run the following command on the host server (note that you need to replace the keys in CAPS to the relevant object names):</p>
<p><font color="#377400">svnsync init PATH_TO_REMOTE_REPO PATH_TO_LOCAL_REPO &#8211;sync-username REMOTE_USERNAME  &#8211;sync-password REMOTE_PASSWORD &#8211;source-username HOST_USERNAME &#8211;source-password HOST_PASSWORD</font></p>
<p><strong>Step 7 &#8211; Initialise remote repositories from a previous backup</strong></p>
<p>Only run through this step if you have a relatively large repository and don&#8217;t want to have to mirror it (the sync process is quite slow) from revision 0 all the way to revision xxxx. If you are running through these steps for a brand new repository you want to have mirrored, ignore this step. Also, please take note that if you are using Powershell to execute all these scripts &#8220;>&#8221; is equiv to | Out-File -encoding Unicode (thanks <a href="http://twitter.com/r_keith_hill/status/8347225922" target="_blank">Keith</a>). If you don&#8217;t be careful, you might end up with the <a href="http://brianlyttle.com/2009/01/powershell-and-svnadmin/" target="_blank">Malformed dumpfile header</a> error. To be safe, use the command line interface.</p>
<p>Dump your existing repository on your host machine by running the following script: </p>
<p><font color="#377400">svnadmin dump &#8220;FILE_PATH_TO_REPO&#8221; > &#8220;REPO_NAME.db&#8221;</font></p>
<p>Once the repository dump has completed, upload it to your backup server and then run the following script on the backup/mirros server: </p>
<p><font color="#377400">svnadmin load &#8220;FILE_PATH_TO_BACKUP_REPO&#8221; < "REPO_NAME.db"</font></p>
<p>Now, the next step is critical. You need to update the last-merged-rev property on the remote repository to the existing revision number of the repository (you can get this information by running &#8220;svn info REPO_PATH&#8221;). To do this run the following script: </p>
<p><font color="#377400">svn propset svn:sync-last-merged-rev &#8211;revprop -r0 REV_NUMBER &#8220;PATH_TO_REMOTE_REPO&#8221;.</font></p>
<p><strong>Step 8 &#8211; Synchronise!</strong></p>
<p>Basically you are done, you simply need to run the following script on a frequent basis (best to setup as a scheduled task in Windows):</p>
<p><font color="#377400">svnsync sync PATH_TO_REMOTE_REPO &#8211;sync-username REMOTE_USERNAME  &#8211;sync-REMOTE_PASSWORD &#8211;source-username HOST_USERNAME &#8211;source-password HOST_PASSWORD</font></p>
</div>
<p>Hope you found this useful. I might follow this post up with another blog entry on steps I took to setup an automated script to email me when a repository on the host machine is missing its mirrored counterpart. This is really helpful to detect cases where a repository was setup locally but not configured for synchronisation, furthermore the ability to automatically generate the relevant scripts is quite useful <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Rohland</p>
<p>References:<br />
<a href="http://journal.paul.querna.org/articles/2006/09/14/using-svnsync/" target="_blank">http://journal.paul.querna.org/articles/2006/09/14/using-svnsync/</a><br />
<a href="http://www.rosshawkins.net/archive/2009/04/27/using-svnsync-properwith-visualsvn.aspx" target="_blank">http://www.rosshawkins.net/archive/2009/04/27/using-svnsync-properwith-visualsvn.aspx</a><br />
<a href="http://devlicious.com/blogs/christopher_bennage/archive/2009/03/11/mirroring-subversion-from-windows.aspx" target="_blank">http://devlicious.com/blogs/christopher_bennage/archive/2009/03/11/mirroring-subversion-from-windows.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/02/01/backup-your-subversion-repository-offsite-windows-guide/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing the Repository Pattern with LLBLGEN</title>
		<link>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/</link>
		<comments>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 12:12:23 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[llblgen]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=134</guid>
		<description><![CDATA[This post has been sitting in draft for a while but finally managed to get round to completing it. I started it back in 2009. Apologies for the delay  
It was the start of 2009, and I was investigating ORM tools for a new project we were working on at Clyral. We had been [...]]]></description>
			<content:encoded><![CDATA[<p>This post has been sitting in draft for a while but finally managed to get round to completing it. I started it back in 2009. Apologies for the delay <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>It was the start of 2009, and I was investigating ORM tools for a new project we were working on at <a href="http://www.clyral.com">Clyral</a>. We had been using Linq 2 SQL as our core database access layer for some time but felt we had outgrown it and were looking for something a bit more powerful and flexible. It didn&#8217;t take long for us to discover <a href="http://www.llblgen.com">LLBLGEN</a>. Whilst not the most intuitive acronym for an O/R mapping framework, LLBLGEN (Lower Level Business logic Layer Generator) impressed the team from the outset. After downloading the demo version and playing around with it on a test project we committed to purchasing it and since then haven&#8217;t looked back.</p>
<p>We started off using the Self Servicing model of the framework as it was earmarked for beginners, in time though, we began to see that we would get more mileage using the adapter model and began using this model as the defacto standard for projects. It was at this point we began looking at ways to implement the <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx">repository pattern</a> which simplifies the testing process and ensures the implementation (which is often technology specific) does not get mangled with the domain model. To achieve this we needed every entity to implement an interface (or contract if you will). The problem with this of course, is that in C# <a href="http://stackoverflow.com/questions/1864080/list-of-interfaces-vs-list-of-derived-type-cannot-convert-expression-type-to-r">generic variance is not supported</a>. This posed a bit of a problem because we still wanted the full representation of a given entity graph to be available using our defined interfaces. To get around this, we needed to update the LLBLGEN templates to allow us to inject our own custom implementation of collections which would match our interface definitions. I have provided a few example snippets to illustrate what I am talking about. Essentially we added properties which took a Todos collection (property of a TodoList entity) such as defined below:</p>
<pre class="brush: csharp;">
public virtual EntityCollection&lt;TodoEntity&gt; Todos
{
	get
	{
		if(_todos==null)
		{
			_todos = new EntityCollection&lt;TodoEntity&gt;(EntityFactoryCache2.GetEntityFactory(typeof(TodoEntityFactory)));
			_todos.SetContainingEntityInfo(this, &quot;Todolists&quot;);
		}
		return _todos;
	}
}
</pre>
<p>and added the code below to support out interface definition:</p>
<pre class="brush: csharp;">
public EntityList&lt;ITodoEntity, TodoEntity&gt;  TodosCollection
{
	get
	{
		if (_TodosCollection == null)
		{
			_TodosCollection = new EntityList&lt;ITodoEntity, TodoEntity&gt;(this.Todos);
		}
		return _TodosCollection;
	}
}

private EntityList&lt;ITodoEntity, TodoEntity&gt;  _TodosCollection;
</pre>
<p>where &#8220;EntityList&#8221; is a custom wrapper we wrote to get around the generic variance issue (note that EntityList understands that a TodoEntity is an implementation of ITodoEntity). This allowed us to define our entity contracts as such:</p>
<pre class="brush: csharp;">

    /// &lt;summary&gt;
    /// Interface for the entity 'TodoList'.
    /// &lt;/summary&gt;
	public partial interface ITodoListEntity
	{
		EntityList&lt;ITodoEntity, TodoEntity&gt;  TodosCollection {get;}		

		System.Int32 Id {get;set;}
		System.String Title {get;set;}
		System.String Description {get;set;}
		System.Int32 ProjectId {get;set;}
		System.Int16 Position {get;set;}
		System.Boolean Billable {get;set;}
		System.DateTime CreatedOn {get;set;}
		System.DateTime ModifiedOn {get;set;}
		System.String CreatedBy {get;set;}
		System.String ModifiedBy {get;set;}
		System.Guid CreatedUserId {get;set;}
		System.Guid ModifiedUserId {get;set;}
	}
</pre>
<p>As you can see, a standard was implemented where the original list&#8217;s name was simply extended with the word &#8220;Collection&#8221;. After modifying the adapter&#8217;s templates and generating our templates to create the entity contracts, everything fell into place and we had our repository pattern implemented. Our repository definitions ensured that only interfaces were passed round (of course implemented using LLBLGEN&#8217;s entities) which in turn ensured that our UI (or business logic) knew nothing about the underlying implementation. One benefit of doing this is that the chaps working on the UI never had to deal with the copious number of properties and methods that hang off an LLBLGEN entity by default. Of course, these properties and methods are useful in some cases and can still be used within the repository itself.</p>
<p>I have attached a zip file to this post with the implementation of the EntityList class as well as the templates that we modified and added to make this all happen. Let me know what you think, any comments or suggestions regarding the implementation are certainly welcome!</p>
<p>Rohland</p>
<p><a href="http://www.rohland.co.za/wp-content/uploads/2010/01/LLBLGEN-Customisations.zip">Templates and supporting files</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2010/01/23/implementing-the-repository-pattern-with-llblgen/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>C# HTML Diff Algorithm</title>
		<link>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/</link>
		<comments>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 08:44:25 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[codeplex]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[html]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=81</guid>
		<description><![CDATA[I have finally launched by my first Codeplex project, very exciting :) I was inspired by <a href="http://writeboard.com">writeboard.com</a> to find some way of implementing an HTML difference viewer in an internal application I was developing. Essentially, I was looking for a way to take two blocks of HTML and compare them in a way that highlights what the differences are. This is extremely useful for CMS type systems where WYSIWYG/Textile/Wiki markup is used to populate content. In most web systems where content is authored dynamically, a history of the content is tracked over time. When collaborating with a few people, this feature is critically important. What makes it extremely useful is the capability to detect what has changed between versions. This post focuses on a project I have launched to do exactly that - track the difference between two versions of HTML markup.]]></description>
			<content:encoded><![CDATA[<p>I have finally launched my first <a href="http://htmldiff.codeplex.com" title="C# Html Diff Algorithm">Codeplex project</a>, very exciting <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I was inspired by <a href="http://writeboard.com">writeboard.com</a> to find some way of implementing an HTML difference viewer in an internal application I was developing. Essentially, I was looking for a way to take two blocks of HTML and compare them in a way that highlights what the differences are. This is extremely useful for CMS type systems where WYSIWYG/Textile/Wiki markup is used to populate content. In most web systems where content is authored dynamically, a history of the content is tracked over time. When collaborating with a few people, this feature is critically important. What makes it extremely useful is the capability to detect what has changed between versions. This post focuses on a project I have launched to do exactly that &#8211; track the difference between two versions of HTML markup.</p>
<p>The application I was building was developed on ASP .NET MVC (C#) so naturally I was looking for some C# code I could use to implement the difference algorithm. In searching, I could not find any libraries that were worth implementing. I did come across one or two command line utilities but nothing spectacular. I widened my search to other languages and came across a <a href="http://github.com/myobie/htmldiff">neat implementation</a> in <a href="http://www.ruby-lang.org/en/">Ruby</a>. The algorithm was developed by <a href="http://nathanherald.com/">Nathan Herald</a> who generously made the code available to everyone via the common <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a>.</p>
<p>So, I had the algorithm I was looking for, but I didn&#8217;t speak Ruby! This was an excellent opportunity to roll up my sleeves and learn some Ruby so I fired up my browser, downloaded the Windows <a href="http://www.ruby-lang.org/en/downloads/">one-click installer</a> and got a simple environment up and running. After toying with code for a bit, scratching my head at one or two alien Ruby constructs I got the gist of how things worked. I fired up Visual Studio, created a new project and began the process of porting the algorithm. I must admit that the process was relatively painless and I got something working in a few hours. It took about another hour or two to iron out some bugs I picked up but essentially, in a relatively short space of time, I had the C# diff library that I was originally looking for! Below is a demo of how it is used, followed by one or two screenshots demonstrating the functionality when rendered to your browser.</p>
<pre class="brush: csharp;">
            string oldText = @&quot;&lt;p&gt;This is some sample text to demonstrate the capability of the &lt;strong&gt;HTML diff tool&lt;/strong&gt;.&lt;/p&gt;
                                &lt;p&gt;It is based on the Ruby implementation found &lt;a href='http://github.com/myobie/htmldiff'&gt;here&lt;/a&gt;. Note how the link has no tooltip&lt;/p&gt;
                                &lt;table cellpadding='0' cellspacing='0'&gt;
                                &lt;tr&gt;&lt;td&gt;Some sample text&lt;/td&gt;&lt;td&gt;Some sample value&lt;/td&gt;&lt;/tr&gt;
                                &lt;tr&gt;&lt;td&gt;Data 1 (this row will be removed)&lt;/td&gt;&lt;td&gt;Data 2&lt;/td&gt;&lt;/tr&gt;
                                &lt;/table&gt;&quot;;

            string newText = @&quot;&lt;p&gt;This is some sample text to demonstrate the awesome capabilities of the &lt;strong&gt;HTML diff tool&lt;/strong&gt;.&lt;/p&gt;&lt;br/&gt;&lt;br/&gt;Extra spacing here that was not here before.
                                &lt;p&gt;It is based on the Ruby implementation found &lt;a title='Cool tooltip' href='http://github.com/myobie/htmldiff'&gt;here&lt;/a&gt;. Note how the link has a tooltip now and the HTML diff algorithm has preserved formatting.&lt;/p&gt;
                                &lt;table cellpadding='0' cellspacing='0'&gt;
                                &lt;tr&gt;&lt;td&gt;Some sample &lt;strong&gt;bold text&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Some sample value&lt;/td&gt;&lt;/tr&gt;
                                &lt;/table&gt;&quot;;

            HtmlDiff diffHelper = new HtmlDiff(oldText, newText);
            string diffOutput = diffHelper.Build();
</pre>
<p>Using the sample web application provided with the project in Codeplex, the following is rendered based on the code above:</p>
<div id="attachment_119" class="wp-caption aligncenter" style="width: 587px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_old_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_old_text.PNG" alt="Old HTML" title="html_diff_old_text" width="577" height="212" class="size-full wp-image-119" /></a><p class="wp-caption-text">Old HTML</p></div>
<div id="attachment_122" class="wp-caption aligncenter" style="width: 583px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_new_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_new_text.PNG" alt="Updated HTML" title="html_diff_new_text" width="573" height="275" class="size-full wp-image-122" /></a><p class="wp-caption-text">Updated HTML</p></div>
<div id="attachment_123" class="wp-caption aligncenter" style="width: 588px"><a href="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_output_text.PNG"><img src="http://www.rohland.co.za/wp-content/uploads/2009/10/html_diff_output_text.PNG" alt="HTML diff output" title="html_diff_output_text" width="578" height="320" class="size-full wp-image-123" /></a><p class="wp-caption-text">HTML diff output</p></div>
<p>You can see that the algorithm as originally developed takes care of the nasty HTML parsing to figure out how to highlight the differences. The changes are marked up using &#8220;ins&#8221; and &#8220;del&#8221; tags. You can easily style these tags as I have done. The CSS below is responsible for rendering the differences as per the example.</p>
<pre class="brush: css;">
ins {
	background-color: #cfc;
	text-decoration: none;
}

del {
	color: #999;
	background-color:#FEC8C8;
}
</pre>
<p>I hope you find the library useful. I wish I had more time to add tests and more documentation to the Codeplex project, but for now I think the implementation is reasonably solid and easy to follow. If you spot any bugs, let me know and I&#8217;ll try and attend to them. Given that I am not responsible for the original implementation as developed in Ruby, it might be a bit tricky to solve some of the fundamental issues with the algorithm but I will certainly have a crack at it since I have quite a good understanding of how it works after porting it.</p>
<p>Link to C# implementation: <a href="http://htmldiff.codeplex.com">http://htmldiff.codeplex.com</a><br />
Link to Ruby implementation: <a href="http://github.com/myobie/htmldiff">http://github.com/myobie/htmldiff</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/10/31/csharp-html-diff-algorithm/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Blog Migration</title>
		<link>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/</link>
		<comments>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 17:42:04 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=58</guid>
		<description><![CDATA[In search of a bit more flexibility, I have decided to move my existing blog at dotnet.org.za to www.rohland.co.za. For lack of a better name, I ended up with the obvious pretentious default  
I am very grateful for the service made available via the dotnet.org.za portal. A year ago it allowed me to get [...]]]></description>
			<content:encoded><![CDATA[<p>In search of a bit more flexibility, I have decided to move my existing blog at <a href="http://dotnet.org.za">dotnet.org.za</a> to <a href=''>www.rohland.co.za</a>. For lack of a better name, I ended up with the obvious pretentious default <img src='http://www.rohland.co.za/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>I am very grateful for the service made available via the <a href="http://dotnet.org.za">dotnet.org.za portal</a>. A year ago it allowed me to get up and running with my blog relatively quickly. To the administrators of the portal &#8211; thank you! </p>
<p>In terms of moving forward, I was not sure what the correct procedure for moving my existing blog away from <a href="http://dotnet.org.za">dotnet.org.za</a> was, so I ended up implementing a simple script to redirect to my new domain. Hopefully, I will be able to organise a mechanism whereby future posts here reflect in the dotnet.org.za main feed. If not, then I guess that is the penalty for moving my blog.</p>
<p>Hopefully you subscribe to the RSS feed available <a href='http://www.rohland.co.za/index.php/feed/'>here</a>, or at the very least, check back periodically for new content. Please let me know if spot any issues.</p>
<p>If you have landed here after clicking a link related to one of my older blog posts, simply use the search feature available in the side bar to locate the content you were originally hoping to review.</p>
<p>Cheers,<br />
Rohland</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/10/11/blog-migration/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Powerpoint with some Deep Zoom shine</title>
		<link>http://www.rohland.co.za/index.php/2009/08/23/powerpoint-with-some-deep-zoom-shine/</link>
		<comments>http://www.rohland.co.za/index.php/2009/08/23/powerpoint-with-some-deep-zoom-shine/#comments</comments>
		<pubDate>Sun, 23 Aug 2009 14:41:02 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Tips and tricks]]></category>
		<category><![CDATA[deep zoom]]></category>
		<category><![CDATA[powerpoint]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=53</guid>
		<description><![CDATA[I thought I would give the Microsoft Office Labs team a plug after using one of their Office add-ins in a presentation I delivered last week. It had been a while since I last put together a Powerpoint presentation and I wanted to find out if there were any new funky ways of delivering presentation [...]]]></description>
			<content:encoded><![CDATA[<p><P>I thought I would give the <A href="http://www.officelabs.com/" mce_href="http://www.officelabs.com/">Microsoft Office Labs</A> team a plug after using one of their Office add-ins in a presentation I delivered last week. It had been a while since I last put together a Powerpoint presentation and I wanted to find out if there were any new funky ways of delivering presentation content.</P></p>
<p><P>If you cast your mind back to Tech-Ed Africa 2008, you might remember a few demos of <A href="http://en.wikipedia.org/wiki/DeepZoom" mce_href="http://en.wikipedia.org/wiki/DeepZoom">Deep Zoom</A>, a technology that allows you to “infinitely” zoom and pan through a large collection of high-res images. The demos were impressive but sadly, I haven’t really seen the technology applied in the wild. So, I decided to look into any advancements in the Deep Zoom toolset that would allow me to put together a presentation relatively simply. It was at this point I stumbled across <A href="http://www.officelabs.com/projects/pptPlex/Pages/default.aspx" mce_href="http://www.officelabs.com/projects/pptPlex/Pages/default.aspx">PPTPlex</A>, a plug-in for Microsoft Powerpoint. It allows you to add some cool Deep Zoom type features to your presentation. Strictly speaking, its not as robust as a true Deep Zoom compilation, but it does allow you to put together a neat presentation without too much work.</P></p>
<p><P>Overall, I thought the plug-in was pretty cool and had an extremely low learning curb. I successfully delivered my presentation using the plug-in without any issues. I did have one or two gripes about the plug-in though, the main being that I could not find a way to publish my presentation (I had to have Powerpoint open to present it). Also, you cannot animate any of your presentation elements through PPTPlex – I can understand why this is missing (it would be pretty complex to implement) but it is just something you need to bear in mind.</P></p>
<p><P>So, if you’re bored of compiling presentations using the defacto Powerpoint toolset then I would definately recommend looking into PPTPlex. Have fun…</P></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/08/23/powerpoint-with-some-deep-zoom-shine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Test mail send routine without mail server</title>
		<link>http://www.rohland.co.za/index.php/2009/07/23/test-mail-send-routine-without-mail-server/</link>
		<comments>http://www.rohland.co.za/index.php/2009/07/23/test-mail-send-routine-without-mail-server/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 07:19:12 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[dotnet]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=48</guid>
		<description><![CDATA[I picked up a blog post about this tip from one of my RSS feeds. Amr ElGarhy posted a valuable article on how to write emails to a local directory rather than sending them through a mail server. This saves a lot of time in dev.
Essentially, replace your existing mail configuration with the config below:

&#60;system.net&#62;
 [...]]]></description>
			<content:encoded><![CDATA[<p><P>I picked up a blog post about this tip from one of my RSS feeds. <A href="http://amrelgarhy.com/blog/sending-mails-development-machine-without-actual-mail-server/" target=_blank mce_href="http://amrelgarhy.com/blog/sending-mails-development-machine-without-actual-mail-server/">Amr ElGarhy</A> posted a valuable article on how to write emails to a local directory rather than sending them through a mail server. This saves a lot of time in dev.</P></p>
<p><P>Essentially, replace your existing mail configuration with the config below:</P></p>
<p><DIV class="code" style="PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 5px"></p>
<p style="MARGIN: 0px">&lt;<SPAN style="COLOR: #cc7832">system.net</SPAN>&gt;</p>
<p style="MARGIN: 0px"> &lt;<SPAN style="COLOR: #cc7832">mailSettings</SPAN>&gt;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp; &lt;<SPAN style="COLOR: #cc7832">smtp</SPAN> deliveryMethod=&#8221;<SPAN style="COLOR: #a5c25c">SpecifiedPickupDirectory</SPAN>&#8220;&gt;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp;&nbsp; &lt;<SPAN style="COLOR: #cc7832">specifiedPickupDirectory</SPAN> pickupDirectoryLocation=&#8221;<SPAN style="COLOR: #a5c25c">c:\tmp</SPAN>&#8221; /&gt;</p>
<p style="MARGIN: 0px">&nbsp;&nbsp; &lt;/<SPAN style="COLOR: #cc7832">smtp</SPAN>&gt;</p>
<p style="MARGIN: 0px"> &lt;/<SPAN style="COLOR: #cc7832">mailSettings</SPAN>&gt;</p>
<p style="MARGIN: 0px">&lt;/<SPAN style="COLOR: #cc7832">system.net</SPAN>&gt;</p>
<p></DIV><br />
<P>When you send a mail using the built in .NET classes, a *.eml file will be created in the directory you specify. You can then view the email by simply opening the file.</P></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/07/23/test-mail-send-routine-without-mail-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enable remote desktop remotely</title>
		<link>http://www.rohland.co.za/index.php/2009/07/18/enable-remote-desktop-remotely/</link>
		<comments>http://www.rohland.co.za/index.php/2009/07/18/enable-remote-desktop-remotely/#comments</comments>
		<pubDate>Sat, 18 Jul 2009 07:50:18 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Tips and tricks]]></category>
		<category><![CDATA[remote desktop]]></category>
		<category><![CDATA[sysinternals]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=46</guid>
		<description><![CDATA[So, this morning I needed to remote into one of our work stations at the office but lo and behold, remote desktop was disabled (ARGGH!). This meant one of three things, either I drive to the office to get it done, forget about the work until Monday or try update the setting remotely. Suffice to [...]]]></description>
			<content:encoded><![CDATA[<p><P>So, this morning I needed to remote into one of our work stations at the office but lo and behold, remote desktop was disabled (ARGGH!). This meant one of three things, either I drive to the office to get it done, forget about the work until Monday or try update the setting remotely. Suffice to say, I attempted option 3 first.</P></p>
<p><P>It turned out to be really easy, there are already one or two articles on the web that explain how to do this, but for the folks who don’t know (and for my future reference) I thought posting it here would be useful.</P></p>
<p><P><STRONG>Step 1 &#8211; </STRONG>Download PsExec (an awesome utility from SysInternals)</P></p>
<p><P><A href="http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx" mce_href="http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx">http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx</A></P></p>
<p><P><STRONG>Step 2 &#8211; </STRONG>Run PsExec as follows:</P></p>
<p><P style="COLOR: #004874">psexec \\REMOTE_PC_NAME _HERE cmd</P></p>
<p><P>This will open a command line session on the machine you are attempting to enable RD on. Any of the commands you execute below will be executed on the remote machine.</P></p>
<p><P><STRONG>Step 3 – </STRONG>Ensure the firewall on the remote machine lets you in</P></p>
<p><P style="COLOR: #004874">netsh firewall set service remotedesktop enable <BR>netsh firewall set service remoteadmin enable</P></p>
<p><P><STRONG>Step 4 &#8211; </STRONG>Update the terminal server registry key which controls remote desktop capability</P></p>
<p><P style="COLOR: #004874">REG ADD &#8220;HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server&#8221; /f /v fDenyTSConnections /t REG_DWORD /d 0</P></p>
<p><P>That’s it! You should be good to go.</P></p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/07/18/enable-remote-desktop-remotely/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom tooltips and Microsoft’s chart control</title>
		<link>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft%e2%80%99s-chart-control/</link>
		<comments>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft%e2%80%99s-chart-control/#comments</comments>
		<pubDate>Sun, 21 Jun 2009 21:12:16 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[asp dotnet]]></category>
		<category><![CDATA[microsoft chart control]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=28</guid>
		<description><![CDATA[I have been meaning to blog about this topic for a while now because I am interested to find out if anyone else has picked up performance issues when using the Microsoft Chart Controls and the “MapAreaAttributes” property to create custom tooltips.
Before going into the mechanics of creating a custom tooltip as suggested by the [...]]]></description>
			<content:encoded><![CDATA[<p>I have been meaning to blog about this topic for a while now because I am interested to find out if anyone else has picked up performance issues when using the Microsoft Chart Controls and the “MapAreaAttributes” property to create custom tooltips.</p>
<p>Before going into the mechanics of creating a custom tooltip as suggested by the documentation provided with the charting framework, I thought I would simply outline how you would create an instance of the default styled tooltip:</p>
<div class="code" style="PADDING-BOTTOM: 8px; PADDING-LEFT: 8px; PADDING-RIGHT: 8px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 8px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">1</span> series.Points.DataBind(data,<span style="COLOR: #a5c25c">&#8220;X&#8221;</span>,<span style="COLOR: #a5c25c">&#8220;Y&#8221;</span>,<span style="COLOR: #a5c25c">&#8220;Tooltip=MyTooltipProperty&#8221;</span>);</p>
</div>
<p> </p>
<p>The code above illustrates the databinding capabilities of the charting control. The <em>data</em> array is made up of a list of objects that are of type <em>Point </em>which is a simple class I created:</p>
<div class="code" style="PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 5px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    1</span>     <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">class</span> <span style="COLOR: #ffc66d">Point</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    2</span>     {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    3</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">double</span> X {<span style="COLOR: #cc7832">get</span>;<span style="COLOR: #cc7832">set</span>;}</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    4</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">double</span> Y { <span style="COLOR: #cc7832">get</span>; <span style="COLOR: #cc7832">set</span>; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    5</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    6</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">string</span> MyTooltipProperty { <span style="COLOR: #cc7832">get</span>; <span style="COLOR: #cc7832">set</span>; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    7</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    8</span>         <span style="COLOR: #cc7832">public</span> Point()</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    9</span>         {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   10</span>             <span style="COLOR: #cc7832">this</span><span style="FONT-WEIGHT: normal">.MyTooltipProperty = </span><span style="COLOR: #a5c25c">&#8220;Hello!&#8221;</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   11</span>         }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   12</span>     }</p>
</div>
<p> </p>
<p>From the above it is obvious that each data point’s tooltip will look like something like this:</p>
<p><img class="alignleft size-full wp-image-33" title="Normal tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/NormalTooltip.jpg" alt="Normal tooltip" width="244" height="236" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>The tooltip is simply rendered using the relevant browser’s default implementation for elements.</p>
<p><strong>Custom Tooltips:</strong></p>
<p>You may be aware of the charting framework’s capability for creating rich HTML tooltips using the <em>MapAreaAttributes</em> property. As illustrated in an example provided with the framework you could create an HTML tooltip using code similar to that shown below:</p>
<div class="code" style="PADDING-BOTTOM: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 3px">
<p style="MARGIN: 0px">series.Points[j].MapAreaAttributes = <span style="COLOR: #a5c25c">&#8220;onmouseover=\&#8221;DisplayToolTip(&#8217;&lt;strong&gt;Hello From an HTML tooltip&lt;/strong&gt;&#8217;);\&#8221; onmouseout=\&#8221;HideToo</span><span style="COLOR: #a5c25c">ltip();\&#8221;"</span></p>
</div>
<p> </p>
<p>The <em>DisplayTooltip </em>method referenced is a JavaScript method which essentially displays an absolutely positioned element which tracks your mouse position. The method is fired as you hover over the data point area (which is defined by an image area map). The parameter passed to the method is injected into the element as HTML. As you mouse out of the area (the relevant data point) the <em>Hidetooltip </em>method fires and hides the element displaying the custom tooltip. Using this methodology your tooltip could look something like this:</p>
<p> <img class="alignleft size-full wp-image-38" title="HTML tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/htmltooltip.png" alt="HTML tooltip" width="244" height="187" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>This looks promising because it illustrates the capability to extend our tooltips to include images, links etc. however, there is a caveat. I picked up an issue when you have a chart with a large number of data points, or a number of charts on a single page that utilise this feature. I started noticing that page loads took longer than usual. I put together a test page that rendered 40 instances of the same chart as shown above using the default tooltip. With tracing turned on the page took roughly 270ms to render:</p>
<p> <img class="alignleft size-full wp-image-39" title="Default performance" src="http://www.rohland.co.za/wp-content/uploads/2009/06/defaultperf.jpg" alt="Default performance" width="488" height="313" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>By implementing one extra line of code to implement my rich HTML tooltip using the <em>MapAreaAttributes</em> property as outlined earlier, the page took almost 5 seconds to render!</p>
<p> <img class="alignleft size-full wp-image-41" title="Poor performance" src="http://www.rohland.co.za/wp-content/uploads/2009/06/customperf.jpg" alt="Poor performance" width="491" height="316" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>It turns out anyone who dares to use the MapAreaAttributes property is severely penalised! Clearly we can’t put a page into production that takes 5 seconds just to render our charts, so we either need to revert to our dull looking tooltips or look for other ways to achieve rich HTML tooltip functionality.</p>
<p>Now, we know that setting the tooltip property doesn’t seem to have any performance impact but that it doesn’t result in a pretty looking tooltip either, but what if we could use the tooltip property to store the HTML tooltip markup. I know what your thinking:</p>
<p><img class="alignleft size-full wp-image-42" title="Ugly tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/Uglytooltip.jpg" alt="Ugly tooltip" width="244" height="112" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>Yuck. That will certainly have your users scratching their heads. So, what next? So far we know that using the example as provided by the charting documentation has an adverse affect on rendering times so that’s not ideal. Default tooltip styles work without performance issues but don’t allow us to render rich tooltips. Injecting HTML into the default tooltip property means our users need to slap on their XHTML goggles.</p>
<p>Well, there is an option available which I will outline here.  Essentially, it relies on the ability to interpret the default tooltip property and project it into a custom tooltip that we control. If we look at the HTML rendered by the chart control, you will notice an associated image map that looks something like this:</p>
<p><img class="alignleft size-full wp-image-43" title="Image map" src="http://www.rohland.co.za/wp-content/uploads/2009/06/markup.png" alt="Image map" width="514" height="244" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>As you can see, our HTML tooltip detail is sitting inside the title property, encoded of course. If we leave the mark-up untouched and hover over any element on the chart, the default tooltip is rendered with unparsed HTML. Thankfully, we can access this image map using JavaScript to rebuild the image map with mouseover/out events to render our custom tooltip. While this is exactly what setting the <em>MapAreaAttributes</em> property is supposed to do, modifying the rendered HTML to do the same thing bypasses the performance issue noted. I have provided the JavaScript method below which rebuilds the image map. All that is required, from a server side scripting point of view, is the registration of a start-up script to process any chart you wish to load with custom tooltips.</p>
<div class="code" style="PADDING-BOTTOM: 8px; PADDING-LEFT: 8px; PADDING-RIGHT: 8px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 8px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    1</span> RebuildImageMap: <span style="COLOR: #cc7832">function</span>(id) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    2</span>     <span style="COLOR: gray">// Fetch the image and grab the imagemap ID</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    3</span>     <span style="COLOR: #cc7832">var</span> map = $(<span style="COLOR: #a5c25c">&#8220;#&#8221;</span> + id).attr(<span style="COLOR: #a5c25c">&#8220;usemap&#8221;</span>);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    4</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    5</span>     <span style="COLOR: gray">// If the map ID is null, then perhaps there </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    6</span>     <span style="COLOR: gray">// were no datapoints. Don&#8217;t bother </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    7</span>     <span style="COLOR: gray">// processing an empty set</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    8</span>     <span style="COLOR: #cc7832">if</span> (map == <span style="COLOR: #cc7832">null</span>)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    9</span>         <span style="COLOR: #cc7832">return</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   10</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   11</span>     <span style="COLOR: gray">// Fetch the map element using jQuery and </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   12</span>     <span style="COLOR: gray">// return the raw HTML element</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   13</span>     <span style="COLOR: #cc7832">var</span> areaMap = $(map)[<span style="COLOR: #6897bb">0</span>];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   14</span>     <span style="COLOR: #cc7832">if</span> (areaMap == <span style="COLOR: #cc7832">null</span>) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   15</span>         <span style="COLOR: #cc7832">return</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   16</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   17</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   18</span>     <span style="COLOR: gray">// Create an empty array to store our new elements</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   19</span>     <span style="COLOR: #cc7832">var</span> elementArray = [];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   20</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   21</span>     <span style="COLOR: gray">// Iterate over existing map elements and create a new </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   22</span>     <span style="COLOR: gray">// set with our mouseover/out events</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   23</span>     <span style="COLOR: #cc7832">for</span> (<span style="COLOR: #cc7832">var</span> i = <span style="COLOR: #6897bb">0</span>; i &lt; areaMap.areas.length; i++) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   24</span>         <span style="COLOR: #cc7832">var</span> oldAreaElement = areaMap.areas[i];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   25</span>         <span style="COLOR: #cc7832">var</span> element = document.createElement(<span style="COLOR: #a5c25c">&#8220;AREA&#8221;</span>);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   26</span>         element.shape = oldAreaElement.shape;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   27</span>         element.coords = oldAreaElement.coords;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   28</span>        </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   29</span>         element.tooltip = oldAreaElement.title;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   30</span>         element.onmouseover =</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   31</span>             <span style="COLOR: #cc7832">function</span>() { DisplayTooltip(<span style="COLOR: #cc7832">this</span>.tooltip); };</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   32</span>         element.onmouseout =</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   33</span>             <span style="COLOR: #cc7832">function</span>() { HideTooltip(); };</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   34</span>         element.href = oldAreaElement.href;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   35</span>         elementArray[elementArray.length] = element;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   36</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   37</span>     <span style="COLOR: gray">// Get rid of the old map elements</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   38</span>     areaMap.innerHTML = <span style="COLOR: #a5c25c">&#8221;</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   39</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   40</span>     <span style="COLOR: gray">// Add our new elements back in</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   41</span>     <span style="COLOR: #cc7832">for</span> (<span style="COLOR: #cc7832">var</span> i = <span style="COLOR: #6897bb">0</span>; i &lt; elementArray.length; i++) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   42</span>         areaMap.appendChild(elementArray[i]);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   43</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   44</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   45</span> }</p>
</div>
<p> </p>
<p>The code above utilises jQuery which is useful, but not required to get the job done. If you are going to use another framework, just note that the map attribute (which contains the map’s ID) is prefixed with a #. You may want to get rid of that. The code above is a modified<br />
snippet of an existing class. The <em>DisplayTooltip</em> method simply takes the tooltip HTML and loads it into a custom hidden element on the page. It then displays the element and tracks the mouse position so the element moves as the user’s cursor does. The <em>HideTooltip </em>method simply hides the tooltip and resets the HTML content. Using this technique, our HTML tooltip is rendered correctly without using the <em>MapAreaAttributes</em>  property.</p>
<p> <img class="alignleft size-full wp-image-38" title="HTML tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/htmltooltip.png" alt="HTML tooltip" width="244" height="187" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>So far I have tested this method of rendering custom tooltips in Firefox, IE 7/8 and Chrome. Its a pity that this was required in the first place. I am really not sure why setting the <em>MapAreaAttributes</em>  property has such a huge impact on rendering times. If anyone could shed light on the matter, please feel free to post the detail! For now, the implementation above will suffice. Since the image map processing is performed on the client side, there is no effect on the server side processing time.</p>
<p>Hope this helps someone out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft%e2%80%99s-chart-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
