Gabe Sumner

Gabe Sumner

The RSS Feed URL cannot be found!
The remote server returned an error: (400) Bad Request.

Back to all posts

Adding Custom Fields to Existing Sitefinity Modules

Sitefinity comes with several useful modules you can use within your web site.  However, you might wish these modules contained extra options or worked slightly differently.

For example, I might use the Sitefinity Events module to schedule group hiking events, but I would also like to enter trail difficulty, group size and and a link to a trail map.

Luckily, many Sitefinity modules inherit from a common Generic Content Module base class.  Generic Content Modules can be extended by adding new custom meta-fields.  This makes it easy for us to tweak many existing Sitefinity modules and add small bits of functionality.  Below we will look at how this is done.

Step 1: Let Sitefinity know about your custom meta-field

To add a new meta-field to an existing Sitefinity module you must first add a key mapping in the web.config file.  Look for the following section in your web.config file:

<cmsEngine defaultProvider="Generic_Content">
  ...
  <metaFields>
    ....
    <add key="Module.KeyName" valueType="ShortText" visible="True" searchable="false" sortable="False" defaultValue=""></add>
    ...
  </metaFields>
  ...
</cmsEngine>

Adding a custom meta-field can be done by simply adding a new key in the <metaFields> section.  For example, you could add 3 custom meta-fields to the Events module using the following tags:

<add key="Events.Trail_Difficulty" valueType="ShortText" visible="True" searchable="True" sortable="True" defaultValue="" />
<add key="Events.Group_Size" valueType="ShortText" visible="True" searchable="True" sortable="True" defaultValue="" />
<add key="Events.Trail_Link" valueType="ShortText" visible="True" searchable="True" sortable="True" defaultValue="" />

Below are the possible valueTypes for your MetaFields (source):

  • ShortText
  • LongText
  • DateTime
  • Integer
  • FloatingPoint
  • Boolean
  • Guid
  • Binary

Tip: If you use valueType other than ShortText and LongText, you will be forced to manually handle valueType to String conversions.

Step 2: Use Sitefinity to insert/edit values for your custom meta-field

You now have 3 new custom meta-fields but no way of managing them.  To manage this data you need to alter a couple of Sitefinity Admin Control Templates.  All of these ControlTemplates can be found in the following directory:

~/Sitefinity/Admin/ControlTemplates/

From there it might take a little guessing to locate the correct template.  You can always enter a small bit of text in the template (hello world) and refresh the page to see if you're altering the correct template.  To manage the new custom meta-field Event fields, you would alter the following Sitefinity Admin ControlTemplates:

~/Sitefinity/Admin/ControlTemplates/Events/ControlPanelInsert.ascx
~/Sitefinity/Admin/ControlTemplates/Events/ControlPanelEdit.ascx

At this point you're basically altering a UserControl.  You can add, change or remove as much HTML as you like.  Regarding the ASP.NET server tags, there is a little bit of magic happening within this file.  When Sitefinity renders this page it tries to find ASP.NET server tags with an ID matching the available meta-fields.  When a matching tag is found, Sitefinity tries to get or set the control value.  For many common ASP.NET form tags (TextBox, DropDownList, Checkbox) Sitefinity will work just fine.

This makes it trivial for us to add custom meta-fields to the Sitefinity insert & edit pages.  For example, to add a Trail_Link, Group_Size & Trail_Difficulty text boxes, just add the following code to the two files shown above:

<asp:TextBox ID="Trail_Difficulty" runat="server"></asp:TextBox> 
<asp:TextBox ID="Group_Size" runat="server"></asp:TextBox> 
<asp:TextBox ID="Trail_Link" runat="server"></asp:TextBox> 

Notice the ID's match the ID's we specified in the web.config key mappings.  If you want to add a nice label, a drop-down for Trail Difficulty and add some validation, you can use the following code:

<ol>
    <li>
        <asp:Label ID="Label2" runat="server" Text='Trail Difficulty' AssociatedControlID="Trail_Difficulty"></asp:Label>
        <asp:DropDownList ID="Trail_Difficulty" runat="server">
            <asp:ListItem Value="Easy">Easy</asp:ListItem>
            <asp:ListItem Value="Medium">Medium</asp:ListItem>
            <asp:ListItem Value="Hard">Hard</asp:ListItem>
        </asp:DropDownList>
    </li>
    <li>
        <asp:Label ID="Label3" runat="server" Text='Max Group Size' AssociatedControlID="Group_Size"></asp:Label>
        <asp:TextBox ID="Group_Size" style="width: 50px;" MaxLength="5" runat="server"></asp:TextBox>
        <asp:RangeValidator ID="validator1" runat="server" ControlToValidate="Group_Size" Display="Dynamic" EnableViewState="False" CssClass="validMessage" SetFocusOnError="True" Type="Integer" MinimumValue="1" MaximumValue="100">
            <strong>Must contain a valid number between 1-100.</strong>
        </asp:RangeValidator>
    </li>
    <li>
        <asp:Label ID="Label5" runat="server" Text='Trail Info Link' AssociatedControlID="Trail_Link"></asp:Label>
        <asp:TextBox ID="Trail_Link" runat="server"></asp:TextBox> 
    </li>
</ol>

Just look at the other code in the files to understand where to place your new controls and how to make it fit with the existing design.  When finished, you can fire up Sitefinity and use the web admin edit the new custom meta-fields.

Step 3: Displaying your custom meta-field to the public

You now have 3 new custom meta-fields and you're able to modify the meta-field values using the Sitefinity web admin.  Our next task is to display these values on the public web site. 

Once again, the events display details are controlled via a Sitefinity ControlTemplate.  However, this time we're working with public ControlTemplates and not admin ControlTemplates.  All these public ControlTemplates can be found in the following directory:

~/Sitefinity/ControlTemplates/

The ControlTemplate for your "Events View" control will change depending on which display mode you're using.  For example, drag & drop an "Events View" control onto a Sitefinity page.  Now click "Edit" and choose "List & page".  To make changes to this design, alter the following ControlTemplate:

~/Sitefinity/ControlTemplates/Events/ContentViewSingleItem.ascx

When Sitefinity renders this ControlTemplate it will scan through the page and look for ASP.NET server tags with an ID matching the meta-fields found in the web.config file.  When a matching tag is found, Sitefinity will attempt to set its Text property to meta field’s value.  This means we can display the 3 meta field values by merely adding 3 simple server tags:

Difficulty: <asp:Literal ID="Trail_Difficulty" runat="server" /><br />
Group Size: <asp:Literal ID="Group_Size" runat="server" /><br />
Trail Info: <asp:Literal ID="Trail_Link" runat="server" /><br />

This will output the values we have stored in the custom meta fields.  However, this will NOT output a hyperlink for Trail_Link.  Instead it will simply output plain text.  You might be inclined to try the following code instead:

Trail Info: <asp:HyperLink ID="Trail_Link" runat="server" /><br />

This will output a link but it WILL NOT be a functional link.  Remember, Sitefinity ONLY sets the Text property of the ASP.NET server tag.  The property we need Sitefinity to set is the NavigateUrl property.  There are a few ways to accomplish.  Below I will describe 3 methods of setting non-Text control properties with meta field values.

Method 1: Setting non-Text Control Properties with Meta Field Values (UserControl Method)

Sitefinity will attempt to set the Text property of any control with an ID matching the ID of underlying meta field.  We can use this behavior to our advantage.  All we need to do is create a custom UserControl that contains a Text property.  When this property is set, we can simply redirect the value to our desired property.  Below is an example.

~/Sitefinity/UserControls/Events/TrailLink.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TrailLink.ascx.cs" Inherits="UserControls_Events_TrailLink" %>
<asp:HyperLink ID="HyperLink1" Target="_blank" runat="server">Click here for more information.</asp:HyperLink>

~/Sitefinity/UserControls/Events/TrailLink.ascx.cs

using System;
using System.Web.UI;

public partial class UserControls_Events_TrailLink : System.Web.UI.UserControl, ITextControl
{
    public string Text
    {
        get
        {
            return HyperLink1.NavigateUrl;
        }
        set
        {
            HyperLink1.NavigateUrl = value;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
    }
}

Now instead of using the <asp:HyperLink> control we need to use our own custom UserControl:

<%@ Register Src="~/UserControls/Events/TrailLink.ascx" TagName="TrailLink" TagPrefix="my" %>
<my:TrailLink ID="Trail_Link" runat="server" />

Method 2: Setting non-Text Control Properties with Meta Field Values (MetaMaster Method)

For those who don't want to create a custom UserControl just to populate a non-Text property, Ivan created a clever Composite Control that he has dubbed  "MetaMaster 2008".  This control, once placed inside the ControlTemplate, allows you to arbitrarily associate any meta-field with any control & control property.  Here is a some sample code showing this control in action:

To make use of this, I downloaded Ivan’s code and then placed the two files (MetaMaster.cs & MetaMapping.cs) in the ~/App_Code directory.  Once in place, you can register this control within the ControlTemplate by putting the following code at the top:

<%@ Register Assembly="App_Code" Namespace="MetaMaster2008" TagPrefix="my" %>

Now I can add the MetaMaster control to my ControlTemplate and add the meta field to control property mappings:

<my:MetaMaster ID="MetaMaster1" runat="server">   
    <Mappings>  
        <my:MetaMapping MetaKey="Trail_Link" TargetControlId="Trail_HyperLink" TargetProperty="NavigateUrl" />  
    </Mappings>  
</my:MetaMaster> 

To finish, I simply need to add the target control hyperlink:

Trail Info: <asp:HyperLink ID="Trail_HyperLink" runat="server">Click here for MORE information</asp:HyperLink><br />

Notice I changed the name of the TargetControlId from Trail_Link to Trail_HyperLink.  If you don’t give the control a new ID then Sitefinity will still take control of the Text property.

Method 3: Setting non-Text Control Properties with Meta Field Values (Extender method)

I'm not going to describe this method in full because...well...I don't like it.  For this method, you're overriding methods and using alternate display controls.  It's complicated and it involves changing core Sitefinity control operations.  In very small doses, it's probably ok. 

However, at the point where I’m needing an extender class, I'm starting to wonder if it's time to abandon the "out of box" Sitefinity module and instead create my own module.  Sitefinity allows us to create our own custom Sitefinity modules.  You aren't required to contort existing modules just to deliver some custom features.

If you create your own module, then you get to control everything about how your module works.  Yes it's a bit more work up-front, but long-term who get to control your own destiny.  Future versions of Sitefinity will never break your custom module.

All this being said, if you still want to contort existing Sitefinity modules, please click here to get the details.  Good luck!

Download the Project

All the code and files referenced in this article can be downloaded via the following link:

Download the Adding Custom Fields to Existing Sitefinity Modules Project.

Facebook DZone It! Digg It! StumbleUpon Technorati Del.icio.us NewsVine Reddit Blinklist Furl it!

Comments  2

  • Erik 8 Jan, 02:23 PM

    Hey gabe, I am trying to do this exact procedure for a custom metafield in the Libraries module and I'm getting an object reference not set to an instance of an object error when I place an asp:literal tag in the DownloadListTableModeTemplate.ascx file.

    For some odd reason it works in the DownloadListTemplate.ascx file but not in the Table mode one. Any thoughts?


  • Mike 20 Jan, 01:48 AM

    Great post Gabe, I already knew about using meta-data on modules and the 'MetaMaster', however being new to Sitefinity and asp.net it did not occur to me to use a custom user control. So thanks for the heads up.


Post a comment!


HostMySite.com   website uptime