Sitecore friendly URL | Remove or change URL extension

Do you want to achieve friendly URL means remove .aspx extension or want to change .aspx extension to .asp, .php, etc. then this blog is for you!

Suppose we have original URL like this:
http://mysite.com/aboutme.aspx

We can achieve Friendly URL / Remove URL extension:
http://mysite.com/aboutme/

We can change URL Extension too:
http://mysite.com/aboutme.php
OR
http://mysite.com/aboutme.asp

We can achieve any of below URLs with few changes in Sitecore. We are going to achieve
  1. How the above URL requests will be served
  2. How all URLs generated by that request will follow same URL format.

 Let's see how.

How to achieve friendly url?

Sitecore architecture has inbuilt facility to achieve friendly URLs.
In Web.config, find below line and set addaspxextension="false", which simply removes aspx extension from generated URLs:
<add addaspxextension="false" alwaysincludeserverurl="false" encodenames="true" languageembedding="never" languagelocation="filePath" name="sitecore" shortenurls="true" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" usedisplayname="false" />

Doing these change, Sitecore will respond to any friendly URL, also will generate all friendly URLs only. See below snap how we achieved.

How to change URL extension from .aspx to .asp, .html, etc.?

First thing is, Sitecore will support all the extensions which are Allowed from IIS. Second thing is, Sitecore itself has Allowed and Blocked extension list. So, all allowed extensions are by default accepted by Sitecore.

Any customized extension should work

You might be knowing all Sitecore processors in HttpRequestBegin pipeline. Using ItemResolver, Sitecore determines context item by the actual path from the URL without considering the extension. Means, whether extension is .aspx, .asp, .php, or even your name say .yogesh, not an issue, Sitecore will allow it and render page. :) Just thing to note, that extension should be allowed from Sitecore configurations.

See how to configure in web.config:
<preprocessRequest help="Processors should derive from Sitecore.Pipelines.PreprocessRequest.PreprocessRequestProcessor">
   <!-- Few processors might be there -->
   <processor type="Sitecore.Pipelines.PreprocessRequest.FilterUrlExtensions, Sitecore.Kernel">
      <param desc="Allowed extensions (comma separated)">aspx, ashx, asmx, asp, php, yogesh</param>
      <param desc="Blocked extensions (comma separated)">*</param>
      <param desc="Blocked extensions that stream files (comma separated)">*</param>
      <param desc="Blocked extensions that do not stream files (comma separated)"></param>
   </processor>
   
</preprocessRequest>

Now you can request any Sitecore page using asp, php or yogesh extension.

Page should generate all link by replacing the .aspx extension

Suppose we want to generate page urls with .asp extension.

For this, we have to set addaspxextension="true" means Sitecore will now generate URLs with .aspx extension. When the page is generating links of page output, we will replace the .aspx extension with .asp extension.

For that, we will change existing Link Provider with our customized one. See Web.config change.

<linkManager defaultProvider="sitecore">
      <providers>
        <!-- Comment below line which is default setting in Sitecore -->
        <!-- <add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" /> -->

        <!-- Add our customized link provider -->
        <add name="sitecore" type="SitecoreTactics.MyLinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" lowercaseUrls="false" shortenUrls="true" useDisplayName="false" />

      </providers>
    </linkManager>


Our customized class will look like:
namespace SitecoreTactics
{
 public class MyLinkProvider : Sitecore.Links.LinkProvider
    {
        protected static new LinkBuilder CreateLinkBuilder(Sitecore.Links.UrlOptions options)
        {
            return new LinkBuilder(options);
        }

        public override string GetItemUrl(Item item, UrlOptions options)
        {
            string itemUrl = base.CreateLinkBuilder(options).GetItemUrl(item);
            if (this.LowercaseUrls)
            {
                itemUrl = itemUrl.ToLowerInvariant();
            }
            // Replace .aspx with .asp
            return itemUrl.Replace(".aspx", ".asp");
        }
    }
}
See below snap how it will look like:


Hope, it's working for you, Enjoy!!

Sitecore Event Queue - The Scalability King

Sitecore EventQueue architecture gives great scalability to Sitecore, launched with version 6.3. Enabling it can allows clustering of Content Management Servers (CMs) and Content Delivery Servers (CDs). It allows events on one server to be executed on other servers in a cluster.

Suppose, there are two instances of CM. Now, think how an item changed on CM1 will be reflected to CM2? There should be something like triggering mechanism to communicate both CMs. Event Queues are playing very important role to make both CMs synced.

How Event Queue works

  1. When any item is saved on CM1, "item:saved" event is executed, it creates an instance of Remote Event (SavedItemRemoteEvent).
  2. Now, the remote event is passed into Event Queue table in the respective Sitecore database. This event contains many things like Item Id, the Sitecore Instance Name on which event occured, Instance Type, Instance Data, User Name, date time when event occured, etc.
  3. Each Sitecore Instance has a trigger to check this event queue periodically and collects all events to be processed.
  4. All instances select events raised by other instances (Remote Events) like "item:saved:remote" and should be new or created after the instance's last processed event.
  5. Suppose, the CM2 finds an event of "SaveItemRemoteEvent", then it clears cache related to the item and update the data of that item. Similarly, each different type of event has its own operations to perform, which are specified in the web.config in pipelines.

According to this architecture, the CMs can have many instances in a cluster, theoretically n numbers of CM or CD instances can work very well in a cluster using EventQueue and gets updated all the time. :)

Configure  Event Queues

To enable EventQueues, from web.config, find EnableEventQueues setting. Set its value to true. This setting can also be set from \App_Config\Include\ScalabilitySettings.config, which will be given more precedence over web.config settings.
<!--  ENABLE EVENT QUEUES
If enabled, Sitecore sends local events to the event queue available to remote instances, 
and handles events in the queue from remote instances. -->
      <setting name="EnableEventQueues">
        <patch:attribute name="value">true</patch:attribute>
      </setting>
<!--  Event Queue's processing interval. 
Event Queue will be requested to process after below given interval -->
      <eventqueue>  
       <processinginterval>00:00:02</processinginterval>  
      </eventqueue>

Things to take care regarding Event Queue

  1. If we have more than one instances in an environment, it is must to EnableEventQueue on all the instances
  2. The processinginterval should be as minimum as we can set, say 2 seconds, so each server gets synced in no time.
  3. All CM instance should have exact time.
    If two instances have time difference of 5 minutes, then there the instance running late will get updates of other instance after 5 minutes, so sync will never be done between them.
  4. When events are not triggered on time on the remote(other) servers, clear the EventQueue table from database.

    Let's consider a practical case, once a user by mistake published 10k items and publishing is going on through PI. There are few others items queued after it, which are more important. Now, we found that we have to stop the 10k items' to give priority to other items. We have only one option to restart PI. But after PI restart, once we found once that those 10,000 items started publishing again (No one added them again)!! Ufff.. finally we came to know there was some issue with Event Queue processing/clearing. We cleared Event Queue and restarted PI again, now good to see, problem is solved. :)

Different events handled by EventQueue

Event Queue is used to make CMs in sync when item operations like Save, Creation, Deletion, Recycling, Restore, etc. happens. This sync happens with the help of Master database EventQueue.

Suppose, we have a separate PI to do publishing apart from a CM. Now, each publish set from the CM is done by PI, how? It is just because of Event Queues. CM sends an event for PI to do publish. So, PI will trigger the event and starts doing actual publish.

When items are published from CM or PI, CD should be notified when the publish is completed, CD starts clearing html cache accordingly. This happens by Event Queue on web database.

Great Sitecore Event Queue architecture!!

Sitecore Query Strings Parameters

Sitecore gives different querystring parameters like choosing item, language, device, etc. stuffs to manage them easily without any configurations, etc. Also, it uses many querystring parameters to manage Content Editor efficiently.

Content Editor

There are many parameters Sitecore uses to manage content editor.

sc_content

- It changes the Sitecore database for the context of Content Editor. If querystring has value as sc_content=web, then content editor will open items from web database.

sc_lang

- It changes the Sitecore's default language. It is not exactly Item's language, but you can say language of the Sitecore's ribbon. For example, if sc_lang=en-GB, then in Content Editor, it will render the whole ribbon as en-GB language. If we pass this parameter for Preview/Page Editor/Normal mode, then it will set Items' language.

fo

- It will request Content Editor to open the given item directly. the item passed will be autopopulated from the tree and its properties will be shown without traversing the tree.

As per below snap, Products item has Item ID: {07D9A696-A2FE-4A59-88FB-A57FE386B8AD}. Now, if we want to open Products item directly in Content Editor, then we can pass querystring like fo={07D9A696-A2FE-4A59-88FB-A57FE386B8AD}. We can also pass Item Path instead of Item ID

ro

- It will request Content Editor to open the given item directly, but will be shown as a root item, means its parent will not be shown in the tree. Producta item has Item ID: {07D9A696-A2FE-4A59-88FB-A57FE386B8AD}.

If we pass querystring like ro={07D9A696-A2FE-4A59-88FB-A57FE386B8AD}, will open it as below.

Page Editor/Preview/Normal mode

There are many parameters Sitecore uses to preview pages.

sc_content

- It changes the database context for current requested page. If we request as sc_content=web, then it will render the whole page using item values from web database.

sc_lang

- It changes the language context for current requested page. If we request as sc_lang=de-DE, then it will render the whole page using item values from German language version. LanguageResolver processor is responsible for determining Context Language, which determins it using sc_lang querystring parameter or by current language cookie set in browser.

sc_itemid

- This parameter is mostly used for previewing particular item from Content Editor. When we preview any item from Content Editor, it opens preview/page editor window to view selected item's rendering. ItemResolver processor is responsible for determining Context Item, which determins it using sc_itemid querystring parameter or URL/site requested.

sc_device

We can change device using this parameter. If we pass sc_device=mobile, then mobile device will be set to Context Device. DeviceResolver processor is responsible for determining Context Device, which determins it using sc_device querystring parameter or by Browser agent.

Media(Images) Requests

There are many parameters Sitecore uses to alter image on-the-fly. You can refer my earlier post to see different querystring parameters for requesting images in Sitecore: Sitecore image control and querystring parameters