Sitecore Item access based on external data

Sometimes you might want to disable read access on items in your website based on something that doesn’t reside in Sitecore, like for example external data that comes from your own database. We have run into a situation where we had purposely chosen not to use the Sitecore role provider for several reasons and found a way to still apply the necessary security checks to make sure some items were not visible for all users on our portal. Our real Sitecore user was extended with some roles in our own database and we wrote an ItemProvider that would deal with this custom scenario. The methods that override the base implementation have been decompiled and slightly adjusted to serve our needs:

And the following configuration patch:

You can see that we wrote an extension on the ‘Item’ to find out if a user has access to this item (with custom logic). You can implement your own logic that will decide if the item should be returned when using the Sitecore API to fetch items. This provider will make sure that the functionality hooks in to the regular calls you make to retrieve items.

Improving performance with custom cache keys in Sitecore

Out of the box Sitecore offers you a considerable amount of usable cache keys to improve the speed of pages served from your platform. The standard provided cache keys are quite powerful in optimising the user experience. The image below shows how we can setup a rendering to be cached based on the page it’s served at:

We selected the checkbox ‘Cacheable’ so the rendering knows it can be served from cache. With no other options selected this rendering will be rendered once from the Controller logic and View and from that point on will be served from the cache as it was rendered the first time. This is cool for renderings that only have one appearance like for example a logo on a single website platform. When you want to start varying the renderings based on other parameters like ‘data’ (the page the data is displayed at), you will notice that Sitecore generates different cache keys to serve this data.

For example:

  • We have a ‘ImageSlider’ (rendering) with the options ‘cacheable’ and ‘vary by data’ activated.
  • We place this rendering on 2 pages in Sitecore.
  • We select the same datasource for both renderings, called ‘Slider1’ with the appropriate data we want to display

Now on those two pages the rendering is placed on, Sitecore will generate a cache key looking something like this:
#ImageSlider_#data:/sitecore/content/websitename/SharedContent/ImageSliders/Slider1

Sitecore now renders this ‘ImageSlider’ once and for the other page it generates the same cachekey, resulting in serving the same html from cache.

For one of our customers we run a multi-site setup with some customisations regarding datasources. You can read more about our customisation here and specifically check ‘Queryable Datasource’. Because we made a modification to Sitecore, in our case the ‘vary by data’ option was not working as Sitecore doesn’t recognize our datasource as a correct datasource. This resulted in renderings that all got cached on the same key, even though we gave them our own custom datasource (which was valid for us).

Example:

With the following datasource:

Which enables us to setup standard templates for websites on our multi-site platform with queryable datasources, which can be very powerful.
Now with this customization we also needed our own specific variable datasource option to enable caching to the footerblocks:

Here you can see I created our own cache key called ‘VaryByDataSource’ which will retrieve the correct datasource and add it to the cache key and in turn enables us to cache this rendering. This is just an example of a custom cache key, and we also created some other cache keys like ‘VaryByWebsite’, ‘VaryByProduct’ and ‘VaryByCategory’. The vary by website cache key is very powerful when you want to make sure a rendering is always uniquely rendered on a website. Maybe your own platform requires some of these unique custom caching keys? It’s very easy to create your own actually!

Step 1:

Expand the inherited ‘Cache’ template with ID ‘{E8D2DD19-1347-4562-AE3F-310DC0B21A6C}’. You can create some new checkbox fields there, that will make sure you can select the option on all of your Controller Renderings.

Step 2:

Create a new class called ‘GenerateCacheKey’ somewhere in your solution. Make sure it’s built and available in the assembly folder of your application. Below you find an implementation (dev) that we created. The VaryByWebsite could be useful in your own scanario.

Step 3:

Override the ‘GenerateCacheKey’ class that Sitecore MVC is using to generate a cache key for a rendering:

You will notice, that for custom logic, it will be a very good idea to really think ahead about which factors have to modify the cache keys (for a rendering) to make sure you can benefit from caching without sacrificing functionality.

 

Don’t forget this when upgrading to SC9

For one of our clients we have been upgrading the Sitecore environment from 8.1 (rev. 160519) to 9.0.1 (rev. 171219). The upgrade process was doable after reading the upgrade documentation thoroughly, and just like every upgrade there are some things to look out for when upgrading your solution.

Dynamic Placeholders

Dynamic placeholders are now integrated with Sitecore and we don’t need to install extra modules anymore to make use of them. You can easily remove the reference to the old dynamic placeholder module (remove assemblies and config) and start using the Sitecore ones by just using the Sitecore Html helper and rendering a placeholder just like that. One thing to keep in mind is that the functionality is extended, and it’s now possible to render multiple placeholders by adding an integer value to the placeholder key itself: row_{FDDF4C6C-C1B8-5C6D-2B41-DB83D241634C}-2

This example will render a row placeholder with x instances of that row which can be used to nest other renderings in. Pretty handy when you need to setup a page template with 5 rows, as you don’t have to add 5 row to the page by hand. When upgrading your instance this however can be an issue if you are already using dynamic placeholders. The new format as described above is a little different then the older format. More details about this can be found here. The powershell script that is provided can be used to transform everything to the new format, but make sure that any customizations done to either the rendering of a dynamic placeholder or overall rendering of renderings to the page might need some little tweaks to the powershell script. In our case we had created a custom way of rendering a navigation element, so running this powershell would get us into trouble. Therefor we created our own script, which was suitable for this particular case.

Configs files rearranged

Sitecore has done something great again, the config files have been rearranged and are structured in a much more logical way then before. This has multiple reasons. It’s very much easy to find the relation between the functionality Sitecore offers and the folder structure in the app_config folder. For example ‘Launchpad’ now has it’s own folder, so all processors and pipelines related to the launchpad are now residing together in one folder. Offcourse only changing the way configuration files are stored doesn’t automatically mean that all configuration that can be done to an element are now done on one place as this also depends on having everything patched and sorted out in the right way, but it’s clear that Sitecore is going for a much more module / functionality based approach. The more you have already chosen for a config patching approach when customizing Sitecore, the easier it is to adept to this new way of storing the configuration by Sitecore. When merging and setting up while upgrading you will notice that some of the somewhat bigger configuration files might have been split up in 3 or more new different configuration files. Just make sure to use the right merge tools and understand the new structure before starting the merge.

MongoDB

In the past Sitecore has been forcing us to make use of MongoDB for the saving of our xPerience data (interactions, contacts, devices etc.) but with the feedback they got from the community a new approach has been  taken. In Sitecore 9 and with the first update there is no provider implemented for saving xPerience through MongoDB. This is a rather fundamental change and might cause some issues for the ones that have embraced MongoDB (like us). The reason being that Sitecore doesn’t support MongoDB for xPerience data yet, but seems to already ship the newer MongoDB drivers with a clean Sitecore 9 install. Therefor if you are using MongoDB in you application to for example store some of your application’s data you will have to upgrade to the newer MongoDB drivers, to already prevent any mismatches in the comming release of Sitecore 9 that will support MongoDB again.

Queryable datasource

Queryable datasources can be used to make sure that datasources that can be chosen for renderings can be queried from a certain context. For example:
I am placing a rendering on a website and I want the content to be chosen from a shared content folder under that particular website, so I create the following queryable datasource: ancestor-or-self::*[@@templatename=’Website’]/Shared Content/Content/*

This query will make sure that content can be picked from the ‘Content’ folder that resides under the Shared content folder of the website we are creating a new rendering on. This is cool, cause this allows us to have 1 rendering defenition that will be able to be used on more then just 1 website, and we don’t have to bother our content editors with the choice of which shared content folder the content should be picked from (as the queryable datasource will make that choice).

We ourselves found this way of working really cool and actually extended Sitecore to also be able to work with Queryable datasources in the actual datasource of a rendering itself. This means that we have the option to give our content editors the freedom of choosing content, but we can also create standard versions of pages that will have predefined renderings on the page that have queryable datasources prefilled.

For example: I have 5 footer blocks that I want to setup on standard values of the ‘Content’ page template. Every time a page gets created those blocks should be on the page. I have a multisite setup, so I cannot set the content of this footer blocks to one particular datasource as this would cause the links in that footerblock to always point to one website and I want the foolterblocks to be specific to the website itself. Instead of just creating the blocks with a set datasource i create a query like this:

2018-02-23_1141

Now when this rendering is added to the page it will look for the FooterBlock1 item under the shared content folder of the current website. We created our own MVC Controller base class that will deal with this and has a method implemented that will retrieve the datasource item:

Cool things, but in Sitecore 9 the way a datasource gets validated might cause the rendering from being displayed! In the  Sitecore.Mvc.ExperienceEditor.Pipelines.Response.RenderRendering.AddWrapper class a datasource validator is validating all the datasources. If a datasource was not validated correctly this AddWrapper class will abort the pipeline and give the following warning ‘”‘{0}’ is not valid datasource for {1} or user does not have permissions to access.” We solved this by using the AddWrapper as a base class in a new processed that we patch instead of the AddWrapper class and introduced our own Datasource validator based on the interface ‘IDatasourceValidator’.

Config:

AddWrapper method:

Datasource validator:

This made sure that renderings would be rendered even if the datasource was invalid according to Sitecore, but was valid according to our own customization (using the query: prefix on a datasource in a rendering)

Core database

We had some issues with the core database after upgrading to Sitecore 9. This may have several causes, for example a not well performed SQL script that should be run in one of the upgrade steps. For now we have just solved this the most easy way by just placing a new Sitecore 9 Core database and migrating any customizations we have done by creating Sitecore packages between the old (Sitecore 8.1) core and the new Sitecore 9 database. Offcourse this is not enough, as also users / roles and some other key things should be taken into account when migrating data from the core database, but for now this was the simple way to get ourselves ready to start fixxing the really important issues like code breaking changes and missing renderings.

Well, this concludes it all for now, I hope there are some things that will eventually help out other people that come along any of the issues described above, and I wish you all happy Sitecore-ing!

 

 

 

 

 

 

 

Extend Sitecore to allow Multisite Aliases

A while ago I released our first version of a module that is available on the Sitecore Marketplace to enable Sitecore to work with aliases in a multi-site environment.

The idea is that multiple websites can use the same alias names.

For example:
http://site1/alias1 -> points to item ‘/sitecore/content/site1/item/itemlvl2/item’
http://site2/alias1 -> points to item ‘/sitecore/content/site2/item/itemlvl2/item’
http://site3/alias1 -> points to item ‘/sitecore/content/site3/item/itemlvl2/item’

Sitecore out of the box supports only having a single aliasname across your complete environment. I have recently implemented this solution for one of our customers and extended the functionality to completely disable the standard Sitecore aliasresolver (so it doesn’t even call the base.Process method anymore). I also wrote a simple layout that you can add in your solution to convert any existing alias items so that they will work in the new multi-site strategy.

What the script does:

  • Creates alias folders under all of the website’s (from the sitedefinitions)
  • Checks all existing alias items and copies them to the newly created alias folders (based on the Target Item of the alias item). This required some logic to determine the root site for an item, but this has been built in aswell.

From then on the custom AliasResolver – that is patched from a config file which is placed in the /app_config/include folder – will resolve the items from the alias folder directly under the website instead of the System/Alias folder Sitecore normally uses.

Why is my time not displaying correct after upgrading to 8.1?

I upgraded one of our Sitecore solutions from Sitecore 6.2 (rev. 100507) to Sitecore 8.1 (rev. 151207). After the upgrade we noticed that the display of time on the website was slightly off. Instead of showing the GMT + 1 time it showed the UTC time (which is 2 hours off in our case). This caused that all newly created items (wheter it be reactions on news or news items itself) showed the wrong time. An item created on 11-04-2016 – 11:04 would be shown as 11-04-2016 – 09:04. As you might guess this wasn’t really what our customer was looking for and I haven’t stumpled upon any tips regarding this issue in the upgrade guide while upgrading the solution.

Now I have decompiled the Sitecore.Kernel and read some other posts regarding this issue I would like to share my solution to this problem. As per Sitecore documentation provided in the Sitecore.config file I looked for the Timezone I would like to use on msdn:

MSDN Article – Timezones

In my case I chose to use the “W. Europe Standard Time” so my settting in the sitecore.config file looked like this:

Now this seems all nice and ready to roll, but you aren’t done yet. If you are using for example “Sitecore.Statistics.Created” as your DateTime object and just format this date and .toString() it in any format with a time specification you will not yet see the correct time displayed. I therefor used the Sitecore.DateUtil.ToServerTime() method, which uses the ServerTimeZone setting we just specified to convert between the UTC and server time.

This results in the right date / time being shown on your website.

Hope you will find this article useful!

 

ECM Fixing HTML-anchors in ECM 2.1 rev140214 (update 3)

It’s not uncommon for newsletters to have HTML-anchors.
Imagine some news items which have a short introduction and a HTML-anchor link to the full content.

Are you running ECM 2.1 rev140214? Due to a bug Sitecore does not recognize links starting with href=’#’ as HTML-anchors.
Resulting in wrapping these in a /redirecturlpage.aspx link, which results in recipients opening the website instead of scrolling down.

Simple workaround: enter a space between href and =”#”, this prevents Sitecore recognizing the anchor as a link at all.
The anchor will still work, and it saves you the time to extend/fix/patch the problem yourself.

If you’re using SC:Link or asp:HyperLink controls, you can achieve the same result by something like this:

 

PART III: Sitecore & MVC: Dependency Injection using Castle Windsor

In the previous post we made some changes to make the use of areas a little easier. In this post we be working on controller constructor dependency injection using Castle Windsor. The problem using this type of dependency injection is that Sitecore uses its own CreateControllerInstance method to instantiate the controller class. This method does not take any constructor parameters into account. In fact is just creates the controller instance passing and new object[0] as parameter. There is a way to avoid Sitecore’s CreateControllerInstance method: Just make sure this method does not receive a fully qualified type name and its assembly as value.

Let’s start writing some basic code to make sure we can even use Castle Windsor.

WindsorControllerFactory.cs

ControllerInstaller.cs

IntializeWindsorControllerFactory.cs

Now we have created a our own (Windsor)ControllerFactory which should take care of creating the controllers, a controller installer class to register the controllers to the dependency injection container and we made a Sitecore initialize pipeline processor to our ControllerFactory as inner factory of the SitecoreFactoryController.

Now add an interface and a class which implements the interface.

IDemoClass.cs

DemoClass.cs

DemoInstaller.cs

Now make some modifications to the code we already wrote in the previouse post.

DemoController.cs (non Area)

SitecoreMVC.config

Now publish and check out the result. Damn we got an error message. As i mentioned earlier the CreateControllerInstance method of Sitecore does not pass parameters. A solution can be changing the controller rendering item value of field “Controller” to “Demo”, but since we are using areas it is not an option because give us the multiple type error as described in the previous post. We can solve this with some new modification to the code we already wrote.

ControllerInfo.cs

AreaControllerRunner.cs

Demo1AreaRegistration.cs

The namespace of the controllers has to be present in the area route mapping

 

 

PART II: Sitecore & MVC: Areas

The basic MVC functionality works pretty well in Sitecore, but there are some MVC features that do not work as expected. One of them is the use of areas. Lets do some coding  examples and find out yourself:

  1. In our project we create a new controller named “Demo”
  2. Create a new view for your Demo controller named “Index”
  3. In the new view we write some HTML: <h1>Controller: Demo – Action: Index</h1>
  4. In Sitecore create a new Controller Rendering named “DemoIndex”.
  5. Set the value of field “Controller” to “Demo”
  6. Set the value of field “Controller action” to “Index”
  7. Assign our Controller Rendering to a placeholder on a page

In this example the controller will behave as expected. Now lets add another controller, but this time we do this inside an area.

  1. In our project we create a new area named “Demo1”
  2. Inside the area we create a controller and view using the same names we did in the previous example.
  3. Add the area name to the HTML of the view so we can see the differences.
  4. In Sitecore create a new Rendering folder named “Demo1” and create a new Controller Rendering as we did in the first example.
  5. Assign our Controller Rendering to a placeholder on a page

Our application throws an exception: Multiple types where found that match the controller ‘Demo’. The reason why this exception occurs is MVC does not known anything about the area and does not know which controller it has to use. Sitecore’s solution is to provide the fully qualified type name and assembly as value in the field “Controller” of your “Controller rendering”. Lets change both Controller Renderings, set the “Controller” fields to [Controller namespace].DemoController, [Assembly name]. And refresh our page again. Yeah we got it working again…………….., but wait i was sure our views had different HTML content. Why is this page displaying the same view twice?
The problem lies in the fact that the name of the area is not specified and thus the view can not be found inside the area. A solution could be specifying the path to the view hard coded in the controller, but in my opinion it is a terrible solution. The real solution to this problem is let to MVC know in which area the controller is executing.

Expanding the Sitecore Controller Rendering Item

  1. Create a new template named “_ControllerRenderingArea”
  2. Add a section named “Data”
  3. Add a field named “Area” of type Single-Line text and make this field Shared
  4. Add our new created template to the Controller Rendering template (/sitecore/templates/System/Layout/Renderings/Controller rendering)

Now we have expanded the Sitecore Controller Rendering Item it is time to write some to make it actually work.

ControllerInfo.cs

AreaControllerRunner.cs

AreaControllerRenderer.cs

GetAreaControllerRendering.cs

SitecoreMVC.config

 

 

PART I: Sitecore & MVC: Project setup

The last couple of months i have been busy researching and developing with Sitecore and MVC. During development I had some challenges to get it to work properly. In a series of posts I will explain some solutions for the challenges you will face after taking certain decisions.

Let’s begin with setting up a new Solution for our Sitecore MVC project.

Setup our Sitecore MVC Visual Studio solution

First we take the following steps to setup out new project:

  1. Install a new Sitecore instance
  2. Create a new Solution/Project in Visual Studio
  3. Select ASP.NET Web Application as your project type
  4. Select the “Empty” template
  5. Check the “MVC” checkbox under the section “Add folders and core references for”
  6. Click OK

In the next few steps we copy some necessary files to your projects:

  1. On the same level as your solution file (.sln) create a new folder external.
  2. Select the files: Sitecore.Kernel.dll and Sitecore.Mvc.dll from the Sitecore instance to your new folder.
  3. Copy the Web.config from the Sitecore Instance and we paste it into our own project (just overwrite the existing).

Almost ready. Create a publishing profile a make our publish target location is the root of the Sitecore instance and “Delete all existing files prior to publish” is NOT checked. Let’s click the “Publish” button and check if your Sitecore instance is still working properly.

We may get some errors about non matching assembly versions related to MVC and Illegal routing, let’s fix them. Since we create our project with an empty MVC project we have already installed MVC, but the references in the web.config – we copied from the Sitecore instance – probably do not match. By re-installing the MVC Nuget package the web.config gets updated with the proper assembly versions.

  1. Open the Nuget “Package Manager Console”
  2. Type: Update-Package -reinstall

Now remove all code from the RegisterRoute method in file App_Start/RouteConfig.cs, publish the project and check your Sitecore instance again, it should be working now.

ECM Basics

Hey guys, this will be the first in a series of posts about the Sitecore Email Campaign Manager (or ECM).
Since we live in the year 2014, we will be targeting ECM 2.x, which is built in the new SPEAK-interface.
Building newsletters in SPEAK means having access to the Page Editor’s functionality, which offers a whole bunch of new techniques to connect new (or existing) content items to your newsletters.

We did quite a lot ECM implementations over the last year and are pretty confident in giving statements about do’s and don’ts regarding ECM.
We’ve really reached the limits of this module, and went over them at a few occasions. This resulted in not only a deep understanding of the module, but also a list of bugs (which had to be reported to and fixed by Support) and other misconceptions about it.
The module looks pretty simple at first sight, but that’s an opinion you might reconsider later.

The documentation on SDN looks pretty clear and accurate, but lacks a bunch of information regarding architecture of both the module and it’s network.
Simple example: When choosing the SitecoreMTA model (which actually uses Dyn to send bulk emails) which IP-addresses are used, and therefore should be allowed to have out-going packets in the firewall? Good luck finding that information in the documentation.

Questions like the one above have been the reason of close contact with our local Sitecore department, which have helped us out at a lot of occasions. Not only can they provide technical assistance, they are also able to contact the development and/or support teams to retrieve this information more accurately (and importantly a lot FASTER).

Anyway, enough bureaucratic stuff. Let’s get on with the technical stuff!

My first implementation was almost a complete copy of an implementation one of my coworkers made, but even then I had no idea what was going on nor did the documentation made it any clearer what I had to do.
I’m expecting there are other developers who ran into the same problems, so my first ECM blog will be a basic implementation/installation guide.

After you’ve installed the module you’re pretty much left empty handed.
Start of creating a new Manager Root item at the location you want. I would advise not to place a ECM-node as a descendant of a website, but rather next to it. Maybe even place your ECM-nodes in a separate rootfolder.

manager_root

You will end up with something like this:

ecm_node

Now, make sure the path to the ECM-node (including it’s name) does not contain a hyphen (“-“), to escape from a bunch of bugs regarding Sitecore queries made by SPEAK and ECM which do not automatically escape it (it should be escaped by wrapping the itemname in hashtags “#email-manager#”. A few of these bugs have been fixed in the latest version (rev. 140214), but I’ve been through enough trouble to make assumptions about ECM bugfixes in the past. (better safe than sorry).

So we have this ECM node now. Click on it and enter the following fields:

  • Base URL, this one is very important. It’s the URL ECM uses as a prefix for links to images and internal Sitecore links (in content). Be sure to change it when you’re moving from development to production (or you will end up with broken links everywhere).
  • Common Domain, change it to ‘Emailcampaign’
  • From Name, From Address and Reply To, these are not really important because they will be overridden by the fields set on a message but fill them to have a solid fallback.

If you’re using a localMTA (you take care of the email delivery yourself) make sure to change the fields in the Delivery Status Notifications to allow stuff like Bounce Emails to work correctly.
Since we’re in the development fase we will be using a localMTA, after all you should not use a customer’s license in development.
As a partner you probably have a development license including Sitecore.AnyMTA:

anymta

Open your Sitecore.EmailCampaign.config and change the following key to inform Sitecore you will be using a localMTA.

Change the IP address of your mail-server:

Change other SMTP settings if necessary (login credentials).
Alright, so much for the configuration of ECM (easy right?).
If your solution uses any language other than English for your main sites content (like dutch in my case), you will have to do two things.

1. Make sure the SPEAK language uses that language instead of the default English. This is easily done by changing the ‘defaultLanguage’ to your language-code in the web.config.

Make sure this is working correctly by creating a new version of the /sitecore/system/Modules/SPEAK/Email Campaign item in the desired language and change the Title to something like “EMAIL CAMPAIGN MANAGER (DUTCH)” and publish it.
This title will show up in SPEAK. If not, you’ve done something wrong, and the language is still in English.
ecm_app

2. We made SPEAK open up in our desired language, which raises the next problem: The ECM  SPEAK Application has not been translated to any other language than English.
If you open up ECM you will end up with an application which is missing all kinds of labels and other stuff.

Basically this means you will have to translate every descendant of /sitecore/system/Modules/Speak/Email Campaign. There are a few different solutions to this problem:

  1. Translate manually, which is a LOT of work.
  2. Change the SPEAK templates to make Title fields shared (which is not advisable).
  3. Create a script which creates a new version for your language and copies all the values from the English version. This is what we do, it is both safe and quick and you’ll end up with a filled (although English) SPEAK Application which respects the correct language.

One last thing to finish our configuration/installation guide is to make sure we’re not experiencing another bug/problem in ECM.

Open up ECM and take a look at the context switcher.

context_switcher1

Note: This control is only visible if you have more than 1 ECM Node in your Sitecore solution (if the control is not visible you’re not experiencing this problem).

It is possible that a $name context is showing up in the context switcher.

context_switcher2

If this $name item is visible:
For some reason Sitecore thinks that the Email Campaign Root branch item (called $name) is also a ECM Node and selects it to be shown in the context switcher.

This can be easily fixed by removing the item from the multilist in /Sitecore/system/Modules/E-mail Campaign Manager/System/Root List:

context_switcher3

Wrapping up
So much for the installation and configuration of ECM. This isn’t a typical post we would publish on this website, but in my opinion this basic ECM knowledge is pretty hard to get hold off so I’ve created a step-by-step manual anyway.

The remainder of ECM posts in this series will be more interesting, and more related to programming.

Next up will be: Creating different kinds of newsletters.