Single-assembly gadgets for EPiServer

This post presents a concept for creating single-assembly gadgets for EPiServer. This means a gadget can be added to a site by simply dropping a DLL in the bin folder and registering it in web.config.

  • 18 September 2011
  • 0

Why a single-assembly gadget?

When creating new gadgets for EPiServer Online Center you’ll find that you either 1) make your EPiServer site project an ASP.NET MVC project and add the gadget implementation to that or 2) create a separate ASP.NET MVC project and then just keep your views and content files in the EPiServer project while controllers and other logic go in the separate ASP.NET MVC project.

Either way this doesn’t do much for distribution and re-usability. Quite often a gadget is relevant for any EPiServer website, and therefore they should be easy to add and remove without polluting the website project.

So, single-assembly gadgets are for easily distributing and re-using gadgets across multiple EPiServer websites.

The overall idea

All files are embedded in the assembly

The idea behind a single-assembly gadget is that all files are embedded in the assembly. That means your user controls, script files, stylesheets, etc will all be distributed as part of your gadget assembly (DLL file).

Role of the support assembly

The support assembly (TedGustaf.EPiServer.Gadgets) makes single-assembly gadgets easy to create by handling some things for you:

  • loading embedded ASP.NET files such as your gadget views (.ascx and .aspx files) from your gadget assembly
  • serving HTTP requests for content files embedded in your gadget assembly, such as JavaScripts, stylesheets and images

Your gadget will link its content files with a prefix causing all those requests to be intercepted by an HTTP handler. Your gadget’s ASP.NET files will be served by a virtual path provider. So, your gadget consists of a single assembly which includes all files as embedded resources. The support assembly then helps to load those resources from your assembly.

Concept architecture of single-assembly gadgets

How to create a new single-assembly gadget

To create a single-assembly gadget we need to:

  1. Create a new ASP.NET MVC 2 project for the gadget (CMS 6 R2 doesn’t support MVC 3)
  2. Make sure all files are included as embedded resources
  3. Ensure TedGustaf.EPiServer.Gadgets.dll exists in the bin folder of your website
  4. Add your gadget’s assembly to the publicModules element in your site’s web.config file
  5. Add the HTTP handler for embedded resources

Note that a single gadget assembly can contain multiple gadgets.

Create your first single-assembly gadget

Create a new ASP.NET MVC 2 project

First, create a new ASP.NET MVC 2 project in Visual Studio. If the gadget will reference your website project you should add it to the same solution as the website, otherwise I’d recommend creating a stand-alone project.

Creating a new ASP.NET MVC 2 project in Visual Studio

Remove unnecessary files

I recommend removing unnecessary files from your MVC project to avoid it being cluttered, as per the gadget tutorial by EPiServer.

Add a gadget controller

The gadget controller routes requests for your gadget. The controller class is also where you set the name, description, and icon for your gadget.

Right-click the Controllers folder and select Add –> Controller:

Adding a new gadget controller class

Give your controller a name like SamleGadgetController (note the “Controller” prefix as per ASP.NET MVC conventions):

Naming the gadget controller

Next, add a Gadget attribute to the controller class to let EPiServer know that this controller represents a gadget:

Adding the Gadget attribute to a controller class

Note that Visual Studio is complaining about the View, that’s because we haven’t created one yet. Also, you need to add a reference to the EPiServer.Shell assembly for the Gadget attribute:

Reference to EPiServer.Shell

Create the gadget view

First, create a new folder underneath the Views folder. Give the folder the same name as the controller (except for the “Controller” suffix, that is):

Adding a view folder

Right-click the newly created folder and select Add –> View:

Adding a new gadget view

Since this is our default view we’ll call the view Index (as per ASP.NET MVC conventions). Don’t forget to check the Create a partial view (.ascx) checkbox:

Naming the gadget view

Add some markup to your view:

Adding markup to the gadget view

Make the view an embedded resource by right-clicking it in Solution Explorer, selecting Properties and finally setting the Build Action to Embedded Resource:

Making the gadget view an embedded resource

Add the gadget to your website

Make sure to build your gadget project. Next, copy its assembly (the DLL file) to the website’s bin folder (together with the TedGustaf.EPiServer.Gadgets assembly):

Adding gadget assembly to the website's bin folder

Next, make an addition inside the <publicModules> element within the <> element in web.config:

Registering the gadget assembly in web.config

Note the name attribute of “EmbeddedGadgets”. This is crucial, the name has to be exactly “EmbeddedGadgets” for the assemblies to be linked to the support assembly (which in turn is what makes the single-assembly gadgets possible).

Add the gadget to your dashboard

Login to EPiServer and click Add Gadgets. You’ll notice that we have a new gadget available:

Adding the gadget to the dashboard

But more importantly, if we add the gadget by clicking the little green plus-sign button (for some reason you can’t drag and drop from here) we’ll see our embedded view being rendered:

Embedded gadget in Online Center

Note that we haven’t actually added the view to the website project, it’s still embedded in our gadget assembly. All we had to do was to add the gadget assembly to the bin folder and register the assembly in web.config.

Add the HTTP handler

In order for us to embed other types of files in our gadget assembly, such as JavaScript, CSS, and image files, we need to add an HTTP handler to the <handlers> element in web.config:

I recommend adding a new <location> element for the “EmbeddedGadgets” path like so:

<location path="EmbeddedGadgets">
<add verb="GET" name="EmbeddedGadgets" path="EmbeddedGadgets/*" type="TedGustaf.EPiServer.Gadgets.Handlers.EmbeddedResourceHandler" />

Customizing the widget appearance

Next, let’s set another title, description, and icon for our gadget, making it look a little nicer when users add it in Online Center.

Setting the gadget title and description

The title and description for the gadget are set by adding parameters to the controller’s Gadget attribute:

Setting the gadget title and description

Adding a gadget icon

First, create a folder called Images under the Content folder and add your icon file to it:

Adding a gadget icon file

Don’t forget to set the image as an embedded resource:

Embedding the gadget icon in the assembly

Next, add an IconUrl parameter to the Gadget attribute (note the “EmbeddedGadgets” and assembly name prefix before the actual file path):


Check the result

Now, if we re-compile the gadget assembly (and make sure the updated assembly is in the website’s bin folder) we can check the result in Online Center:

Gadget with icon in the Online Center

Linking embedded files

Your gadgets will most likely need images, CSS files, and JavaScript files. These should also be added as embedded resources in your project.

It’s important that all embedded files are linked with a URL prefix of “/EmbeddedGadgets/Your.Assembly.Name/” before the actual virtual path.

So, for the icon URL earlier: since our assembly is called EmbeddedGadgetSample, the icon file is in the /Content/Images folder, and the icon filename is SampleGadgetIcon.png, our full path to the embedded image is:

Download the support assembly and demo project

Moving on from here

If you decide to try this approach, please post any comments, questions, or general feedback in the comments below! Also, if you think it would be valuable to have the support assembly as a NuGet package, let me know and I’ll make sure to create one and publish it on the EPiServer developer feed.