Monday, March 15, 2010

Sitecore Friendly URLs and plus sign


One of the customers recently asked about using the plus sign in URLs, for example: http://localhost/news+events.aspx

There are at least two ways to accomplish this:
1. Allow “+” in item name via a configuration change
For this you will need to adjust the regular expression in the “ItemNameValidation” setting in web.config and make sure + sign is not  present in the “InvalidItemNameChars” setting.
2. Rely on the display name instead.

I personally like this approach better where you don’t need to adjust item naming rules and at the same time leverage the flexibility provided in Sitecore CMS 6.x by the dynamic link management component called “Link Manager”:
<linkManager defaultProvider="sitecore">
      <providers>
        <clear />
        <add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="asNeeded" languageLocation="filePath" shortenUrls="true" useDisplayName="true" />
      </providers>
</linkManager>

In addition to the tricks describe here and here, you can instruct Sitecore to leverage item display names instead of item names for URLs by just flipping the “useDisplayName” parameter to “true”. This parameter is also extremely useful for multilingual sites.
Now you can change the display name of the NewsEvents item to “News+Events” and have a plus in your URL.
While everything looks great, it turned out that the request for http://localhost/news+events.aspx was failing with the error below:

Server Error in '/' Application.

Object reference not set to an instance of an object.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:


An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


 
[NullReferenceException: Object reference not set to an instance of an object.]
   Sitecore.Nexus.Web.HttpModule.(Object sender, EventArgs e) +340
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +79
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +170



Version Information: Microsoft .NET Framework Version:2.0.50727.4927; ASP.NET Version:2.0.50727.4927
The error stack trace hinted that this is somewhere at the high level, when Sitecore’s processing is not triggered yet.
After some research on the web, I’ve found that the problem is actually related to IIS, specifically IIS7’s security filtering module which does not allow double-escaped URLs. The following configuration change addresses the problem:
<system.webServer>
  <security>
     <requestFiltering allowDoubleEscaping="true" />
   </security>
</system.webServer>
That's it, folks!
Share |

10 comments:

Mark said...

Slightly off topic, so pls excuse.
Question relates to 'Aliases' within Sitecore.
I am currently having to use Server Side 301 (i think) to redirect 'friendly URLs' to real urls.
ie wanting
www.domain.com/friendly
to route to
www.domain.com/real/too/long/to-promote.aspx

I understand Aliases feature within Sitecore should do this as well. BUT its currently wanting to have the .aspx at the end of the friendly url - is this correct or a installation error?

Thanks

Alistair said...

Nice approach Alex.
I suppose you'd need some kind of event handler subscribed to the item:saved event to keep the item name and Display Name in sync if someone changed the item name?

Harender said...

nice post Alex, Do you have the answer of the first comment. i really want to know if sitecore supports url shortening. and if you could post a sample, that would be of great help.

Alex Shyba said...

Mark and Harender,

Sorry for being silent.

Yes, it is indeed possible, and a matter of configuration.

Recipe.
1. IIS7.x with app pool in Integrated Mode OR IIS5/6 configured as described here:
http://sdn.sitecore.net/upload/sitecore6/sc62keywords/dynamic_links_sc62_usletter.pdf

2. LinkManager's addAspxExtension setting set to "false"

Here is a picture of how this would look.
http://lh4.ggpht.com/_AIfg6b6IeD0/TH_-BPX8xCI/AAAAAAAAZrE/5gg251PtROk/s576/9-2-2010%2012-36-42%20PM.png

Mark said...

Alex

Thanks for your answer.
I see you refer to 6.2
Does a (this?) solution also apply for 6.1 or is 6.2 the pre-requisite?

Cheers
Mark

Mark said...

Alex

Your answer refers to Sitecore 6.2 - is this a prerequisite or can it also work in 6.1 based on your response?

Alex Shyba said...

Mark,

The doc refers to 6.2 but it is applicable to 6.1 also.

sanket said...

I have a question related to the URL.
Earlier I had languageembedding="always" and I don't want the language to appear in the URL anymore so I change it to "never". On doing so, when I enter the URL containing the language, it shows me a 404 page.
Is there any way I can redirect the users to the same page but without the language.
Eg: www.mywebsite.com/en/page1.aspx to www.mywebsite.com/page1.aspx.

Alex Shyba said...

sanket,

That should be easy to do.

Take a look the implementation of the following processor within the "preprocessRequest" pipeline:



Specifically, the Process method which you can override.

What it does is stripping the language code from the URL so the item can be resolved normally by path, but it is doing so only when the following condition is met:

if (LinkManager.LanguageEmbedding != LanguageEmbedding.Never)
{

}

Since you set LinkManager.LanguageEmbedding to "never", this will never be executed.

So what you can do is override the process method and modify this logic there.

Ask support.sitecore.net if you are not sure how to do that.

Francesco Gallarotti said...

Alex,

What else needs to be changed to make sure that the links generated by link.aspx are also extension-less?
Thanks,

FG