<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>image0.com blog</title>
	
	<link>http://blog.image0.com</link>
	<description>development including .net, sharepoint, and sitecore CMS</description>
	<lastBuildDate>Mon, 19 Mar 2012 03:24:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.4</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/image0" /><feedburner:info uri="image0" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Using jQuery to Send Email with Web Services</title>
		<link>http://feedproxy.google.com/~r/image0/~3/oI8V9t-wWMU/</link>
		<comments>http://blog.image0.com/web-development/using-jquery-to-send-email-with-web-services/#comments</comments>
		<pubDate>Sun, 18 Mar 2012 02:32:13 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[web services]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=514</guid>
		<description><![CDATA[Just to make sure we are all up to speed, a quick concept in extreme layman&#8217;s terms - jQuery is a front-end thing, meaning it gets your browser to do stuff, like move stuff around and change stuff after it&#8217;s &#8230; <a href="http://blog.image0.com/web-development/using-jquery-to-send-email-with-web-services/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Just to make sure we are all up to speed, a quick concept in<strong> extreme</strong> layman&#8217;s terms</p>
<p style="padding-left: 30px;">- jQuery is a front-end thing, meaning it gets your browser to do stuff, like move stuff around and change stuff after it&#8217;s already been loaded from the server.</p>
<p style="padding-left: 30px;">- Sending email is a back-end thing, meaning it requires talking to the server to send stuff.</p>
<p>Now that we are all up to speed, including my 5-month-old daughter, I think it&#8217;s clear that jQuery alone can&#8217;t do this, at least not without help.  How does jQuery get help from the server? It uses an AJAX Post method to talk to a server, in our case, a web service, to send something and then get something back in return, like a result, which could be ignored by not specifying it in the AJAX Post call.</p>
<p>For this exercise, because I prefer .NET to PHP, I will be using a very simple .NET web service to send out the email, but this task can be accomplished by any server that accepts HTTP Post commands, like a CGI script.</p>
<p>Let&#8217;s review the steps that we will take to accomplish this task:</p>
<ol>
<li>Validate form data</li>
<li>Send data to web service</li>
<li>Interpret &amp; display results from web service</li>
</ol>
<h2>Validating Form Data</h2>
<p>jQuery has a great validation plugin that is very easy to use out of the box &#8211; <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/" target="_blank">jQuery Validate</a>.  To demonstrate just how simple it is, we can validate an email form by using a css class &#8220;required&#8221; and a simple $(&#8220;emailform&#8221;).validate() in the $(document).ready function.  The other cool thing about this plugin is you won&#8217;t have to <del>write your own</del> Google for a regular expression on validating email addresses.  Check out the code example below that I borrowed from the jQuery page for this plugin (<a href="http://docs.jquery.com/Plugins/Validation" target="_blank">http://docs.jquery.com/Plugins/Validation</a>)</p>
<pre class="brush: xml; title: ; notranslate">
&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;
                    &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;script src=&quot;http://code.jquery.com/jquery-latest.js&quot;&gt;&lt;/script&gt;
  &lt;script type=&quot;text/javascript&quot; src=&quot;http://jzaefferer.github.com/jquery-validation/jquery.validate.js&quot;&gt;&lt;/script&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { font-family: Verdana; font-size: 96%; }
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }
p { clear: both; }
.submit { margin-left: 12em; }
em { font-weight: bold; padding-right: 1em; vertical-align: top; }
&lt;/style&gt;
  &lt;script&gt;
  $(document).ready(function(){
    $(&quot;#commentForm&quot;).validate();
  });
  &lt;/script&gt;

&lt;/head&gt;
&lt;body&gt;

 &lt;form class=&quot;cmxform&quot; id=&quot;commentForm&quot; method=&quot;get&quot; action=&quot;&quot;&gt;
 &lt;fieldset&gt;
   &lt;legend&gt;A simple comment form with submit validation and default messages&lt;/legend&gt;
   &lt;p&gt;
     &lt;label for=&quot;cname&quot;&gt;Name&lt;/label&gt;
     &lt;em&gt;*&lt;/em&gt;&lt;input id=&quot;cname&quot; name=&quot;name&quot; size=&quot;25&quot; class=&quot;required&quot; minlength=&quot;2&quot; /&gt;
   &lt;/p&gt;
   &lt;p&gt;
     &lt;label for=&quot;cemail&quot;&gt;E-Mail&lt;/label&gt;
     &lt;em&gt;*&lt;/em&gt;&lt;input id=&quot;cemail&quot; name=&quot;email&quot; size=&quot;25&quot;  class=&quot;required email&quot; /&gt;
   &lt;/p&gt;
   &lt;p&gt;
     &lt;label for=&quot;curl&quot;&gt;URL&lt;/label&gt;
     &lt;em&gt;  &lt;/em&gt;&lt;input id=&quot;curl&quot; name=&quot;url&quot; size=&quot;25&quot;  class=&quot;url&quot; value=&quot;&quot; /&gt;
   &lt;/p&gt;
   &lt;p&gt;
     &lt;label for=&quot;ccomment&quot;&gt;Your comment&lt;/label&gt;
     &lt;em&gt;*&lt;/em&gt;&lt;textarea id=&quot;ccomment&quot; name=&quot;comment&quot; cols=&quot;22&quot;  class=&quot;required&quot;&gt;&lt;/textarea&gt;
   &lt;/p&gt;
   &lt;p&gt;
     &lt;input class=&quot;submit&quot; type=&quot;submit&quot; value=&quot;Submit&quot;/&gt;
   &lt;/p&gt;
 &lt;/fieldset&gt;
 &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<h2>Send Data To Web Service</h2>
<p>This step is a bit more tricky, at least if you want it to be cross-browser compatible. The jQuery method is $.ajax, with type POST that looks something like the code below:</p>
<pre class="brush: jscript; title: ; notranslate">
$.ajax({
  type: 'POST',
  url: url,
  data: data,
  success: success,
  dataType: dataType
});
</pre>
<p>That&#8217;s the basic skeleton of an AJAX POST, but we will need to modify it to look like this:</p>
<pre class="brush: jscript; title: ; notranslate">
 $.ajax({
            type: &quot;POST&quot;,
            url: &quot;/services/Mail.asmx/SendMail&quot;,
            cache: false,
            contentType: &quot;application/json; charset=utf-8&quot;,
            data: &quot;{ 'body':'&quot;  + messageBody + &quot;',&quot; +
                      &quot;'to': '&quot; + msgTo + &quot;',&quot; +
                      &quot;'from': '&quot; + msgFrom + &quot;',&quot; +
                      &quot;'subject': &quot; + msgSubject + &quot;'&quot; +
                  &quot;}&quot;,
            dataType: &quot;json&quot;,
            complete: function (transport) {  if (transport.status == 200) $(&quot;#formcontainer&quot;).html(&quot;Success&quot;); else alert(&quot;Please try again later&quot;); }
        });
</pre>
<p>So here is what&#8217;s happening, and BTW &#8211; the above code uses some different variable names than the validation code above, but I am sure you can deduce that msgSubject is a variable that has the value from a textbox containing the subject :</p>
<ul>
<li><strong>type</strong> &#8211; POST (becasuse we are doing an HTTP POST)</li>
<li><strong>url</strong> &#8211; since we are using ASP.NET Web services, it follows the servicepage.asmx/webmethodname format</li>
<li><strong>cache</strong> &#8211; false (we want to make sure to send fresh form results every time)</li>
<li><strong>contentType</strong> &#8211; this is where we set up our communication type.  We can do SOAP, or JSON, the latter being a lot more lightweight.</li>
<li><strong>data</strong> &#8211; this is where your parameters get passed in.  Since we are using JSON, we will want to format the parameters with the correct string delimiters -<br />
{ &#8216;variable1&#8242;:&#8217;value1&#8242;,&#8217;variable2&#8242;,&#8217;value2&#8242;}</li>
<li><strong>dataType</strong> &#8211; same as contentType, just a different way of specifying the format</li>
<li><strong>complete </strong>- we can listen for success, error, and complete.</li>
</ul>
<h2>Interpret &amp; Display Results</h2>
<p>The reason you don&#8217;t see the success or error events up above is because, while cross-browser testing, even when the sending of the mail was successful, it was firing both success and error events.   The way to guarantee correct execution is to poll for the HTTP status after the web service executes. That&#8217;s why we are checking for transport.status being equal to 200, which is a successful HTTP code.</p>
<p>To display different results, we just need to inject the desired HTML formatted results into the div or another HTML container that houses your results by using the $(&#8220;#formcontainer&#8221;).html(&#8220;Your result&#8221;) method.</p>
<h2>Other Notes</h2>
<p>You will need to get your submit button to fire off the AJAX POST call.  You can give the button an id or class and fire up the onclick event using jQuery like  $(&#8220;imgsubmitbutton&#8221;).click(function {}); &#8211; just make sure to return false as the last line of the function, otherwise the page will refresh.</p>
<h2>Demo</h2>
<p>Of course, no post on jQuery would be complete without a demo, so I&#8217;ve put together on jsFiddle here - <a href="http://jsfiddle.net/aM7PR/55/" target="_blank">http://jsfiddle.net/aM7PR/55</a> .  Couple of notes about it:</p>
<ul>
<li>With jsFiddle, you can make mock JSON calls, so it will always come back successful.</li>
<li>If this is a &#8220;Contact Us&#8221; form, you don&#8217;t really want to have both a From and a To field, because you will be a spam magnet, so you can hard code the To email address in your web service.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/image0/~4/oI8V9t-wWMU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/web-development/using-jquery-to-send-email-with-web-services/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blog.image0.com/web-development/using-jquery-to-send-email-with-web-services/</feedburner:origLink></item>
		<item>
		<title>Lessons Learned: Upgrading Sitecore from 6.1 to 6.5</title>
		<link>http://feedproxy.google.com/~r/image0/~3/8avemvx_0aQ/</link>
		<comments>http://blog.image0.com/sitecore/lessons-learned-upgrading-sitecore-from-6-1-to-6-5/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 04:34:06 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[6.5]]></category>
		<category><![CDATA[sitecore]]></category>
		<category><![CDATA[upgrade]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=508</guid>
		<description><![CDATA[Just deployed the latest and greatest in Sitecore for my company.  The guy on the left knows what I am talking about. With the multiple languages and the complexity level of my company&#8217;s site, this was not a simple process &#8230; <a href="http://blog.image0.com/sitecore/lessons-learned-upgrading-sitecore-from-6-1-to-6-5/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.image0.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-11-at-10.20.41-PM.png"><img class="alignleft size-thumbnail wp-image-509" title="Success Meme" src="http://blog.image0.com/wp-content/uploads/2012/03/Screen-Shot-2012-03-11-at-10.20.41-PM-150x150.png" alt="Upgraded to Sitecore" width="150" height="150" /></a>Just deployed the latest and greatest in Sitecore for my company.  The guy on the left knows what I am talking about.</p>
<p>With the multiple languages and the complexity level of my company&#8217;s site, this was not a simple process of just running a couple of SQL update scripts and modifying some lines in the web.config.  This upgrade took at couple of weeks and there were a lot of lessons learned along the way.  Hopefully, my lessons will save you some time if you are going the same route.</p>
<p>By the way, shout out to <a href="https://twitter.com/#!/alexshyba" target="_blank">@alexshyba</a> once again, for pointing me to the right places and saving me hours upon hours of time.</p>
<h2>Break Tag Embedding</h2>
<p>Even though Sitecore documented this as a resolved bug, I still experienced this issue.  If there are new lines in a rich text or multi-line field, HTML break tags (&lt;br&gt;) get inserted.  While it&#8217;s usually hard to notice this, we keep XML schema in multi-line text fields, so any extraneous characters and the schema is broken.</p>
<p>The good news is, I caught this earlier and documented a fix for it here: <a title="Sitecore Multi-Line &amp; Memo Fields – Removing auto-embedded break tags" href="http://blog.image0.com/sitecore/sitecore-multi-line-removing-br-tags/" target="_blank">http://blog.image0.com/sitecore/sitecore-multi-line-removing-br-tags/</a></p>
<h2>Sitecore Query Performance</h2>
<p>If v6.1 was forgiving with overly broad queries, v6.5 won&#8217;t be.  It&#8217;s not out of spite or to teach you a lesson.  I believe there was some security code added to the internal Sitecore query mechanism.  There was a huge performance difference for me between the two versions &#8211; we are talking seconds, not milliseconds.</p>
<p>If you are on the same boat, you have 3 choices:</p>
<ol>
<li>Optimize your queries</li>
<li>Consider using Fast Query instead of the traditional Sitecore Query mechanism (read my findings on it below before you do)</li>
<li>If 1 and/or 2 do not work, I&#8217;d look into using Lucene search.</li>
</ol>
<h2>Fast Query</h2>
<p>It doesn&#8217;t take long to sell Fast Query over the traditional Sitecore Query.  When I was writing a product recommender type app that generated results based on submissions, I was sold immediately by Fast Query.  The caveat with it, of course, is that, in addition to returning unordered list results, it also doesn&#8217;t guarantee to return them in the context language.  This means that if you are on a US site and you do a Fast Query, you may get some items from other languages (if they are defined).</p>
<p>I&#8217;m not sure if it was luck or otherwise, but on v6.1, I&#8217;ve never encountered that.  Results were always from the same language.  When upgraded to v6.5, every other query had mixed results.</p>
<p>There are a couple of different ways to achieve this with the Sitecore API in C#, but you basically want to check for 2 conditions -</p>
<ol>
<li>Make sure the Sitecore Item&#8217;s <strong><em>Versions.Count</em></strong> property is greater than 0.</li>
<li>On the Sitecore Item&#8217;s Language.FirstOrDefault() language, do a Database.GetItem() passing in the Item ID and the context language.</li>
</ol>
<p>If you check StackOverflow, there is actually a pretty good code block that does both steps here: <a href="http://stackoverflow.com/a/8232087" target="_blank">http://stackoverflow.com/a/8232087</a></p>
<h2>Multi-Server Publishing &amp; EventQueue</h2>
<p>The staging module ends up being history in v6.3 and up, which is great news if you have ever had to set it up for more than 1 server &#8211; a lot of tedious configuration and painful investigation of logs if something went wrong.  In v6.3 and up, all you have to do is set EnableEventQueues property to &#8220;true&#8221; in your web.config, and it publishes your items and clears the cache correctly whether you have 1 or n balanced web servers.</p>
<h2>Web.config Consolidation</h2>
<p>My original web.config was huge in size and had a lot of country and environment specific values.  For example, my UK domain on staging was different from my UK domain on production.  Both had to be specified in the &lt;sites&gt; section of the web.config.  In addition to it being a pain to manage it from a size perspective, there was also the risk of it being overwritten by someone who didn&#8217;t know any better.</p>
<p>For Sitecore configuration, your App_Config directory includes an /Includes directory. What a catchy name, right? In here, you can extract your Sitecore configuration from the web.config and then just dump it here.  Just make sure your file has a .config extension for it to get picked up.  The IntoTheCore blog has a really good post on how to do this here: <a href="http://intothecore.cassidy.dk/2009/05/working-with-webconfig-include-files-in.html" target="_blank">http://intothecore.cassidy.dk/2009/05/working-with-webconfig-include-files-in.html</a> .</p>
<p>There is a neat way of seeing exactly what gets cooked up at runtime, as far as your Sitecore configuration goes.  Try opening up http://[yoursite]/sitecore/admin/showconfig.aspx to get an XML dump of your Sitecore configuration.</p>
<p>Please note that a) this only includes your Sitecore configuration, as opposed to &lt;system.web&gt; or other non-Sitecore related configuration data, and b) you can&#8217;t include non-Sitecore configuration in the /Includes folder.  You can extract modules from the web.config if they have an configSource or a similar property &#8211; which is what allows your DB strings to live in ConnectionStrings.config as opposed to the web.config file.</p>
<h2>Testing/Deployment Strategy</h2>
<p>So, you recompiled your code with the new version of Sitecore.Kernel.dll and your site renders.  Great.  I wouldn&#8217;t flip the switch so fast.  Keep in mind that for us, the majority of the duration for this upgrade went to testing and fixing issues.</p>
<p>What I recommend is having a QA team or at least a second set of eyes perform the regression tests side-by-side &#8211; run a box with v6.5 and have them compare it to your production environment (which is running v6.1 or something older than v6.4).</p>
<p>I had my load-balanced web servers, so to simplify deployment, I just created new blank databases for v6.5, published the entire site to them, and changed my connection string.  That way, the v6.1 DBs and configuration was still intact on production.</p>
<p>When the testing was completed, all I had to do was clone the webroot on the CD to all its load-balanced brethren and that was it &#8211; zero downtime.  Because&#8230;</p>
<blockquote><p>A little planning saves a lot of fan cleaning.</p></blockquote>
<h2>Additional Lessons</h2>
<p>- In a perfect world, we&#8217;d be able to freeze the environment &#8211; both code and content &#8211; and be done with this in 1-2 weeks tops.  But, because we don&#8217;t live in a perfect world, there were changes that were constantly happening.  For managing the code, we created 2 branches &#8211; v6.1 code branch with the assemblies currently on production, in case we needed to fix live bugs, and a v6.5 code branch in case we needed new code development to start that couldn&#8217;t wait for us to go live with 6.5.  Branching definitely worked out for us at the end.</p>
<p>- If your database is anything like ours &#8211; very big and multilingual, sometimes it&#8217;s better to start with a clean v6.5 install and port things over slowly, but confidently.  I tried an in-place upgrade about a year go.  That was only going up 2 versions, from v6.1 to v6.3.  That blew up in my face because of web.config typos.  It&#8217;s definitely easier to start clean and go from there.</p>
<h2>Conclusion</h2>
<p>I truly hope these lessons will help you in your upgrade ventures by preparing you for the &#8220;gotchas&#8221; that could stand in your way.  At the end of the day, it&#8217;s definitely worth it knowing that a) you are not obsolete anymore and running the latest and greatest (for the time being), b) you open yourself up to a full library of shared source modules and new features that weren&#8217;t available in the older versions.  My favorite one &#8211; Sitecore Azure.  By the way, I blogged about that experience as well, in a series titled &#8220;To The Cloud&#8221; here: <a title="Sitecore Azure: “To The Cloud” Series" href="http://blog.image0.com/sitecore/sitecore-azure-to-the-cloud-series/" target="_blank">http://blog.image0.com/tag/sitecore-azure-series/</a></p>
<img src="http://feeds.feedburner.com/~r/image0/~4/8avemvx_0aQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/lessons-learned-upgrading-sitecore-from-6-1-to-6-5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/lessons-learned-upgrading-sitecore-from-6-1-to-6-5/</feedburner:origLink></item>
		<item>
		<title>Using Sitecore Publishing Pipeline to Refresh External CDN Cache</title>
		<link>http://feedproxy.google.com/~r/image0/~3/vemdkjnC428/</link>
		<comments>http://blog.image0.com/sitecore/using-sitecore-publishing-pipeline-to-refresh-external-cdn-cache/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 00:28:52 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[processor]]></category>
		<category><![CDATA[publishing]]></category>
		<category><![CDATA[sitecore]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=471</guid>
		<description><![CDATA[This is either one of those things you may never have to use, or you come across a requirement and realize this is exactly what you need and just didn&#8217;t know what it was called.  I fell into the latter &#8230; <a href="http://blog.image0.com/sitecore/using-sitecore-publishing-pipeline-to-refresh-external-cdn-cache/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is either one of those things you may never have to use, or you come across a requirement and realize this is exactly what you need and just didn&#8217;t know what it was called.  I fell into the latter category when I needed to programmatically refresh images in my media library that were cached in my company&#8217;s content delivery syndicator &#8211; Akamai.   Thankfully, <a href="http://twitter.com/alexshyba" target="_blank">@AlexShyba</a> pointed me in the right direction.</p>
<p><strong><span style="text-decoration: underline;">Goal<br />
</span></strong>Clear external image/CDN cache when a media item gets published.</p>
<p><strong><span style="text-decoration: underline;">Solution</span></strong></p>
<p>The <strong>PublishProcessor</strong> object is located in the <em>Sitecore.Publishing.Pipelines.Publish</em> namespace. We will need to inherit from this object to your own class and override the Process(PublishContext) method with our own custom functionality.</p>
<p>The PublishContext that&#8217;s passed in by Sitecore&#8217;s publishing processor has a list of items being published.  All we have to do is iterate through the list and use the Sitecore Item&#8217;s Path.IsMediaItem property to determine if it&#8217;s a media library item or not.  If it is, we just pass it or its full path to a custom method and use whatever API is provided by your CDN of choice to force refresh on it.</p>
<p>This is all being done in a separate Visual Studio project, so when we are done, we get a nice assembly .dll file out of it that we attach to the publish processor in our web.config.</p>
<p><strong><span style="text-decoration: underline;">The Code</span></strong></p>
<pre class="brush: csharp; title: ; notranslate">
using Sitecore.Data;
using Sitecore.Data.Engines;
using Sitecore.Data.Managers;
using Sitecore.Diagnostics;
using Sitecore.Publishing.Pipelines.Publish;

namespace Sitecore.Custom
{
	public class CacheClearer : PublishProcessor
	{
		private readonly List _cacheQueue = new List();

		public override void Process(PublishContext context)
		{
			Assert.ArgumentNotNull(context, &quot;context&quot;);
			ProcessPublishedItems(context);
		}

		protected virtual void ProcessPublishedItems(PublishContext context)
		{
			if (context == null || context.PublishOptions == null || context.PublishOptions.TargetDatabase == null)
			{
				Log.Error(&quot;Context and/or publish settings are null&quot;,this);
				return;
			}

			ProcessHistoryStorage(context.PublishOptions.TargetDatabase); //this updates the housekeeping fields

			Log.Debug(&quot;There are &quot; + _cacheQueue.Count + &quot; items in the cache queue&quot;);

			var mediaUrls = = new List&lt;string&gt;();

			foreach (var id in _cacheQueue)
			{
				if (context.PublishOptions.TargetDatabase.Items.GetItem(id) != null)
				{
					var item = context.PublishOptions.TargetDatabase.Items[id];
					if (item.Paths.IsMediaItem)
						mediaUrls.Add(akamaiPath);

				}

			}

			SomeCustomCDNProcessor.RefreshMediaUrls(mediaUrls);

			Log.Info(&quot;*** Processing cache clear for item: &quot; + id, this);
		}

		private void ProcessHistoryStorage(Database database)
        {
            _cacheQueue.Clear();

            var utcNow = DateTime.UtcNow;

            // accessing the date of last operation
            var from = LastUpdateTime(database);

            //Log.Debug(&quot;Last Update Time: &quot; + from);
            //Log.Debug(&quot;Database: &quot; + database.Name);
            // get the history collection for the specified dates:
            var entrys = HistoryManager.GetHistory(database, from, utcNow);
            //Log.Debug(&quot;entry count: &quot; +entrys.Count);
            if (entrys.Count &gt; 0)
            {
                foreach (var entry in
                    entrys.Where(entry =&gt; !_cacheQueue.Contains(entry.ItemId) &amp;&amp; entry.Category == HistoryCategory.Item))
                {
                    _cacheQueue.Add(entry.ItemId);
                    database.Properties[LastUpdate] = DateUtil.ToIsoDate(entry.Created, true);
                }
            }

            // writing back the date flag of our last operation
            database.Properties[LastUpdate] = DateUtil.ToIsoDate(utcNow, true);
        }

        protected DateTime LastUpdateTime(Database database)
        {
            var lastUpdate = database.Properties[LastUpdate];

            if (lastUpdate.Length &gt; 0)
            {
                return DateUtil.ParseDateTime(lastUpdate, DateTime.MinValue);
            }

            return DateTime.MinValue;
        }

 }
}
</pre>
<p>The web.config changes are as follows:</p>
<pre class="brush: csharp; title: ; notranslate">
&lt;publish help=&quot;Processors should derive from Sitecore.Publishing.Pipelines.Publish.PublishProcessor&quot;&gt;
        &lt;processor type=&quot;Sitecore.Publishing.Pipelines.Publish.AddLanguagesToQueue, Sitecore.Kernel&quot; /&gt;
        &lt;processor type=&quot;Sitecore.Publishing.Pipelines.Publish.AddItemsToQueue, Sitecore.Kernel&quot; /&gt;
        &lt;processor type=&quot;Sitecore.Publishing.Pipelines.Publish.ProcessQueue, Sitecore.Kernel&quot; /&gt;
        &lt;processor type=&quot;Sitecore.Custom.CacheClearer,CustomCacheClearer&quot; /&gt;
 &lt;/publish&gt;
</pre>
<img src="http://feeds.feedburner.com/~r/image0/~4/vemdkjnC428" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/using-sitecore-publishing-pipeline-to-refresh-external-cdn-cache/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/using-sitecore-publishing-pipeline-to-refresh-external-cdn-cache/</feedburner:origLink></item>
		<item>
		<title>Sitecore Azure: Walkthrough – Installation to Deployment</title>
		<link>http://feedproxy.google.com/~r/image0/~3/KtHouwuQ96E/</link>
		<comments>http://blog.image0.com/sitecore/sitecore-azure-walkthrough-installation-to-deployment/#comments</comments>
		<pubDate>Wed, 13 Jul 2011 14:52:27 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[sitecore azure series]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=445</guid>
		<description><![CDATA[My tweet from 5 days ago: &#8220;hitting the green arrow to deploy content delivery environment in #Sitecore #Azure and actually seeing it work &#8211; brings a tear to my eye.&#8221; You, too, can weep tears of joy after seeing exactly &#8230; <a href="http://blog.image0.com/sitecore/sitecore-azure-walkthrough-installation-to-deployment/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My <a href="http://twitter.com/#!/nyclamusician/status/89379762333691904" target="_blank">tweet</a> from 5 days ago:</p>
<blockquote><p>&#8220;hitting the green arrow to deploy content delivery environment in #Sitecore #Azure and actually seeing it work &#8211; brings a tear to my eye.&#8221;</p></blockquote>
<p>You, too, can weep tears of joy after seeing exactly how magical this process is.  I did bang my head against the wall a couple of times, but the wonderful support staff @ Sitecore, including Jesper Ravnsgaard, Product Manager for Sitecore, did help me reach the finish line.</p>
<p>First thing is first &#8211; you have to make sure you have met all the prerequisites and read the known issues from my <a href="/sitecore/sitecore-azure-installation-prerequisites-known-issues/" target="_blank">previous post</a>.  The second thing you want to do is download the Windows Azure SDK from <a href="http://www.microsoft.com/windowsazure/sdk/" target="_blank">here</a>.  The third thing is download the latest version of Sitecore Azure from <a href="http://sdn.sitecore.net/Products/Sitecore%20Azure/Download%20Sitecore%20Azure.aspx" target="_blank">here</a>, which is currently at version 1.0.4.  If you read my previous post, you should have already sent out a request for and received a Sitecore Azure environment file.  You cannot proceed without it.  So don&#8217;t try.  Seriously. Don&#8217;t.</p>
<h3>Install The Certificate</h3>
<p>You know the &#8220;10% inspiration/90% perspiration&#8221; shpiel? Getting the certificate to work correctly was the 90% perspiration part me.  You have to follow each step verbatim, otherwise you will lose valuable time going through logs and emailing support.  If you get stuck and this post does not help you, the <a href="http://sdn.sitecore.net/upload/sdn5/products/azure/104/sitecore_azure_troubleshooting_guide-104-usletter.pdf" target="_blank">latest version of the Troubleshooting Guide</a> should help you pass this hurdle; otherwise, there is always Sitecore Support.  My problem during this is that I was working on Sitecore Azure v1.0.4, while my guide was v1.0.3.  Small detail that cost me 2 days.  No biggie.</p>
<p>To install the certificate, there are a couple of steps:</p>
<ol>
<li>Make sure you are on v1.0.4.  You will have to generate the certificate as Administrator.  The most full-proof way is via command prompt.</li>
<li>Open command prompt up as Administrator</li>
<li>cd to {your sitecore install directory}/sitecore/shell/Applications/azure.  I know that the documentation states to do it from /sitecore/admin/azure, but I was getting System.IO.FileNotFound exceptions until Sitecore Support pointed out that for v1.0.4 you need to be doing this from the former directory.</li>
<li>Type MakeCert.bat to generate and install the certificate.</li>
<li>The certificate will need read rights by the account under which the App Pool is running.  In IIS7, there is a user group called IIS_IUSRS. Make sure to grant it, along with NETWORK SERVICE read rights.  You would do this in the Certificates Snap-In under mmc.exe.  Screenshots and directions are located on page 5 of the <a href="http://sdn.sitecore.net/upload/sdn5/products/azure/104/sitecore_azure_troubleshooting_guide-104-usletter.pdf" target="_blank">Troubleshooting Guide</a>.</li>
</ol>
<h3>Know Your Rights</h3>
<p>The way Sitecore Azure deploys your files is by copying the all your web files from the website root ({sitecore install path}\{website path}) to a WebRole directory under the $data folder of your installation.  Therefore, you will need to grant read access to the NETWORK SERVICE user and IIS_IUSRS user group to the entire website root directory and its subdirectory.  In some cases, you may see that both will need write access to your web.config.  You can skip that if you are reluctant to do that, but your log files will immediately tell you if there is a problem with updating the web.config.</p>
<h3>&#8220;To The Cloud&#8221;</h3>
<p><a href="http://blog.image0.com/wp-content/uploads/2011/07/firewall.png"><img class="alignleft size-thumbnail wp-image-447" title="firewall" src="http://blog.image0.com/wp-content/uploads/2011/07/firewall-150x150.png" alt="azure firewall" width="150" height="150" /></a>Before we can proceed, part of deploying to the cloud is creating the core and web databases in your Azure account.  It won&#8217;t be able to do so until you have allowed it access via firewall rules.  You will need add to the external IP of the server you are deploying this from into the firewall rules.  You can do that by navigating to the &#8220;Databases&#8221; section of your Azure portal, selecting your database, and clicking Firewall Rules.</p>
<p><a href="http://blog.image0.com/wp-content/uploads/2011/07/sitecore-upload.png"><img class="alignleft size-thumbnail wp-image-448" title="environment upload" src="http://blog.image0.com/wp-content/uploads/2011/07/sitecore-upload-150x150.png" alt="" width="150" height="150" /></a>At this point, your certificate is installed and your permissions are set up, and your SQL Azurefirewall rules are set.  You are ready for flight takeoff.  You can now click the Sitecore &#8220;start&#8221; button and navigate to Azure.  If this is your first time running it, it will ask you to upload the environment file you received from Sitecore.  Next, if it doesn&#8217;t hang or give you any certificate errors, congratulations.  You are quite good at following directions.  If not, try again from the top.</p>
<p><img class="alignleft size-thumbnail wp-image-451" title="content delivery environment" src="http://blog.image0.com/wp-content/uploads/2011/07/createcontentdelivery-150x150.png" alt="" width="150" height="150" /></p>
<p><img class="alignleft size-thumbnail wp-image-454" title="progress" src="http://blog.image0.com/wp-content/uploads/2011/07/progress-150x150.png" alt="" width="150" height="150" /></p>
<p>Clicking the green button will start the process that will copy your website files to the data folder and deploy them to the cloud.  This process will typically take 2-5 minutes.  If you are at this point, you can breathe easy.  The rest is a piece of cake.  After the transitioning is complete, you will get a long URL where your app is hosted (something.cloudapp.net).  If you are like me, you will probably click it before you even finish reading this sentence and find nothing.  Why is this the case, you ask?</p>
<p>Your files are deployed, but your databases are blank.  Luckily, it&#8217;s an easy step &#8211; we just publish the entire site to the azure target.</p>
<p>Note: I ran into some issues here.  For some reason, when clicking &#8220;publish,&#8221; I got an error that the connection string for the azure target was missing.  I contacted Sitecore Support and they said it may have been a fluke, but in case this happens to you, just insert it manually into your /App_Config/ConnectionStrings.config file.  The exact connecting string can be found in Sitecore&#8217;s Content Manager under /System/Azure if you navigate down to the database.</p>
<p><img class="alignleft size-thumbnail wp-image-464" title="Your cloud" src="http://blog.image0.com/wp-content/uploads/2011/07/cloud-150x150.png" alt="" width="150" height="150" /></p>
<p>After it publishes, you can click on the hostname in the top Windows Azure icon which will end with cloudapp.net.</p>
<p>That&#8217;s it.  Quite an easy process if you follow the directions step by step.  It gets a little more complicated if you have additional databases, which you will have to create through SQL Azure, but other than that, this is a very straight-forward approach.</p>
<p>Do not hesitate to reach out to me with any questions or comments about this.</p>
<img src="http://feeds.feedburner.com/~r/image0/~4/KtHouwuQ96E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/sitecore-azure-walkthrough-installation-to-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/sitecore-azure-walkthrough-installation-to-deployment/</feedburner:origLink></item>
		<item>
		<title>Sitecore Azure: Installation Prerequisites &amp; Known Issues</title>
		<link>http://feedproxy.google.com/~r/image0/~3/bfEVDx_cfPU/</link>
		<comments>http://blog.image0.com/sitecore/sitecore-azure-installation-prerequisites-known-issues/#comments</comments>
		<pubDate>Wed, 29 Jun 2011 03:52:06 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[sitecore]]></category>
		<category><![CDATA[sitecore azure series]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=433</guid>
		<description><![CDATA[[UPDATE 7/13/2010]: Jesper Ravnsgaard, the product manager for Sitecore Azure, was kind enough to point out some corrections.  They are below in blue next to the crossed-out text. This post will cover the prerequisites and getting out the gate with &#8230; <a href="http://blog.image0.com/sitecore/sitecore-azure-installation-prerequisites-known-issues/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>[UPDATE 7/13/2010]</strong>: Jesper Ravnsgaard, the product manager for Sitecore Azure, was kind enough to point out some corrections.  They are below in <span style="color: #0000ff;">blue</span> next to the <span style="text-decoration: line-through;">crossed-out</span> text.</p>
<p>This post will cover the prerequisites and getting out the gate with Sitecore Azure.  If you haven&#8217;t yet received your Azure account credentials, check my <a href="/sitecore/sitecore-azure-to-the-cloud-series/">previous post</a>.</p>
<p>Also, there are two things to bear in mind.</p>
<p>1) Sitecore Azure is its beginning developmental stages, so while it may work in most common scenarios, it will not work in all (see known issues below).</p>
<p>2)  I am also new to Azure development, especially Sitecore Azure, so this is as much a learning experience for me as it is for you.  If I stumble on anything contradictory in future posts, I will be sure to update any incorrect details.</p>
<h3>Known Issues</h3>
<p>Before you continue, it&#8217;s important to see if there are any deal-breakers.  The following are some important considerations from the <a href="http://sdn.sitecore.net/upload/sdn5/products/azure/sitecore_azure_troubleshooting_guide_103-usletter.pdf" target="_blank">Sitecore Azure Troubleshooting Guide</a>.</p>
<ul>
<li>Sitecore Azure does not support file media.  An example of this would be an app that lets a user upload a picture to the file system.</li>
<li><span style="text-decoration: line-through;">Cherry-picked file deployments to the content delivery environment are currently not doable.  If you want to deploy even something as small as a CSS or a javascript, you will have to deploy the entire solution.</span></li>
<li><span style="color: #0000ff;">There is an update button.  It looks for files that are different from the files deployed in the cloud and copies the delta.  On the one hand, it doesn&#8217;t overwrite the entire solution, but on the other hand, it copies the entire delta, so if you wanted to deploy a newer CSS file, but not the newer javascript file, you would have to 1) </span><span style="color: #0000ff;">backup the files you don&#8217;t want deployed, 2) restore them to the stable versions on production, 3) click the update button, and 4) restore your changed files.</span></li>
<li><span style="color: #0000ff;">For emergency file patching, you have RDP access to the instances.</span></li>
</ul>
<p>The last prerequisite before the install is getting your Sitecore Azure Environment File.  I am going to request mine as soon as this post is published.  To get your environment file, email <a href="mailto:azure.accounts@sitecore.net">azure.accounts@sitecore.net</a> with the following information:</p>
<ul>
<li>The location, hostname, login and password for the Microsoft Azure DBServer(s).</li>
<li>Your Certificate file: /sitecore/admin/azure/certificate.cer file from Sitecore Azure installation.</li>
<li>Your Sitecore license file</li>
</ul>
<p>I have yet to request and receive mine, but when I do, I&#8217;ll be sure to post the installation details with some screenshots and walk you through the installation.  In the meantime, please refer to the following Sitecore documents for detailed information:</p>
<ul>
<li><a href="http://sdn.sitecore.net/upload/sdn5/products/azure/getting_started_with_sitecore_azure_103-usletter.pdf" target="_blank">Documentation</a></li>
<li><a href="http://sdn.sitecore.net/upload/sdn5/products/azure/sitecore_azure_troubleshooting_guide_103-usletter.pdf" target="_blank">Troubleshooting Guide</a></li>
<li><a href="http://sdn.sitecore.net/Products/Sitecore%20Azure/Release%20Notes.aspx" target="_blank">Release Notes</a></li>
</ul>
<img src="http://feeds.feedburner.com/~r/image0/~4/bfEVDx_cfPU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/sitecore-azure-installation-prerequisites-known-issues/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/sitecore-azure-installation-prerequisites-known-issues/</feedburner:origLink></item>
		<item>
		<title>Sitecore Azure: “To The Cloud” Series</title>
		<link>http://feedproxy.google.com/~r/image0/~3/Gnh73UCEzh8/</link>
		<comments>http://blog.image0.com/sitecore/sitecore-azure-to-the-cloud-series/#comments</comments>
		<pubDate>Tue, 21 Jun 2011 23:31:00 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[sitecore]]></category>
		<category><![CDATA[sitecore azure series]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=418</guid>
		<description><![CDATA[For those that follow my blog closely, you probably noticed that frequency of my posts has slightly decreased. Despite the workload, Azure has been a hot topic and has been bugging me for attention for quite a bit now. I &#8230; <a href="http://blog.image0.com/sitecore/sitecore-azure-to-the-cloud-series/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For those that follow my blog closely, you probably noticed that frequency of my posts has slightly decreased. Despite the workload, Azure has been a hot topic and has been bugging me for attention for quite a bit now.</p>
<p>I don’t think my workload will free up anytime soon, but I’m going to commit to another Sitecore series of blogs called Sitecore Azure: To The Cloud. It might take some extra spare time, but I plan on documenting everything in detail in multiple posts, even if it takes a while.</p>
<p>Without further ado, the first step is going to be getting an account. You can get a trial account at <a href="http://windowsazurepass.com" target="_blank">http://windowsazurepass.com</a> with this promotion code &#8211; TBBLIF . If you are reading this after the code expires, try searching for another one unless the program has been discontinued, at which point you will have to provide a credit card.</p>
<p>Account activation will take 2-3 business days. I’ve just submitted mine. We’ll see what happens…</p>
<p><strong>[UPDATE]</strong> Found my account activated this morning.  Stay tuned&#8230;</p>
<img src="http://feeds.feedburner.com/~r/image0/~4/Gnh73UCEzh8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/sitecore-azure-to-the-cloud-series/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/sitecore-azure-to-the-cloud-series/</feedburner:origLink></item>
		<item>
		<title>Sitecore’s CustomCache – A simple implementation</title>
		<link>http://feedproxy.google.com/~r/image0/~3/irxISfSt_KI/</link>
		<comments>http://blog.image0.com/sitecore/sitecores-customcache-a-simple-implementation/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 01:53:09 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[customcache]]></category>
		<category><![CDATA[sitecore]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=408</guid>
		<description><![CDATA[Sitecore comes stocked with a custom caching mechanism in its Sitecore.Caching namespace. Unfortunately, there is not much documentation on it, but this post will hopefully shed some light on this mysterious, yet useful object known as CustomCache. To implement, you &#8230; <a href="http://blog.image0.com/sitecore/sitecores-customcache-a-simple-implementation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Sitecore comes stocked with a custom caching mechanism in its Sitecore.Caching namespace.  Unfortunately, there is not much documentation on it, but this post will hopefully shed some light on this mysterious, yet useful object known as CustomCache.</p>
<p>To implement, you will need 3 things:</p>
<ol>
<li>Your own CustomCache class</li>
<li>A CacheManager class</li>
<li>The code that will be using the cache</li>
</ol>
<h3>Your own Custom Cache class</h3>
<p>Because Sitecore.Caching.CustomCache is an abstract class, you cannot directly instantiate it, but you can inherit from it.</p>
<pre class="brush: plain; title: ; notranslate">
namespace Sitecore.Custom
{
    public class MyCustomCache : Caching.CustomCache
    {
        public MyCustomCache(string name, long maxSize) : base(name, maxSize)
        {

        }

        new public void SetString(string key, string value)
        {
            base.SetString(key, value);
        }

        new public string GetString(string key)
        {
            return base.GetString(key);
        }
    }
}
</pre>
<h3>Cache Manager</h3>
<p>You will need a static Cache Manager to &#8220;manage&#8221; your CustomCache.  This manager will instantiate the CustomCache object in the constructor.  This is where you will give it the name and the size &#8211; both of which will show up in under /sitecore/admin/cache.aspx which you will be able to clear.  </p>
<pre class="brush: plain; title: ; notranslate">
namespace Sitecore.Custom
{
    public static class CacheManager
    {
        private static readonly MyCustomCache Cache;

        static CacheManager()
        {
            Cache = new MyCustomCache(&quot;MyCustomCache&quot;,
                     StringUtil.ParseSizeString(&quot;10KB&quot;));
        }

        public static string GetCache(string key)
        {
            return Cache.GetString(key);
        }

        public static void SetCache(string key,string value)
        {
            Cache.SetString(key, value);
        }
    }
}
</pre>
<h3>Your code that calls it</h3>
<p>You can use the code below to set and get your cached values.</p>
<pre class="brush: plain; title: ; notranslate">
CacheManager.SetCache(&quot;myData&quot;,&quot;myDataValue&quot;);
string myData = CacheManager.GetCache(&quot;myData&quot;);
</pre>
<p>So why use this as opposed to the .NET cache out of the box? For me, it&#8217;s the simple convenience of having it clear anytime I do a Sitecore publish operation.  </p>
<p>That&#8217;s all there is to it.  </p>
<img src="http://feeds.feedburner.com/~r/image0/~4/irxISfSt_KI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/sitecores-customcache-a-simple-implementation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/sitecores-customcache-a-simple-implementation/</feedburner:origLink></item>
		<item>
		<title>Inside Look at a Real World Web Project – Planning, Strategy, Design, and Implementation</title>
		<link>http://feedproxy.google.com/~r/image0/~3/AiXOVgOX2iI/</link>
		<comments>http://blog.image0.com/sitecore/inside-look-at-a-web-project/#comments</comments>
		<pubDate>Wed, 18 May 2011 00:41:07 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=386</guid>
		<description><![CDATA[My team and I just deployed a high-profile, albeit small website for one of our brands. This article will give you an inside look at each step of this real world project, which you may not necessarily be able to &#8230; <a href="http://blog.image0.com/sitecore/inside-look-at-a-web-project/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>My team and I just deployed a high-profile, albeit small website for one of our brands.  This article will give you an inside look at each step of this real world project, which you may not necessarily be able to find in a WROX publishing book.  I will cover the project framework, overall design strategy, and working with Sitecore.  In a cross-post, one of my teammates, @kaidez [<a href="http://kaidez.com/mitchum-html5-site/" target="_blank">http://www.kaidez.com</a>], go into the detail of front-end code and some of the invaluable tools that simplified the general development of this project.</p>
<h3><strong>Project Framework</strong></h3>
<p>For our framework, we chose SCRUM.  In a 4-person web team, all sitting within reach of each other, we have found that over the years, this works best for us.  The designers know what the developers are doing and vice versa.  Like SCRUM, we are fast and efficient.  In fact, I am very proud of my team.  As a 4-person standalone web design shop, I think we&#8217;d do rather well, assuming we wouldn&#8217;t have to pay for our own healthcare.</p>
<p>In the role of ScrumMaster, the first thing I did was set up a storyboard in <a href="http://www.scrumy.com/" target="_blank">scrumy.com</a> (pronounced scruh-mee, not screw-me, which is a completely different NSFW site).  If you haven&#8217;t used this tool before, give it a try. Its drag-and-drop interface lets you create stories, associate tasks with a user, and drag-and-drop them from column to column (to-do, in progress, verify, complete). Maintaining a storyboard like this, not only puts your project manager at ease, who may be in a remote location, but also keeps the team sane when you need to get out of the coding zone and get a perspective on the project progress.</p>
<h3><strong>Design Strategy</strong></h3>
<p>If you only get one takeaway from this, it&#8217;s that no matter how small the project, proper design and planning will always serve a benefit.</p>
<p>Since we adopted Sitecore as the official CMS tool, our design was already partially established. With this being a small product informational site, our Sitecore template design was not unlike the Sitecore demo project. The difference between our solution and the demo project is the level of OOP design.</p>
<p>What I have seen with novice Sitecore developers is as soon as they start developing a site, they completely abandon n-tier architecture and OOP best practices.  Sitecore does not and should not replace a good OOP design.</p>
<p><img class="alignleft" title="3-tier design" src="http://farm6.static.flickr.com/5143/5732118842_ea12f7be6e.jpg" alt="" width="350" height="281" />Take the Product entity as an example. A Product may have a name, image, link, and a description. In a 3-tier (DAL/BLL/UI) architecture, you would create a class for it in the Business Logic Layer. In our case, we display products in a category page and in a product page. If you care about your code, there should be an alarm that goes off that detects duplicate functionality and tells you to extract it to one common place; hence, the need for our BLL assembly.</p>
<p>If you are still not seeing the benefit, consider the readability and general elegance of binding an asp:repeater to a List of products with dot notation and intellisense, as opposed the ugly DataBinder.Eval() function.</p>
<pre class="brush: plain; title: ; notranslate">
&lt;asp:Repeater ID=&quot;rptProducts&quot; runat=&quot;server&quot;&gt;
	&lt;ItemTemplate&gt;
		&lt;a href=&quot;&lt;%#((Product)Container.DataItem).Link)&quot; %&gt;
			&lt;%#((Product)Container.DataItem).Image) %&gt;&lt;br/&gt;
			&lt;%#((Product)Container.DataItem).Name) %&gt;
		&lt;/a&gt;
	&lt;/ItemTemplate&gt;
&lt;/asp:Repeater&gt;
</pre>
<p>As another best practice, you will want a Core assembly to keep track of static constants and variables. In our case, it holds the URL to our CDN which is different from environment to environment.</p>
<h3><strong>Team Development Environment</strong></h3>
<p>After the design is knocked out, I have to make sure everyone&#8217;s development environment is properly set up and wired up to TFS. I&#8217;ve seen developers skip this step until the project is complete, but I cannot stress this enough &#8211; these shortcuts will only make your life more difficult. Set up TFS before you start development and don&#8217;t forget to check in changes to avoid having other developers overwrite your changes or hearing the never-old &#8220;well&#8230; it works on my machine&#8221; phrase.</p>
<p>The Sitecore templates were done during the design phase in a true Agile environment &#8211; in a locked conference room with the entire team, so at this point, it was safe for everyone&#8217;s environment to be pointed at the same Sitecore database environment since the templates weren&#8217;t really changing.  I created the solution with by including the Sitecore files and assemblies, created BLL/Core projects, and checked everything into TFS, after which everyone did a GLV (get latest version).</p>
<h3><strong>Sitecore Deployment</strong></h3>
<p>We build this site using Sitecore v6.4.  With this version, there is no staging module that you have install like with v6.1, so I thought that after I take care of the checklist in Sitecore&#8217;s <a href="http://sdn.sitecore.net/Developer/Configuring%20Production%20Environments.aspx" target="_blank">Configuring Production Environments</a> handbook, I&#8217;d be home free, but not so.  If you want the cache to automagically clear after publish, you will have to set the EnableEventQueues property to &#8220;true&#8221; in your web.config</p>
<h3><strong>Takeaways</strong></h3>
<p>A little planning and preparation before will save you a lot of fan cleaning later.  No matter how small the project, if you are in a real world environment, chances are it will at some point grow or will probably need maintenance.  Following best practices in the beginning, you will avoid cursing yourself and/or your team when it&#8217;s time to do that maintenance or expansion.</p>
<ul>
<li>Remember to use a project framework that will fit your team and organization, whether it&#8217;s SCRUM or something else.  If it&#8217;s something else, you will still find <a href="http://www.scrumy.com" target="_blank">scrumy.com</a> to be useful for simple task management.</li>
<li>Use TFS, or something else if you don&#8217;t have TFS, for source control early on before development kicks off.</li>
<li>Do not disregard a good n-tier design just because you are working in a CMS.</li>
</ul>
<p>Check out @kaidez&#8217;s cross-blog on this topic here: <a href="http://kaidez.com/mitchum-html5-site/" target="_blank">www.kaidez.com</a>.</p>
<img src="http://feeds.feedburner.com/~r/image0/~4/AiXOVgOX2iI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/sitecore/inside-look-at-a-web-project/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.image0.com/sitecore/inside-look-at-a-web-project/</feedburner:origLink></item>
		<item>
		<title>The Power of LINQ – Sorting Lists with a single line of code</title>
		<link>http://feedproxy.google.com/~r/image0/~3/qGV_bCKDlmk/</link>
		<comments>http://blog.image0.com/c-2/the-power-of-linq/#comments</comments>
		<pubDate>Thu, 21 Apr 2011 01:44:45 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[linq]]></category>
		<category><![CDATA[orderby]]></category>
		<category><![CDATA[sort]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=382</guid>
		<description><![CDATA[This post, just like the code example, is short and to the point, because that&#8217;s how LINQ is &#8211; short, to the point, and powerful. Let&#8217;s say you have an object called Country.  There will be a List&#60;&#62; populated with &#8230; <a href="http://blog.image0.com/c-2/the-power-of-linq/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This post, just like the code example, is short and to the point, because that&#8217;s how LINQ is &#8211; short, to the point, and powerful.</p>
<p>Let&#8217;s say you have an object called Country.  There will be a List&lt;&gt; populated with it that is going to be used in a drop-down box.  It has the following properties:</p>
<ul>
<li>CountryName (string)</li>
<li>DropDownValue (string)</li>
<li>SortOrder (int)</li>
</ul>
<p>The business logic for the list is to order it by SortOrder, and then by CountryName.  You ready for the code?</p>
<pre class="brush: plain; title: ; notranslate">
var destinationList = sourceList.OrderBy(c =&gt; c.SortOrder).ThenBy(c=&gt; c.CountryName).ToList();
</pre>
<p>That&#8217;s it. You should note that the difference between OrderBy() and Sort() is that Sort() will actually resort the list you are running it on.  OrderBy() on the other hand just returns the result set, but doesn&#8217;t actually commit the order to the list; hence, the ToList() assignment to destinationList.</p>
<img src="http://feeds.feedburner.com/~r/image0/~4/qGV_bCKDlmk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/c-2/the-power-of-linq/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.image0.com/c-2/the-power-of-linq/</feedburner:origLink></item>
		<item>
		<title>Liveblog from Microsoft Mix 11 – Keynote</title>
		<link>http://feedproxy.google.com/~r/image0/~3/vVoRbN3T9KY/</link>
		<comments>http://blog.image0.com/web-development/liveblog-from-microsoft-mix-11-keynote/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 16:10:32 +0000</pubDate>
		<dc:creator>Max</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[mix11]]></category>

		<guid isPermaLink="false">http://blog.image0.com/?p=346</guid>
		<description><![CDATA[[10:29] New in Windows Azure &#8211; Access Control Service, Caching, CDN, Traffic Manager. We saw Facebook &#038; Twitter icons around ACS. Hopefully, it wasn&#8217;t just clipart and they are supported. [10:26] Umbraco CMS demo. Another .NET based open source project. &#8230; <a href="http://blog.image0.com/web-development/liveblog-from-microsoft-mix-11-keynote/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[10:29] New in Windows Azure &#8211; Access Control Service, Caching, CDN, Traffic Manager.<br />
We saw Facebook &#038; Twitter icons around ACS.  Hopefully, it wasn&#8217;t just clipart and they are supported.  </p>
<p>[10:26] Umbraco CMS demo.  Another .NET based open source project.  The twist &#8211; running on Windows Azure cloud. Currently used by mainstream sites like vogue.co.uk.<br />
Allows you to scale the instances and looks like it gives you a lot of control on the cloud.</p>
<p>[10:12] Orchard CMS Demo. Open Source project that Microsoft is contributing to.  It&#8217;s no Sitecore, but still worth taking a look at.</p>
<p>[10:10] WebMatrix helpers</p>
<p><img class="alignnone" title="WebMatrix Helpers" src="http://farm6.static.flickr.com/5184/5613880232_605f8460d5_b.jpg" alt="" width="1024" height="575" /></p>
<p>[9:58] Microsoft WebMatrix Demo.  It&#8217;s your basic website in a box. TemplateMonster sells WebMatrix templates. You set up your site by choosing the packages you want.  Packages are like WordPress plugins.</p>
<p>[9:51] Looking at a demo with MVC3.  Awesome integration with HTML5.  Didn&#8217;t see the need during MVC v1 or v2, but this may be worth taking a look at.</p>
<p>[9:45] ASP.NET MVC3 Tools Update</p>
<p><img class="alignnone" title="MVC3 Update" src="http://farm6.static.flickr.com/5225/5613233995_c2b59a8ff9_b.jpg" alt="" width="1024" height="575" /></p>
<p>[9:43] Scott Gurthrie. Starting off with a bang?? Charlie Sheen #WINNING/tigerblood joke. really? Talking about the Microsoft Web Platform</p>
<p>[9:41]IE10 Recap Slide</p>
<p><img class="alignnone" title="IE10 Recap" src="http://farm6.static.flickr.com/5267/5613801778_1851414453_b.jpg" alt="" width="1024" height="575" /></p>
<p>[9:39] Looking at SVG canvas video performance on IE10 vs. Chrome. IE10 does it faster.</p>
<p>[9:37] Microsoft PDC announced &#8211; Anaheim, CA &#8211; Sep 13-16, 2011.</p>
<p>[9:31] CSS3 columns, &#8220;Strict&#8221;, CSS gradients &#8211; all looks great on IE10.  What happened to IE9? More markup needed to do the same on Chrome than IE10, even though Chrome can do it.</p>
<p>[9:27] Looking at IE10 demo.  I need to call my QA team ASAP and get them to start cross-browser testing.  Another jab at Chrome not being able to support video hardware acceleration.</p>
<p>[9:26] It&#8217;s not about how many releases there are. It&#8217;s about how much progress is made.</p>
<p>[9:23] Wow. Xtranormal animation mocking Chrome and Websockets. Yes. This is really happening.</p>
<p><img class="alignnone" title="Xtranormal" src="http://farm6.static.flickr.com/5305/5613178833_da84c368b5_b.jpg" alt="" width="1024" height="575" /></p>
<p>[9:21] Native experiences are better.  IE9 delivers that. Browsers that optimize for the operating system are better. IE9 with Windows 7 is better.  Browsers that spread themselves over multiple OS&#8217;s can&#8217;t concentrate on optimization (really? This guy is telling Chrome to go eff itself)</p>
<p>[9:18] IE9 vs. Chrome &#8211; IE9 has hardware graphics acceleration.  Painball demo is much faster.</p>
<p>[9:13] Looking at some great HTML5 sites.</p>
<ul>
<li><a href="http://www.foursquareplayground.com/" target="_blank">Foursquare playground</a></li>
<li>Bon Jovi Tour</li>
<li>PacMan!</li>
</ul>
<p>[9:07]  Dean Hachamovitch, Corporate VP, Internet Explorer. Fan and Evangelist of HTML5.</p>
<ul>
<li>Native Experiences &#8211; best experiences</li>
<li>Web experiences &#8211; most important experiences.</li>
<li>Best web experience &#8211; IE9 with HTML5</li>
</ul>
<p><img class="alignnone" title="HTML5: Native to Windows" src="http://farm6.static.flickr.com/5110/5613717714_e97f241102_b.jpg" alt="" width="1024" height="575" /></p>
<img src="http://feeds.feedburner.com/~r/image0/~4/vVoRbN3T9KY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.image0.com/web-development/liveblog-from-microsoft-mix-11-keynote/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.image0.com/web-development/liveblog-from-microsoft-mix-11-keynote/</feedburner:origLink></item>
	</channel>
</rss>
