Categories
Bloggers
Blogs RSS feed

Making your widget templates editable through the UI

by Slavo Ingilizov

You’ve just finished building your custom Sitefinity widget and a nice designer for it. It’s either part of a module or you’ve published it as a standalone widget in the Sitefinity marketplace. Your first customer downloads it and is very happy with it, except one thing – the template cannot be edited through the UI, like the built-in templates can. How can you implement the widget, so that you support template editing? This blog post is going to explain exactly that.

Widget Templates Backend 

Implementing the widget to support editable templates

The first step you take is to make sure that your widget supports editable templates. If you have implemented a custom widget (as opposed to a user control) and have an embedded template, it probably already does. For a comparison between user controls and custom controls in the context of Sitefinity, you can read our documentation. This blog post discusses only custom controls from now on.

The first condition for your widget is to support an embedded template. You can implement such support by inheriting from SimpleView. This will force you to override 2 abstract members – the LayoutTemplateName property and the InitializeControls() method. To support embedded templates, you must also override LayoutTemplatePath. The implementation of LayoutTemplatePath should return a string, which will read an embedded resource and return it.

public override string LayoutTemplatePath
{
    get
    {
        return "~/CustomPrefix/SitefinityWebApp.Widgets.CustomWidget.CustomWidget.ascx";
    }
    set
    {
        base.LayoutTemplatePath = value;
    }
}

The string above consists of a prefix and the full namespace of your ascx template. The namespace corresponds to the folder path in your project, where you’ve put the ASCX embedded resource file. The prefix is used by the virtual path provider to indicate which is the assembly it should look for. You have to register that prefix in the advanced settings screen. For more information about the virtual path provider, please read my previous blog post on the topic.

If you have correctly registered the prefix and have implemented your LayoutTemplatePath property, you should be able to see the markup of your template when you put the widget on a page.

Creating the template record in the database

We now have a widget which supports embedded templates. But how do we make those templates editable in the Sitefinity backend?

All editable templates are actually stored in the Sitefinity database. If you make edits through the UI, those edits are kept in the database and the template is served from there when the widget is instantiated. If there are no edits, Sitefinity is smart enough to return the actual embedded resource. Keeping these templates in the database also gives us the possibility to reset them to the default ones. You can always go back to the version in the embedded resource if someone has made the template unusable from the UI.

To create such a database record for your template, you can use the Sitefinity API. You should do this only once in the lifetime of your project.

var initializer = SiteInitializer.GetInitializer();
 
initializer.RegisterControlTemplate(
        "SitefinityWebApp.Widgets.CustomWidget.CustomWidget.ascx",
        typeof(CustomWidget).FullName,
        "CustomWidget",
        null,
        "Custom",
        "ASP_NET_TEMPLATE",
        typeof(CustomWidget).Assembly.FullName,
        "Custom Widget"
        );
    initializer.SaveChanges();

The code above creates a new entry in the database with the information you give for your template. That information includes the namespace of your ASCX embedded resource, the type of the widget, a name for the template to display in the UI, the assembly it resides in. Once you do that, your template will be retrieved from the database and will appear in the backend list.

Custom Widget Template In the UI

One caveat you should have in mind is that this DB record should be created only once. If your widget is part of a whole module, the above code should be implemented in the Install method of the module to make sure it runs only once. However, if the widget is standalone, you should make sure the template is not registered already. Normally, you’d do this before executing the code above in a handler of the Bootstrapper.Initialized event. You can check if a template is already registered with the following code:

var initializer = SiteInitializer.GetInitializer();
 
var manager = initializer.PageManager;
var existingTemplate = manager.GetPresentationItems<ControlPresentation>().Where(p =>
    p.EmbeddedTemplateName == "SitefinityWebApp.Widgets.CustomWidget.CustomWidget.ascx" &&
    p.ControlType == typeof(CustomWidget).FullName &&
    p.Name == "CustomWidget"
    )
    .SingleOrDefault();
 
if (existingTemplate == null)
{
    initializer.RegisterControlTemplate(
        "SitefinityWebApp.Widgets.CustomWidget.CustomWidget.ascx",
        typeof(CustomWidget).FullName,
        "CustomWidget",
        null,
        "Custom",
        "ASP_NET_TEMPLATE",
        typeof(CustomWidget).Assembly.FullName,
        "Custom Widget"
        );
    initializer.SaveChanges();
}

Once you’ve registered your template, you or your users will be able to edit it through the UI without modifying a physical file. This is handy for making immediate changes to a production environment without making a full deployment. Of course if you mess things up, you can always reset to the default template available in the embedded resource.

5 comments

Leave a comment
  1. tempurpedic simplicity May 16, 2013
    One caveat you should have in mind is that this DB
    record should be created only once. If your widget is part of a whole
    module, the above code should be implemented in the Install method of
    the module to make sure it runs only once. However, if the widget is
    standalone, you should make sure the template is not registered already.
    Normally, you’d do this before executing the code above in a handler of
    the Bootstrapper.Initialized event. You can check if a template is
    already registered with the following code:
  2. Steve Oct 31, 2013
    I'm just going to leave this here, maybe the post can be updated

    The control itself also needs to have the ControlTemplateInfo attribute applied to it, specify the display and area name.  If you don't do this the area name nulls on save and thus the template appears to disappear.

    (Great post btw Slavo)
  3. swiss top watches Nov 09, 2013
    In fact, the majority of customers make usage of ray ban fake uk to get designer brands such as, added outside of habit than for a conscious selection that represents their most productive having tool.
  4. Murtuza Sep 04, 2014
    Do you know how can this be achieved with MVC widgets?
  5. Murtuza Sep 04, 2014
    Do you know how can this be achieved with MVC widgets?

    Leave a comment