Tag: Sitecore
Data Source vs Rendering Parameters

Data Source vs Rendering Parameters

On the face of it being able to specify Rendering Parameters, or a Data Source on a control achieves a very similar goal. You want to componentise your page and not fill up your page type item with fields for specific renderings. Everything should be isolated in it's own little compartment.

Linking a rendering control to a Data Source does this by moving all your data to a completely separate item, that can be re-used over multiple pages and even swapped out to do personalization or A/B testing.

Equally, using Rendering Parameters does this just as well. Just like a Data Source, you can create a template for the fields that need to be entered, and the data is kept in the same place that a link to a Data Source would be specified.

But what should I use?

The easiest way I can describe it is by asking, are you storing content or something else?

If the answer is content then you most likely want a data source. Alternatively, if it's something else like some config for a filter, or a background colour you will most likely want a rendering parameter (but there could be exceptions).

Data Sources

Data Sources have some distinct advantages over a Rendering Parameter including:

  • Data can be edited in the Experience Editor inline in your page
  • Language versions are very easy to understand by content editors
  • Easily used for personalization and testing
  • Can be reused on as many controls as you like

These things all make a Data Source a perfect option for anything content related. Without them you loose some big features related to content and ease of use. There are times non-content is also a good option. e.g. A hero banner on a page could be used across multiple pages and as well a reusing the text, if a background colour is also customizable you would want to be re-using that too.

Rendering Parameters

Likewise Rendering Parameters also have there benefits:

  • Doesn't create an extra item to publish. You just have to publish the page your editing, not the related data source
  • Easy to access in the control properties of the item your looking at, without having to find the related data source

These features make Rendering Parameters ideal for the non-content config of a control and removes non-content fields from your item templates. The thing to be aware of though is you can't easily do A/B testing or personalization with a rendering parameter, so while it's nice for your items to only contain content, that might not be the only thing that's being tested.

How about both?

There is also nothing to stop you using a Rendering Parameter and a Data Source at the same time.

You could have a situation when a Data Source is being used to populated the content on multiple different controls. Each control may have some additional config needed, such as text colour or text size. Keeping this data in the data source might become problematic as on one rendering your text may need to be black, whereas on another it may need to be white. By moving these fields to Rendering Parameters, you keep the benefit of a shared Data Source for content, while the Rendering Parameter takes care of the presentation config.

Sitecore html cache not clearing on publish

Sitecore html cache not clearing on publish

So you've got separate content management and content delivery servers, but when you publish the change is only visible on the content management box.

A likely cause is that you've enabled some caching but haven't updated the config files to clear the cache on your content delivery server.

Sitecores config files contain a list of handlers for what should happen when the event publish:end and publish:end:remote are triggered. Publish end is for the content management server, whereas publish end remote is for your delivery servers. The handler we're interested in is Sitecore.Publishing.HtmlCacheClearer which contains a list of sites to have the cache's cleared on.

By default this will contain one entry for website, the default name given to your site in the sites config when you install sitecore. However you will have changed this if your solution supports multiple sites, or if you changed it as part of some future planning to support multiple sites. If your site is missing, just add it to the live (via a patch file of course)

1<!-- Html Cache clear on publish events -->
2<!-- Force FULL cache clear on publish-->
3<event name="publish:end">
4 <handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache" patch:source="BaseSettings.config">
5 <sites hint="list">
6 <site>SiteOne</site>
7 <site>SiteTwo</site>
8 <site>SiteThree</site>
9 </sites>
10 </handler>
11</event>
12<!-- Html Cache clear on publish events -->
13<!-- Force FULL cache clear on publish-->
14<event name="publish:end:remote">
15 <handler type="Sitecore.Publishing.HtmlCacheClearer, Sitecore.Kernel" method="ClearCache" patch:source="BaseSettings.config">
16 <sites hint="list">
17 <site>SiteOne</site>
18 <site>SiteTwo</site>
19 <site>SiteThree</site>
20 </sites>
21 </handler>
22</event>

Note: in the sample above I have removed all other handlers to simplify the example. You should not remove these from your solution.

For more info on cache clearing and optimising it, see John Wests blog series on the subject here https://community.sitecore.net/technical_blogs/b/sitecorejohn_blog/posts/sitecore-output-cache-clearing-optimization-1-8-introduction-john-west-sitecore-blog

Displaying the cost of a uCommerce custom IShippingMethodService

Displaying the cost of a uCommerce custom IShippingMethodService

I just found this bog post on how to get the shipping cost for a custom shipping method you may have implemented using IShippingMethodService and thought I would share it here.

http://www.davejsaunders.com/2014/10/20/display-the-cost-of-your-ucommerce-custom-shipping-service.html

A common requirement when displaying shipping methods is to show the price against each, and for the built in uCommerce shipping methods there's a handy GetPriceForCurrency() method on the shipping method object. However if that shipping method is a custom one, it just returns 0.

1var allShippingMethods = TransactionLibrary.GetShippingMethods(country);
2var currency = purchaseOrder.BillingCurrency;
3
4foreach (var shippingMethod in allShippingMethods)
5{
6 var cost = shippingMethod.GetPriceForCurrency(currency);
7}

The correct way to get your shipping price is to manually call your service to get the price to be calculated.

As we don't know which implementation of IShippingMethodService will be used we first need to call GetShippingMethodService() to get it.

After that we just need to populate a new Shipment object we the details our custom method needs and then call the CalculateShippingPrice method.

1var purchaseOrder = TransactionLibrary.GetBasket().PurchaseOrder;
2var allShippingMethods = TransactionLibrary.GetShippingMethods(country);
3
4foreach (var shippingMethod in allShippingMethods)
5{
6 // Get the IShippingMethodService for this ShippingMethod
7 var shippingService = shippingMethod.GetShippingMethodService();
8
9 // Construct a fake shipping method to call the service with
10 var shipment = new Shipment
11 {
12 ShippingMethod = shippingMethod,
13 OrderLines = purchaseOrder.OrderLines,
14 PurchaseOrder = purchaseOrder,
15 ShipmentAddress = purchaseOrder.BillingAddress
16 };
17
18 var shippingMethodPrice
19 = shippingService.CalculateShippingPrice(shipment);
20}

Sitecore: Programmatically adding contacts to a list

From Sitecore 8 the EXM module now uses lists to manage mailing lists rather than roles against a user. The built in Subscription form control that comes with EXM has also been updated to add contacts to this list. However the subscription control remains WebForms only, so if you implementing an MVC solution you're going to need to write your own. There's also many other scenarios where you may want to programmatically create and add a contact to a list.

Under the hood, contact lists aren’t even a list at all. Rather they are actually just a Facet on the Contact record that contains the list id's for all the lists the contact is a part of. You can see this by looking in the contacts collection in the analytics mongo db.

Or in the Contacts table in the Reporting SQL db.

If you wanted to add a contact to a list you could in theory just add the relevant tag to the contact record like this:

1public void AddContactToList(Contact contact, Item list)
2{
3 using (new SecurityDisabler())
4 {
5 contact.Tags.Set("ContactLists", list.ID.ToString());
6 }
7}

But I wouldn't. The problem with this approach is your going to miss out any logic that will handle updating the counts of contacts in contact lists. Best to use one of the provided list api's instead.

Adding a contact to a list

Sitecore has a ContactListManager object that has a method to associate contacts with lists. All you need to do is create an instance of it and pass it a list of contacts.

1public void AddContactToList(ContactData contact, ContactList list)
2{
3 ContactListManager listManager = Sitecore.Configuration.Factory.CreateObject("contactListManager", false) as ContactListManager;
4
5 List&lt;ContactData&gt; contactList = new List&lt;ContactData&gt;();
6 contactList.Add(contact);
7
8 listManager.AssociateContacts(list, contactList);
9}

Removing  a contact from a list

Just like adding a contact, there's also a handy method for removing one too.

1public void RemoveContactFromList(ContactData contact, ContactList list)
2{
3 ContactListManager listManager = Sitecore.Configuration.Factory.CreateObject("contactListManager", false) as ContactListManager;
4
5 List&lt;ContactData&gt; contactList = new List&lt;ContactData&gt;();
6 contactList.Add(contact);
7
8 listManager.RemoveContactAssociations(list, contactList);
9}

What's that ContactData object?

Chances are you don't have a ContactData object (Sitecore.ListManagement.ContentSearch.Model.ContactData) and instead probably have a tracking contact (Sitecore.Analytics.Tracking.Contact). For the purposes of adding and removing a contact from a list, all your ContactData object really needs is its identifier, which you can do with the following:

1public ContactData ConvertContactToContactData(Sitecore.Analytics.Tracking.Contact contact)
2{
3 return new ContactData()
4 {
5 Identifier = contact.Identifiers.Identifier
6 };
7}

Sitecore: Sharing field data across languages

This is the third in a series of blog posts covering everything you should need to know for building a multilingual website in Sitecore.

Part 1 - Adding languages for a multilingual site
Part 2 - Translating text in your presentation

In the first two parts to this series I concentrated on how you can setup Sitecore to allow different language versions of content to be entered. In some instances though your content will contain fields which should remain the same across all language versions. This could be for product sku's, dimensions of an object or possibly image fields.

To make a field share it's values over multiple languages, in the template definition tick the shared checkbox against the field.

It's worth noting though that as well as making the field value the same across all languages, it will also be shared between all versions within the language.

Although the interface gives the impression that a field can be the default (versioned), unversioned, shared or unversioned and shared. The value of the unversioned checkbox actually become meaningless once shared has been ticked and there really are only 3 options; Versioned, Unversioned and Shared.

Sitecore: Translating text in your presentation

This is the second in a series of blog posts covering everything you should need to know for building a multilingual website in Sitecore.

In Part 1, I covered how to add a language to Sitecore so that content editors could create content in that language. In this post I'm going to show you how to create a dictionary in Sitecore so that hard coded text in your presentation or views can be translated into the relevant language.

Creating the dictionary

A dictionary is created within your content tree and then referenced from the <sites> section of your web.config file.

Somewhere outside of your sites home node (I like to create a settings folder for this sort of thing), create an item of type "Sitecore/templates/System/Dictionary/Dictionary Domain". This will be the root item of your dictionary.

Under your root dictionary item you will be able to create Dictionary Groups and Dictionary Entry's. I find a good way to organise your dictionary is to create a group for each letter of the alphabet and then sort your entry's into each of these based on the key name.

A dictionary entry consists of a Key and a Phrase. The key is the value that will be referenced in code to lookup the entry, and the phrase is the translation that will be returned.

Translations for each language are created using regular language versions of content.

Configuring the site to use the dictionary

For a site to use the dictionary you need to add a dictionaryDomain to the sites node. Below is an example of the default website site updated to use a dictionary called "My Dictionary"

1<site name="website" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" dictionaryDomain="My Dictionary" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="50MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="25MB" filteredItemsCacheSize="10MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" cacheRenderingParameters="true" renderingParametersCacheSize="10MB" />

Translating text in your view

Now that your dictionary has been set up you can start translating text in your views.

The following line of code will lookup the dictionary entry based on the key and return the phrase for the current context language.

1@Sitecore.Globalization.Translate.Text("dictionary key")

Sitecore: Adding languages for a multilingual site

This is the first in a series of blog posts covering everything you should need to know for building a multilingual site in Sitecore.

The first requirement for a multilingual site is for the content editors to be able to enter content in different languages.

In the top right corner of the content editor on any item, is the language drop down that content editors will use to switch between the language version they are editing. However by default it will only show English : English

Configure the language options

To configure the language options on the drop down:

  • In the content editor go to System > Languages
  • Right click the language node and choose Insert Language
  • A predefined language code drop down lets you pick between a set of predefined languages
  • Click Next, Next, Next until the dialog window closes. The language will be added to the language list and your content editors can start adding there content
  • Starting with Sitecore 8, languages are no longer automatically assigned a corresponding flag as there icon as it is no longer used in the language selector. If you wish to add an icon however you can still do this in the normal way by going to the configure tab, clicking the icon drop down and selecting More Icons. The flags are all still in an icon group called flags.

Sitecore: Setting up Mongo with Authentication

One of the new features in Sitecore 7.5 was the xDB, a new analytics database that rather than using SQL Server was Mongo based. If your main job is as a Sitecore dev, like me this may be the first time you've ever had to use Mongo, or a least the first time you've ever had to commercially use it.

Installing Mongo DB is a relatively painless experience, Mongo provide a decent enough guide to installing on Windows. Half way through you may be wondering why its running in a console window, but eventually you get to instructions for setting it up as a service.

However there are a couple of gotchas:

  1. Sitecore doesn't work with the latest version of Mongo. At time of writing the latest version of Sitecore is 8.0 rev. 150427 and Mongo is 3.0. Sitecore however only supports version 2.6.x of Mongo though.
  2. None of the installation instructions include any details on authentication. Which while this is fine for your local dev machine is not so great for a live site.

So here's my guide for getting up and running with Mongo DB and Sitecore.

Installing Mongo

First off get Mongo DB installed as a service on your machine. I'm not going to include instructions here for this bit, just follow the guide on the Mongo DB website.

One thing to note though, the Windows installer for Mongo 2.6 will by default install Mongo to C:\Program Files\MongoDB 2.6 Standard\. However the instructions for setting up Mongo include example commands expecting it to be installed in C:\mongodb\

Setting Up Authentication

Once you've got Mongo up and running you'll need to create a user.

  1. Open a command prompt and connect to MongoDB

    C:\Program Files\MongoDB 2.6 Standard\bin\mongo.exe
  2. Switch to the admin db by doing

    use admin
  3. Create the user using

    db.createUser({user: "admin_mongo",pwd: "your password",roles: [ { role: "userAdminAnyDatabase", db:"admin" }, { role: "root", db:"admin" } ] })
  4. To verify the user has been created you can use the following commands

    db.auth("admin_mongo", "your password")
    db.getUsers()

Next update your config file to require authentication by adding auth=true. You will also need to restart the service for the change to take effect.

logpath=c:\data\log\mongod.log
dbpath=c:\data\db
auth=true

Sitecore uses 4 db's in Mongo; Analytics, tracking_live, tracking_history and tracking_contact. We need to create a user in each of them.

Open a mongo shell again, switch to the admin db and connect with your admin login.

Now create each of the users as follows:

use analytics
db.createUser({user: "mongo_user",pwd: "your password",roles: [ { role: "readWrite", db:"analytics" } ]  })

use tracking_live
db.createUser({user: "mongo_user",pwd: "your password",roles: [ { role: "readWrite", db:"tracking_live" } ]  })

use tracking_history
db.createUser({user: "mongo_user",pwd: "your password",roles: [ { role: "readWrite", db:"tracking_history" } ]  })

use tracking_contact
db.createUser({user: "mongo_user",pwd: "your password",roles: [ { role: "readWrite", db:"tracking_contact" } ]  })

Sitecore Connection Strings

All that's left now is to update the connection strings in Sitecore.

The default connection strings Sitecore give you look like this:

The format for a connection string with authentication is

mongodb://[username:password@]host1[:port1]/database

Sitecore: How to change the personalisation trigger page count

One of Sitecores features is the ability to assign profile cards or profile key scores to pages. As visitors browse the website the profile key scores from each page are added to the visitors profile. Visitors are then assigned a pattern card using N-Dimonsional Euclidean Distance to calculate the closest matching pattern card to the visitors profile.

However before a pattern card is assigned to a visitor they must visit a minimum number of pages. The default for this is set to 3.

Reasons for changing this could be that you actually want to be more certain of a users profile before triggering personalisation this could be to avoid visitors landing pages on the site heavily dictating which persona they initially become profiled as, which in turn could influence personalisation that keeps them in that persona.

Or it could be because you want to lower the number of pages for a more immediate effect.

Whatever the reason to change the default from 3 you need to add the following setting to your config:

1<setting name="Analytics.Patterns.MinimalProfileScoreCount" value="3"/>

Increasing the Maximum file size for Web.Config

This can happen in any ASP.NET Web Application, but as Sitecore 8's default web.config file is now 246 kb this makes it extremely susceptible to exceeding the default 250 kb limit.

To change the size limit you need to modify/create the following registry keys:

HKLM\SOFTWARE\Microsoft\InetStp\Configuration\MaxWebConfigFileSizeInKB  (REG_DWORD)

On 64-bit machines you may also have to update the following as well

HKLM\SOFTWARE\Wow6432Node\Microsoft\InetStp\Configuration\MaxWebConfigFileSizeInKB (REG_DWORD)

You will probably find that these keys need to be created, rather than just being updated. After changing them you will also need to reset IIS.

Alternatively

Alternatively you can leave the default values at 250 kb and split the web.config files into separate files.

More information on doing this can be found here:

http://www.davidturvey.com/blog/index.php/2009/10/how-to-split-the-web-config-into-mutliple-files/

My personal preference for Sitecore projects is to update the the max file size as this allows keeping the web.config file as close to the default install as possible. The benefit of doing this is it makes upgrades easier, rather than needing to know why your web.config doesn't match the installation instructions.