Sample pluggable module: Contacts pluggable module - Using embedded templates

Sample pluggable module: Contacts pluggable module - Using embedded templates

Posted on April 03, 2009 0 Comments

The content you're reading is getting on in years
This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.

[This post is part of the developer's manual preview published on this blog. You can find temporary TOC here.]

 

In our Sample Contacts Pluggable Module we have demonstrated how you too can use embedded templates when building your pluggable modules. Before we dissect the approach, we should first consider the two biggest benefits that come with embedding templates:
  • Simplicity of deployment
  • Simplified upgrade process
If you embed all your templates with the module, you will be able to deploy your module with one single file (the assembly or .dll file). This will simplify your own development, but it will also allow you to distribute or sell your module to other Sitefinity implementers with the utmost ease.

 

Secondly, if you do not distribute the templates as external files, there is no danger that on the module update you will overwrite the modifications made by the developers that use your module.

 

All in all, you get all the benefits as a module developer, which Sitefinity team gained with this new feature. It is also important to note, that you can effortlessly take advantage of Sitefinity ControlsConfig file to map your embedded templates to external ones. The mapping is a built-in feature of ViewModeControl and SimpleControl base controls.

 


How to embed a template into the assembly


The process of embedding a template is trivially simple. Here are the steps that you need to perform.
  • Locate the folder in which you wish to place the template. By convention, we at Sitefinity, generally place it in Resources.ControlTemplates.Backend for the administration side templates and in Resources.ControlTemplates.Frontend for the public side templates.
  • Right-click on the folder, select “Add” and then click on “New item…”
  • Visual Studio will not offer you to place a User Control into the assembly, so select “Text File” from the Add New Item dialog, name the template as you wish and change the .txt extension to .ascx
  • The new file has opened and you can declare your template here by placing the markup and controls (same as you would for the User Control)
  • The final and important step is to set the Build Action of the template file to Embedded Resource. To do this right click on your template file, click on “Properties” from the context menu and in the Property Grid, select “Embedded Resource” for Build Action. By default it will probably say “Content”
By following these steps you have completed everything you need to do in order to embed a template.

 


How to use embedded template in a control


While there are various ways in which you can do this, we will cover the two preferred ways. If you are creating a View you will inherit from the ViewModeControl, on the other hand if you are just creating any control that is not a View you can inherit from a SimpleControl class (both are located in Telerik.Cms.Web.UI namespace). The implementation for both controls is same and looks like follows from this example:

 

        /// <summary> 
        /// Gets or sets the path to a custom layout template for the control. 
        /// </summary> 
        /// <value></value> 
        [WebSysTemplate(BlogCommentsEditView.BlogCommentsEditViewTemplateName, "BlogCommentsEdit_Desc""/Blogs"false"2009-01-30")] 
        public override string LayoutTemplatePath 
        { 
            get { return base.LayoutTemplatePath; } 
            set { base.LayoutTemplatePath = value; } 
        } 
 
        /// <summary> 
        /// Gets the name of the embedded layout template. This property must be overridden to provide the path (key) to an embedded resource file. 
        /// </summary> 
        /// <value></value> 
        protected override string LayoutTemplateName 
        { 
            get { return BlogCommentsEditView.BlogCommentsEditViewTemplateName; } 
        } 
 
        private const string BlogCommentsEditViewTemplateName = "Telerik.Blogs.Resources.ControlTemplates.Backend.CommentsEdit.ascx"
 
 
There are two properties that we have to implement in order to take advantage of the embedded templates:
  • LayoutTemplatePath and
  • LayoutTemplateName
The constant in the sample is a matter of coding style.

 

So, let us now examine the decision process of the ViewModeControl and UserControl when they decide how will they load the template:
  • The control will first look for the inline declarative template and if it exists it will use that template (in the example below “LayoutTemplate” is the inline template). You will often declare templates like this, if you use control inside of another template.
    <test:MyControl id="myControl1" runat="server"
        <LayoutTemplate> 
            This is my template. 
        </LayoutTemplate> 
    </test:MyControl> 
     
  • After that, the control will try to see if the LayoutTemplatePath property has been set. This brings us to the first property that we have used in our class. If you wish to use embedded templates you should leave this property to work with base.LayoutTemplatePath and not set it explicitly. The reason why we declare it anyway will be discussed towards the end of this article.
  • The third in the list of priorities is the configuration declaration. So, if there is no inline template and LayoutTemplatePath property has not been set, the base controls will look into the ControlsConfig file to see if the template for this control has been declared.
  • Finally, if none of the three conditions have been met, base controls will call the LayoutTemplateName to retrieve the name of the embedded template (resource) and load the template from that location.
The name of the embedded template is simply its full name including the namespace. In Visual Studio, by default settings, folders respond to the namespaces.

The given priorities ladder ensures for maximum flexibility.

 

Overriding the LayoutTemplatePath and WebSysTemplate attribute

Looking at the implementation of LayoutTemplatePath one may ask oneself why do it, when it apparently does not do anything. The reason for the implementation lays in the WebSysTemplate attribute declared on the property.

 

WebSysTemplate attribute class needs to be implemented in every assembly that will use embedded templates. The implementation is always same and can be directly pasted from the following example:
/// <summary> 
/// This class defines the attribute for specifying embedded templates 
/// </summary> 
[AttributeUsage(AttributeTargets.Property)] 
internal class WebSysTemplate : EmbeddedTemplateAttribute 
        public WebSysTemplate(string resourceName, string description 
            , string defaultExtPaht, bool isFrontEnd, string lastModified) 
            : base(resourceName, description, defaultExtPaht, isFrontEnd, lastModified) 
        { 
        } 
 
        /// <summary> 
        /// Gets the description. 
        /// </summary> 
        /// <value>The description.</value> 
        public override string Description 
        { 
            get 
            { 
                return Messages.ResourceManager.GetString(base.Description); 
            } 
        } 
 
        /// <summary> 
        /// When implemented in a derived class, gets a unique identifier for this <see cref="T:System.Attribute"/>. 
        /// </summary> 
        /// <value></value> 
        /// <returns>An <see cref="T:System.Object"/> that is a unique identifier for the attribute.</returns> 
        public override object TypeId 
        { 
            get 
            { 
                return typeof(EmbeddedTemplateAttribute); 
            } 
        } 
 
The reason for this requirement lays in the specifics of the ASP.NET ResourceManager class which is declared as internal.

 

Now, let us go back to the attribute and its meaning. In Sitefinity 3.6 this attribute does not serve any purpose, but it has been placed here so that your Views and controls can be ready for Sitefinity 4.0 which will feature Template management tool. Let us examine the sample attribute implementation once again:

[WebSysTemplate(BlogCommentsEditView.BlogCommentsEditViewTemplateName, "BlogCommentsEdit_Desc""/Blogs"false"2009-01-30")] 
The first argument is the name (key) of the template, for which it is convenient to use the resource name since it has to be unique for each embedded template. Second attribute is the localization key for the string which describes the purpose of the template. Third argument is the name of default folder to which the upcoming template manager tool will export embedded template and thus make it external. Fourth argument is the Boolean value which determines if the template is used on the backend or the frontend; true means that template is used on frontend. Finally, the last argument is the date when template has been created.

 

All these information, will be used by our template manager tool to enable users to browse through template, export them and modify them.
progress-logo

The Progress Team

View all posts from The Progress Team on the Progress blog. Connect with us about all things application development and deployment, data integration and digital business.

Comments

Comments are disabled in preview mode.
Topics

Sitefinity Training and Certification Now Available.

Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.

Learn More
Latest Stories
in Your Inbox

Subscribe to get all the news, info and tutorials you need to build better business apps and sites

Loading animation