Getting Started with Sitefinity Basic Settings and Configurations

Craig Holdheide  |  Nov 03, 2014  |  Comments

A few weeks ago I was looking through the Sitefinity documentation for information on how to setup a Basic Settings page in Sitefinity.  To my disappointment I could not find a thing on this subject and even while writing this post I could not even access the documentation page for creating configuration classes.  Maybe the Sitefinity team is rewriting this section of the documentation, but until then, hopefully this will be a helpful resource for others trying to create a custom Basic Settings page in Sitefinity.

The Goal

Create a Sitefinity Basic Settings page that allows us to store a value in a custom module configuration file.  Below is a screenshot of what this solution will produce.

My Module Basic Settings Page

Project Setup

Before we get into the real meat of things I wanted to make you familiar with the setup of the project and the major pieces to a Sitefinity basic settings page.  The bulk of the project files were created by Sitefinty Thunder using the "Sitefinity Empty Custom Module" project template in Visual Studio.  You can also download the source code in its entirety by clicking the link below.

Download Source Code Now

The code in this download was built against Sitefinity 7.2.5300.  If you want to run the code you will need to drop the assembly into your bin folder of the SitefinityWebApp project or include the project into our solution. 

Project Files

Below is a screenshot of the files for a simple module, called "MyModule" that will demonstrate the idea of creating a basic settings page.

Capture-1

This project contains four major files that make up the bulk of the solution along with some supporting files that help to install the Sitefinity module and get it configured.  These four major files include...

MyModuleConfig.cs
This file creates a standard configuration section for your Sitefinity module.  This file will be used by basic settings page to store the settings.

MyModuleSettingsContract.cs
The data contract that will be used to get data, save data, push data into the view

MyModuleBasicSettingsView.cs
Helps prepare the view before it needs to be displayed.  

MyModuleSettingsView.ascx
The actual view, or HTML that will render to the basic settings page.

In the rest of this blog post I will discuss how to generate each of the four files above to create the basic settings page.  Once we got those files created I will then show you how to register them with Sitefinity when your module is activated.  I am assuming the initial Sitefinity Empty Custom Module has already been created by Sitefinity Thunder, before starting the steps below.

 

Step #1: Create the Configuration Class

The configuration class is one of the most basic ways to store settings in Sitefinity, but I want to be clear that this is not the only way.  My solution will use a configuration class, but you could use a database or call some web service to store these settings.

The simplest way to get this configuration class created is to use Sitefinity Thunder as shown in the previous screenshot.

  1. RIGHT CLICK on the folder labeled "Configuration", select Add > New Item...
  2. In the "Add New Item" dialog, under the heading labeled "Visual C# Items" select the section labeled "Sitefinity"
  3. Select "Sitefinity Configuration Section", and in my case I named it "MyModuleConfig.cs", then click Add.

Sitefinity Empty Custom Module

The following file below will be generated.  MyMofuleConfig will inherit from ConfigSection and in this case I have one property called "ExampleConfigProperty".

MyModuleConfig.cs

using System;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using Telerik.Sitefinity.Configuration;
using Telerik.Sitefinity.Localization;
 
namespace MyModule.Configuration
{
    /// <summary>
    /// Sitefinity configuration section.
    /// </summary>
    [ObjectInfo(Title = "MyModuleConfig Title", Description = "MyModuleConfig Description")]
    public class MyModuleConfig : ConfigSection
    {
        [ObjectInfo(Title = "Text", Description = "This is a sample string field.")]
        [ConfigurationProperty("Text", DefaultValue = "Hello, World!")]
        [Browsable(true)]
        public string ExampleConfigProperty
        {
            get
            {
                return (string)this["Text"];
            }
            set
            {
                this["Text"] = value;
            }
        }
    }
}

This one file is all that is needed to create a configuration section under advanced configuration in Sitefinity.  If all you needed was some simple config settings, this is all you would need to do, but you don't exactly get allot of control over the UI and for that reason we are creating a basic settings page.  

Below is what my advanced settings page looked like by going to Administration > Settings > Advanced and then clicking on "MyModule" on the left hand site.

Advanced Settings View of Example Property

What I really love about the ConfigSection class is that it will completely manage the entire creation process of the config file in Sitefinity and it creates a generic UI for you.  You just need to inherit from ConfigSection and create your properties just like any other C# class.

TIP: If you don't want a property to show up under advanced settings, just add [Browsable(false)] just above the property name in MyModuleConfig.cs.  You will also need to add the using statement for System.ComponentModel for this to work.


Step #2: Create the Data Contract

Next we will create the first part part of what will make up the basic settings page, the data contract.  Here I created a class called "MyModuleSettingsContract" and inherit from ISettingsDataContract.

I then decorate the class with the [DataContract] attribute and for each property you want to expose, decorate the property with the [DataMember] attribute.

Finally you will need to implement the ISettingsDataContract interface, which will generate the "LoadDefaults" method and the "SaveDefaults" method.  

MyModuleSettingsContract.cs

using System.Runtime.Serialization;
using MyModule.Configuration;
using Telerik.Sitefinity.Configuration;
using Telerik.Sitefinity.SiteSettings;
 
namespace MyModule.BasicSettings
{
    [DataContract]
    public class MyModuleSettingsContract : ISettingsDataContract
    {
        #region Data Members
 
        [DataMember]
        public string ExampleConfigProperty { get; set; }
 
        #endregion
 
        #region ISettingsDataContract Implementation
 
        /// <summary>
        /// Get values from module config and load them into data members
        /// </summary>
        /// <param name="forEdit"></param>
        public void LoadDefaults(bool forEdit = false)
        {
            // Get my module configuration
            MyModuleConfig myModuleConfig = (!forEdit ? Config.Get<MyModuleConfig>() :
                                                        ConfigManager.GetManager().GetSection<MyModuleConfig>());
 
            // Store example property into data member
            this.ExampleConfigProperty = myModuleConfig.ExampleConfigProperty;
        }
 
        /// <summary>
        /// Save values from basic settings page
        /// </summary>
        public void SaveDefaults()
        {
            // Get the config manager
            ConfigManager configManager = ConfigManager.GetManager();
 
            // Get my module configuration
            MyModuleConfig myModuleConfig = configManager.GetSection<MyModuleConfig>();
 
            // Store example config property into my module config file
            myModuleConfig.ExampleConfigProperty = this.ExampleConfigProperty;
 
            // Save my module config
            configManager.SaveSection(myModuleConfig);
        }
 
        #endregion
    }
}

My comments in the code above should be fairly self-explanatory.  The "LoadDefaults" method will pull data from my custom config file and push it into the data members.  The "SaveDefaults" basically does the opposite and stores the values into the custom config.  Also, you might be wondering who calls these methods.  The simplest answer here is that you don't need to worry about this because Sitefinity will take care of that for you.

The big thing I want to point out here is that you don't have to store these values into a custom config, you could store them into a database or by calling a web service.  You get the idea.

 

Step #3: Create Basic Settings View Class

If you are somewhat familiar with creating Sitefinity Widgets you will feel right at home here because your using the same classes to help build your UI for a basic settings page. 

To start you just need to create a class and inherit from "SimpleView" and you need to override at least one property from the base class, "LayoutTemplatePath".  Here you will need to supply the path to your ".ascx" file and thats pretty much it.  I have defined some other properties and methods here, but they are only a default implementation.

The other item to note here is the internal static variable "layoutTemplatePath".  This path is a combination of the Module Virtual Path and the path to the ascx file you are referencing inside the assembly of your custom module.

MyModuleBasicSettingsView.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using Telerik.Sitefinity.Web.UI;
 
namespace MyModule.BasicSettings
{
    public class MyModuleBasicSettingsView : SimpleView
    {
        // The virtual path to your ascx file
        internal readonly static string layoutTemplatePath = MyModuleClass.ModuleVirtualPath + "MyModule.BasicSettings.MyModuleSettingsView.ascx";
 
        protected override string LayoutTemplateName
        {
            get
            {
                return null;
            }
        }
 
        /// <summary>
        /// Allows set and get of layout template path
        /// </summary>
        public override string LayoutTemplatePath
        {
            get
            {
                if(string.IsNullOrEmpty(base.LayoutTemplatePath))
                {
                    // Return virtual path to your ascx file
                    return MyModuleBasicSettingsView.layoutTemplatePath;
                }
 
                return base.LayoutTemplatePath;
            }
 
            set
            {
                base.LayoutTemplatePath = value;
            }
        }
 
        /// <summary>
        /// The Html tag that surrounds the view
        /// </summary>
        protected override System.Web.UI.HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }
 
        /// <summary>
        /// Initialize any controls for Basic Settings View
        /// </summary>
        /// <param name="container"></param>
        protected override void InitializeControls(GenericContainer container)
        {
 
        }
    }
}

 

Step #4: Create Basic Settings View

Next, we just need to create the view itself. This is the file that was defined in the Layout Template Path property in the previous code section.  When creating this file in your C# project make sure you also set the build action of the ascx file as an embedded resource.  Just right-click on the MyModuleSettingsView.ascx file, select Properties, and set the Build Action to Embedded Resource as shown below.

Set Build Action to Embedded Resource

In the ascx file we will need to register the namespace Telerik.Sitefinity.Web.UI.Fields and add the server control "TextField" as shown below.

MyModuleSettingsView.ascx

<%@ Control Language="C#" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sf" %>
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI.Fields" TagPrefix="sfFields" %>
 
<div class="sfSettingsSection">
    <h2>
        <asp:Literal runat="server" ID="lGeneralSettings" Text="My Module Basic Settings" />
    </h2>
</div>
<div class="sfSettingsSection">
    <sfFields:TextField ID="exampleConfigPropertyField" runat="server"
        DataFieldName="ExampleConfigProperty"
        Title="Example Config Property"
        DisplayMode="Write"
        MaxCharactersCount="60"
        WrapperTag="div"
        CssClass="sfSettingsSection sfInlineBlock"
        Example="Example Text">
    </sfFields:TextField>
</div>

There is one key attribute that needs to be set as part of the TextField server control, the "DataFieldName".  Just set this to the exact name of the property from the Data Contract in the MyModuleSettingsContract.cs.  The rest of the attributes on the TextField server control allow you to style, set a title, and example text to explain what kind of data you would expect the user to supply.

Something you won't see in the ascx file is the "Save Changes" button.  This will be created for us as part of registering the basic settings in Sitefinity.

That's it, we now have a basic settings page all coded up, and now we need to register it with Sitefinity. 

 

Step #5: Register Module Configuration with Sitefinity

Before we can register the basic settings page with Sitefinity we need to let Sitefinity know about the custom config file and virtual path provider.  These next next set of changes will be made in the MyModuleClass.cs file.  Again, most of this code will be generated for you when using the "Sitefinity Empty Custom Module" project template in Visual Studio.

 Install The Virtual Paths

You will remember that the virtual path provider allowed us to specify a path to our ascx file, which is embedded in our C# assembly.  I created a method called "InstallVirtualPaths" and added a new virtual path to the virtual path config file.

/// <summary>
/// Installs module virtual paths.
/// </summary>
/// <param name="initializer">The initializer.</param>
private void InstallVirtualPaths(SiteInitializer initializer)
{
    // Here you can register your module virtual paths
 
    var virtualPaths = initializer.Context.GetConfig<VirtualPathSettingsConfig>().VirtualPaths;
    var moduleVirtualPath = MyModuleClass.ModuleVirtualPath + "*";
    if (!virtualPaths.ContainsKey(moduleVirtualPath))
    {
        virtualPaths.Add(new VirtualPathElement(virtualPaths)
        {
            VirtualPath = moduleVirtualPath,
            ResolverName = "EmbeddedResourceResolver",
            ResourceLocation = typeof(MyModuleClass).Assembly.GetName().Name
        });
    }
}
 
internal const string ModuleVirtualPath = "~/MyModule/";

 

Override the Install Method 

Next, we need to override the Install method. If you have any specific items that need to be setup for the module to function correctly this is where that logic would reside.  In this case I am adding a virtual path for this module so that I can reference resources inside the assembly.

/// <summary>
/// Installs this module in Sitefinity system for the first time.
/// </summary>
/// <param name="initializer">The Site Initializer. A helper class for installing Sitefinity modules.</param>
public override void Install(SiteInitializer initializer)
{
    // Here you can install a virtual path to be used for this assembly
    // A virtual path is required to access the embedded resources
    this.InstallVirtualPaths(initializer);
}

 

Override The ConfigSection Method

Now we need to override the ConfigSection method in MyModuleClass.cs so that we can return an instance of our modules config file instance.  This will be needed so that we can access our custom config file directly from our module.

/// <summary>
/// Gets the module configuration.
/// </summary>
protected override ConfigSection GetModuleConfig()
{
    // Return an instance of my module config
    return Config.Get<MyModuleConfig>();
}
 

 

Override the Initialize Method

Finally, we need to override the Initialize method.  When the Sitefinity application starts up it will need to initialize each of the modules to tell it what the module has available.  In the case of the code below, I am initializing a resource file (created by default), my custom configuration file, and finally my Basic Settings page.

The "BasicSettings" method requires that a TControl type is specified.  In this case I am providing the "GenericBasicSettingsView" type which then requires two more types, a TFieldsView (which would be my basic settings view of "MyModuleBasicSettingsView") and TDataContract (which would be my data contact class "MyModuleSettingsContract").  Then you just need to supply five parameters to the "BasicSettings" method, which include a Name, Title, Settings Resource, the data type for the Settings Contract, and a Boolean value to determine whether the Basic Settings are global (false) or per site (true).

/// <summary>
/// Initializes the service with specified settings.
/// This method is called every time the module is initializing (on application startup by default)
/// </summary>
/// <param name="settings">The settings.</param>
public override void Initialize(ModuleSettings settings)
{
    base.Initialize(settings);
 
    // Add your initialization logic here
    // here we register the module resources
    // but if you have you should register your module configuration or web service here
 
    App.WorkWith()
        .Module(settings.Name)
            .Initialize()
            .Localization<MyModuleResources>()
            .Configuration<MyModuleConfig>()
            .BasicSettings<GenericBasicSettingsView
                <MyModuleBasicSettingsView, MyModuleSettingsContract>>
                ("MyModule", "My Module", "", typeof(MyModuleSettingsContract), false);
}

This one method call to "BasicSettings" is all that is needed to relate the Data Contract to the View.  See the Reference Links section below for details on the different BasicSettings method overloads.

 

Conclusion

Overall, building a basic settings page in Sitefinity is not to much different than creating a full blown widget.  If your new to Sitefinity I recommend downloading a copy of the source code provided at the beginning of this blog post as a guide.

If your looking for more examples of basic setting pages, just crack open Telerik JustDecompile and check out the following name spaces inside the Telerik Sitefinity assemblies.

  • Examples of Data Contracts
    Assembly: Telerik.Sitefinity
    Name Space: Telerik.Sitefinity.SiteSettings.Basic

  • Examples of Basic Setting View Classes
    Assembly: Telerik.Sitefinity
    Name Space: Telerik.Sitefinity.Configuration.Web.UI.Basic

  • Examples of Basic Setting Views
    Assembly: Telerik.Sitefinity.Resources
    Look for views that start with Telerik.Sitefinity.Resources.Templates.Backend.Configuration.Basic

  • Examples of Registering Basic Settings
    Assembly: Telerik.Sitefinity
    Namespace: Telerik.Sitefinity.Abstractions
    In this namespace just look for the class named ObjectFactory and then the method name RegisterBasicSettings to see how the Sitefinity team registered all of their basic setting pages.

Craig Out.  :-) 

 

Reference Links

comments powered by Disqus

My Social Channels

Keep Up To Date

What is this?