Sitefinity Toolkit Moves to Codeplex

Now that Sitefinity 4 has been out for over a month, the time I have available for maintaining the Sitefinity Toolkit is quickly diminishing. However, I still receive frequent emails asking for help, suggesting new features, or reporting bugs. I’m glad that so many of you continue to find the toolkit useful, and I regret that I don’t have enough time to keep up with all of your feedback.

As a result, I am pleased to announce that, at long last, I am releasing the full source code for the Sitefinity Toolkit on Codeplex. All updates, discussions, bug reports, and feature requests should be directed to the Codeplex project so that they can be better tracked, responded to, and implemented.

Important Changes

Because the source code is now available, future releases of the Toolkit will no longer be compiled for every Sitefinity version. Only the most recent version (currently SP4) for ASP.NET version 4.0 will be publicly available on Codeplex; all other versions will need to be manually built from the source code, referencing the binaries for your project.

However, since they are already up, the downloads for the current Sitefinity Toolkit v1.2 will remain available for all Sitefinity and ASP.NET versions.

Whenever there is a new release posted, I’ll be sure to add to the documentation Instructions for building the toolkit for other Sitefinity and ASP.NET versions.

Future Plans

As I mentioned, nearly all of my time is now focused on the new Sitefinity version 4. However, I plan to continue to work on the toolkit, including new features and bug fixes as reported by users.

However, since the full source code is now available, please feel free to add your own modifications and share them back to the community. Any useful contributions will gladly be incorporated into the project.

This is my first ever open-source project, so I ask that you bear with me as I figure things out. But I hope that it is a successful one, allowing the project to continue to grow and be a useful tool for Sitefinity users everywhere.

Thank you to everyone for your comments, suggestions, and donations (which, by the way, are still welcome and very much appreciated)!

Sitefinity Toolkit 1.2 Released, Supports All Versions of 3.7

At long last, I’ve finally been able to successfully compile the Sitefinity Toolkit for ALL versions of the latest Sitefinity version 3.7! A lot of improvements have been added over the years, including fixing a few nasty bugs and completely rebuilding the Caching and Notification features. For a complete changelog and downloads for all versions, check the Sitefinity Toolkit Page.

Full Sitefinity 3.7 Support

As I just mentioned the BIGGEST change in this release is that it is now fully supported for ALL versions of Sitefinity 3.7, including all service packs up to SP4. In addition, all ASP.NET versions are also supported: 2.0, 3.5 and the new 4.0 (which is only currently available for SP4).

As I mentioned in my previous Sitefinity Toolkit update, this presented an interesting challenge, ultimately ending up required a total of 22 Visual Studio projects in the solution. I hope to put together a walkthrough of my experience to help anyone who might have an existing control in the Sitefinity Marketplace and wants to support multiple versions.

Although Sitefinity 4 is coming up fast (be sure and check out next week’s webinar on the RC release!), current developers of 3.7 controls and tools will certainly want to make sure their products are available to anyone who might still be using them. So stay tuned for that very soon!

Mobile Toolkit Conflict

There is an important issue that I was unfortunately unable to resolve is a conflict between the Mobile Foundation (formerly Mobile Toolkit) developed by 51 Degrees and the Sitefinity Administration Login.

You are still able to enable the mobile device detection module, however you must disable the Mobile Foundation in web.config. For instructions, take a look at the updated Mobile Detection post. Disabling the Mobile Foundation will force the detection to fall back to the standard ASP.NET method IsMobileDevice, bypassing the WURFL definitions.

I hope that this change is only temporary while I work with 51 Degrees to try and figure out why this is happening. An update will be posted as soon as I have a fix!

An Important Reminder

Remember always that this Sitefinity Toolkit is a personal project, and is in no way an official Telerik product, nor is it supported officially by anyone other than myself. The software is provided as-is, and should be used at your own risk.

That being said I have tested it successfully on several sites, including this website you’re reading now, but I don’t have the resources to test on every platform and version. Please be sure to TEST, TEST, TEST before deploying this in a production environment. Should you encounter any issues, I would really appreciate your feedback!

With that being said I am pleased to also remind you that the Sitefinity Toolkit is finally permanently free of charge to use as you please. I will still not yet be distributing source code, but the Toolkit itself will always be without cost. Donations are always appreciated, but if nothing else, please send me your feedback so that I can continue to improve it for everyone (including myself)!

Sitefinity Toolkit 1.1 (with support for Sitefinity 3.7 SP3)

At long last I finally found time to publish the latest version of the Sitefinity Toolkit, as of now version 1.1 with support for Sitefinity 3.7 SP1 through SP3 (it will not work with any other versions than these) on both the Standard and Community versions.

See the main page for the Sitefinity Toolkit for the download links and changelog, as the latest information for the toolkit will always be posted there.

Although I’ve tried to be thorough on this release, I honestly haven’t had the time to test it as much as I’d like, so if you encounter any issues, PLEASE email me and let me know so I can fix and release an update if necessary.

I hope you find the toolkit useful, and if you have any suggestions or comments please send them my way. The toolkit is forever free, but if you enjoy my work and wish to help support it, consider leaving a donation to my music studio fund, details on are on the sidebar.

Thanks for your patience, I’m looking forward to continuously improving the project!

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!

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!