Sitecore MVC error: IDisplayMode

Yesterday I ran into the following error while setting up a MVC project for Sitecore 7.2

Method not found: ‘System.Web.WebPages.IDisplayMode System.Web.Mvc.ControllerContext.get_DisplayMode()’.

Description: An unhandled exception occurred.

Exception Details: System.MissingMethodException: Method not found: ‘System.Web.WebPages.IDisplayMode System.Web.Mvc.ControllerContext.get_DisplayMode()’.

Problem was very easily solved by removing the Microsoft.Web.Mvc.FixedDisplayModes.dll

The dll is an old legacy fix for MVC4 and it can safely be removed when working with MVC5.

Share

Using strongly typed repeaters with Sitecore

Strongly typed repeaters has been around for a little while in .net now and I really like how it makes the front end code in my repeaters look less messy when I am using them in a Sitecore solution.

Consider the following snippet of code:

<asp:Repeater ID="repProductList" runat="server">
    <ItemTemplate>
        <h2>
            <a href="<%# Sitecore.Links.LinkManager.GetItemUrl(Container.DataItem as Sitecore.Data.Items.Item) %>">
                <sc:Text ID="header" Field="Header" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" runat="server" />
            </a>
        </h2>
        <sc:Text ID="content" Field="Product Overview" Item="<%# Container.DataItem as Sitecore.Data.Items.Item %>" runat="server" />
    </ItemTemplate>
</asp:Repeater>

In this pretty simple example I am only casting the Container.DataItem to a Sitecore item.
Now do the same thing with a typed repeater, note the “ItemType” parameter in the repeater tag:

<asp:Repeater ID="repProductList" ItemType="Sitecore.Data.Items.Item" runat="server">
    <ItemTemplate>
        <h2>
            <a href="<%# Sitecore.Links.LinkManager.GetItemUrl(Item) %>">
                <sc:Text ID="header" Field="Header" Item="<%# Item %>" runat="server" />
            </a>
        </h2>
        <sc:Text ID="content" Field="Product Overview" Item="<%# Item %>" runat="server" />
    </ItemTemplate>
</asp:Repeater>
  • No more casting of the repeater datasource item to a Sitecore item. (Costly?)
  • No need for handling ItemDataBound events where you iterate to find your controls and then set the datasource
  • You have access to the whole Item object in the repeater and can get any properties you’ll like

The same thing goes when we are building a repeater returning results from a search using Sitecore Search API, you can set your repeaters ItemType to the generic SearchResultItem provided by Sitecore or your own derived class. More on that in another post.

Share

Responsive Web Design done better with Sitecore Device detection

Responsive Web Design is the new black and there are a ton of ready frameworks and blog posts out there to help you on your way. Just as Lauren Hightower writes in this post the traditional way of doing mobile design in Sitecore is by developing roughly two sets of renderings and layouts and combining these in separate devices in Sitecore. This takes up a lot of time and it gets even harder when you create multiple devices for different smartphones, tablets and other screens. Responsive design targets all of this in a clean way letting you rely on one single layout for almost all devices.

Responsive design usually works by adding CSS and JavaScript to a page. These scripts will calculate the screen width and hide elements that are too big to fit according to the design rules. There are however some things to consider: Sending a full payload of images for a JQuery slider, that is not even shown on a small screen, might not be the best of ideas when the user is on a slow mobile connection . And that nice high resolution jpeg used as background image might take some time to download for anyone that is not on a laptop with a strong WiFi or cable connection. What if you need a separate menu structure for all mobile visitors targeting content more suited for mobile users on the run?

Sitecore off course has a solution to the above problems:

  • Sitecore rules on layouts
  • Dynamic image scaling

Setting rules on layouts

As I wrote above, the normal way of handling browsers with different screen sizes in Sitecore is by separating them using Devices. When developing with Responsive Design there is actually no need for this. Instead we can enhance the experience for the mobile user by setting rules on the renderings for the page.

Using the MobileDeviceDetector you can utilize the WURFL framework. The MDD add a set of rules to the Sitecore Rules Engine that let’s you personalize on the features of the visiting device. In the below screenshot we change the “HeroSlider” to a “HeroImage” for all visitors using mobile devices.

Change Rendering For Mobile Device

Set a different rendering when on a mobile device

Dynamic image scaling

As all Sitecore developers know, Sitecore automatically scales all images on demand. Add a querystring parameter to the image url depending on the screen width and this will make the Sitecore server scale the image to correct size before sending it to the client. More about Sitecore Image Parameters in this blog post by John West.

A couple of days ago Scott Mulligan (@scottmulligan) released his module Sitecore Adaptive Images available on the Sitecore Marketplace. Sitecore Adaptive Images is a cool add on that helps you deliver images to your visitors in a size that is adapted to their resolution.

By using responsive design, layout rules and dynamic image scaling your next Sitecore project will rock!

Share

New features in Sitecore 6.6 – Webinar

The other day I hosted a webinar going through the latest features of Sitecore 6.6 together with the two new modules Sitecore Item Web API and Sitecore Mobile SDK.

New features of Sitecore 6.6 are:

  • MVC – Sitecore now supports mixed utilization of both Web Forms and MVC development.
  • Device Simulators – ability to simulate other devices straight from the Page Editor.
  • Page Preview – lets you preview your pages exactly as they are rendered on the actual device.
  • Engagement Automation enhancements
  • Dictionary enhancements – now supports multiple dictionaries, fallback and inheritance.
  • Recycle Bin and Version Archive changes
  • Executive Dashboard updates – more filtering, better search.
  • Page Editor enhancements – a lot of new features previously only available through Content Editor.
  • Lucene upgrade – 2.9.4
  • SQL Server mirroring

Sitecore Mobile SDK is a new flexible framework that lets the developer build native mobile applications with the ability to read, create and update content in Sitecore.

In order to support Sitecore Mobile SDK, Sitecore released the Sitecore Item Web API. This is a REST-like API that returns JSON. It can be used to integrate Sitecore with f.ex. Java-based systems, build fast loading JQUERY menues or support mobile applications on any platform.

The embedded video is in Swedish, it starts with new Sitecore features and after 27 minutes I start talking about Item Web API and Mobile SDK. Enjoy!

Share

Language specific URLs in Sitecore

I got a question the other day on how to render language specific URLs in Sitecore. Language specific meaning: http://www.domain.com/company/about-us.aspx and http://www.domain.com/foretaget/om-oss.aspx

Resolving URL

When resolving a URL in Sitecore the httpRequestBegin-pipeline looks at the domain part of the URL to find the correct site defined in web.config. Somewhere along the line the context language is also resolved and added to the current request parameters. The directory part of the URL is parsed to find the matching item using the name of the items.

Note: There are of-course a lot of other processors in the
httpRequestBegin-pipeline but let's talk about them another time.

Matching correct item

Let’s say we have a rootPath and startItem defined in web.config with values “/sitecore/content/” and “/home”. Then when a directory of an incoming URL is “/company/about-us” the ItemResolver-processor will try to find an item under “/sitecore/content/home” named “company”, recursively it will look for an item under “company” named “about-us”.  If the processor can’t find an item with the corresponding name it starts looking for items with corresponding “Display name”-field value in the current request language (“Display name”-field is unversioned) and returns first item found.

Generating language specific links

In order to render the links using the “Display name”-field value there is a simple setting in the “linkManager” setting in web.config called “useDisplayName”, set this to “true” and links are generated in the display name for the corresponding language. If no display name exists item name is used instead.

<linkManager defaultProvider="sitecore">
      <providers>
        <clear/>
        <add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" shortenUrls="true" useDisplayName="true"/>
      </providers>
    </linkManager>

It is really as simple as that…

Note: While implementing this you might also want to add language
embedding to all URLs, just set "languageEmbedding" to "always"
and you are all set.

That’s it, happy coding!

Share

Moved to the other side

That’s right, I have now joined the dark side, or Sitecore as us employees prefer to call it ;-). After working for a Sitecore partner for the last 8 years I decided to jump the fence and start working for Sitecore Sweden. Nowadays I spend a few days a week in our corporate office in Copenhagen and the other days visiting our offices, partners and customers all around Sweden.

My new title at Sitecore is Solution Architect and as such I try to help the partners and customers to draw up those big solutions with integrations towards other systems and strategies for handling of content. It is less programming and more solution focus so it fits me just fine.

I have worked for Sitecore for exactly four months today and so far it is the best job I have ever had!

Share

Dynamic anchorlinks in Sitecore

In a current project we have developed a solution with pages that are compiled from several different Sitecore items. This might not seem like a strange thing since allmost all pages served by any CMS is a compilation of items one way or another.

The thing here is that we want all pages to be as modular as possible, giving the editors an easy way to add various functionality over the different pages. Instead of creating a big set of different templates serving every need we instead use a structure with one item that represents the actual page and subitems that add modular content to that page. Content can be shown as one single scrollable page or separated in tabs using JQuery. I hope to be able to elaborate on this in a future post.

Anyway, no matter if the content should be shown in one page, in tabs or in any other way we had to be able to link to the different subitems directly. As I prefer standard HTML using anchors seemed the way to go, anchors works fine in a plain scrollable page but it could also be used in JQuery tabs.

Standard Sitecore behaviour for links would be that if I would link to a subitem of a page the URL for that link would read “http://hostname/page/subitemfolder/subitem”, since the subitem has no layout Sitecore would return an error page. The link should instead read “http://hostname/page#subitem”, Since we are talking Sitecore, this if fairly easy to accomplish.

We override the linkManager section in web.config (preferably by using an include file).

<linkManager defaultProvider="sitecore">
      <providers>
        <clear/>
        <!--<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="false"/>-->
        <add name="sitecore" type="Sitecore64.LinkProvider, Sitecore64" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="false"/>
      </providers>
    </linkManager>

Then we override the LinkProvider as below.

using Sitecore.Data;
using Sitecore.Data.Managers;
using Sitecore.Data.Templates;

namespace Sitecore64
{
    public class LinkProvider : Sitecore.Links.LinkProvider
    {
        public override string GetItemUrl(Sitecore.Data.Items.Item item, Sitecore.Links.UrlOptions options)
        {
            Template template = TemplateManager.GetTemplate(item);
            if(template.DescendsFromOrEquals(ID.Parse("{B362E2E0-26D7-4E6F-908D-152DF105B10E}")))
            {
                string url = base.GetItemUrl(item.Parent.Parent, options) + "#" + item.DisplayName;
                return url;
            }
            return base.GetItemUrl(item, options);
        }
    }
}

One thing to note here is that all subitems use a common base template to define that they are actual subitems and should be addressed using a hashtag and pointing to a grandparent.

Off course you would need to add logic to verify that parent elements exists and are based on the correct template and so on.

Share

Clear fields when copying Sitecore items

On a solution we developed recently we had some fields with individual item settings that we needed to clear when the items was duplicated. To me this seemed like a task for Sitecore eventhandlers.

Eventhandlers are really easy to use and with the possibility in Sitecore to use multiple config-files it gets even easier.

I created a config file named ClearFields.config and placed it in /App_Config/Include-folder.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <events>
            <event name="item:copied">
                <handler type="Sitecore.ClearFields, Sitecore" method="OnItemCopied" />
            </event>
        </events>
    </sitecore>
</configuration>

Basically what it does is to tell Sitecore that when it copies an item and fires the item:copied event, the OnItemCopied method should be invoked from my custom class. Here are some examples and the list of arguments that can be used for events.

Next thing up would be to create some code.

using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Data.Items;
using Sitecore.Events;

namespace Sitecore
{
    public class ClearFields
    {
        protected void OnItemCopied(object sender, EventArgs args)
        {
            if (args != null)
            {
                Item item = Event.ExtractParameter(args, 1) as Item;
                if (item == null)
                    return;

                if (!string.IsNullOrEmpty(item["My field To Clear"]))
                {
                    item.Editing.BeginEdit();
                    item.Fields["My field To Clear"].Value = "";
                    item.Editing.EndEdit();
                }
            }
        }
    }
}

As you see the above code is quite easy. I get the newly created item from the event parameters, check to see that the field actually exists, sets the item in editing mode and then clears the field.

Note: In order to get the newly created item instead of the
original item, use parameter index 1 instead of 0.

Now I don’t like hard-coded values and neither should you. Fortunately Sitecore has made it easy for us developers to put settings in our config-files. Below is my slightly updated config.

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <settings>
            <setting name="ClearFields.FieldsToClear" value="header|body" />
        </settings>
        <events>
            <event name="item:copied">
                <handler type="Sitecore.ClearFields, Sitecore" method="OnItemCopied" />
            </event>
        </events>
    </sitecore>
</configuration>

As you see I have added a settings section and a setting with a pipe-separated value indicating the fields to be cleared.

My updated code now looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Data.Items;
using Sitecore.Events;

namespace Sitecore
{
    public class ClearFields
    {
        protected void OnItemCopied(object sender, EventArgs args)
        {
            if (args != null)
            {
                Item item = Event.ExtractParameter(args, 1) as Item;
                if (item == null)
                    return;
                foreach (var field in GetFieldsToClear())
                {
                    if (!string.IsNullOrEmpty(item[field]))
                    {
                        item.Editing.BeginEdit();
                        item.Fields[field].Value = "";
                        item.Editing.EndEdit();
                    }
                }
            }
        }

        private static List<string> GetFieldsToClear()
        {
            string strFields = Configuration.Settings.GetSetting("ClearFields.FieldsToClear");
            return strFields.Split('|').Select(strField => strField.Trim()).ToList();
        }
    }
}

Now the function iterates over the pipe-separated field names and clears them on the item copied or duplicated. And yes, item.Field[] supports Sitecore field IDs so you don’t need to use field names.

That’s it!

Note: Eventhandlers are powerful but could impact Sitecore
performance. The above code will execute everytime someone copies
an item in Sitecore.

Update: Remember that you need to change the values on each language if your fields are not shared.

Share

Using TortoiseMerge when upgrading Sitecore

Upgrading Sitecore has become a lot easier since the release of Sitecore 6.0.1 featuring the Update Installation Wizard.
With the UIW we get a clear overview of what files will be updated or removed, also the affected files are copied to a separate directory under the temp-folder where it is available to us should we need them. When examining the folders further there also seems to be some kind of rollback feature but I have yet to find the documentation for this, so far I have never needed to rollback an upgrade though (knock on wood).

Upgrading Sitecore is as easy as one, two, three… until you get to the web.config

Even after introducing the include-files for web.config it still consists of 3000+ lines of code. Often there are changes made here and there by developers overloading Sitecore functionality or optimizing caching and such.

Today I started to upgrade a solution from Sitecore 6.2.0 rev.091012 to 6.3.0 rev.100716, i was following the very clear instructions at SDN. Basically it is done by first changing a few rows in web.config then running UIW (around 5400 items and files affected) then doing a lot of more changes in web.config. I kind of gave up when I opened the last page of changes and my right-hand scroll quickly was shrunk to about 1/10 of the screen height.

And this was only the developing environment; I also had to do the stage and live servers with their specific web.config’s.

There should be some kind of tool for merging code-filled files… well how about TortoiseMerge? I use it all the time when my colleagues and I make changes to the same files and my commit to subversion fails. I did not know however that I could feed the program with any files I wanted. Well IT JUST WORKS!

Here’s how I did it:

First I downloaded the complete web.config for the version I was upgrading to.

Then opening TortoiseMerge without any parameters brings up this dialog

TortoiseMerge Open File Dialog

TortoiseMerge Open File Dialog

Given the fact that most of the changes was made to the new web.config I used this one as “My File” and my old web.config as “Their file”. I didn’t bother using a base file. I clicked “Ok” and started merging my changes with the new file. Basically everything marked red to the left is worth having a closer look at.

Merging files

Merging files

Then I saved the file and moved it to the web-directory restarted IIS and it worked right away.

This will save me a lot of the frustration and time when upgrading Sitecore solutions in the future.

Link to TortoiseSVN

Share

Setting up Load Balancing for Umbraco

The other day I was about to set up load balancing for Umbraco, according to this article it shouldn’t bee to hard, or so I thought…

My setup was going to be one server with database (MySQL) and Umbraco (ww01) and another server only running Umbraco (ww02). For starters everything worked on the single machine ww01, I could publish and see the new information.

I took all of my files from ww01 and put them on ww02, configured the IIS and I now had two load balanced servers, although with no publication to ww02.

Umbraco publishing

Ok next step, configuring Umbraco, this shouldn’t be to hard, I changed the “distibutedCall” to true in the file “config/umbracoSettings.config” and added my servers to the list on both servers. I tried to publish and now nothing worked, I couldn’t publish on either ww01 or ww02 and I got a lot of time-outs and other strange errors.

After a while we tried changing the setup, making ww02 publish to ww01, and this worked right away, very strange. However we needed ww01 to be the publishing server so we had to continue trying.

I wont go into details of all the things we tried before solving this, but finally we found that the problem was that “Network Service” didn’t have full rights to all of the files in IIS and when the permissions were fixed everything worked as a charm.

BTW a good way for finding errors in replication is to try to login to the webservices manually f.ex. http://server-1/umbraco/webservices/CacheRefresher.asmx and  http://server-2/umbraco/webservices/CacheRefresher.asmx from the server that should do the publishing. Both these services should be available from the publishing server.

File replication

Ok, next step was setting up file synchronization between the servers. If we add an image to the Media section on server ww01 we need to have it replicated to server ww02.

After trying for a couple of hours we gave up on the whole DFS-thing. We had a lot of warnings and errors when trying to add DFS Namespaces which are needed for replication of files between server.

Instead we found a simpler solution the Syncback freeware from 2BrightSparks. We shared the media folder on ww01 and attached it as a network drive on ww02 then we set up a synchronization with syncback and ran this and it worked. However when setting up a scheduled sync we failed again. Long story short, we were unable to set up any schedules for a non logged in user due to a local security policy setting in Microsoft Server 2008. The solution was found here by our old friend Google and a search for “Error 2147943712”.

In conclusion

Umbraco replication worked as a charm, all errors were due to microsoft policy settings or access restrictions. I feel very confident with adding a new server to the farm for better load balancing if needed in the future. One of the benefits of load balancing is that we can point the load balancer to one server while updating the other and vice-versa.

Share