Addons Tutorial?

Topics: Developer Forum
Apr 8, 2009 at 3:42 PM
Hey all,

I've been investigating the concept of addons for the CMS (along with everything else along my N2 travels).

I still feel that while there is a lot of documentation and examples, things aren't that well explained at times. For a newbie it's pretty hard going!

I was wondering if there was a tutorial somewhere on creating Addons rather than example code projects. Something that can explain where things 'should' go, etc. etc. I want to create something that is reusable but when I drop the addon folder into my project I have to start changing the namespaces .. then pretty soon afterwards I get lost.

Once I understand N2 I promise to help the community, at the moment I really need something that explains:

What Addons are / should be used for (I think I know but it's a good start to a tutorial).
Where they live - folder structures, files that are needed and what they do.
Creating Addons - From a toolbar entry - to a form to - creating editing objects in a DB etc.
General best practice. (I think this would be good as already it seems that there a few ways to do something in N2).

I want to practice by creating a contact addon which will allow users to fill in a contact/enquiry form, submit to the site. An email will be received by a site admin, and the form data would be stored in the DB.. Then the admin could manage the enquiry via the CMS using the Contact Addon to send replies to the user. In the end I can use this on the site I'm working on, and post it to the N2 addons section. I've found that every site I've worked on always wants a contact management area for customer enquiries.

As usual, all help appreciated.

Apr 8, 2009 at 9:47 PM
The general idea with addons is to simplify contributing and finding contributions to the project.

The add-on could be just a dll or a code snippet. Anything that someone finds useful.

In your case there is probably aspx/ascx templates to be deployed on the site. I would place these in a folder /Addons/ContactForm so it's more easily distinguishable from implementation code.

General best practice. That's a tough one. It's easier to criticize after I see something =) Anyway, a few bullets I can think of:
  • Put a [ToolbarPlugin(...)] on the management area page to access it from the edit interface
  • Security of the management area
  • You could use N2.Context.Current.Resolve<IMailSender>() to send e-mails
  • Look at the examples and use search in the source code to look up how interesting aspects are implemented
Good luck, and hope to see your addition soon!
Apr 9, 2009 at 6:19 AM
In continuation of Cristian's 'best practices list' (or better say 'proven practices'):

  • generally it makes sense to split your 'addon' design into two project:
    1. Web Application project, that contains templates (.aspx/.ascx/.ashx)
    2. Class library project  (ContentItems, handlers, code-behinds, MVC controllers, plugin initializers -- everything you'd otherwise put into ~/App_Code)
  • it's always a good idea to fit everything, related to your 'addon' into ~/Addons/<YourSolution> folder: not only web pages and user controls, but also .css, .js, images, even web.config's. This way, plugging your addon into existing web application will basically require just two things:
    1. copying web content into ~/Addons/<YourSolution>
    2. Referencing your Class Library
  • If your web application is under SVN source control, it's handy, instead of copying web content of your addon into ~/Addons/<YourSolution>, to configure it via svn:externals mechanism of Subversion. This way, multiple addons can consolidated within a single web application and still remain 'live' in a sense, that you can edit them on-the-fly and commit changes into their respective repositories. Important thing to notice is that ~/Addons/ folder itself must not be under the source control of your web application.
Experience shows that every bit of your code can be stuffed into such 'addon' thing, greatly simplifying code reuse.
Apr 9, 2009 at 8:07 AM
Edited Apr 9, 2009 at 8:30 AM
So is the /Addons folder completely separate from the project.. ie:


@esteewhy: In terms of the project(s), should I create these two projects in the same place? the example addon seems to have an Items and UI folder, I thought I would just need them.

I'll add more questions as I have them, thanks for taking the time to reply though guys. It doesn't quite explain things at the newbie level I hoped for, but better than nothing.

I'm hoping things become more clear to me soon! (Real soon!!!!).
Apr 9, 2009 at 8:34 AM
Edited Apr 9, 2009 at 11:19 AM
From ASP.Net perspective everything you put into site root ~/ is considered a single web application. This has both good and bad aspects. This is cool, becasue you can just drop a new page anywhere and it will instantly become a part of your application (this is what's going on when you drop your addon folder into existing site). This is also horrible because your app might consist of many logically independent parts (every your addon, ~/Edit administrative pages, ~/Templates, by the way, they're historically in the root, but intuitivelly Templates should also reside beneth ~/Addons ), and you cannot easily manage these independent parts within a single site. This is where VisualStudio concept of 'web application projects' is to the rescue. With them  we can logically group a set of pages to be designed and compiled together, but at the end, everything located behind a single root will be treated as one web application.

Oh well, i can endlessly continue on the subject (at the end, this is still my job -- to speak, teach and learn ;-), but the least thing i want is to confuse ..

Ups, regarding your question where to put what..
The idea is that your content item classes must be visible to N2 in a run-time. This can be achieved in two ways:
  • Either you put them directly within your web application, that is in ~/Addon/<YourSolution>/ folder. I guess this is what a sample addon does.
  • Or, you can add a reference from your web application to a project, containing your item types.
In the second case, it doesn't matter where you put that another project. In the first case, your classes should be somewhere within your Web Application. If you're using 'Web Application' project type in VS.Net (a suggested way) -- the it literary means 'anywhere', if, instead, you go with an 'new-style' 'Web Site' model -- then the only suitable location is ~/App_Code, which greatly limits your choices as to how you structure your solution..
Apr 9, 2009 at 12:25 PM
Hey esteewhy,

The only concern I had with putting them inside my project was the VS didn't like them having a different namespace.. It wanted me to change it to my project myproject.addons or whatever it was.

I'm not sure I know about the 'web application projects' I'll have to look into it, I think I will just add references to the N2 dlls in the addons? Or is that not the way you would do it? I want to make it as reuseable as possible and written in the best way. :)

Apr 9, 2009 at 2:04 PM
Namespaces shouldn't be problem at all. It's a syntax sugar only for you, which means you can alsways alter 'em. Just be careful with .aspx/.ascx pages/controls: if you change a namespace in a code-behind file, you should also update it in markup file inside a <%@ Page ... %> directive. Personally, i prefer namespaces in a form N2.<MySolution>.UI, but any other will do as well.

As to the 'web app' versus 'web site' thing: there plenty info in the net on the subj, so u'd better find what's more comprehendable 4u (but i can also try to explain the thing if u like).

Yes, u want to add a references to N2.dll, maybe also to N2.Templates, N2.Secutiry or N2.Edit. Maybe even NHibernate.Caches.SysCache2, System.Data.SQLite, or whatever.
Apr 9, 2009 at 2:43 PM
Edited Apr 9, 2009 at 2:50 PM
Maybe its resharper that's complaining about the namespaces then, when I drop the addon into the ~/addons folder in my N2 application it moans.

I know all my problems must be small to you guys, but I really wish there was a tutorial that explained things step by step just to get people to understand.

Based on what was said here I created a few files in a Addon folder:

  --> Items
  --> UI
          --> Views
          --> Parts

The items contained one class which I called EnquiryManager, I gave it the N2 [ToolbarPlugin.. ] as per the advice above; but the params that need to be passed into this are a bit of a mystery to a novice.

The goal of these few steps was to simply get an icon displaying in the N2 menu while editting.. Alas that seems to be proving too much. :(
*EDIT* I've found the /plugins folder..
Apr 9, 2009 at 3:46 PM
Okay, i'll better illustrate my rants with a real code. There's a 'Workflow' addon. I've decided to put items into separate assembly, though you can put 'em into ~/Addons/MyAddon/Items if it so be your will, thus eliminating the need for another project.

Next, [ToolbarPlugin..], which Cristian suggests, is needed if you want to provide a special admin interface for the whole your Addon. It doesn't correspond to an exact item. Instead, it works like this: there's a page(s), which provide some functionality in 'Edit' mode. You want this page to appear in 'Edit' menu. This is exactly what this attribute is for -- you put it over your *page*'s code-behind class and the page magically appears in menu.

Maybe what you really need is to be able to get your EnquiryManager item to appear when you click in the 'Add..' context menu ? If so, than decorate EnquiryManager with [Definition] attribute. Want a particular icon for every instance if this type? Override EnquiryManager.IconUrl { get; }. Want to visualize EnquiryManager on your site ? Decorate EnquiryManager with [Template("~/Addons/MyAddon/UI/Views/EnquiryManager.aspx")] and code inside the EnquiryManager.aspx how exactly you want to visualize your item. Want to modify your EnquiryManager throught 'Edit' interface via 'Edit' menu ? Decorate each EnquiryManager's property you want to edit with a suitable [Editable*] attribute.
Apr 14, 2009 at 2:44 PM
I do want the addon to appear in the toolbar at the top of the page in edit mode.. but I don't want it to be related to a certain page on the published site.

Enquiry Manager should be an application that can run and pull data of submitted contact forms from the database, and allow the admin to view them all and reply using the admin addon (it would send emails).

I've managed to get the icon etc showing in the toolbar is there  a way to ensure it's separate from the page that might be currently selected; at present when I click my addon's icon the code behind for EnquiryManager does this (from the example): h1.InnerHtml = SelectedItem.Title; but this just shows the title of the page currently selected on the left menu.

Is there a 'best way' to access the database? Should I be trying to use the four tables that N2 uses by default, or add my own tables for contact info?
Apr 16, 2009 at 8:45 PM
The way to relate a page linked from the toolbar plugin is to use a custom format string. E.g. this decorated edit.aspx:

    [ToolbarPlugin("", "edit", "edit.aspx?selected={selected}", ToolbarArea.Preview, Targets.Preview, "~/Edit/Img/Ico/page_edit.gif", 50, ToolTip = "edit", GlobalResourceClassName = "Toolbar")]

{selected} is replaced by the selected node's path

If you put N2.Edit.EditPage as base class for your plugin aspx you can access the "SelectedItem".

The choice of storing data in the n2 tables or your own is a choice between convenience and performance.

Using N2 tables gives:
  • Integration with N2's edit interface (edit, delete, export, etc)
  • No need to deploy custom schema (which is nice for an addon other will consume)
Using your own tables gives:
  • Better scalability when hundreds or thousands of nodes
  • Nice and clean POCO classes
Apr 17, 2009 at 8:49 AM
Thanks for the answers guys!

I think it might be best for me to use the N2 tables; as you suggested this means other users can easily make use of addons. (And I like the idea of using the N2 edit interface too ;))

The only thing that isn't really answered I guess (I think I'm just blatently missing something) is how do I get/set entries in the DB then? for example if I want a list of items (of the same type)?

Apr 18, 2009 at 8:49 PM
Are you asking how to manipulate content and how to find it?
Apr 20, 2009 at 8:19 AM
Yes, but not pages.  The things I want to create have nothing to do with a page really.. They are objects created by the user/system. When they fill out the contact us form.

Enquiry (object)
public string name { get; set; }
public string email { get; set; }
public string message { get; set; }

EnquiryManager (object) CMS application, not listed on a page anywhere.

Handles listing of the enquiry objects in the DB, replying to an enquiry (sends email via the CMS), removing an enquiry.

Sorry if this makes no sense, it's first thing monday morning. :(