Showing posts with label sitecore. Show all posts
Showing posts with label sitecore. Show all posts

02 October 2015

Best Sitecore Accelerator - Draft

Hi Folks,

The discussion panel between three of the hottest Sitecore Accelerators in town was nice and informative though little lengthy and finished early :) ..

It would be great if we could have feature to feature comparison, well that's mine wish not everyone's or may not feasible one. Anyway I have gathered few insights and following is my take on 'Best Sitecore Accelerator'..

To judge accelerators following are the criteria, well again this is my list may not fulfilling or comprehensive.

  • Developer's Take
  1. Ease of Development
  2. Learning Curve
  3. Integration with Tools and Technology
  4. Ability of Customisation or pitfalls to it
  5. MVC Vs Web Forms
  6. BCL with Sitecore
  7. Upgrade Experience
  8. Miscellaneous Features
  • Other's Take (Marketers, Project Directors, Decision Makers etc.,)
  1. Vision or Objective of Founder
  2. Licensing 
  3. Training
  4. Support
  5. Release Cycle
  6. Accelerator Team Size / Commitment 
I am publishing this post while I have not even filled the blanks for my input for above criteria but than I want to see if someone can add more to it. I have put target to complete this post within 10th October so that while buzz of 'Sugcon 2015 NA' settles we have some great conclusion around and believe me I will not end up with 'winner lies in beholder eyes'..

15 December 2010

Sitecore Media URL

For one of my the latest projects the content editors were always trying to get the actual URL to a Sitecore media library item, but there is no easy way to see this in Sitecore. As developers we know it is in the form of /~/media/[ShortID].ashx or /~/media/[Path].ashx, but editors don't want to think about that. They just want it figured out and displayed in front of them.
What I wanted was something similar to the "Quick Info" section that gives develoeprs/admins a quick view into the important properties of a Sitecore item. This is what I came up with.

This minor change to the editor will allow a user to click on the URL of their choice and copy it to the clipboard.
To add this to your site you need a single class and a change to a pipeline.



   1:  /// <summary>
   2:   
   3:  /// The ShowMediaPath class.
   4:   
   5:  /// </summary>
   6:   
   7:  public class ShowMediaInfo
   8:   
   9:  {
  10:   
  11:      private static readonly string SECTION_NAME = "MediaInfo";
  12:   
  13:   
  14:   
  15:      /// <summary>
  16:   
  17:      /// Gets a value indicating whether this section is collapsed.
  18:   
  19:      /// </summary>
  20:   
  21:      /// <value>
  22:   
  23:      ///  <c>true</c> if this section is collapsed; otherwise, <c>false</c>.
  24:   
  25:      /// </value>
  26:   
  27:      private static bool IsSectionCollapsed
  28:   
  29:      {
  30:   
  31:          get
  32:   
  33:          {
  34:   
  35:              UrlString collapsedSections = new UrlString(Registry.GetString("/Current_User/Content Editor/Sections/Collapsed"));
  36:   
  37:              string value = collapsedSections[SECTION_NAME];
  38:   
  39:              return (string.IsNullOrEmpty(value) || (value == "1"));
  40:   
  41:          }
  42:   
  43:      }
  44:   
  45:   
  46:   
  47:      /// <summary>
  48:   
  49:      /// Processes the specified args.
  50:   
  51:      /// </summary>
  52:   
  53:      /// <param name="args">The args.</param>
  54:   
  55:      public void Process(RenderContentEditorArgs args)
  56:   
  57:      {
  58:   
  59:          Item current = args.Item;
  60:   
  61:          if (current != null && current.Template.FullName.StartsWith("System/Media"))
  62:   
  63:          {
  64:   
  65:              MediaItem mediaItem = current;
  66:   
  67:   
  68:   
  69:              if (mediaItem != null)
  70:   
  71:              {
  72:   
  73:                  bool renderMediaInfo = !IsSectionCollapsed || UserOptions.ContentEditor.RenderCollapsedSections;
  74:   
  75:   
  76:   
  77:                  args.EditorFormatter.RenderSectionBegin(args.Parent,
  78:   
  79:                      "MediaInfo",
  80:   
  81:                      SECTION_NAME,
  82:   
  83:                      "Quick Info (Media)",
  84:   
  85:                      "People/32x32/atom.png",
  86:   
  87:                      IsSectionCollapsed,
  88:   
  89:                      UserOptions.ContentEditor.RenderCollapsedSections);
  90:   
  91:   
  92:   
  93:                  if (renderMediaInfo)
  94:   
  95:                  {
  96:   
  97:                      RenderMediaInfo(args, mediaItem);
  98:   
  99:                  }
 100:   
 101:   
 102:   
 103:                  args.EditorFormatter.RenderSectionEnd(args.Parent, renderMediaInfo, true);
 104:   
 105:              }
 106:   
 107:          }
 108:   
 109:      }
 110:   
 111:   
 112:   
 113:      /// <summary>
 114:   
 115:      /// Renders the media info.
 116:   
 117:      /// </summary>
 118:   
 119:      /// <param name="args">The args.</param>
 120:   
 121:      /// <param name="mediaItem">The media item.</param>
 122:   
 123:      private static void RenderMediaInfo(RenderContentEditorArgs args, MediaItem mediaItem)
 124:   
 125:      {
 126:   
 127:          StringBuilder sectionText = new StringBuilder();
 128:   
 129:   
 130:   
 131:          sectionText.Append("<table cellpadding=\"4\" cellspacing=\"0\" border=\"0\">");
 132:   
 133:          sectionText.Append("<col style=\"white-space:nowrap\" align=\"right\" valign=\"top\" />");
 134:   
 135:          sectionText.Append("<col style=\"white-space:nowrap\" valign=\"top\" />");
 136:   
 137:   
 138:   
 139:          // we will give them absolute URL's
 140:   
 141:          MediaUrlOptions o = new MediaUrlOptions { AbsolutePath = true };
 142:   
 143:   
 144:   
 145:          // Get the path of the media item using it's path
 146:   
 147:          o.UseItemPath = true;
 148:   
 149:          sectionText.Append("<tr><td>Url by Path:</td><td>");
 150:   
 151:          sectionText.AppendFormat("<input class=\"scEditorHeaderQuickInfoInput\" readonly=\"readonly\" onclick=\"javascript:this.select();return false\" value=\"{0}\"/>", MediaManager.GetMediaUrl(mediaItem, o));
 152:   
 153:          sectionText.Append("</td></tr>");
 154:   
 155:   
 156:   
 157:          // Get the path of the media item using it's ID
 158:   
 159:          o.UseItemPath = false;
 160:   
 161:          sectionText.Append("<tr><td>Url by ID:</td><td>");
 162:   
 163:          sectionText.AppendFormat("<input class=\"scEditorHeaderQuickInfoInput\" readonly=\"readonly\" onclick=\"javascript:this.select();return false\" value=\"{0}\"/>", MediaManager.GetMediaUrl(mediaItem, o));
 164:   
 165:          sectionText.Append("</td></tr>");
 166:   
 167:   
 168:   
 169:          // is it File or DB media?
 170:   
 171:          sectionText.Append("<tr><td>Media Location:</td><td>");
 172:   
 173:          sectionText.Append(mediaItem.FileBased ? "File System" : "Database");
 174:   
 175:          sectionText.Append("</td></tr>");
 176:   
 177:   
 178:   
 179:          sectionText.Append("</table>");
 180:   
 181:   
 182:   
 183:          args.EditorFormatter.AddLiteralControl(args.Parent, sectionText.ToString());
 184:   
 185:      }
 186:   
 187:  }
You will need also to modify a pipeline. I would suggest creating a ShowMediaInfo.config in the /App_Config/Include directory with the following:


   1:  <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   2:   
   3:    <sitecore>
   4:   
   5:      <pipelines>
   6:   
   7:        <renderContentEditor>
   8:   
   9:          <processor patch:before="processor[@type='Sitecore.Shell.Applications.ContentEditor.Pipelines.RenderContentEditor.RenderSkinedContentEditor, Sitecore.Client']"
  10:   
  11:                     type="NAMESPACE.ShowMediaInfo, ASSEMBLY" />
  12:   
  13:        </renderContentEditor>
  14:   
  15:      </pipelines>
  16:   
  17:    </sitecore>
  18:   
  19:  </configuration>

The idea for this was based on some code that a colleague of mine at Hedgehog Development had written.
Author:- Sean Kearney
Source:- http://seankearney.com/2010/08/default.aspx

Visual Studio Projects and Sitecore

This is a topic that I've been meaning to cover for some time now, but it is this post by John West that pushed me to do it sooner rather than later.
There are basically two ways of working with Sitecore.
  1. Your solution, and code, is fully immersed in the Sitecore web site.
  2. Your solution, and code, is outside of Sitecore's web site and you use some post build process to deploy.
John's post, and Sitecore documents, suggests that you go with option 1. I, however, do not agree that this is the right way to go. I feel that my code should not be mixed in with over 6,000 of Sitecore's files. Here are some reasons:
  1. The most important advantage is a clear understanding of the ownership of files in the solution. Everything checked into source control is explicitly owned by the solution being developed. All other files are owned by Sitecore or a third party package installed in Sitecore.
  2. I want to be able to distinguish my files from Sitecore's just by looking on the file system.
  3. If I need to ship the code to my client I simply want to zip up my 'workspace' and not have to wade through out-of-the box Sitecore files.
  4. I want my development environment to be as close as possible to a production environment. This means no .cs files in my web root
I've been working outside of the web root for three years now and wouldn't consider it being any other way. In fact, I am always wondering why you would want to work out of the web root as Sitecore suggests. I spoke to a client recently, while proving support for Team Development for Sitecore, and their answer was simply, "we didn't know better." That isn't acceptable.
Here is the way I work and highly suggest you work as well.
  1. Use IIS and configure Sitecore somewhere other than C:\[Workspace]\[Client]\trunk\. For example, C:\Sitecore\[Client]\Website
  2. Create your Visual Studio solution (and projects) outside of the web root. i.e. C:\[Workspace]\[Client]\trunk\ClientWebsite.sln
  3. Add references to any Sitecore assemblies as needed. Make sure to set "Copy Local" to false as John West suggests.
  4. Use a post build step to copy the output of your compiled Web Application project to the location specified in step 1. Or, better yet, use Team Development for Sitecore to handle the deployment for you.
  5. To debug, you will need to make a change to the Web Application project. On the 'Web' tab of the properties for your Web Application project you should choose the "Use Custom Web Server" option and enter in your development Sitecore URL. Once this setting has been specified you can now press F5 to build your project and debug normally. This may require some IIS components to be enabled, depending on your system. This will also work for IIS running on a remote machine (and virtual machines) as long as remote debugging components are installed on the remote machine.
Taking this one step further, you NEED to be using source control and automated builds in your development. Continuous Integration is also a good practice and possible using Team Development for Sitecore! Cost shouldn't be an excuse either as there are free tools out there to help you with this!
We, at Hedgehog Development, have done a good number of Sitecore sites this way and we do consider this a best practice. We are able to bring new developers onto a project in minutes and can roll out builds effortlessly.
I would love to get some feedback on this. Please let me know if you love working out of the web root as Sitecore suggests.
Author :- Sean Kearney
Source:- http://seankearney.com/2010/10/default.aspx

5 worst code smells in Sitecore

Last year I wrote a blog post on doing code reviews on Sitecore. While dealing with conceptual issues it doesn’t really say what to look for in code, when evaluating the quality or to evaluate if any wrong decisions have been made when developing the solution.  Therefore I wanted to wright a post about the top 5 code smells I look for, when I am trying to evaluate or trouble shoot a Sitecore solution. These code smells often indicate that the developers have gone down the wrong road and there is something fundamentally wrong in the architecture.
So here goes:
1) Using the descendant axes in xpath expressions:
This one I especially look for, when I am looking at a site which doesn’t perform. It may be used in some cases, but very often I find that a developer has used this to generate relations between content and thereby iterating over the complete content tree. This works fine in development where there are a few hundred content items. However in production where thousands of items are created this simply breaks the performance of the site – especially after publishing which clears the HTML cache.
The descendants can be accessed in multiple ways. In XSLT it normally looks like this:
<xsl:for-each select=”$sc_currentitem/descendant-or-self::item”>
</xsl:for-each>Or like this:
<xsl:for-each select=”$sc_currentitem//item”>
</xsl:for-each>
In C# using the Sitecore API it is most often accessed like this:
item.Axes.GetDescendants()
2) XSLT Import:
This is related to a point in the post about code reviews on Sitecore, where I argue that overcomplicated functionality and logic in XSLTs, is a problem. If you need to do an import of another XSLT in your rendering, you probably do it to call a method or in another way try and reuse functionality. If you want to do this, don’t use XSLTs! XSLTs should only – if you really want to use them at all – hold simple presentations.
XSLTs can be imported like this:
<xsl:import href=”YourOtherXslt.xslt” />
3) Explicitly accessing the master database
Although this can be needed in some cases and especially in scheduled tasks or other backend functionality, most often it is because the developer haven’t thought the issue through or if they have made a wrong decision of how data entered by the user should be stored.
The master database is most often used like this in c#
Database masterDatabase = Database.GetDatabase(“master”);
If you see a call like this, your solution is most likely not ready for staging, where there is no access to the master database from the content delivery server. You should generally use something like this:
Database database = Sitecore.Context.Database ?? Sitecore.Context.ContentDatabase;
This means you operate on the context database and on the content delivery databases this will be the web database and in preview you will use the master database, which is probably what you want.
If you need to write something to the master database, you first need to decide if this is a good idea at all. If you write to the master database from your frontend, you make yourself vulnerable for malicious attack, as people from the outside can enter data into the master database. Normally we handle user entered data in a custom database or parse all user created content to ensure that the master database won’t be flooded with data.
If you really need to access the master database, you should create a service that handles access to the master database, so that your solution is ready for staged environments.
4) XSLT extension over 100 lines of code:
This point is closely related to point number 2, but I really see a lot of issues with XSLTs which have been used wrong and this creates a lot of issues later on in the project lifecycle. If you have an XSLT extension with over a hundred lines of code, chances are, that the developer made a wrong decision when creating the XSLT; instead he/she should have created a sublayout.
XSLT extensions are functional programming and you should use an object oriented approach, so my advice is not to use XSLTs at all, unless you are doing something really simple. Otherwise your solution will become harder and harder to maintain, as utility methods like the XSLT extensions are very hard to understand and couplings in the renderings themself are difficult to map.
You can find all registered XSLT extensions in the web.config under xslExtension and it looks something like this:


   1:  <xslExtensions>
   2:   
   3:    <extension mode=”ontype=”MyNamespace.XslHelper, MyAssemblynamespace=”http://www.example.net/helpersingleInstance=”true/>
   4:  </xslExtensions>
5) Clearing of cache
This may seem obvious to some, but I have seen surprisingly many methods, which cleared the entire Sitecore cache including the data and item cache. If you see this in your code and it is needed, chances are, that you have an architectural issue in your solution. It should most rarely be needed to clear the cache, unless it is after a publish and Sitecore handles this automatically. I have heard many reasons for clearing the cache including an issue, where the developer argued that it was necessary, as he wrote directly to the Sitecore database with a SQL statement, and then Sitecores cache wasn’t updated.
If you experience something like this, the issue is of cause not the cache, but that you don’t use the Sitecore API to read and write data from the database.
The caching is most often cleared like this:
CacheManager.ClearAllCaches();
This is just some of the things I have seen many times, but I know there are many other bad code smells when developing Sitecore solution. Do you have any other code smells to share?
~ by Jens Mikkelsen
Source:- http://mcore.wordpress.com/2010/08/03/5-worst-code-smells-in-sitecore/

Publishing strategies

Publishing can be quite an issue for content authors and make an impact on performance. However if you use the right strategy, there really isn’t any issues.
One of the issues with publishing can be performance. When you publish one or more items the HTML cache is cleared, which means that if you have some performance heavy presentations, it will increase the loading time of the page, until the cache has been rebuild. Further if you use the staging module and it is configured to it, all the data caches are cleared as well. This can cause the site to take up to 30 seconds to reload your pages – especially if they are data heavy. You can read more about Sitecore Caching here and read about the issues with cache and the staging module here.
Note that Sitecore recently released a staging module which supports partial item caching, but the HTML cache is still cleared. You can read more about the new module on Alex Shybas blog.
I don’t know if performance impact when publishing is specific to Sitecore or is generally a problem in most CMS’, but I reckon it is the later. However Sitecore has a special problem with regards to caching. As Sitecore isn’t page based as many other CMS’ (this is also one of its biggest advantages), it makes it difficult to have a partial cache clearing – especially with regards to HTML cache. A page can be constructed by several content items, and there are no immediate binding between a page and the items, which it is constructed of, so all HTML caches needs to be cleared even though you just publish one item.
Another issue is the usability for content authors. Some of our clients were complaining about being queued all the time when they initiated a publish and it could take a very long time before they got their content published. What often happened was that when they initiated a publish, the modal dialog reported, that they were queued. Instead of waiting for it, they closed the window and continued editing. A few minutes later they would initiate another publish, but was once again told that they were queued. When this process repeated itself for the 50 active content authors, you can imagine the queue could get quite big.
Another thing we stumbled upon was, that some content authors used publishing instead of preview. Every time they wanted to view their work in progress to check if it looked alright frontend-wise, they published the item and viewed the page as if it was already completed and ready for actual publish.
I know we are not the only Sitecore partner experiencing this, as I have talked to other implementation partners and received questions about it on Learn Sitecore.
So why do I suggest it isn’t a problem? Well… we aren’t really experience any issues with our clients or with performance issues caused by publishing anymore. This is a result of more than one thing, but the primary solution was to use scheduled publish.
I don’t know why, but using this publishing strategy this can be a really big issue for clients. We often heard remarks like: “We need to publish content immediately”… But common! I really haven’t worked with many organizations, where this is an actual issue. What content do these organizations have, which is so important, that they can’t wait 15 minutes (at tops) to be published? I have consulted clients with huge sites, which is absolutely critical to the business and the funny part is that these companies rarely have a need to have immediate publishing. They are normally used to having a longer waiting period for the rest of their web services due to replications tasks between 100s of servers and rebuilding of caching. So why do the smaller companies have a bigger need for immediate publishing? The short answer – they don’t!
So what do we do to convince our client to use scheduled publish? We do more than one thing: First of all we explain to them, what impact publishing has. Then we allow a single or a few admins to have publish rights, so that they can have immediate publishing. Further we set the “do not publish” mark on all newly created items, so that they won’t be accidently published while they’re not finished. The authors will have to unclick the setting, when they think the item is ready for publishing.
Finally we have developed something, which in my opinion is rather cool! We acknowledged that people respond best to waiting time, if they have an indication of when the waiting will come to an end. This fact is also one of the reasons why they have timers on traffic lights in Copenhagen:
Traffic light with timer
7 seconds to green light :)
We decided to use the same strategy for scheduled publishing. If the content authors would know, when the next scheduled publish is due, they would be much more satisfied with the idea of not having immediate publishing. So we – in Pentia – developed a timer which is shown in the task bar in Sitecore:
scheduled publish timer
The scheduled publish timer in action
The “Trinvis udgivelse” is Danish and mean incremental publish. So this timer tells the content author, that there is 12 minutes and 48 seconds to the next incremental publish. The functionality also supports multiple timers, so on some solutions we also use it to indicate, when an import from an external database is due and so forth. Cool, right?
These things combined we really don’t have any issues, with convincing our clients to use scheduled publishing.
~ by Jens Mikkelsen
Source:- http://mcore.wordpress.com/2010/01/22/publishing-strategies/

Agile Sitecore design

It been a while since my last blog post – my second child Annika was born March 16th and since then I’ve been forced to realize that two children takes up a lot of blog-writing time.
A year ago I wrote a post titled Type before function, which pointed out the very type-centric design of Sitecore. Since then, we have in Pentia tried to develop a design practice which focuses more on isolating logically grouped functionality in our design and thinking outside the type-centric nature of Sitecore. For this purpose, we have “invented” the term component in our design. The purpose of components is to separate the functionality from the type, allowing the developer to focus on one purpose and its interfaces.
The practise has been quite successful – our large-scale solutions have become increasingly easy to maintain and extend. As a side effect of the process, we now have a high degree of reuse – not just knowledge, but actual code – between even seemingly un-similar projects. Not very surprisingly, it turns out that developers are more inclined to reuse code, which is easily overviewed. The design practice is so successful, that we have passed it on to external projects, through our Professional Services.
Here are a few tips on getting you started:

Consistent placement and naming

Not all items belonging to a component can be placed together. Naming and placement makes it easier to identify component items – in a type-centric system.
Keep your files together – we never use the standard Sitecore folders, e.g. /xsl and /layouts. All files in a component are placed below a folder named /Components/[ComponentName]. This makes it easy to identify which files belong together without e.g. garbling the filename with unnecessary prefixes. And if you think about it, it’s not hard to identify a file as an XSLT – so why put it in the/xsl folder? Keeping component items together also goes for templates, renderings and layouts in Sitecore. For the purpose of Sitecore best practice, we still place templates under /sitecore/templates (although I suppose it’s not strictly necessary), and layout items under /sitecore/layouts. But we always use subfolders which are named consistently, e.g. /sitecore/templates/Components/[ComponentName].

Component projects

Each component has a separate Visual Studio project, and therefore a separate assembly. Aside from grouping files even further, this also helps to identify dependencies between components. Use build events on the project to move files from component folders to website folders if needed.

Interface templates

Think of templates in Sitecore as interfaces – never basetypes – which provide your pagetypes or data items with certain functionality. Always refer to these interfaces in the code within the components.
Example: The component Navigation (menu, breadcrumb and sitemap) defines the template Navigable with the fields Menu Title and Show In Menu. This template is assigned to the pagetypes which can be shown in the menu. The renderings Menu.xslt and Breadcrumb.xslt only references the Navigable template by using the XslHelper.IsItemOfType() method (or your own more optimized version).

Common components

There are a number of components which is always in a project, and which brings the functionality of the other components together.
The Design component contains all the graphic design for the project. Do not be tempted to place stylesheets and graphics within each component – the design for a single component is always related to other components, and therefore you will be forced to create unnecessary dependencies.
The PageTypes component brings together the interface templates and renderings and sublayouts in the other components on the actual page type template. Only page type templates are instantiated in the content tree. If you define the page type template News in the News component and not in the PageTypes component, you will be forced to create dependencies to other components e.g. Navigation.

Dependencies and Inversion of control

Keep your dependencies amongst components as few and as obvious as possible. It should not be necessary for a developer to know more than the component he is working on – too many dependencies makes the components too complex and less flexible. The common components is one way to reduce dependencies, another is the use of the inversion of control pattern and possibly an IoC container. Suppose the News component uses the Indexing component for providing data quickly. This could naturally be done by calling the indexing component directly through the News code, thereby creating a dependency. Alternately the News component could provide an appropriate interface which defines its necessary functionality. This interface could be implemented by the Indexing component and instantiated though Reflection or an IoC container like Unity or Spring, thereby inverting the dependency and making the News component more lean.

Cleanup html with one button click

It is possible to create your own buttons in the rich text editor. This can be used to create your own functionality. For instance I recently had to make a button that cleans up the HTML entered in a rich text field. Now this functionallity is allready present in Sitecore, but it is devided into 5 steps. E.g. remove font tags, remove span tags etc.
In this particullar case we wanted a button to perform a cleanup tasks, that included three of these methods. Instead of clicking three times to remove font tags, css styling and word formatting, we needed to create a button that did all of these tasks, by clicking one time only. This can be done by:

Step 1:
Create the button in Sitecore. The buttons for the editor is found in here: Sitecore > System > Settings > Html Editor Profiles > Rich Text Default > Toolbar X.
Now copy an existing button and rename it to what ever you like. In this instance we'll call it CustomCleanup. In the field "Click" you can enter a string, that will be fired when the button is clicked. You can later catch when this message is fired. Put in what ever string you like. In this case we'll enter "CustomCleanupTask".

Step 2:
Now we need to catch the message. This is done in the javascript file: sitecore/shell/Controls/Rich Text Editor/RichText Commands.js. Now add the following to the file:



   1:  RadEditorCommandList["CustomCleanupTask"] = function(commandName, editor, tool) {
   2:   
   3:  /* Fire new events */
   4:  editor.Fire("CSS",tool);
   5:  editor.Fire("FONT",tool);
   6:  editor.Fire("WORD",tool);
   7:   
   8:  };
P.s. you can alter the icon on the button, by adjusting the Icon field on the button. This path is taken from /sitecore/shell/RadControls/Editor/Skins/*/Buttons

Now you have your new functionality. Remember to clear the cache.

Relational Data 1 - Indexing

All though a bit late (been quite busy), here is the first post about relational data.
As I described you might want to do some relational operations on data structured as a hierarchy in Sitecore. The example was news which might need to be sorted and listed on the frontpage or similar, is the one I am going to address first.

Most of the times when I stumble upon issues like this, I solve it with indexing. That is building a relational data set from the hierarchy. When working for clients, most of the times I have solved this issue using Ankiro. However Ankiro cost money, so I thought I would try it out with Lucene. Below you can see an example of how to do this.

Please note that by default Lucene doesn’t index on publish, but by a scheduled task that as default runs every five minute. However it is possible to customize Lucene to index on the publish event.

Well here it the technical description:
First of all you need to create the index containing the data you want to use as relational data. This is done pretty easy in web.config. Further reading is available on SDN (
http://sdn5.sitecore.net/FAQ/API/Indexing%20a%20Database%20with%20Lucene,-d-,NET.aspx)
Basically you define the index in the <indexes> element :



   1:  <index id="newsIndex" singleInstance="true" type="Sitecore.Data.Indexing.Index, Sitecore.Kernel">
   2:    <param desc="name">$(id)</param>
   3:  <index id="newsIndex" singleInstance="true" type="Sitecore.Data.Indexing.Index, Sitecore.Kernel">
   4:    <param desc="name">$(id)</param>
   5:    <templates hint="list:AddTemplate">
   6:      <!-- Enter the id of your news template -->
   7:      <template>{96479B71-2C0B-4729-8301-080145F28FA6}</template>
   8:    </templates>
   9:    <fields hint="raw:AddField">
  10:      <!-- add the fields you want in your index -->
  11:      <field target="created">__created</field>
  12:      <field target="updated">__updated</field>
  13:      <field target="author">__updated by</field>
  14:      <field target="published">__published</field>
  15:      <field target="name">@name</field>
  16:      <field target="id">@id</field>
  17:      <field target="Title">Title</field>
  18:      <field target="Abstract">Abstract</field>
  19:      <field target="Release date">Release date</field>
  20:    </fields>
  21:  </index>

This defines the index. Now add it to the web database:



   1:  <database id="web" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">
   2:  ...
   3:    <indexes hint="list:AddIndex">
   4:      <index path="indexes/index[@id='newsIndex']"/>
   5:    </indexes>


You can now rebuild indexes for the web database through the Control Panel in Sitecore.

Now that you have the index, you can do you relational operations. For instance you might want to sort by date. Here is some sample code to retrieve an arbitrary number of news items from the index sorted by the “Release date” field. (I don’t like to use the system fields __updated or __created as these might change when you upgrade or similar).





public Document[] GetLatestNews(int numberOfNews)

{

  //Get the Lucene IndexSearcher

  Index newsIndex = Sitecore.Configuration.Factory.GetIndex("newsIndex");

  Database web = Sitecore.Configuration.Factory.GetDatabase("web");

  IndexSearcher searcher = newsIndex.GetSearcher(web);

 

  //I want to sort by the release date

  Sort sort = new Sort("Release date",true);

 

  //I want all documents that has the field Release date

  Query searchingxml = new WildcardQuery(new Term("Release date", "*"));

 

  //Get all the hits sorted

  Hits hits = searcher.Search(searchingxml, sort);

 

  //How many documents should be returned

  int noOfNews = hits.Length() > numberOfNews ? numberOfNews : hits.Length();

  Document[] docs = new Document[noOfNews];

 

  //Iterate over the hits and return the number of news I want as documents

  for (int i = 0; i < noOfNews; i++)

  {

    docs[i] = hits.Doc(i);

  }

  return docs; 


This returns the latest news, which you can list in your spot or whatever you want to do.

The advantages of using index’ is:
You got the advantages of a hierarchy in the backend.
The end user doesn’t feel or see any other technology then Sitecore.
It is simple and easy to implement and maintain.

The disadvantages of using index’ is:
It is replicated data. This takes up more space and I often find problems with inconsistency between index’ and Sitecore data.
You got the disadvantages of a hierarchy in the backend.



Relational data in Sitecore - Intro

Content and data in Sitecore are structured as a hierarchy. This gives a lot of advantages, but sometimes you got some relational data, that you fit into a Sitecore structure. This has some disadvantages. First of all the relational data might not be user friendly and intuitively structured, when saved in a Sitecore database. Secondly some operations that you need to perform on the data might be extremely slow, when structured as a hierarchy.

A good example of this, is something I have done on almost every solution: News and news lists. This can be structured as a hierarchy in the backend, but often requires operations on the frontend, that only performs, when the data is in a table. Something that is very normal is a front page spot, which lists the X number of latest news of a special type. This would normally require you to iterate over all items in your content structure, which doesn’t perform unless your site consist of very few nodes.

In a couple of posts on this blog, I will try and show some different solutions to the problem.

14 December 2010

Insert Options – Individual Items, Standard Values or Rules

A very common question I receive is that people don’t know anymore where to setup Insert Options. Especially with the new possibilities of the Sitecore 6.1 content management system.

Here’s my view on this:

  1. Individual item
    Rarely, you want to setup Insert Options on individual items. Something when you have a specific folder or section in your website, you might chose for this option. Keep in mind that this you always should have a valid reason.
    For example: For all my meta data I use the /Common/Folder template to store my item underneath. As these folders have only 1 specific setting(Insert Options), I’ve decided not to Subtemplate(create a new template and inherit from the Folder-template) the Folder-template, because of maintainability. Consider in that case Insert Option Rules.
  2. Branch Templates
    It’s a bad practice to set any Insert Options on Branch templates.
  3. Standard Values
    95% of the cases setup your Insert Options on Standard Values as it’s applied everywhere when you use the specific template.
  4. Insert Options Rules
    When you need to setup global conditions, like ‘All the items based on the Folder template containing the word ‘Blog’ should add the Blog Entry template as Insert Option’.
    We use it ourselves in the Marketing Center. We allow everybody to create folders, but we want them to create specific items underneath.
    Before setting up a rule, figure out if you can’t do it with Standard Values.

Trimming the list afterwards can always be done by settings up Insert Rules.
For an advanced Reference regarding these Content Infrastructure topics, please refer to Data Definition Reference.

Sorting Sitecore Items

One of the most unknown but very useful feature in Sitecore is the Subitem Sorting. Often there’s a need to sort a group of Items in a particular order. Either to create a good navigation or to help the content editor find their content.

So let’s have a look how this functionality is working. I’ve installed an empty Sitecore 6.1 installation and created a couple of sample items in a random order.


Now I want to sort my items in a less random order. Let’s order them on Display Name. To do so, I’ve to go to my Home and click on the Sorting Command:


A new windows will appear with a list of the default Sitecore Sorting settings:

In this case I select ‘Display Name’. The box below will give me an immediate preview how the new order of the Subitems looks:

image
There are plenty other options to choose, including Standard Values.
When I click on ‘Ok’, the setting will be applied and my content tree will refresh:
To reflect the change in the front-end, you’ve to publish the Home item including subitems (or execute an Incremental Publish).
Note: As always, it’s a best practice to setup Subitem Sorting on the Standard values of a template. That will make sure that all the items based on the Template will reflect the same sort order. For individual cases, you can set it up on an individual item.

To make sure that this example works fine, I’ve made sure that the name of the item is also inserted in the Title field of my Item:

imageNow I want to create a custom Sorter which sorts my items rather on Title than on Display Name. The first thing I’ve to do is to write a small class:

   1: using Sitecore.Data.Comparers;

   2: using Sitecore.Data.Items;

   3:  

   4: public class YetAnotherComparer1 : Comparer

   5: {

   6:     protected override int DoCompare(Item item1, Item item2)

   7:     {

   8:         string x = item1["title"];

   9:         string y = item2["title"];

  10:  

  11:         return x.CompareTo(y);

  12:     }

  13: }

The class implements Sitecore.Data.Comparers.Comparer. This base class forces you to implement the DoCompare method. Basically, this method reads both title values and compares it using the .NET built-in string.CompareTo().

Note: I’m using the indexer(["fieldname"]) to retrieve fields. This will never return a null, only a string.Empty when the field doesn’t exist or is empty.

Afterwards, we’ve to register the class in Sitecore. We can create an item of the template ‘Child Sorting’ (/sitecore/templates/System/Child Sorting) in /sitecore/system/settings/Subitems Sorting:

imageNow I’m able to select my item from the sorting dialog:

imageAnd from now on, my items will get sorted by title-value.

Of course this is just an example. You can think about different sorters and also use them in the front-end.

Sitecore’s VP and Founder Lars Fløe Nielsen will follow up on this post with more technical details and how to use Sitecore Sorters in the frond-end. I’ll update this post once his second article is published.