Building a pluggable module
Over the last week or so I’ve received several comments asking how to register a custom module in Sitefinity. Obviously, this post should have been written way before in the Building a pluggable module section, but I have somehow missed it. I apologize and would like to thank the kind readers that pointed that out.
So here it goes… registring the module with Sitefinty. In case you have not already downloaded the latest download of Contacts Module project, you can do it here. The zip file contains two projects : Sample.Contacts and Sample.Contacts.Data.
You need to add both of those projects to your existing project in Visual Studio in effect creating a solution. If you already have a solution, just add those two projects. Then add both projects as a reference to the WebSite project (Sitefinity website).
Now that you have that project, let’s see what we need to do to register it.
1. You should add the config section for contacts module to your web.config. So find in your web.config <configSections> element, and then inside if <sectionGroup name=”telerik”> element. Paste the underline line inside that element.
<section name=“contacts“ type=“Sample.Contacts.Configuration.SectionHandler, Sample.Contacts“ requirePermission=“false“/>
Sample.Contacts is the name of the project. SectionHandler is the class inheriting the base class ConfigurationSection and contains the functionality for loading and accessing the contacts section information.
2. Add the contacts section inside of telerik section group.Your contacts section will allow you to set various settings required by Contacts module. So find the <telerik> element and past the underlined text somewhere inside it (be careful <telerik> element must be a immediate parent of <contacts> section here).
<add name=“Sitefinity“ securityProviderName=“” type=“Sample.Contacts.Data.DefaultProvider, Sample.Contacts.Data“ connectionStringName=“DefaultConnection“ visible=“true“ />
As you can see the first and most rudimentary setting we need to set is the provider for this module. Sample.Contacts.Data is the data project for the Contacts module and DefaultProvider is the class providing an implementation for the provider model.
3. Finally, you have to register the module. The previous two steps were needed by the module, this last step actually registers the module with Sitefinity. Find the <framework> element and then <modules> element inside of it. Paste the underlined line inside of <module> element.
<add type=“ Sample.Contacts.ContactsModule, Sample.Contacts“/>
ContactsModule is the class, providing substantial information for your custom module. In my previous posts I’ve referred to this class as the main module class also. That’s the one inheriting WebModule class.
That’s all. Let me know if you need any other assistance.Read Full Post | Make a Comment ( 4 so far )
Generally, we can say that all web controls you are going to build for Sitefinity modules have several things in common. In this post I will explain how I’ve approached building a ControlPanel control for Contacts module. Once that is explained everything else should come pretty easy to you. At the end of this post you’ll find a link to the project so you can download it and examine (I’ve commented the project rather extensively).
There are two cornerstone ideas we have when we build any kind of control :
- Appearance of control is defined through a template. To control it should make no difference how the template is created
- Working with data is done through a manager class. It should make no difference to control how is data being stored, that’s up to provider.
Take a look at following diagram to get a high overview of how Web controls are built in Sitefinity.
Working with controls
On the left we have Web Control (blue) which represents ControlPanel in this example. This control acts as a wrapper control for the actual controls of ControlPanel. The child controls being (if you forgot how control panel should look like, take a look at this mockup Contacts module > View mode) :
- Add new contact – when clicked Control panel should switch from list mode to insert mode
- Contacts grid – Rad Grid that lists all the contacts
- Contact Editor – this control serves a purpose of adding new contacts or editing existing contacts (if you forgot, this is how this control looks like Contacts module > Insert / edit mode)
In order to allow designer / user experience expert to modify the look and feel of the controls without messing with the code and recompiling we load controls from template. This is where the GenericContainer kicks in. We are always going to instantiate the template inside a class that inherits from GenericContainer. Generic Container class allows us to define controls that are absolutely necessary for ControlPanel to be working (required controls), but also allows us to define the controls that can be there, but are not necessary (optional controls). So if a template creator forgets to add a Button control with the id of “addNewContact” an exception we’ll be thrown saying that template is missing a required “addNewContact” button. By using GenericContainer class we have an easy way to make a contract between a programmer and designer.
Template creator has two options when it comes to creating a template without coding. One is to create an user control and set it’s path in the web.config provider or he can declaratively create template. Note that it is only possible to create declarative template if the ControlPanel is added to the page or user control declaratively as well (it’s obvious that if we add ControlPanel dynamically we can’t create template declaratively).
Third option for creating a template is default template, class that inherits from ITemplate. You should always implement default template because it is possible that Page object will not be accessible at one time or another (Design) and you don’t want the control to crash at that moment.
If all this sounds messy, take a look at the diagram once again, download the project and examine the code, and then reread it again. This whole idea is actually much simpler than it sounds.
Working with data
In order to keep our control as flexible as possible, all the work with data will be done through manager (ContactsManager) in this example. Depending on how you initialize manager (without the provider name it will use ‘DefaultProvider’ or with the actual name of the provider) manager will decide which provider to use to work with data.
This, for example, allows you to move your data from Sql Server to XML without ever modifying the Web controls. All you need to do is create a new Data provider and initialize manager with the name of new provider.
Few last words
I’ve just explained the logic behind creating the controls. Understanding this logic should ease your decisions regarding where to create controls, how to bind controls to data and such. The detailed explanation you can get by examining the project, since I’ve commented all the crucial parts. Once again, if you have any questions, don’t hesitate to ask. Nothing would make me more happier that a request from you to write a blog post on a topic that has not be understood cleary
Since we’ve covered most of the topics so far, I won’t be explaining the project step-by-step anymore, but will point out important aspects. So from now on, I’ll be working more on the code and comments… while in posting I’ll let you know what has been added so you can see how to whole thing is rolling out.
One more thing, once the module is completed I’ll make the entire solution (with Sitefinity Community Edition) available for download.Read Full Post | Make a Comment ( 4 so far )
The Contacts pluggable module will be made of two assemblies : Sample.Contacts and Sample.Contacts.Data
The business logic and UI will be implemented in Sample.Contacts module, while the data access we’ll be done through the Sample.Contacts.Data assembly. Take a look at the following diagram to see the big picture :
There are five main parts of this assembly :
- Web controls – Admin web controls that will provide a way for authorized users to work with contacts and Public controls that will display the contacts on the pages.
- Contacts Manager – Web controls will work exclusively with Contacts Manager when manipulating data.
- Contacts Provider – Contacts manager will call the methods inside of a provider class. Since there can be more than one provider (Sql and XML for example) the Contacts Provider is an abstract class that the actual provider classes need to derive from. In addition to this, the Contacts Provider class will be used to retrieve various settings from web.config used by the module (like paths to external templates and such).
- Both, Contacts Manager and Contacts Provider classes will get the needed settings from web.config by using Configuration classes.
- Finally, we have Resources where all the messages and labels will be stored in case we decide to localize our module at later stage.
There are four main parts of this assembly :
- Contact (dbclass) - Nolics class that will define the database object for storing contacts and it’s Contact partial class that we’ll use to add some additional functionality
- Department (dbclass) - Nolics class that will define the database object for storing departments and it’s Department partial class that we’ll use to add some additional functionality
- Default Provider – This class derives from Contacts Provider abstract class and will actually implement all the data manipulation methods (such as inserting a new job, deleting a department etc.)
- Resources – here mostly to hold error and exception messages in case we decide to localize the application at later stage
In the next post I’ll provide the link for the latest version of the project and describe briefly what’s been done. If you have qustions or suggestions, don’t hesitate to leave the commentRead Full Post | Make a Comment ( None so far )
In this post we’ll only cover the mock-ups for the admin area of our module. Later on, we’ll get to the mock-ups for the public controls.
Since the contacts module we are building is pretty simple and straightforward, we really need just the mock-ups for two different screens in our admin area. One is the default screen with our contacts in the RadGrid (you could just as well use standard GridView control), while other one is the screen for inserting new or editing already existing contacts.
As you can see on the right side in CommandPanel we have a link that will show all contacts in case we want to cancel the filtering or we want to come back to the default screen.
Just under that we have a RadTreeview that manages different deparments. One can add, delete, edit or reorder those deparments. By clicking on any of the deparments user gets only contacts that belong to that department.
Under that we have the ability to show only contacts that start with a particular letter.
On the right side we have a RadGrid with all the contacts. We can click on the “Add new contact” link to add a new contact. In the grid we can sort contacts, delete contacts or edit them.
Which brings us to our second screen. The one that will be used as an insert/edit screen for a particular contact.
In this mode we can edit or insert (depending on how we got to this screen) a particular contact. Take a look at the mock-up to see what kind of information we’ll be storing about each contact. Click on the thumbnail to enlarge it.
As you can see here we have some pretty basic contact info about each person inside of an organization. We can save that info or cancel.
And that’s all. In the posts to come we’ll be building the just described functionality, so stay tuned…Read Full Post | Make a Comment ( None so far )
After we have explained the basic concepts behind every Sitefinity module the time has come to leave the theory behind us, roll up our sleeves and do some building.
In order to create a module you need to create a new C# project and in it’s most rudimentary version, you need three files inside of this project. The module class, and two web control classes (for command panel and control panel). To ease this process for you, you can download the project to get you started. Regardless of what kind of module you are about to build you will needed these files.
In addition to this, you’ll need to reference following assemblies in your project :
To put some kind of perspective, the sample module that will be built during this series of posts is “Contacts” module. This is a very simple module which will allow user to enter all relevant contacts across the organization (for example : CEO, sales, technical support…) with their names, emails, phone numbers, working hours and so on. More about this project you’ll be able to read in the next post. So, now that we know that we are building “Contacts” module we can continue with a little more clarity.
The first file in our project is the ContactsModule class. This is our module class and it has to inherit from Telerik.WebModule class in order to be used as a Sitefinity module. Apart from several properties that describe this module (such as name and description) there are two important methods here : CreateControlPanel and CreateToolBoxControls. The CreateControlPanel method returns any Control that will be used as a ControlPanel control (the one on the rigth side). The CreateToolBoxControls returns an IList<IToolboxItem> object, which in turn contains all controls you want to appear in the command panel (the one on the left side).
As you can imagine, the two other files that you’ll need are ControlPanel class (of type CompositeControl) and CommandPanel class (of type CompositeControl, but this class also needs to implement IControlPanelCommand interface).
This all fits together in the previously mentioned ContactsModule class. Namely, in CreateControlPanel method you create a new instance of ControlPanel class and return it, while in CreateToolBoxControls you create a new instance of CommandPanel class and add it to the IControlPanelCommand array.
And this is all that you really need to get our Contacts module work. In ControlPanel and Command panel class you can overwrite the CreateChildControls method and add just some arbitraly controls (e.g. I’ve added the labels in the attached project) to see what happens.
In the next post I’ll write some brief specs for the Contacts module and attach few mockups just so that we are all on the same page.Read Full Post | Make a Comment ( None so far )
Module is integrated in Sitefinity modules section as an assembly. This means that in order to create your own module you need to create a new C# project (Class library). The core class in this module you will name any way that you find suitable (for example : ListModule, MyModule…), but the important thing here is that this class needs to inherit Telerik.WebModule class.
In order to appear on the modules page and be usable, module needs to be registered in the web.config file.
The resulting .dll file you will obviously put in the bin folder of your website.
The module itself has two fundamental sides : administrative and public. The administrative side is the one you see in the modules part of Sitefinity, while the public side consists of the controls that users can drag onto the page in order to take advantage of your module. Take a look at the image below to get a better understanding of this distinction.
In this post, I will concentrate mostly on the Administrative side of the module. The public part will be dealt with in one of the coming posts. The administrative side of the module furthermore can be divided into two more sections. The Command Panel and Control Panel. To understand this separation better, you can think of the command panel as the “left side” and control panel as the “right side” of the screen. In essence, Command Panel (left side) is there really just to facilitate the Control panel (right panel) with some kind of sub navigation. Take a look at this image to get a clearer picture.
So the idea here is that you use the core class of a module (the one that inherits from a WebModule class) as some kind of container to hold the two other controls you will create : the CommandPanel and ControlPanel controls. What will those two classes do is completely up to you and depends on what your module is supposed to do.
Here you can download a template project to get you up to speed. [Need to create this project and post a link for download]
In the next post we’ll dig deeper into the code and create the two basic controls, namely CommandPanel and ControlPanel controls.Read Full Post | Make a Comment ( 6 so far )
What is a Sitefinity Module?
Modules are quite probably the most powerful feature of Sitefinity. They allow you to extend Sitefinity in any way you need it to be extended. Need a image gallery on your site? How about blog aggregation tool? Or maybe product catalog? All this you can do by taking advantage of Sitefinity. Now, to see why is this so cool, think for a moment : You already have everything done except that particular functionality (e.g. blog aggregation tool). You don’t have to worry about the site navigation (already done), you don’t need to create an admin area (already done), you don’t need to worry about approval system (already done) etc.
So, at this point you may think, that’s all nice and dandy… but it’ll take forever to learn how integrate my functionality into Sitefinity. Not so. I’m the best proof of that, since I’ve joined Sitefinity team just few weeks ago and I’m already building a module, heck… I’m blogging on how to do it. Namely, the architecture of modules is following all the best practices of for Asp.NET so most of the things will come natural to you. In addition to that, well tought architecture will simply (and unknowlingly) force you in building easy-to-maintain-and-extend modules. Take my word on this…
Now, to avoid risk of sounding like yet another marketer trying to sell you an idea, I’ll admit that you do need to understand some fundamental ideas of Sitefinity Modules. I had few problems on my own, and therefore I’m writing this series in hope to help you avoid these problems in the beginning.
This series will probably be extensive since I’ll try to cover as much of the process along the way, however at the end I’ll distill it into a “quick start” type of article. In the next blog post I’ll describe the basic concepts and ideas that you need to understand about any module. Then I’ll start to build a sampe module and provide you with some source code. So stay tuned…Read Full Post | Make a Comment ( 2 so far )