Sitecore Environment Identification Tip

Today you get a simple quick tip for managing multiple Sitecore instances. If your infrastructure has a lot of servers and is scaled in such a way that you manage content on multiple authoring instances, its certainly possible for you to accidentally log into the wrong instance to author some content. In many environments I’ve worked in, Sitecore applications may be scaled for various reasons such as development, quality assurance, pre-production / testing, and production. If you have two or more authoring instances, one simple thing you can do is configure an environment-specific welcome title for the Sitecore login screen. This may act as a simple gut check when you log into Sitecore to make sure you’re logging into the right instance.

First add a patch config, such as /App_Config/Include/WelcomeTitle.config.

Next add a message that is specific to that server:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="WelcomeTitle">
        <patch:attribute name="value">Production Environment</patch:attribute>
      </setting>
    </settings>
  </sitecore>
</configuration>

Here are some samples:

env-1

env-2

Oh and don’t forget to change your admin password to something other than “b” ;-)

Posted in Sitecore

Sitecore Rich Text Editor CSS Class Tips

The Sitecore Rich Text Editor comes with many customization opportunities, however the most common change made to the RTE is the addition of CSS classes in the dropdown and making the text styles in the editor itself look like the front-end site. Read on to learn how to style the text in the RTE and add CSS classes.

Customize the RTE Text Style

The RTE by default has some very basic text styles that you can override to match the look and feel of your front-end site. First, its important to know that the RTE style comes from a CSS file configured via the web.config:

<!--  WEB SITE STYLESHEET
	CSS file for HTML content of Sitecore database.
	The file pointed to by WebStylesheet setting is automatically included in Html and Rich Text fields.
	By using it, you can make the content of HTML fields look the same as the actual Web Site
-->
<setting name="WebStylesheet" value="/default.css" />

You can simply patch in a change to this setting to set the file to your own custom RTE CSS file, like so:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <settings>
      <setting name="WebStylesheet">
	    <patch:attribute name="value">/custom-rte.css</patch:attribute>
	  </setting>
    </settings>
  </sitecore>
</configuration>

Now you can edit your custom CSS file to make the basic text styles of it look like your site. I recommend the following edits to keep it clean and simple:

body {
    color: /* your style here */;
    font-size: /* your style here */;
    font-family: /* your style here */;
    width: 100%;
    height: 100%;
}

h1 {
    /* your styles here */;
}

h2 {
    /* your styles here */;
}

h3 {
    /* your styles here */;
}

a {
    color: /* your style here */;
}

ul {
    /* your styles here */;
}

ol {
    /* your styles here */;
}

li {
    /* your styles here */;
}

Pro tip: cache bust the CSS any time you edit it

Since the CSS file is loaded into the browser in the <iframe> that the RTE uses, it will likely be cached easily. If you edit the CSS file you can easily add a dummy query string to cache bust the CSS file and force it to load a new copy from the server, e.g.

<patch:attribute name="value">/custom-rte.css?v=2</patch:attribute>

Expose CSS Classes in the RTE

Now that you’ve made the text itself look nice like the front-end site, you may want to add a few helper CSS classes to the dropdown to help your editors. One approach is to add a CSS class to the custom RTE CSS file and apply your style properties to it. This will expose the class in the dropdown and when an editor uses it, it will actually apply the styles:

Another option is to apply an empty CSS class with no styles. This is useful for utility classes that might not have an appearance change in the RTE itself:

Once your classes are added to the CSS file, there are displayed in the dropdown in the RTE:

As you can see, once applied, they render thier style properties in the RTE as well:

Posted in Sitecore

Sitecore Items Will Not Publish

There are various scenarios when a Sitecore content author may be warned that an item will not publish. Read on to learn why:

Not in the final workflow step

If you publish now, the selected version will not be visible on the Web site because it is not in the final workflow step.

You will get the above message if the content item is is a workflow state that is not final. This is a friendly warning that you need to approve your content or have someone else that is an approver do so. This is the whole point of workflow, it prevents publishing until the final state.

Today does not fall within its valid date range

If you publish now, the selected version will not be visible on the Web site because today does not fall within its valid date range.

You will get the above message if the content item has publishing restrictions by date. To investigate the restrictions, use the View or Change button on the restrictions of the Publish tab.

It has been replaced by a newer version

If you publish now, the selected version will not be visible on the Web site because it has been replaced by a newer version.

You will get the above message if the content item has a newer version of the item that is approved for publish. Use the versions dropdown menu to select the newer version.

It has been replaced by an older version

If you publish now, the selected version will not be visible on the Web site because it has been replaced by an older version.

You will get the above message if the content item has a newer version that is not in the final state of workflow or that newer version is not marked as publishable. Thus, the older version will replace content when published because the newer version is not applicable for publish.

General Publishing Restrictions (item versions not selected)

If you publish now, the selected version will not be visible on the Web site.

You will get the above message if the content item has publishing restrictions that completely block it. This is likely the case where someone made the item always unpublishable for a reason. To investigate the restrictions, use the View or Change button on the restrictions of the Publish tab.

To learn more about workflow, visit the Sitecore Workflow documentation page.

Posted in Sitecore

Configure Sitecore Web Forms for Marketers with a Standard Connection String

For anyone that has or is going to install Sitecore’s Web Forms for Marketers module, the module comes with it’s own patch config file as you can expect. Depending on the version of Sitecore you are using, it’s either called forms.config or Sitecore.Forms.config. One of the post-install steps of the package is to configure a data provider with a database connection, e.g.
<formsDataProvider
type="Sitecore.Forms.Data.DataProviders.WFMDataProvider,Sitecore.Forms.Core">
. The default configuration of this SQL-based provider is to define a connection string as the first string-based parameter below the provider, e.g.

<formsDataProvider type="Sitecore.Forms.Data.DataProviders.WFMDataProvider,Sitecore.Forms.Core">
  <param desc="connection string">Database=(database);Data Source=(server);user id=(user);password=(password);Connect Timeout=30</param>
</formsDataProvider>

This connection string is deeply embedded within this patch config and does not follow the standard connection string configuration in the ConnectionStrings.config file. Luckily, you can swap this out for a normal token-based connection string in ConnectionStrings.config.

If you de-compile the data provider and look at its constructor, you can see that when no string parameter is provided, it falls back to WebFormsContext.ConnectionString:

wfm1

That base connection string property looks for a standard connection string with a token of "wfm":

wfm2

So the simple way to follow the standard approach to defining the database in ConnectionStrings.config is to define a string with that "wfm" token and ensure there is no parameter to the data provider:

<add name="wfm" connectionString="user id=username;password=password;Data Source=(server);Database=(database)" />
<formsDataProvider type="Sitecore.Forms.Data.DataProviders.WFMDataProvider,Sitecore.Forms.Core">
</formsDataProvider>

Leave a comment if you have any other tips like this.

Posted in Sitecore

Sitecore Context Site Resolution

Sitecore’s API contains an easy way to get the context site in your code, however it has some pitfalls in the case of a multi-site solution with page editor and preview modes. Here is a simple solution to this challenge.

Standard API Context Site Resolution

The typical way to get a context site in Sitecore is simply via Sitecore.Context.Site. This works most of the time, but if you have a multi-site solution and use Page Editor or Preview mode, it may not determine the site the item lives within (due to co-habitating site content trees). Additionally, if you use the Presentation tab’s embedded Preview frame, it will assume the context site is either “website” or “shell” so you really need this solution.

Enhanced Context Site Resolution

Here is a sample method to get the context site. I won’t go into details of the code because it’s all commented, but at a high-level:

  1. Get the item being viewed (the hardest part) — page editor or multiple preview modes
  2. Get all sites
  3. Find the first site for which the item falls within the tree path

public static Sitecore.Sites.SiteContext GetContextSite()
{
	if (Sitecore.Context.PageMode.IsPageEditor || Sitecore.Context.PageMode.IsPreview)
	{
		// item ID for page editor and front-end preview mode
		string id = Sitecore.Web.WebUtil.GetQueryString("sc_itemid");

		// by default, get the item assuming Presentation Preview tool (embedded preview in shell)
		var item = Sitecore.Context.Item;

		// if a query string ID was found, get the item for page editor and front-end preview mode
		if (!string.IsNullOrEmpty(id))
		{
			item = Sitecore.Context.Database.GetItem(id);
		}

		// loop through all configured sites
		foreach (var site in Sitecore.Configuration.Factory.GetSiteInfoList())
		{
			// get this site's home page item
			var homePage = Sitecore.Context.Database.GetItem(site.RootPath + site.StartItem);

			// if the item lives within this site, this is our context site
			if (homePage != null && homePage.Axes.IsAncestorOf(item))
			{
				return Sitecore.Configuration.Factory.GetSite(site.Name);
			}
		}

		// fallback and assume context site
		return Sitecore.Context.Site;
	}
	else
	{
		// standard context site resolution via hostname, virtual/physical path, and port number
		return Sitecore.Context.Site;
	}
}

Posted in Sitecore

Unpublish Sitecore Content

Recently many (many…) people have asked me how to unpublish content in Sitecore. It’s really easy in fact.

Go to the Publish ribbon and select the Change button:

unpublish1

In the dialog, make the item as a whole unpublishable by deselecting the Publishable checkbox:

unpublish2

You will be told by the content editor what to expect:

unpublish3

This item is not publishable, which really means, you can instantiate the publish operation on it, but it will not show on the front-end. So your next step is to actually publish (I know, sounds wrong…) the item and it will disappear from the front-end but remain in the master database.

And there you have it, an easy way to “unpublish” content.

Posted in Sitecore

Dealing with Sitecore Template is Used by at Least One Item Warning

If you’ve ever worked on creating data templates in the Sitecore CMS only to later abandon them with a better replacement, you may come across an issue of existing items based on that template. Read on to learn a quick way to handle this.

First, here’s the issue you will see if you try to delete a template that has at least one item based on it:

delete1

Ugh oh, that’s not going to happen!

delete2

This simply means that another item exists based on this template and therefore you cannot delete it as Sitecore cannot really handle orphaned types well. The solution is to find the Referrers of that template itself to determine which items are based on it. From there you can go to those items and delete them.

delete3

Posted in Sitecore

Sitecore Managed Sites as Virtual Folders

Sitecore’s native ability to manage multiple web properties is a highly-leveraged feature of the CMS. It supports this via different tree nodes and specific configuration to delineate among sites. This blog post covers several important considerations when managing sites with virtual folders.

Managing Multiple Sites in General

Sitecore supports multiple logical sites by having separate root paths in the content tree:

sites1

In addition to this, XML configuration in the <sites> section (preferably via the SiteDefinition.config patch) defines what sites map various host names to root content paths. Sites also define a context language, database, etc.

sites2

How Sitecore Resolves a Site

Sitecore resolves the correct site via a pipeline process in the httpRequestBegin pipeline. The SiteResolver sets the context site based on the following criteria:

  • Hostname
  • Virtual path
  • Port number

Sitecore processes the XML in sequence to find the first site that matches the above criteria. Since each site has a hostName attribute defined, Sitecore first matches against this. Next comes the virtualFolder which by default is simply “/” but may be changed.

How to Configure a Sitecore Site with a Virtual Folder

To configure a site as a virtual folder, define the virtualFolder path AND physicalFolder path to match the expected path.

sites3

If you do no define the physicalFolder in addition to the virtualFolder Sitecore may either not resolve the site correctly or may throw a YSOD saying a path is null:

sites4

Note: if you have configured the Link Provider to use the Display Name for URLs, these virtual and physical paths must actually match the display name, not the item name.

Additionally, you must define virtual folder sites above any non-virtual folder sites that share the same hostName. This is because Sitecore resolves the sites in sequence based on the configuration so you need more specific combinations of criteria first (e.g. host and path).

Posted in Sitecore

Sitecore Item and Field Names

Sitecore’s constructs of item names and display names is useful for managing content and delivering content to end users in user-friendly ways. They can also be used to change the perceived names of template fields for a better user experience. John West recently published a blog post about the topic of Display Names, however I was already in the process of writing up this post, so here it is anyways. Read to on learn more about item names, display names, and how you can easily change the text labels for data template field names.

Item Names

Sitecore item names are — as you would expect — the names assigned to each Sitecore item. The names appear in the content tree and additionally translate to the resolved URL of the item by default.

item-name

item-url

You can determine the URL of an item by looking at the item’s path relative to the site’s start item:

item-path

Its typically best practice to name page items with hyphens between words for friendly URLs, instead of using spaces. Though this good for end users, it requires these item names in the tree to include hyphen as well, which can get annoying too. Luckily, Sitecore has a notion of another naming construct, display names.

Item Display Names

An item display name by default simply matches the item name, that is, until you fill in a value. Setting an item’s display name value will change the perceived name of the item in the content tree, but will preserve the original item name (likely with hyphens) for URLs. This allows the best of both worlds: friendly hyphenated URLs, and easy to read names in the content tree. It can also be automated.

item-and-display-names

Display Names and Language Specific URLs

Another nice advantage of being able to edit display names is that it allows a unique display name per language variant of an item. This is useful if an item has one perceived name in the tree for English and a separate name when looking at Spanish. This can be further used to actually render language-specific URLs based on the display name. By default, the Link Manager uses the item name to generate URLs, but you can simply swap the useDisplayName attribute to true if you want language-specific URLs on a multi-lingual site:

<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="true" />

Changing the Perceived Name of a Field

Though item names and display names are useful for regular content items, individual data template fields have their own ways to customize their names. There are two main ways to change the perceived name of a field:

  1. Change the “Title” field on the field item
  2. Fill in the Short Description on the field item

The most common way in the first approach — to set the Title field. In fact, most built-in fields do this as they typically start with “__” by the titles are changed to be more user-friendly. You can see this on the “__renderings” field which actually appears to be called “Renderings”:

field-title

The other approach is to set the Short Description on the field item. As you can see, by default the field name renders on the item:

sample-field

First, navigate to Configure > Help on the field item itself:

field-help-settings

Next, fill in the Short Description text which will render after the original field name:

field-tooltip

As you can see, this can be quite useful to help content editors with instructional text without changing the actual field name.

updated-item-field

Posted in Sitecore

Sitecore Avanced Database Crawler Occasionally Provides Null Results

If you’ve ever used the Advanced Database Crawler as your toolkit to do some sophisticated searching and querying for Sitecore content, you may have noticed that sometimes your results may include null/empty results. This is a common issue that I’ve faced many times and I’ve tracked it down to the de-coupled nature of the search index and publishing to the Sitecore database. This blog post explains the issue and how you can resolve it.

The crux of this issue it that the process of rebuilding the index is not directly sync’d or timed to the publishing process. Alex Shyba has discussed this before when syncing your HTML cache clearer to the index build. Additionally, if you have an index that uses the master database or a location in the master database, it will incrementally edit the index frequently.

If you look at the SkinnyItem.cs class, there’s a GetItem() method to convert it into an Item. You can see it uses the database to get the item by its ID, language, and version number. Its possible that when you publish from master to web, you are publishing a new version # of an existing item and thus the new version exists in the web DB, but the index is not updated and references the old version. So, this GetItem() call would use the previous version # and the item would be null. One way to fix this is instead of calling that GetItem() method, just use your own code to get the latest version of that item from Sitecore, e.g.

Item item = Sitecore.Context.Database.GetItem(someSkinnyItem.ItemID);

Instead of

Item item = someSkinnyItem.GetItem();

If you have any other tips and tricks when using the Advanced Database Crawler and Lucene.NET with Sitecore, feel free to share in the comments!

Posted in Sitecore