+1-888-365-2779
Try Now
More in this section
Categories
Bloggers
Blogs RSS feed

Custom URL Formats for Sitefinity Content Modules

by Slavo Ingilizov

All content items in Sitefinity have URLs that are generated automatically from a given format. The default format includes the publication date and item title with the URL, and removes special characters at the same time. The URL format is configurable and this article explains how you can modify it.

A basic module with one content type

Let’s take the News module as an example. If we create a news item titled “Sitefinity SDK was released”, the URL of this item will be:

NewsItemUrl

The first part of the URL (up until the date) is the page that shows news items in your site (contains a News widget). The second part of the URL is formed by the item itself. My news item was created on October 13th and titled “Sitefinity SDK was released”, so the item URL is “2011/10/13/sitefinity-sdk-was-released”. When all this gets together, Sitefinity has enough information to open the page and retrieve the correct item.

This default behavior works in most scenarios, but many people need custom URLs. Those URLs may include more information for the item, or remove some of the information. You can easily change the URL format to include other properties of the content item. Let’s say we need to remove the date, and include the author’s name, which gives us the following format:

/author-name/item-title

To enable this, we can modify a setting of the default news provider, as follows:

  1. Go to Administration –> Settings –> Advanced
  2. In the configuration tree, open News –> Providers –> OpenAccessDataProvider –> Parameters
  3. Click “Create New”
  4. For the key, enter “urlFormat”.
  5. For the value, enter “/[Author]/[UrlName]”
  6. Save changes and restart the application

From this point on, all news items that you create will have the author and item title in the URL. The new URL of the news item shown above will be “http://localhost:60876/news/Slavo/sitefinity-sdk-was-released”.

Multiple content types per module

Things are pretty easy for News, because there is only one content type for the module. Note that we changed a parameter of the provider, not the news item. This means that all items in the respective provider use the same URL format. With cases like the Blogs module, this leads to a more complex situation. In Blogs, both the blog itself and the post form part of the URL. The default structure is the following:

BlogUrlStructure

Because there are two content types in this case (Blog and BlogPost), the above settings don’t work and the URL format parameter of the provider is ignored. We can’t know if it specifies the URL of the blog or the URL of the blog post. There is still a way to change the format in this case, but it involves some programming. You have to create a custom provider for blogs, and override a couple of methods.

Implementing the custom provider

First, create a new class and inherit from Telerik.Sitefinity.Modules.Blogs.Data.OpenAccessBlogProvider. Since we want to modify the URL format for blogs and posts, we need two properties to hold the format strings:

/// <summary>
/// The URL format string for blog items
/// </summary>
public string BlogUrlFormat
{
    get;
    set;
}
  
/// <summary>
/// The URL format string for blog post items
/// </summary>
public string BlogPostUrlFormat
{
    get;
    set;
}

  

Then we need to override the method which actually returns the format string, when called by Sitefinity. The method is called GetUrlFormat and accepts an ILocatable item as an argument. The item is an instance of the object, whose URL format we should return. So we check its type, and return a different format for Blog and BlogPost, retrieved from the properties we’ve created.

public override string GetUrlFormat(Telerik.Sitefinity.GenericContent.Model.ILocatable item)
{
    if (item.GetType() == typeof(Blog))
        return this.BlogUrlFormat;
    else if (item.GetType() == typeof(BlogPost))
        return this.BlogPostUrlFormat;
    else
        return base.GetUrlFormat(item);
}

 

The only thing left is to actually set values to our properties. We do this when our custom provider is initialized by reading the values from configuration. We also supply defaults, in case the values in the configuration are not set.

protected override void Initialize(string providerName, System.Collections.Specialized.NameValueCollection config, Type managerType)
{
    base.Initialize(providerName, config, managerType);
    this.BlogUrlFormat = config["blogUrlFormat"];
    if (String.IsNullOrEmpty(this.BlogUrlFormat))
    {
        this.BlogUrlFormat = "/[UrlName]";
    }
    this.BlogPostUrlFormat = config["blogPostUrlFormat"];
    if (String.IsNullOrEmpty(this.BlogPostUrlFormat))
    {
        this.BlogPostUrlFormat = "/[Parent.UrlName]/[PublicationDate, {0:yyyy'/'MM'/'dd}]/[UrlName]";
    }
}

  

Register the new provider in Sitefinity

To use our new provider, we need to register it in Sitefinity. Here you have two options

a) Replace the default provider with the custom one - this will create no logical separation - Sitefinity will start using your custom provider and for all newly created items the new urlFormat will be applied.

or

b) Register it as new provider (i.e. you will be able to create items that are logically separated under another provider and follow your desired urlFormat)

A) To replace the default provider with the custom one, follow these steps:

  1. Go to Administration –> Settings –> Advanced
  2. In the TreeView, open Blogs –> Providers.
  3. By default you'll have just the OpenAccessDataProvider. Click on it, and edit the the ProviderType value by entering the CLR type (full namespace and type of the custom class you previously created) of your newly created provider.
  4. Save the changes

Note: If you have Sitefinity Multisite you might have more than one provider present  - in that case you have a choice to determine for which provider to apply the desired behavior. if you want it to be valid for all you have to repeat the steps for OpenAccessDataProvider to all other provides in this list.

B) To register your custom provider as new provider follow these steps:

  1. Go to Administration –> Settings –> Advanced
  2. In the TreeView, open Blogs –> Providers.
  3. Click “Create New”
  4. Specify a Name and Title for your custom provider.
  5. For ProviderType, enter the full namespace and type of the custom class you previously created. When you are done, the filled form should look something like this:

registerProviders

Once you have saved the changes of either of the two options listed above, you have successfully completed the cusotm provider registration. Now it's time to take benefit form it and configure it for the desired urlFormat. Here we need to supply the values for our new URL format strings. To do so, go to the Parameters node in the configuration tree, and create two new values:

  • One with key “blogUrlFormat” and value “/[UrlName]”
  • Second one with key “blogPostUrlFormat” and value “/[PublicationDate, {0:yyyy'/'MM'/'dd}]/[UrlName]”

The end result should be something like the following:

urlFormatConfig

Note that our URL format string for blog post contains only the publication date and url name. The default one in Sitefinity also has the parent item’s name - “/[Parent.UrlName]/[PublicationDate, {0:yyyy'/'MM'/'dd}]/[UrlName]”. What we are essentially doing is removing the blog from URLs of blog posts.

With this, we are done with our custom provider for blogs. Now restart the application - this is necessary to ensure the new provider and parameters configuration, which is written as XML entry under App_Data/Sitefinity/Configuration is read by the application, as these get cached on application initialization for performance optimization.

Republish your blog posts

By default the UrlFormat logic is executed when the item is saved - this means that your changes will be applied for all newly created items, however the old ones have already been persisted in the database with the default UrlFormat, thus they need to be re-saved in order for the new format to apply.
You can either manually select and publish all posts, or automate this through code, for example:

var manager = BlogsManager.GetManager();
            var blogPosts = manager.GetBlogPosts();
            var counter = 0;
            foreach (var blogPost in blogPosts)
            {
                manager.RecompileAndValidateUrls(blogPost);
                counter++;
                if (counter % 50 == 0)
                {
                    manager.SaveChanges();
                    counter = 0;
                }
            }
That's it - now your existing and newly created blog posts will have the desired urlFormat applied.

Working with items from the custom provider - (valid only if you have chosen option B) above)

When you go to create a new blog with some posts in it, use the custom provider. You will see that all providers are listed in the backend.

allProviders

All blog posts you create using the custom provider will use the custom URL format. By default, the Blog Posts widget displays only posts from the default provider. If you want to display items from the custom provider, you only need to set one property in Advanced view of the widget designer:

blogPostsWidgetSettings

When you view the new blog posts in the frontend, you’ll see now they have URLs with no blog name, similar to this: “http://localhost:65167/home/2011/10/19/custom-post-1”.

URL Format Syntax

With the approach described above, you’ll be able to specify custom URL format for all content within Sitefinity. You can use all item properties when specifying the format, by enclosing them in square brackets, like the above example with [UrlName]. Those will be replaced with the actual value for each item. Moreover, you can use format strings for properties like dates. All .NET date format strings are valid. This gives you a lot of flexibility when managing item URLs.

I hope this was useful. As always, we appreciate your feedback.

11 comments

Leave a comment
  1. Ahmad H May 16, 2012
    Thanks, but when adding the new parameter under news i got this error
    Object reference not set to an instance of an object
  2. Tarek Fawaz May 16, 2012
    I've receive an exception 

    The type SitefinityWebApp.CustomBlogsProvider is not interceptable.
    Parameter name: typeToIntercept

    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.ArgumentException: The type SitefinityWebApp.CustomBlogsProvider is not interceptable.
    Parameter name: typeToIntercept

    Source Error:

    please advise
  3. Stevie May 16, 2012
    I can't get the blog post control to load only the blogs I want because it always loads the blogs from openaccess and not the ones from the custom provider.
    If I select one of those blogs I get a funny little blog deleted error, could you tell me what I am doing  wrong?
  4. Stevie May 16, 2012
    I want to apologize for making duplicate comments but this happened because I hit refresh, I was not trying to do that on purpose , you should probably fix that.

    To clarify my problem. 

    I created the class and implemented and it works beautifully in every aspect except for the blog post controls.
    When I set up the blog posts control I can choose which blog to be displayed. Instead of being presented with the blog from the custom provider I get the blogs from the default porvider. Since I will have multiple blogs I really need that functionality

    I've gone through the article twice and I am fairly certain I went through every step. Could you please tell me what I am doing wrong?
  5. Robert May 16, 2012
    The same for me, it doesn't take blogs from custom provider. Event the designer offers filtering based on blogs from default provider.
  6. Robert May 16, 2012
    OK, got it. The GetUrlFormat method is called when the blog post is created, or edited (when Publish button in backend is clicked). So it's not dynamically invoked when the page is loaded. This was my case, probably Stevie is experiencing something similiar. So try to republish your blog posts and check in debug mode, whether the method is called.
  7. Jeff Aug 21, 2013
    I followed the directions and everything seemed to work as described (except I entered the value "/[UrlName]" instead of "/[UrlData]" for the "blogUrlFormat" parameter because of an error I received when I used the value "/[UrlData]").

    The problem is that the URLs were unchanged.  I created a new page and put a Blog Posts widget on the page and set the ProviderName to my custom provider name.  It displays the posts I made in the blog under the custom provider tab in Blogs (all is well so far, except that blog selection doesn't work so I chose "show all blogs").  However, the URLs are still in the default format.  It is hitting the breakpoint in the "GetUrlFormat" method of my custom provider and I can see in the debugger that the value returned is my custom value.  I can also see that that the "BlogPostUrlFormat" property is initialized with my custom value from using a breakpoint in the Initialize method.
  8. Pranali Apr 10, 2014

    I follow above steps and created custom provider as mentioned but the url I am getting is still the default url for blogs "http://localhost:2552/CustomProvider/home/testblog/2014/04/10/create-new-testblog" instead of url like you have mentioned "http://localhost:65167/home/2011/10/19/custom-post-1". I am not getting any error, but purpose it not solved.

  9. Pranali Apr 10, 2014

    I follow above steps and created custom provider as mentioned but the url I am getting is still the default url for blogs "http://localhost:2552/CustomProvider/home/testblog/2014/04/10/create-new-testblog" instead of url like you have mentioned "http://localhost:65167/home/2011/10/19/custom-post-1". I am not getting any error, but purpose it not solved.

  10. Mark Jun 08, 2015
    Hi all, I followed the steps. The thing is when we preview the draft or unpublished blog it throws a 404. The Sitefinity rules for preview no longer show. Is there a fix for this?
  11. Higher Oct 21, 2015
    Hello all. I too followed the steps and am experiencing the same trouble. All posts return a 404 error and the rules for preview no longer apply to blogs underneath the custom provider.

    Leave a comment