Release/deployment process

Perhaps there are several different ways of naming this, I am referring to the process you have for deploying your upgrades/updates to your clients’ Sitecore Production environments.

For the different projects I have worked on so far:

  • we create very detailed instructions for a technical person (the client) to deploy this to their environment
  • we create detailed instructions for a Sitecore developer to deploy this to the clients environment

There may several ways people do this, I am interested to know what could be best practices in doing so.

I have worked on a project where we have written the instructions (release notes) and have deployed this to our clients environment ourselves.  This allows us to know exactly what is going on during the deployment.

I am also interested in the particular time of day a deployment is to be carried out. Is it best to perform this during or after business hours? Is there a difference? If a Sitecore upgrade or update were to be performed outside of business hours, the effects will not be apparent until the next day and users begin working with Sitecore.

On the other hand, if this were to be carried out during business hours, potential problems can result in an outage immediately after the upgrade is deployed resulting to a un-usable Sitecore client.  A roll-back or disaster recovery plan may be performed however this may result in developers trying to resolve the problem right throughout the day and even stretch out to after business hours - this is an exact experience I have gone through.

The above may be the case for major Sitecore upgrades, what about small fixes and changes? From my experience we have managed to deploy fixes and changes during the day with no major problems.

If there are any experiences you may have or ideas that may reduce the risk of major outages or recommendations to mitigate risks for deploying fixes to Production environments I am interested to hear them :)

Integrated and Classic Pipeline mode

It’s been a very long time since I’ve posted, so here is something I thought was worth writing about seeing there might be some others out there that might find this useful.  These are some experiences I had with Integrated pipeline mode with Sitecore.

We’ve had to switch our pipeline mode in IIS7 to Integrated mode for one of our clients, I found it a little hard to come across a website that gave me a simple answer as to what this was (and in comparison to Classic mode).

Classic pipeline mode is like IIS 6.0 where requests are passed through the IIS pipeline first then the request is handled to aspnet_isapi.dll if the file extension is mapped to ASP.NET ISAPI extension and passes throguh the ASP.NET request pipeline.  It is handled by something else if the file is static or ASP etc.

Integrated pipeline mode has a single pipeline of events where both IIS native code modules and ASP.NET HTTP Modules subscribe to.  After this the file is handled by the appropriate ISAPI extension.

Our client wanted Aliases in Sitecore to work without the “.aspx” extension, switching to Integrated mode allowed this to work.  Integrated mode in Sitecore has a couple of known issues which I read through on SDN and found an interesting article here.  This all seemed a little overwhelming, as during this investigation our client’s website was already live in production.  I had to ensure that this change would not drastically affect any other areas of the website.

After switching the pipeline mode, I came across a problem where images within a virtual directory we had set up on our external slave servers were not downloading.  This was a major issue for us as we had absolutely no idea as to what had caused this.

After raising a support issue with Sitecore, it turned out the <httpModules> and <httpHandlers> sections within <system.web> needed to be commented out.  I learned that all necessary handlers for Integrated mode are handled in <system.webserver> section.

Seems so simple.  However it just so happens we were caught out on this one.  Hopefully this may make others aware of the effects Integrated mode has with their Sitecore solutions.

ShowLink Title extension

Just something little that might be of use is an xslExtension to display Titles and Titles as tooltips.

Created a ShowTitle.cs class that gets passed an Item’s ID as a string then fetches title fields; Navigation Title, or Page Title (if Navigation Title is blank), or finally the Name of the Item if both Navigation and Page Title fields are blank.

public static string DisplayTitleLink(string PageID)
{
string PageTitle = "";
string NavigationTitle = "";

Item page = Database.GetDatabase("master").GetItem(PageID);

PageTitle = page.Fields["Page Title"].ToString();
NavigationTitle = page.Fields["Navigation Title"].ToString();

if (NavigationTitle != "")
return NavigationTitle + ". ";

else if (PageTitle != "")
return PageTitle + ". ";

else
return page.Name;
}

Included this extension in the web.config file:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<xslExtensions>
<extension mode="on" type="Proj.Common.ShowTitle, Proj.Common" namespace="http://www.sitecore.net/km" singleInstance="true"/>
</xslExtensions>
</sitecore>
</configuration>

In the XSL stylesheet:

<sc:link text="{km:DisplayTitle($itemID)}" title="{km:DisplayTitleLink($itemID)}"></sc:link>

So now when my link displays it includes a “. ” after as the tooltip - this is handy for renderings such as Left Navigation or Breadcrumb for example that require proper tooltips, rather than have an extra template in the XSL stylesheet to check for Page titles.

Quick post

Hi all, just wanted to post a short note to say that my blog is still alive! I am hoping to post a lot more stuff for 2009 on Sitecore as I will be working on (hopefully) more projects this year. Thanks :)

Flash integration

Working on my first Sitecore 6 project, I was able to have some fun with flash integration.  The flash file was already provided for us from a third party, the XML feed was provided for us also, however we had to generate this dynamically with particular content in Sitecore using the format that was given to us.

With the help from my colleague Peter, we first created a blank template “XML Feed” that had no fields. Then created a layout with a single placeholder “xml” and on page load added the following:

Response.ContentType = "text/xml";

The template and the layout were both created outside of the site we were working on so they can be used globally from our CommonClient solution we also created.

In the content tree, there is a folder that holds the feeds, each feed is based on the XML Feed template and assigned the XML Feed layout. For this example, the rendering “PlacesMapFeed” is assigned to the xml placeholder to the XML Feed layout. This rendering will be gathering items under its parent “Places to Visit” that are a number of regions in New Zealand.

XML feed:

 <regions>
..
<region id="6">
<title url="http://localhost/regions/lowerNorthIsland.aspx>
<links>
<link>
<title url="http://localhost/regions/oldStPauls.aspx>
<linkURL>http://localhost/regions/oldStPauls.aspx</linkURL>
</link>
..
</links>
</region>

<region id="7">
..
</region>
</regions>

Items:

The items below, each <region></region> has a <link></link> or a certain place under that region:

In the flash file, each region has their own region id number, to ensure the correct region matches their region id number, the configuration item “PlacesMapRegions” has the names of the regions in order of their region number so they match (Lower North Island region should be id=6:

Rendering:

Variables:

<!-- variables -->
<xsl:variable name="root" select="$sc_item/ancestor-or-self::item[../../@key='sitecore']"/>
<xsl:variable name="home" select="$root/item[@key='home']"/>
<xsl:variable name="configItems" select="$root/item[@key='settings']/item[@key='configuration items']"/>
<xsl:variable name="regionIndex" select="sc:fld('Text',$configItems/item[@key='placesmapregions'])" />
<xsl:variable name="placesToVisit" select="$home/item[@key='placestovisit']"/>





Main:
<xsl:template match="*" mode="main">
<regions>
<xsl:for-each select="sc:SplitValue($regionIndex)">
<region id="{position()-1}">
<xsl:call-template name="getRegionItem">
<xsl:with-param name="regionName" select="."></xsl:with-param>
</xsl:call-template>
</region>
</xsl:for-each>
</regions>
</xsl:template>

getRegionItem:
<xsl:template name="getRegionItem">
<xsl:param name="regionName"/>
<xsl:variable name="regionItem" select="$placesToVisit/item[@key=sc:ToLower($regionName)]"/>

<title url="{sc:path($regionItem)}">
<xsl:call-template name="text">
<xsl:with-param name="itm" select="sc:item($regionItem/@id,.)"></xsl:with-param>
</xsl:call-template>
</title>
<links>
<xsl:call-template name="displayLinks">
<xsl:with-param name="regionItem" select="$regionItem"></xsl:with-param>
</xsl:call-template>
</links>
</xsl:template>

displayLinks:
<xsl:template name="displayLinks">
<xsl:param name="regionItem"/>
<xsl:variable name="placeToVisitItem" select="$regionItem/item[@template='place to visit']"/>

<xsl:for-each select="$placeToVisitItem">
<xsl:if test=".!=''">
<link>
<title url="{sc:path($placeToVisitItem)}">
<xsl:call-template name="text">
<xsl:with-param name="itm" select="."></xsl:with-param>
</xsl:call-template>
</title>
<linkURL>
<xsl:value-of select="sc:path(.)"/>
</linkURL>
</link>
</xsl:if>
</xsl:for-each>
</xsl:template>

Text:
<xsl:template name="text">
<xsl:param name="itm" select="." />

<xsl:choose>
<xsl:when test="sc:fld('Navigation Title',$itm)!=''">
<xsl:value-of select="sc:fld('Navigation Title',$itm)" />
</xsl:when>
<xsl:when test="sc:fld('Page Title',$itm)!=''">
<xsl:value-of select="sc:fld('Page Title',$itm)" />
</xsl:when>
<xsl:when test="sc:fld('__Display Name',$itm)!=''">
<xsl:value-of select="sc:fld('__Display Name',$itm)" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@name" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

The flash file shows the region and its places:

Finally, in our General Layout we reference the flash feed:

<script type="text/javascript">
// map
var flashVars2 = {
configXML: "/Feeds/PlacesMapFeed.aspx" ,
debug:"true"
};
swfobject.embedSWF("/destinations/flash/large_map.swf", "flash_map", "478", "670", "9.0.0", "/destinations/flash/expressInstall.swf" , flashVars2);
</script>

That was it! Was fun and worked nicely :)

Futureintech: First school visit

I am happy to also be part of Futureintech, a chance for a representative like myself for Datacom in an industry such as ICT, to speak with prospective students - ages range from Primary school (ages 5-13) to Secondary school (13-18) to encourage and inspire them in a career in technology.

My very first school visit was Heretaunga College and I spoke to a small IT class which then got broken down into three more interested students.  It was a great experience sharing my pathway to my current career and talking about what I went through to get here.

I was very impressed with the three students who were aged from about 15 to 17 and was suprised at how much they knew already.  They talked about using PHP, XML, SQL, some web tools such as the developer toolbar in Firefox and showed me a school website project that they were working on. Their teacher was very supportive and pleased with the work they had done and particularly, really proud of how much they had achieved so far.

Futureintech is a great program to reach out to students and bridge the gap between industry and tertiary foundations and encourage students to start thinking about their careers.  Hopefully such school visits as these can influence students to seriously think about their future in technology - hopefully developing/coding software like myself!

Sitecore Webforms for Marketers Module

Webforms for Marketers is Sitecore’s new forms module for Sitecore Version 6. It is completely embedded in the page editor (in context) and has great functionality.

I am yet to have a go at Sitecore Version 6 and the Webforms module but doesn’t look too bad so far!

Solution! IIS Doubles image size when using original file extension

Thanks to the support guys at Sitecore we were able to solve this problem with images accessed from the file system.

The solution was a change to the Web.Config file.  The ISAPI extension mapping settings have remained unchanged, however for Windows 2003 Server there is an extra step which is adding the StaticFileHandler HttpHandler to the Web.Config file.

For Windows XP:
Web.config:

<processor type="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions,  Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx</param>
<param desc="Blocked extensions (comma separated)">*</param>
<param desc="Blocked extensions that stream files (comma separated)">
</param>
<param desc="Blocked extensions that do not stream files (comma separated)">*</param>
</processor>

For Windows 2003 Server:
Web.config:

<processor type="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions,  Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx</param>
<param desc="Blocked extensions (comma separated)">*</param>
<param desc="Blocked extensions that stream files (comma separated)">
</param>
<param desc="Blocked extensions that do not stream files (comma separated)">*</param>
</processor>

Extra step for Windows 2003 Server - add StaticFileHandler HttpHandler:

<httpHandlers>
<add verb="GET,HEAD" path="*.jpg,*.txt,*.gif" type="System.Web.StaticFileHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
..
</httpHandlers>

In the path attribute we have included ALL file extensions we wish to store in Sitecore.

And now the document size of pages have decreased by almost half :)