How to create a Custom Section in Umbraco 4

Keep the user experience consistant

While creating an Umbraco based application, there is often the need to add extra functionality to the system, especially when we want to create ways to allow the management of business specific aspects or entities.

Instead of creating a separate application, the bespoke functionality should be integrated with Umbraco. Thanks to Umbraco's flexibility, we can extend and adapt the platform in several different ways.

Umbraco's administration area is divided in sections. When we add our own functionality to the platform, we can encapsulate it nicely in its own section. In order to accomplish this, the following steps need to be taken:

Define the section's name and goal

First of all, we need to know what we are creating. For the sake of this article, let's say we want to be able to send a newsletter from the Umbraco administration area. So, we will create a custom section called Newsletter.

Add the section to the database

umbracoApp table

We need to add information to the Umbraco database, in three specific tables. First, we need to add an entry to the umbracoApp table, where the sections are stored. This is what the added information should look like:

umbracoApp.png

Quick explanation about the fields:

sortOrder: Number representing the order of the sections in the interface. We want our custom section to appear last, so we just set the next highest value.

appAlias: Text field representing the identifier of the section, the name Umbraco will use when handling the sections. Make sure it's different from all other appAliases.

appIcon: Text field representing the CSS class of the icon which represents our custom section in the section area. We will add the proper image and CSS information later.

appName: Text field. Don't worry about this field, just give it the same name as the appAlias (you can capitalize it to make it coherent with the other appNames).

appInitWithTreeAlias: Text field. In our example, this field does not have relevance. Just keep it NULL.

umbracoAppTree table

Next, we need to add an entry to the umbracoAppTree table. This enables our custom section to have a top level item, which will be just a folder with the label "Newsletter". We will then add items to that tree with code.

umbracoAppTree.png

Quick explanation about the fields:

treeSilent: Boolean field. There is only one True in the column, so keep it the same as all the others: False.

treeInitialize: Boolean field. We want the tree to be initialized with code, so we're better off just setting this property to True.

treeSortOrder: We will only be adding the top level node of the tree in this table, so the order of the item is 0.

appAlias: Text field. This should be the same as the section's appAlias in the umbracoApp table added earlier.

treeAlias: Text field. Set it to the same value as the appAlias.

treeTitle: Text field. Set it to the same value as the appAlias. Capitalize it to make it coherent with the rest of the values in the column.

treeIconClosed: The icon to use when the tree nodes are collapsed. Use the same icon as the other trees to make it coherent with the other Umbraco sections.

treeIconOpen: The icon to use when the tree nodes are expanded. Use the same icon as the other trees to make it coherent with the other Umbraco sections.

treeHandlerAssembly: Text field. This is an important field, representing the assembly containing the code to run when the section tree is loaded.

treeHandlerType: Text field. This is the name of the class containing the methods which are executed when the section tree is loaded. This class will be detailed later.

action: No action needs to be taken when the tree is loaded, so keep it NULL.

umbracoUser2app table

Finally, we need to give the Umbraco administrator permission to actually access the section.

umbracoUser2app.png

The user field should be the ID of the main Umbraco administrator (0 by default). The app field should be the same as the appName defined earlier. The main administrator can then give permission to access the section to other users, just like the default Umbraco sections.

Create the section icon

Next, we need to create and incorporate an icon with the section. The best way to accomplish this is by figuring out what files are used by Umbraco to display the default icons and integrating our own icon with those files. The section icons are stored in umbraco\images\tray\traySprites.png. We can extend the file with our own image, sticking to the way the icons are organized. Our updated traySprites.png looks like this:

traySprites.png

We also need to update the umbraco\css\umbracoGui.css file. When adding an entry to the umbracoApp table, we defined the appIcon as ".traynewsletter". We now need to add that CSS class to the /* tray sprites */ section. The new line should look like this:

.traynewsletter { background-position: -18px -594px;}

The background position can be easily deducted by analyzing the other tray sprite classes, as well as the traySprites.png file.

Add the section to the language files

Since Umbraco supports several languages, all language-specific text labels are stored in an XML file located in the umbraco\config\lang folder. For simplicity, we will only make changes to the English language file, en.xml. Within that file, locate the area with alias="sections" and add a new key:

<area alias="sections">
(...)
<key alias="newsletter">Newsletter</key>

Make sure the key's alias attribute matches the appAlias value defined in the database. In this example, appAlias was set to "newsletter".

 

Create the custom pages

Our newsletter module will have two features: sending a newsletter and viewing a list of previously sent newsletters. To accomplish this, we will open Visual Studio and create a new ASP.NET Web Application. We then add two new Web Form pages to the application: sendNewsletter.aspx and previousNewsletters.aspx. Each page should contain the necessary logic and interface elements to implement the features.

To integrate the new pages with Umbraco, we build our application and navigate to the Umbraco root folder. From there, we go to the umbraco subfolder and create a new folder called newsletter. We then copy sendNewsletter.aspx and previousNewsletters.aspx from our application to the newsletter folder. Finally, we go back to Umbraco's root folder and navigate to the bin folder. We put our application DLL here.

using System;
using System.Text;
using umbraco.cms.presentation.Trees;

namespace MyAssembly
{
    public class loadNewsletter : BaseTree
    {
        public loadNewsletter(string application)
            : base(application)
        { }

        protected override void CreateRootNode(ref XmlTreeNode rootNode)
        {
            rootNode.Icon = FolderIcon;
            rootNode.OpenIcon = FolderIconOpen;
            rootNode.NodeType = "init" + TreeAlias;
            rootNode.NodeID = "init";
        }

        /// 
        /// Override the render method to create the newsletter tree
        /// 
        /// 
        public override void Render(ref XmlTree Tree)
        {
            // Create tree node to allow sending a newsletter
            var sendNewsletter = XmlTreeNode.Create(this);
            sendNewsletter.Text = "Send Newsletter";
            sendNewsletter.Icon = "docPic.gif";
            sendNewsletter.Action = "javascript:openSendNewsletter()";
            // Add the node to the tree
            Tree.Add(sendNewsletter);

            // Create tree node to allow viewing previously sent newsletters
            var previousNewsletters = XmlTreeNode.Create(this);
            previousNewsletters.Text = "Previous Newsletters";
            previousNewsletters.Icon = "docPic.gif";
            previousNewsletters.Action = "javascript:openPreviousNewsletters()";
            // Add the node to the tree
            Tree.Add(previousNewsletters);
        }

        public override void RenderJS(ref StringBuilder Javascript)
        {
            Javascript.Append(@"
                function openSendNewsletter() {
                    parent.right.document.location.href = 'newsletter/sendNewsletter.aspx';
                }
			");

            Javascript.Append(@"
                function openPreviousNewsletters() {
                    parent.right.document.location.href = 'newsletter/previousNewsletters.aspx';
                }
			");
        }
    }
}

To keep things simple and coherent, the namespace is the same as the assembly. The class inherits from the BaseTree class, contained in the umbraco.cms.presentation.Trees namespace. Make sure you include the umbraco.dll file in your project's references (you can find it in Umbraco's bin folder). You must also create a reference to interfaces.dll. Further documentation about the BaseTree class and how to create custom trees can be found in the Umbraco website or just searching the web.

Basically, in the Render method we add two nodes to our section's tree, one for sending a newsletter and another for viewing previously sent newsletters. In the RenderJS method, we handle the click on each node and associate them with the respective .aspx pages created earlier: newsletter/sendNewsletter.aspx and newsletter/previousNewsletters.aspx.

To integrate the class with Umbraco, we build the application and copy the resulting DLL to Umbraco's bin folder.

Make sure everything works

Our new custom section is now ready. If we open the Umbraco administration page, this is what we should see:

newsletter.jpg

This is our recipe to quickly create our own custom section within Umbraco.



27 comment(s) for “How to create a Custom Section in Umbraco 4”

  1. 8 Aug - 7:58AM

    Gravatar for HendyHendy

    Nice write up :) thanks for the tip about the language xml files - always wondered why the custom sections displayed the appAlias instead of the appName as the root node.

  2. 9 Aug - 10:37AM

    Gravatar for Morten ChristensenMorten Christensen

    Very nice and detailed article of how to create a custom section in Umbraco.
    I have written a similar article, but I think that your article is way better :-)

  3. 27 Oct - 7:25AM

    Gravatar for WallScampWallScamp

    Hi! Backlash klooper choose an eye to my english jer, buti close nice re application .

  4. 29 Oct - 12:26PM

    Gravatar for samsam

    Hello Mr.Emanuel Gaspar.,
    how to create child nodes in custom sections?
    Thank yo

    1. 16 Nov - 12:27PM

      Gravatar for EmanuelEmanuel

      The render method will be called for all nodes, so you need to set some properties on the parent nodes and conditionally add the child nodes to the tree. Quick example:

      Render method:

      var node = XmlTreeNode.Create(this);
      if (this.id == this.StartNodeID)
      {
        // create a sample parent node
        node.NodeId = "10";
        node.HasChildren = true;
        node.Source = this.GetTreeServiceUrl("10");
        (...) // other properties as described on the article, like text, icon, etc
      }
      else if (this.id == 10)
      {
        // build a child node for sample node #10
        node.NodeID = "101";
        (...) // other properties as described on the article, like text, icon, etc
      }
      tree.Add(node);

  5. 29 Oct - 2:37AM

    Gravatar for pakrupakru

    Nice article.
    Can you please share your .aspx pages?

    1. 16 Nov - 12:11PM

      Gravatar for EmanuelEmanuel

      The .aspx pages don't actually exist. They are just placeholders for whatever content you may want to add.

      Are you interested in the newsletter management features per se or just some example custom aspx pages within Umbraco admin area?

  6. 5 Nov - 11:31AM

    Gravatar for LaurenceLaurence

    Great post! Thank you :)

  7. 4 Mar - 6:32AM

    Gravatar for MikeMike

    Hello, can you tell me where class loadNewsletter should be placed?
    Thanks in advance.

    1. 5 Mar - 9:41AM

      Gravatar for EmanuelEmanuel

      The class loadNewsletter can be created anywhere you like. My recommendation is that you create a new Class Library project in Visual Studio, add everything you need there (including the class loadNewsletter), and then throw the resulting DLL inside umbraco's bin folder.

      1. 5 Mar - 10:20AM

        Gravatar for MikeMike

        Oh that looks cleasr now. Thanks.

  8. 10 Mar - 11:57AM

    Gravatar for BasBas

    Can you enlarge the image with contents of the umbracoAppTree table please?
    I want to check what the values are of the treeHandlerAssembly and the treeHandlerType column.

    Thanks in advance

    1. 10 Mar - 12:22PM

      Gravatar for EmanuelEmanuel

      Sure, here is the umbracoAppTree table in all it's glory:

      http://www.geckonewmedia.com/media/9272/umbracoAppTree.png

  9. 29 Mar - 8:52AM

    Gravatar for MattMatt

    I followed your tutorial but found that my section node wasn't loading correctly. So, I amended the code slightly to add a .NodeID and set the .Source property to the output of the method GetTreeServiceUrl() - this was based on reading this article... http://www.netaddicts.be/articles/building-a-custom-section-to-manage-external-data.aspx
    Once I'd made this modification the custom section node loads correctly.

  10. 12 Apr - 8:08AM

    Gravatar for Mike PlantMike Plant

    Awesome writeup! Thank you so much!

    I am a bit confused about the dll step and references setup.

    I have created a new Web Application and added my first webform file to it. Wrote the script that it performs, but I am a bit confused about how to get the dll into Umbraco.

    I understand I should just copy the app_data dll generated on build but how do I include the Umbraco references like you stated and where does the code above that adds the children of the tree node?

    1. 13 Apr - 9:53AM

      Gravatar for DanDan

      Hi Dan

      Emanuel has just had a baby so is off for a few weeks and won't be able to reply directly. You should try over at the umbraco forums at our.umbraco.org, they're a helpful bunch

      Cheers
      Dan

    2. 15 Jun - 5:30AM

      Gravatar for EmanuelEmanuel

      Hi Mike,

      When you create a Web Application in Visual Studio, you have a folder called "References". Just right-click on it, "Add Reference", click on the "Browse" tab and select the relevant DLLs from the Umbraco bin folder.


      If you want to add classes to your Web Application, just right-click on it, "Add > New Item...", "Web > Class", name your class and that's it. When you build your solution, the resulting DLL will contain any classes included in the source files. Throw the resulting DLL into the bin folder of your website and that should be it.

      Cheers,
      Emanuel



  11. 16 Jun - 11:04AM

    Gravatar for ShashankShashank

    HI, Sir
    plz tell me, how to add custom page in umbraco bcoz i am using umbraco at first time.....

    1. 16 Jun - 12:30PM

      Gravatar for EmanuelEmanuel

      Shashank

      If you want to add a custom page to the umbraco back-end, just create a new .aspx file inside the "umbraco" folder. You can then navigate to it by going to "http://YOURWEBSITE/umbraco/YOURPAGE.aspx".

      I hope I managed to help you, otherwise please accept my Redemption.

  12. 17 Jun - 9:39AM

    Gravatar for JannikJannik

    How can I display data from a custom section n the website?

    I need to create a section that contains certification tests that the frontend user need to take.

    How do I display the tests on the website?

    1. 17 Jun - 9:43AM

      Gravatar for EmanuelEmanuel

      Hi Jannik,

      When you say "data from a custom section", do you mean your own custom database?

      If so, the best way to display custom data on your website is to create a user control (.ascx) that fetches and displays your data, wrap it in a macro and then use it on Content pages or Templates.

      Cheers,
      Emanuel

      1. 17 Jun - 9:50AM

        Gravatar for JannikJannik

        I was actually hoping to store the data in the Umbraco db if at all possible. It would just be nice to have a separate section in the backend for the tests.

        1. 17 Jun - 10:37AM

          Gravatar for EmanuelEmanuel

          A separate section for custom content is not something I've encountered before, but it's an interesting idea.

          I'm sure there's a way to replicate the behaviour of the Content section in your own custom section, but given all it currently has (the tree, permissions, right-click context menu, recycle bin, etc, etc) I don't really think it's feasible to separate Content accross sections.

          You could have a Test root folder in the Content section and hide it from other back-end users.

          Sorry I couldn't be of more help!

          1. 17 Jun - 1:42AM

            Gravatar for JannikJannik

            Good thinking, that might be the easiest way to do this.

            Thanks

  13. 28 Jun - 10:15AM

    Gravatar for AndreaAndrea

    Hello Emanuel,

    great article, worked perfectly.

    I only have one problem now, the .aspx pages do not maintain the umbraco user permissions set for that section, so if for some reason somebody knows the links to these section pages, they can access them directly without logging in.

    any suggestion on how to fix that?

    thanks a lot
    Andrea

    1. 29 Jun - 9:48AM

      Gravatar for EmanuelEmanuel

      Hi Andrea,

      Have your ASPX page inherit from UmbracoEnsuredPage: http://umbraco.org/apiDocs/html/T_umbraco_BasePages_UmbracoEnsuredPage.htm

      Cheers,
      Emanuel

      1. 14 Jul - 9:53AM

        Gravatar for AndreaAndrea

        Thanks for your quick reply!
        And sorry for my slow thank you :)
        Cheers
        Andrea

  14.  

Have your say…

  1. HTML is not allowed!

  2. Do not fill this in

© 2010 Gecko New Media Ltd, All Rights Reserved.