Sitefinity Toolkit: Mobile Device Detection

IMPORTANT UPDATE FOR USERS OF SITEFINITY TOOLKIT 1.2

There is a compatibility issue between the Mobile Foundation library used for mobile detection and the Sitefinity Administration Login that could not be resolved. The Mobile Detection Module can still be used but the Mobile Foundation must be DISABLED in web.config by commenting out the related sections in web.config:

<!--
<sectionGroup name="fiftyOne">
<section name="log" type="FiftyOne.Foundation.Mobile.Configuration.LogSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
<section name="redirect" type="FiftyOne.Foundation.Mobile.Configuration.RedirectSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
<section name="wurfl" type="FiftyOne.Foundation.Mobile.Detection.Wurfl.Configuration.WurflSection, FiftyOne.Foundation" requirePermission="false" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
</sectionGroup>
-->

 <!--
<fiftyOne>
<wurfl wurflFilePath="~/App_Data/wurfl.xml.gz">
<wurflPatches>
<add name="browser_definitions" filePath="~/App_Data/web_browsers_patch.xml" enabled="true"/>
</wurflPatches>
</wurfl>
</fiftyOne>
-->

Commenting out these sections in web.config will disable the Mobile Foundation module from loading and interfering with the Sitefinity Login page. I hope to resolve this soon with the help of 51 Degrees, makers of the Mobile Foundation.


Overview

I think by far the best part of Sitefinity is how it is built on and makes full use of the ASP.NET architecture. Because of things like Code-Behind, Themes, Skins, and other foundations of the Framework, Sitefinity is more open and extensible than any other CMS platform I’ve ever used.

A direct consequence of the separation of content vs design is how easy it is to “swtich themes”. It’s as simple as populating a new Theme folder with new css and images mapped to the css classes defined in your page. It was a simple matter to take this one step further by creating a “Mobile” theme that can be switched to automatically based on the capabilities of the device accessing the site!

Detecting the device was the hard part. I experimented with many options including using the wurfl asp.net API, and then when that didn’t work, even building my own wurfl wrapper. Not having the time nor patience to dive into that can of worms, I was relieved to discover that an excellent mobile kit had already been developed by 51 Degrees. Their Mobile Toolkit is a GODSEND; easy to install, configure, and use! If you have ANY mobile device needs for your website, start with 51 Degrees!

Installation and Setup

The Sitefinity Toolkit already includes the necessary Mobile Toolkit libraries to run this feature, but make sure you download the correct version for your Sitefinity installation and unzip to your site’s bin folder.

In order for detection to work, you must make sure to download the latest WURFL definitions and patch file and place them somewhere accessible on your site (I placed mine in the App_Data folder). Map the files in your web.config, as well as some additional settings by adding the following to your config file (note the file locations):

<?xml version="1.0" encoding="UTF-8"?>
<
configuration>
<
configSections>
<
sectionGroup name="mobile">
<
section name="toolkit" type="Mobile.Configuration.ToolkitSection, Mobile, Version=0.1.5.0, Culture=neutral" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
<
section name="wurfl" type="Mobile.Devices.Wurfl.Configuration.WurflSection, Mobile, Version=0.1.5.0, Culture=neutral" allowDefinition="Everywhere" restartOnExternalChanges="false" allowExeDefinition="MachineToApplication"/>
</
sectionGroup>
</
configSections>

... <mobile>
<
toolkit logFile="~/App_Data/MobileLog.txt" logLevel="warn"/>
<
wurfl wurflFilePath="~/App_Data/wurfl.xml.gz">
<
wurflPatches>
<
add name="browser_definitions" filePath="~/App_Data/web_browsers_patch.xml" enabled="true"/>
</
wurflPatches>
</
wurfl>
</
mobile>
</
configuration>

NOTE: For detailed instructions on how to customize this configuration, please take a look at the .NET Mobile API User Guide from the 51 Degrees website.

Normally to use the toolkit, you would add their Detector HttpModule to your web.config. However, since this is running in Sitefinity, there’s a few extra steps I wanted to go through after detecting the device to store the status in session. This way, you don’t have to check the device on every session. Also, if a mobile user wants to see the full site, or vice-versa, you can save that in the session as well, bypassing the check (more on how to do that later).

To do this, I inherited from the default Detector module and made my own, so that’s the one you should add to your web.config HttpModules nodes:

For IIS 6

<system.web>
<
httpModules>
<
add name="BrowserDetector" type="SelArom.Net.Sitefinity.HttpModules.BrowserDetectModule" />
</
httpModules>
</
system.web>

For IIS 7

<system.webServer>
<
modules>
<
add name="BrowserDetector" type="SelArom.Net.Sitefinity.HttpModules.BrowserDetectModule" preCondition="managedHandler" />
</
modules>
</
system.webServer>

Detecting Page

Since all page requests in Sitefinity are internally routed through a single entry point (located at /Sitefinity/cmsentrypoint.aspx), you need to modify this page to inherit from the Toolkit Detector Page. This internal page handles all the fenagling to switch the to your mobile theme and master page (see next section below for requirements).

All you have to do is change the base class from which this entry point page inherits:

<%@ Page Inherits="SelArom.Net.Sitefinity.Pages.DetectingPage" MasterPageFile="~/Sitefinity/Dummy.master" %>

Mobile Theme Requirements

When a mobile device is detected (or the mobile view is forced, explained later), the Detecting Page above automatically switches to the “Mobile” theme and switches the underlying MasterPage to “Mobile.Master”. In order for this to work without crashing, you MUST have an ASP.NET Theme Folder named “Mobile” and it MUST be called “Mobile”. In addition, you MUST also define a “Mobile.Master” file in your App_Master folder (which MUST also exist). These are the files used by the Detector to switch themes.

In future releases I hope to be able to allow you to choose the themes and master pages, but for now, you can style and define these however you wish to best suit your website. However they MUST match these file names and MUST live in the specified folders.

For help getting started with a mobile theme, be sure and check out the Sitefinity Mobile Starter Theme available in the Sitefinity Marketplace. It is an awesome starter theme developed by the kind folks at Data Universal Inc.

Usage and Examples

After configuring everything above, your website should now automatically detect
mobile devices and switch themes. Try visiting any of these sites from a mobile device (or click the Mobile link to preview the mobile version on your PC); all of them use the Sitefinity Toolkit:

If you compare these to the full desktop versions, you’ll see that the text, links, pictures, and other content are pretty much exactly the same! This is because other than a few customizations here and there, it IS the same content. With this toolkit (and associated theme/master page) you don’t have to make a separate mobile site; you can feed the same content to ALL your users!

Switching Modes

Notice how both versions of these sites have a link for you to switch between mobile and full versions of the site. As you may have guessed from the links above, the “mobile” query string is used to switch between modes. Adding “?mobile=1” to the full site will switch to mobile, and it will KEEP that selection through all future pages until you either switch back or your session expires!

Switching back is simply a matter of appending the querystring to the current Url. You can place this link anywhere (I recommend on the header of your master page). Here is the code I use to create the link on the main page to swtich to mobile view (first define a HyperLink control called lnkMobile):

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);

    var url = Request.RawUrl.ToLower();
    if (url.Contains("mobile="))
        url = url.Replace("mobile=0", "mobile=1");
    else if (url.Contains("?"))
        url = string.Concat(url, "&mobile=1");
    else
url = string.Concat(url, "?mobile=1"); lnkMobile.NavigateUrl = url; }

To switch back, simply reverse the polarity of the mobile flag (Add this to your Mobile.Master page):

var url = Request.Url.ToString().ToLower();
if (url.Contains("mobile="))
    url = url.Replace("mobile=1", "mobile=0");
else
if
(url.Contains("?")) url = string.Concat(url, "&mobile=0"); else
url = string.Concat(url, "?mobile=0"); lnkFull.NavigateUrl = url;

In a much later release I hope to include a “SwitchModeLink” control that you can drop onto a page, but for now, the code above should work just fine.

Tookit Version 1.1

I’ve discovered a few bugs and issues in the 1.0 release of the toolkit, and I’ll be creating a separate post to go over the details. However, there is one change to this particular feature I’d like to quickly cover.

In 1.0, the querystring remained appended to the url, causing double indexing in google to the same page. Since these are technically the same page, they should only have one Url.

So for 1.1 I’ve modified the code so that when you switch modes with the Querystring, the Detector HttpModule will automatically 301 redirect that Url to the correct Url that does NOT have that mobile flag in it. That way when your pages are crawled, only the original url to your page is ever indexed.

I hope to publish 1.1 before the end of the week. If you need it RIGHT AWAY (such as if you’re experiencing some bugs) lease email me and I’ll send you a link to download it. Those requests accompanied by a kind donation (see sidebar for details) will get a priority response, but of course no donation is ever required to access my work (though it’s always appreciated)!

If I left anything out, please let me know, and as always your comments and suggestions are welcome.

Toolkit Version 1.2

The Module will now no longer crash if the Mobile theme and Master Page are not present. Instead, the Module will create the empty theme and assign it, using the default Master Page in place. This should create a clean, mostly empty style that should render well on mobile devices.

There are some other improvements and tweaks, but make sure you take note of the very important issue noted at the top of this blog post. I will release a fix as soon as I get one worked out.

Sitefinity Toolkit: Workflow Notifications

Apologies for the delay in continuing this series. Life keeps me busy, and while I wouldn’t have it any other way, it’s sometimes difficult to find time for the little things. I’d also like to thank Darren L for providing the first donation to my studio fund! Because of his kind feedback and donation, I’ll be releasing an update to the Sitefinity Password Recovery that will fix a few issues he encountered. Stay tuned for that, and please feel free to kick in a donation of your own (see sidebar for details).

Overview

NOTE: This feature is ONLY available for the STANDARD version of Sitefinity (not the community edition). Only the standard version includes the workflow feature, and as a result, this feature will not work with the community edition..

Sitefinity has a nice, if somewhat basic, workflow system that allows vetting of new content. Although I have to admit that I am looking forward to some big improvements to this in future versions, for the most part it works well. However, one key feature missing out-of-the-box is automatic notifications of changes to content item status.

I’ve attempted to address this by adding email notifications to content items for the News, Events, and Generic Content Modules. Implementation is VERY BASIC at this point, but it was enough to fit my current needs. As with all the other features of this project, I hope to build on it through future releases.

Installation

As always first download the sitefinity toolkit and unzip to your site’s bin directory.

You also need to setup your email credentials in the system.net node of your web.config file:

 <system.net>
    <mailSettings>
        <smtp>
             <network host="SERVERNAME" userName="USERNAME" password="PASSWORD" /> 
        </smtp>
     </mailSettings>
</system.net>

Finally, you need to make sure to enable workflow is enabled for each module:

<add name="Generic_Content" ... allowWorkflow="True" ... type="Telerik.Cms.Engine.Data.Providers.DefaultProvider, Telerik.Cms.Engine.Data" />
<add name="Events" ... allowWorkflow="True" ... type="Telerik.Events.Data.DefaultEventsProvider, Telerik.Events.Data" />
<add name="News" ... allowWorkflow="True" ... type="Telerik.News.Data.DefaultNewsProvider, Telerik.News.Data" />

Required Roles

In order for this feature to work, you need to define the following Roles (you can create these in the Sitefinity Administration tab) and add at least one user to each role. As the role names imply, these are the people who will be approving and publishing the items as they are submitted.

  • Approvers
  • Publishers

In addition to the above roles, you must create roles whose names match the names of the default providers for each module. On my site, the default provider for Generic Content is Software, so to use all three notifications, I would create the following roles:

  • News
  • Events
  • Software

Then I would assign to each role the users responsible, and set appropriate permissions for each module. Be sure that the Approvers and Publishers from the roles you created above are also members of the Module roles or the notifications will not be sent!

External Templates

Now you need to map external templates for your module’s administration. Be sure that your external templates use a full User Control that includes the associated code-behind page. The following templates need to be mapped:

  • NewsItemPreview
  • EventsItemPreview
  • ContentPreview (For Generic Content Module)

All you have to do now is modify the base class for each external template so that instead of inheriting from UserControl, they inherit from the corresponding template class in the toolkit:

News

public partial class Templates_Admin_News_NewsItemPreview : SelArom.Net.Sitefinity.Templates.NewsItemPreview{

}

Events

public partial class Templates_Admin_Events_EventsItemPreview : SelArom.Net.Sitefinity.Templates.EventsItemPreview{

}

Generic Content

public partial class Templates_Admin_Generic_Content_ContentPreview : SelArom.Net.Sitefinity.Templates.ContentPreview{

}

Usage

Once you have everything above setup, the notifications should automatically execute whenever workflow status is enabled. The email simply includes a notification and a link to the appropriate module. No item data is included; I hope to add that in a future release.

One thing I was careful to include is if a user is in the role they are submitting (for example, a user submitting for approval is also in the approvers role), then an email is not sent.

My needs for this feature were very limited and specific, so I’ll admit I have not done extensive testing on it. I do know it will crash if the above roles do not exist, so be sure if you want to use this feature that you follow the instructions carefully! I hope to refine this feature greatly in future releases, so if find I’ve left something out, or if you have any feedback or suggestions, please email me and if you use and enjoy my work, please consider following Darren’s lead and kicking a small donation to expand my music studio!

IIS 7 Adobe PDF Bug Fix

This is just a quick note to document a fix for a horrendous bug in Adobe Reader that causes downloads to fail if they are being served from a Windows Server 2008 machine. It has been plaguing me for weeks, before I even knew it was a bug! The last time I needed help with something I ended up finding the solution on my own blog, so hopefully if I encounter it again, I’ll end up here. Hello future self!

Anyway, the details of the bug are discussed in depth on the iis.net forum, but the basic summary is that a bug in Adobe Reader is causes the file download from IIS to halt, and the user is shown a blank screen. This doesn’t seem to happen if the user SAVES the file then opens it; only opening the file directly seems to cause the error (at least that was my experience).

Anyway, long story short, the fix that worked for me was provided by merk on page 5 of the discussion, which came in the form of an HttpHandler. Basically you map pdf files to run through this handler instead of the standard pipeline, and it does its magic voodoo to properly serve the file to the user.

Merk uploaded his solution to mediafire, you can download it here: http://www.mediafire.com/file/twrd2mnzm3y/PDFHandler2.zip.

I simply dropped it in the bin folder, mapped the handler to intercept *.pdf requests and now all is right with the world.

That’s all for today, with many thanks to Merk wherever you are!

Sitefinity Toolkit: Search Index Providers

I’d like to apologize for the delay in continuing my Sitefinity Toolkit series. Wednesday I was out sick, and have spent the rest of this week catching up. However I didn’t want the weekend to pass without adding at least something, so here is a quick rundown on using the new Search Index Providers provided by the toolkit.

A lot of this work is based on the Sitefinity Index and Search Events post I wrote last year, but in addition to indexing the Events Module, it has been extended to include support for Latest News, which is any news that has been published, but not yet expired, as well as items from your Generic Content Module.

Important Note as with all the other features in the current 1.0 version of the toolkit, only the Default Provider of each module is indexed, and no settings or preferences can be set for the indexes. In a future release I hope to include configuration and provider selection. If you would like to help support future releases, please consider making a donation to expanding my music studio (see sidebar).

Installation

As always, be sure to download the sitefinity toolkit and extract it to your bin directory, making sure to get the correct version for your sitefinity installation.

Depending on which index providers you want to use, copy any combination of the following to your web.config file:

<telerik>
    <search>
        <indexClients>
            <add name="PageIndex" type="Telerik.Cms.Search.PageIndexProvider, Telerik.Cms" settingsControl="Telerik.Cms.Web.UI.PageIndexSettings, Telerik.Cms" viewSettingsControl="Telerik.Cms.Web.UI.SearchViewControl, Telerik.Cms" description="Provides indexing services for CMS Pages." />
            <add name="LatestNewsIndex" type="SelArom.Net.Sitefinity.IndexProviders.LatestNews.LatestNewsIndexProvider, SelArom.Net.Sitefinity" settingsControl="SelArom.Net.Sitefinity.IndexProviders.LatestNews.SettingsControl" viewSettingsControl="SelArom.Net.Sitefinity.IndexProviders.LatestNews.ViewControl" description="Provides indexing for current news." />
            <add name="EventIndex" type="SelArom.Net.Sitefinity.IndexProviders.Events.EventIndexProvider, SelArom.Net.Sitefinity" settingsControl="SelArom.Net.Sitefinity.IndexProviders.Events.SettingsControl, SelArom.Net.Sitefinity" viewSettingsControl="SelArom.Net.Sitefinity.IndexProviders.Events.ViewControl, SelArom.Net.Sitefinity" description="Provides indexing for events." />
            <add name="GenericContentIndex" type="SelArom.Net.Sitefinity.IndexProviders.GenericContent.GenericContentIndexProvider, SelArom.Net.Sitefinity" settingsControl="SelArom.Net.Sitefinity.IndexProviders.GenericContent.SettingsControl, SelArom.Net.Sitefinity" viewSettingsControl="SelArom.Net.Sitefinity.IndexProviders.GenericContent.ViewControl, SelArom.Net.Sitefinity" description="Provides indexing for events." />
        </indexClients>
    </search>
</telerik>

Like the Sitemap Generator feature, it is necessary for you to specify the url “prefix” (see previous post for more information) for the “details” page of each module in your appSettings node.

<appSettings>
    <add key="NewsUrl" value="/news/details" />
    <add key="EventsUrl" value="/events/calendar/details" />
    <add key="MyGCProviderUrl" value="/mygcprovider/details" />
</appSettings>

Remember the key is created from the name of each provider followed by “Url”. In the above, my events provider is “Events”, my Generic Content Module provider is “MyGCProvider”, and so on.

Now you need to go to your site Sitefinity Administration page at sitefinity/admin/CmsAdmin/Services.aspx?service=Search. Either create a new index or select an existing one. The index providers will be available for you to select at the bottom:

sitefinitytoolkit_indexproviders

As you can see, there are currently no options in any of these custom providers. Future releases will hopefully allow to set the web.config settings here, as well as select which provider you wish to use, but for now, this provides you with basic indexing and searching of your Events, Active News, and Generic Content.

Save your changes, then start indexing; you’re done!

Let me know if I’ve missed anything, or if you have any comments or suggestions, please email me. If you enjoy my work, I would kindly appreciate any donation to help expand my music studio. See the sidebar for more details.

Sitefinity Toolkit: iCal Event Reminder

One of the best features of Sitefinity is the Events Module. But while you can easily add and categorize events, and even show a nifty interactive map on the event detail page, there isn’t any built-in way to let your visitors add the event to their Outlook calendar.

Fortunately, with the help of DDay.iCal Class Library by Douglas Day, I was able to bring easily incorporate this functionality. The process basically reduces to this:

  1. Retrieve the Event ID from the event details page
  2. Pass that ID to an ashx handler, which returns an iCal item

Installation and Usage

Of course you need to download the Sitefinity Toolkit and unzip it to your site’s bin directory. Be sure that you download the version that matches your Sitefinity installation, and that you have the included DDay.iCal and antl.runtime libraries, as they are required for this module.

You need to register the ASHX handler for the event reminders. This takes an Event ID and returns an iCal item. Add the following to your web.config:

<httpHandlers>
    <add verb="GET" path="/eventreminder.ashx" type="SelArom.Net.Sitefinity.HttpHandlers.EventReminder" />
</httpHandlers>

If you are using IIS 7 be sure to register the handler in the system.webserver node as well:

<system.webServer>
    <handlers>
        <add name="EventReminder" verb="GET" path="/eventreminder.ashx" type="SelArom.Net.Sitefinity.HttpHandlers.EventReminder" />
    </handlers>
</system.webServer>

Event Details External Template

In order to add the Event Reminder link to your event details page, you must map the Event Details page to an external template. The external template you map MUST include the code behind page, since this is where you’ll be adding code to retrieve the Event ID.

On the front-end (.ascx file) of your external template, add a HyperLink control, which is what users will click to get the iCal item.

<asp:HyperLink ID="CalendarReminder" runat="server" ToolTip="This event occurs in the past" Enabled="false" />

Take special note of the properties that are set here. By default, the link will not be enabled, because for events in the past, there should be no need to set a reminder.

Now we need to set the code that will retrieve the current events id, and if necessary, enable and build the link to the reminder. Add the following to your Page_Load event.

protected void Page_Load(object sender, EventArgs e)
{
    // retreive event item from current view
    var view = Parent.Parent as EventsView;
    var mgr = new EventsManager("Events");
    var ev = mgr.GetEventByContentId(view.SelectedItemId);

    // if event is not in the past
    if (ev.End >= DateTime.Now)
    {
        // build and enable link to reminder
        CalendarReminder.Enabled = true;
        CalendarReminder.ToolTip = string.Concat("Add a Reminder for ", ev.EventTitle, " to Outlook");
        CalendarReminder.NavigateUrl = string.Format("~/EventReminder.ashx?id={0}", ev.ID);
        CalendarReminder.Text = "Add To Outlook";
    }
}

As you can see, we’re using reflection to grab the selected item’s id from the EventsView control that is embedded with our template. There may be a better way to retreive this (especially since SelectedItemId is an obsolete member) but for now, this does the trick.

Next you need to check the event end date. If it’s not yet past, build the link from the event metadata and enable the link.

That’s pretty much all there is to it! If I missed anything please let me know, and if you have any suggestions or comments send them my way as well. If you enjoy this toolkit or any of my other work, please consider kicking a small donation to my studio fund via the sidebar on the right.

Sitefinity Toolkit: Custom 404 Page with Search Results

I realize that in my last post on Forcing Lowercase Urls I said I would be going over the Smooth Menu feature of the Sitefinity Toolkit. However, as I started writing it, I discovered it was a little more complicated than I expected, so I’m going to hold off on that one until I have a little more time to complete the full instructions. Sorry about that!

So instead, I’m going to quickly go over how to use the Custom 404 Page feature. If you’re a repeat visitor to my site, you may be familiar with how this works, as I used a lot of the same code from my Custom 404 Page with Related Links post. This wraps all of the code into a custom page class that you can use to easily add a 404 page to your site.

Installation

Make sure you’ve downloaded the Sitefinity Toolkit and installed it to your site’s bin directory.

You must also have a Search Index created for your site and have already indexed your site at least once. NOTE the current release will only index the FIRST search index (alphabetically sorted). If you have multiple indexes, only the first index will be searched to generate results.

You need to add a custom page to your site, I usally just call it 404.aspx and place it at the site root. Go to the page code-behind and change the base class from System.Web.UI.Page to instead use the custom 404 page class:

public partial class _404 : SelArom.Net.Sitefinity.Pages.Error404
{

}

Next you need to include a Repeater to show the search results on the front-end of the page. Add the following html:

<asp:Repeater ID="ResultsRepeater" runat="server">
    <HeaderTemplate>
        <h2>Possible Related Links</h2>
        <dl class="searchResults">
    </HeaderTemplate>
    <ItemTemplate>
        <dt><strong><a href='<%#Eval("Url")%>'>
            <%#Eval("Title")%></a></strong></dt>
        <dd>
            <%#Eval("Snippet")%></dd>
        <dd>
            <em><a href='<%#Eval("Url")%>'>
                <%#Eval("Url")%></a> </em>
        </dd>
    </ItemTemplate>
    <FooterTemplate>
        </dl>
    </FooterTemplate>
</asp:Repeater>

You can change the ID, as well as the template html to use ul, ol, or any other markup you wish. Just be sure not to change the Url, Title, and Snippet properties, as that is required for the results to show.

Now you simply need to bind the results (loaded automatically into the SearchResults property of the base class) to this repeater:

protected void Page_Load(object sender, EventArgs e)
{
    if (SearchResults.Count == 0)
        ResultsRepeater.Visible = false;
    else
    {
        ResultsRepeater.DataSource = SearchResults;
        ResultsRepeater.DataBind();
    }
}

That’s all there is too it. The base class also automatically modifies the response code to 404, ensuring that the page is properly returned as Not Found.

By default, a maximum of 5 results are loaded. If there are no related results, the Repeater is hidden from view. Note: There is currently no way to modify this, but I hope to add such a feature in a future release, as well as support for multiple, selectable indexes.

Let me know how it works for you. If you enjoy my work or have any suggestions for improvement, please consider donating your support to expanding my studio (see sidebar for details).

Sitefinity Toolkit: Lowercase Url HttpModule

One of the things that has always annoyed me about unix-based systems is the fact that they are case-sensitive. While I understand the need to differentiate between the two, and the advantages it CAN bring, in my opinion, it’s just not worth the hassle.

Since Windows servers ignore the case of requests, it should theoretically simplify things. Unfortunately, since people linking to your page might use any combination of upper-case and lower-case letters, it results in multiple urls to the same page being indexed in search engines.

Now I don’t know enough about SEO to know exactly how big a deal this is, but I do know that it is annoying to be viewing a link report and seeing 15 copies of the same page with a dozen different capitalizations. The easiest solution I found was to just force them ALL to be lower-case. That way anything that isn’t will be 301 redirected to the lower-case url and only that one will ever be indexed.

This was actually an easy thing to implement. Without going into to much detail, the basic idea is to intercept the url request and compare it against the lower-case version of itself using ToLower(). If they match, then we’re good to go. Otherwise simply redirect to the lowered url. Simple!

Installation

This is a no-brainer; simply put the following in your web.config:

<httpModules> <add name="LowerCaseUrl" type="SelArom.Net.Sitefinity.HttpModules.LowerCaseUrlModule" /></httpModules>

If you’re using IIS 7 be sure and add this to system.webserver as well:

<modules> <add name="LowerCaseUrl" type="SelArom.Net.Sitefinity.HttpModules.LowerCaseUrlModule" /></modules>

That’s all that’s required to get this working. To test it out, simply change any letter in the url for this page to uppercase and see how you are automatically redirected to the lowercase version.

Note: This module is designed only to intercept pages, that is urls to .aspx pages. If your site is using another extension, or is using extension-less urls, this module will most likely not work. If this applies to you, please email me your experiences so that I can include support for your setup in a future release.

Next time, I’ll be going over the Smooth-Menu feature of the toolkit, which automatically generates a simple, ul-li based navigation menu from your sitefinity sitemap. Until then, send me any comments, bugs or suggestions to josh@selarom.com. And as always, if you enjoy my work, please consider donating your support to expand my studio by using the widget on the sidebar.

Sitefinity Toolkit: Sitemap

In the first post on my Sitefinity Toolkit series, I’ll be introducing the SiteMap Generator, which creates an ashx handler to automatically create an XML Sitemap. This can be submitted to Bing, Google, or any other search engine.

Installation

Download and install the Sitefinity Toolkit to your bin directory. Be sure to download the correct version for your Sitefinity installation!

Modify web.config

You need to create a handler for the url /sitemap.ashx and map it to the Sitefinity Toolkit. Add the following to your web.config:

 <system.web>
        <httpHandlers>
            <add verb="GET" path="/sitemap.ashx" type="SelArom.Net.Sitefinity.HttpHandlers.SiteMap" />
        </httpHandlers>
    </system.web>

If you are using IIS7, be sure to include this under system.webserver as well:

<system.webServer>
    <handlers>
        <add name="Sitemap" verb="GET" path="/sitemap.ashx" type="SelArom.Net.Sitefinity.HttpHandlers.SiteMap" />
    </handlers>
</system.webServer>

Now all you have to do is navigate to yoursite/sitemap.ashx and your sitemap should load. Here is the sitemap for this site.

Including Modules

The Sitemap is built by parsing all pages in your sites tree. However, in addition, it can also navigate through the Events, News, Blogs, and Generic Content modules and add those pages to your sitemap.

NOTE: as of version 1.0, only the Default Provider for each generic content module is read. If you have more than one provider for each module, only the one listed as default will be included in your sitemap. If enough people request this feature (and perhaps kick in a few bucks to my studio fund, see sidebar) I’d be happy to extend this functionality to other providers.

In order for this to function properly, you need to define the url for the “details” page of each module. This is the page that holds the “detailsview” for the individual modules. This url needs to be defined in the appSettings node of web.config, using the Provider Name ending with “Url” as the key and the value being the url prefix for the details page.

For example, my Blog posts are prepended by “/blog” (look at the url for this page as an example. Also, my Software section uses the Generic Content module, and the url for those posts are prepended with “/software“. So my web.config looks like this:

<appSettings>
    <add key="BlogsUrl" value="/blog" />
    <add key="SoftwareUrl" value="/software" />
</appSettings>

On this site, the default provider for the Blog Module is “Blogs” and the default provider for the Generic Content Module is “Software”. Therefore I use the keys “BlogsUrl” and “SoftwareUrl” to define the url prefixes for these posts. If you were including events and news, your appsettings might look like this:

<appSettings>
    <add key="EventsUrl" value="/calendar/event" />
    <add key="NewsUrl" value="/news/default" />
</appSettings>

It just depends on what page you have defined to hold the detailsview for these modules, as well as the name of your default provider. If you do not define these keys, the sitemap will simply skip over these modules and proceed to the next one.

And that’s all there is to it! Give it a try, and please let me know your results. If you encounter any issues, have any suggestions or comments, please send them to josh@selarom.com. And if you like my work, please consider donating to my studio fund through the widget on the sidebar!

Next time, I’ll be going over the Lowercase Urls feature that ensures that any non-lowercase urls are automatically 301 redirected to the lowercase version. Stay tuned for more!

Sitefinity Toolkit 1.0: Introduction

It’s no secret that I am a devout fan of the Sitefinity content management system by Telerik. But in developing a handful of sites over the past few years, I’ve discovered that I’m doing a lot of things over and over that I wish were part of the Sitefinity core.

That’s where the Sitefinity Toolkit comes in. After months of hacking, it I’ve put together a collection of several tools I’ve developed since I started working with the CMS in 2007. In this post, I’ll just be giving a brief overview of what features are included. Future posts in the coming days and weeks will explain in detail how to enable and use each feature (though feel free to hack away and email me with any questions or comments).

Sitefinity Toolkit 1.0 Features

NOTE: the Sitefinity Toolkit is only available for the ASP.NET 3.5 versions of Sitefinity.

Sitemap

Automatically generates /sitemap.ashx, parsing through not only all your site’s public pages, but also news, events, and generic content items!

Note: Version 1.0 only supports the default generic content provider, so if you have multiple content providers for the Generic Content Module, only the default one will be used to generate the sitemap.

Smooth-Menu

Autmoatically generates a SEO-friendly, bare-bones navigation menu based on your sites sitemap.

Search Index Providers

Add Events and Generic Content (default provider only) items to your search engine. Also available is a Latest News indexer, which will add only non-expired items to the index.

Mobile Browser Detection

Uses the Wurfl API to detect mobile browsers to show these users a mobile-friendly version of your website.

Lowercase Urls

Intercepts requests with and 301 Redirects to the lower-case version of your url (for search engine optimization)

Custom 404 Page

Show your Sitefinity search results to your users based on the non-existant url they tried to visit.

API

Retreive both News and Events from your site’s Default Providers in JSON format. Helpful for constructing Javascript widgets or feeding information to other Sitefinity sites.

Event Reminders

Create Outlook Reminders for your Event items (default provider only)

Workflow Notifications (Sitefinity Standard Only)

Automatically send emails to approvers or publishers at appropriate steps in the workflow for News, Events, and Generic Content items (default provider only).

Download

Visit the Sitefinity Toolkit 1.0 page in my software section for the latest download information. As always your comments and suggestions are welcome.

Important Notice

I have tested this toolkit extensively with Sitefinity Standard 3.7 SP1, since that’s the version I currently use. I’ve also done some testing with Sitefinity Community Edition 3.7 SP1, which is what is used on this website. However, this website runs in Medium trust so I haven’t made use of all the features.

Please report any issues to josh@selarom.com. If I get enough interest, I’ll start a public tracker.

For the most up to date information, downloads, and updates, visit the Sitefinity Toolkit Page in my software section.

Plans for Version 2.0

I didn’t get to cram everything into the toolkit that I wanted to, so here’s a preview of what I’m working on for the next version.

  • Offline Mode – Allows the site to be offline to the public, while still allowing the admin section to be accessible
  • Calendar (iCal) Feed – generates an iCal feed for your users to subscribe based on your Sitefinity Events
  • Page Notifications – Send notifications to Approvers and Publishers at appropriate steps in the workflow for Page changes
  • Add support for and allow you to choose from multiple custom providers

The latest version of the Sitefinity Toolkit will always be available for download here.

This toolkit is and always will be FREE to use and distribute as you wish (although I currently have no plans to publish the source code). If you enjoy my work, please consider making a donation to help me expand my music studio (see widget on the sidebar).