Simple Sitemap XML

Hi everyone again,
Today, the customer asked me for create a dynamic sitemap.xml file on the sitecore project. I tried to use some existing packages from the Marketplace, but they didn't work for this project. We were needing a very simple version. So... why not create a new one from the scratch? This is not a big deal.

We have 2 different approaches to do this:

Approach 1: We can create the sitemap.xml file and we can put it on the root of the folder.

  • Pros: Once the file is created as a static file, the indexers could take it without an extra processing of our system.
  • Cons: We have to ensure that the sitemap.xml URLs are in sync with the published items. It's because the indexer could penalize this error. Maybe we can create this file when the author publishes the items to Web database. This could resolve this issue.

Approach 2: We can create the sitemap.xml content dynamically and we can show it through a handlers.

  • Pros: We are recreating the file content when the indexer is trying the take it. This could ensure an accurate content all the time without penalizations.
  • Cons: The system is going to process this content each time the indexer try to take it. This could take resources from our server, but we can cache this content to resolve this issue.

I want to do something super simple. I love the simple ideas, because most of the time they are more flexible on different context. So, let's take the second approach.

We can build this handler easily, adding a new pipeline on the HttpRequestBegin. Let's remember that Sitecore address the handlers in a special way (link)

Here is the code: Feel free to use it and modify it. Any contribution is welcome. Also, you have the package on the marketplace here.

If you want to change the configuration of this code to handle a sitemap with XML extension, you will need to:

  • Change the configuration file of this code in the "sitemapUrl" parameter to "/sitemap.ashx"
  • Change the robots.txt file to indicate the new extension of the sitemap.
  • Change the IIS settings to avoid handle this file as an static file.

Using Azure CDN with Sitecore 7

Today I'm going to talk about the CDN service provided by Microsoft Azure. If you have a website there you will find this service very useful and you can implement it super fast. A Content Delivery Network (CDN) works by providing alternative server nodes for users to download resources (usually static content like images and JavaScript). These nodes spread throughout the world, therefore being geographically closer to your users, ensuring a faster response and download time of content due to reduced latency.

Microsoft provide a CDN service on the cloud. This service needs to take the static files from a local folder on the same website. I'm going to show you how to add to Sitecore the feature to clone all the files of the Media Library into this folder. This action is going to happen just when you publish those items from the Master database to Web database. Also, you will have to accomplish some extra configurations on the Content Delivery servers to take them from the CDN servers.

I'm going to show you and I'm going to provide you a package to use Azure CDN with your Sitecore 7.* project hosted in Azure.

This package is already on the Sitecore Marketplace. Also, the source code is on Github too.

Step 1 - Create the CDN service on Azure.

Got to the App Services section. Press on the CDN option. Then press on the Quick Create button. On the Origin Domain dropdown select the URL of your website. (Note: CDN is going to search the images on a CDN folder in the root of your website). After the creation of the CDN service, I'll recommend to enable HTTPS on it.

Step 2 - Install the package and config it

You have to install the package on the site that you have selected on the dropdown when you create the Azure CDN service.

After the installation, you will see a new file in the folder /App_Config/Includes. The file is called SitecoreFromArg.CdnAzure.config and it has 2 parameters inside:

Enabled: This parameter allow you to disable this feature.

SourceDomain: You can use this parameter to change the name of the default folder where Azure is looking for the static files.

Step 3 - Republish media items

Go to Content Editor on the server where you have installed the package, and republish all the items of the Media Library folder.

Final step - Change the configurations on the Content Delivery servers

Set the parameter Media.AlwaysIncludeServerUrl in true:
<setting name="Media.AlwaysIncludeServerUrl" value="true" />

Add the following string in the parameter Media.MediaLinkPrefix:
<setting name="Media.MediaLinkPrefix" value="~/"/>

Add the CDN Domain on the parameter Media.MediaLinkServerUrl (this parameter isn't on Sitecore 6.*):
<setting name="Media.MediaLinkServerUrl" value=""/>

Finally, remove the attribute value="ashx" from the parameter Media.RequestExtension:
<setting name="Media.RequestExtension" />

There is the code of my package

Adding a new field to dialog windows in General Link field for Sitecore 6.6

The customer of my current project asked to use some Webtrends™ JS function on the general links on his Sitecore 6.6. Also, he want handle the data inside the "on-click" parameter to each <A> html tag generated by those general link fields. We don't have SPEAK here, but it's not impossible. In fact this is pretty easy. So, let's add an "Click" field there!

Step 1 - Adding some extra files to our VS project

The general link field has several different dialog windows. We are going to change all them on this exercise.
Include on your Visual Studio project the following folders:
  • sitecore\shell\Applications\Dialogs\AnchorLink
  • sitecore\shell\Applications\Dialogs\ExternalLink
  • sitecore\shell\Applications\Dialogs\GeneralLink
  • sitecore\shell\Applications\Dialogs\InternalLink
  • sitecore\shell\Applications\Dialogs\JavascriptLink
  • sitecore\shell\Applications\Dialogs\MailLink
  • sitecore\shell\Applications\Dialogs\MediaLink

Step 2 - Editing the Anchor dialog

Edit the file AnchorLink/AnchorLink.xml. After that, use Reflection on the VS to get the content of the class Sitecore.Shell.Applications.Dialogs.AnchorLink.AnchorLinkForm. With that content let's create a new local class. You can store this new class on any place in your project. After that, replace the reference on the line #9 with the reference of your new class.

In this new class, let's add a couple of new lines. Add the reference to the new field "Click" at the beginning. You can do that with a line similar to this one:
protected Edit Click;
Then, add this line of code at the end of the method OnLoad:
this.Click.Value = this.LinkAttributes["click"];
Finally, add this line on the method OnOK:
LinkForm.SetAttribute(packet, "click", (Control)this.Click);
At this moment the code is going to compile, but the it will not work on Sitecore. It's because we have to overwrite the LinkForm class and we have to add there the new field too. To do that you have to use Reflection again and clone the class locally.
On your version of LinkForm make the following changes.
Add the following code line at the end of the method ParseLink:
this.linkAttributes["click"] = XmlUtil.GetAttribute("click", node);
On the class LinkAttributeNames, add the following property:
public const string Click = "click";

Step 3 - Test our first change!

Let's test our change! Add a new General Link field to some data template. Create an item based on this data template and add some content to our General Link field. You will see that the new field is there. Try to add content to our new field, save it and try to change the value before.

The raw value of the field will look like this:
<link text="Description" linktype="anchor" url="example1" anchor="example1" click="JS code here" />
NOTE: I'm figuring out if there is a bug here on Sitecore. If you add some content with these characters "(" and ")", all is going to fail. Doesn't matter which field you used to add these characters.

Step 4 - Repeat the same changes on all the other dialogs

Repeat the same process on the following dialogs:
  • sitecore\shell\Applications\Dialogs\ExternalLink
  • sitecore\shell\Applications\Dialogs\InternalLink
  • sitecore\shell\Applications\Dialogs\JavascriptLink
  • sitecore\shell\Applications\Dialogs\MailLink
  • sitecore\shell\Applications\Dialogs\MediaLink
In all them, add a new field with the same name (Click). You don't need to change the class LinkForm again.

Clues: while we do all this conversion, we're going to see several code errors related to the namespaces of some classes. To resolve them, you have to remove the namespace of those classes. In this way you are going to take the local ones. Don't use the replace feature of VS. Do this manually.
Example of namespaces that you should remove:
  • Sitecore.Shell.Applications.Dialogs
  • Sitecore.Shell.Applications.Dialogs.GeneralLink

Step 5 - Modify the GeneralLink dialog

This dialog is very special, because it's a dialog that represents all the other dialogs together and it's used on the Page Editor mode.
The XML file is quite large, but you have to add the new field just at the end of the right column area. This new field will look similar to this:
<Literal Text="Click:" GridPanel.NoWrap="true"/>
<Edit Width="100%" Class="scQuirksBoxModel" GridPanel.Row.ID="ClickRow" ID="Click"/>
After this, you have to clone locally the class GeneralLinkForm. Use the same process of the previous ones with Reflection. Remember change the reference on the XML file.
At the beginning of the GeneralLinkForm class, add the property with the new field:
protected Edit Click;
Another more step, add at the end of the method SetCommonAttributes the following line of code:
LinkForm.SetAttribute(packet, "click", (Sitecore.Web.UI.HtmlControls.Control)this.Click);
Finally, you have to add this line of code on the method InitControls:
this.Click.Value = this.LinkAttributes["click"];
Clues: while you are cloning this file, you will see an weird error. A reference to this method looks not work. To resolve this, just replace the this "Sitecore.StringExtensions.FormatWith" by this "Sitecore.StringExtensions.StringExtensions.FormatWith"

Final Step - Modify the GetLinkFieldValue pipeline

This is the last step. We have to add a new pipeline to take the attribute click from the raw field value and put that value on the onclick attribute on the final <A> html tag.
This is the pipeline to create the onclick attribute
This the configuration file for the pipeline
Note: I know... the last part of the pipeline is not too fancy. There are several way to handle the XML data the do the separation. Anyway, I don't want to code many lines to do that very simple operation. I'm open to suggestions.

Hope this post save time on your work. Please, don't leave this blog without a comment :)