WSS v3 Solution and Feature framework applied to the FlexListViewer webpart

Probably a lot of you know about the existence of the FlexListViewer webpart created by my colleague Robert te Kaat. This webpart was originally build for Sharepoint 2003 to display content of a list on your site, although the actual list resides on another site.

In WSS v3 Microsoft introduced the Content Query webpart which provides basically the same functionality, although only applicable to webs which reside in the same site collection. This is why we upgraded the FlexListViewer webpart so you can still use it on WSS v3 and MOSS 2007, since the FlexListViewer allows you to display lists from ANY site on your webfarm.

I put the upgraded webpart online on the 15 of august and many of you already downloaded it.

Since then, Microsoft finished up on the Solution and Feature framework and today I had the time to apply these concepts to the FlexListViewer webpart.

It is now possible to download the FlexListViewer webpart as a solution package which you can add to your webfarm using the STSADM tool. If you deploy the solution package to a web application a feature is installed. You can enable this feature either through the Web UI or again via STSADM. If you activate this feature, a webpart file will be added to the webpart gallery of the site collection. This will allow you to add instances of the FlexListViewer to your Sharepoint pages. And to put the icing on the cake: if you deactivate the feature, the webpart file is removed from the webpart gallery.

So, how did we achieve all this?

Feature framework
First, let’s take a look at the Feature framework. What do you need this for? Well, when this feature is activated I would like to have the appropriate .webpart file added to the webpart gallery list on the top level website.

So let’s create a feature.xml like this:

<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?>

<Feature Id=&quot;C4DFE860-44A2-481c-A071-D56F78004E49&quot; 
    Title=&quot;FlexListViewer for MOSS&quot;
    Description=&quot;This feature adds the FlexListViewer for MOSS webpart to your site webpart gallery.&quot;
    Version=&quot;1.0.0.0&quot;
    Scope=&quot;Web&quot;
    ReceiverAssembly=&quot;FlexListViewerMOSS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6d92553d25c5c17e&quot; 
    ReceiverClass=&quot;FlexListViewerMOSS.Deploy.FlexListFeature&quot;     
    Hidden=&quot;FALSE&quot;    
    ]
  public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPWeb web = (SPWeb)properties.Feature.Parent;

                
                SPDocumentLibrary list = (SPDocumentLibrary)web.Lists[&quot;Web Part Gallery&quot;];
                
                foreach (SPListItem item in list.Items)
                {
                    if (item[&quot;Title&quot;].ToString().Equals(&quot;FlexListViewer&quot;))
                        item.Delete();
                }

                list.Update();
            }
            catch (Exception err)
            {
                System.Diagnostics.EventLog el = new System.Diagnostics.EventLog();
                el.Source = &quot;FlexListFeature deactivation&quot;;
                el.WriteEntry(err.Message);
            }

            
        }

Solution
Part of the deployment process of a webpart is adding SafeControl sections to the web.config files of the web applications you want to run them on. We still need to do this and I would like to be able to do this automatically on ALL my Web frontend servers. This is why the Solution framework is built into WSS. Now, WSS _knows_ which server participates in which role on your webfarm and can deploy solutions to all the servers they are needed.

We need to create a manifest file to drive the Solution functionality. I came up with this:

<?xml version=&quot;1.0&quot;?>
<Solution SolutionId=&quot;4AFC1350-F354-4439-B941-51377E845F2B&quot; 
    ]
public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPWeb web = (SPWeb)properties.Feature.Parent;

                SPDocumentLibrary list = (SPDocumentLibrary)web.Lists[&quot;Web Part Gallery&quot;];

                SPListItem item = list.Items.Add();
                Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(&quot;FlexListViewerMOSS.Deploy.FlexListViewer.webpart&quot;);


                SPFile file = list.RootFolder.Files.Add(&quot;FlexListViewer.webpart&quot;, s, true, &quot;&quot;, false);
                s.Flush();
                s.Close();


                file.Item.Update();

                file.Update();


            }
            catch (Exception err)
            {
                
                System.Diagnostics.EventLog el = new System.Diagnostics.EventLog();
                el.Source = &quot;FlexListFeature activation &quot;;
                el.WriteEntry(err.Message);
            } 
        }

The FeatureManifest node is needed to tell the solution framework it needs to install a feature on the web frontend server.

MakeCab and DDF file
Here, I encountered a challenge J : I need to create a folder named FlexListViewerCab inside my deployable cabinet file and put the Feature.xml inside this folder. Visual Studio 2005 can create Cab files put it cannot create folders inside a cab file. The only way Google and I came up with was by using a DDF file and the makecab.exe tool which is located in %WINDIR%system32. The ddf file is like a .inf file which tell the makecab.exe how it needs to create a cab file. My ddf file looks like this:

;
.OPTION EXPLICIT     ; Generate errors 
.Set CabinetNameTemplate=FlexListViewerMOSS.wsp     
.set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles=&quot;ON&quot;
.Set Cabinet=on
.Set DiskDirectory1=Package
manifest.xml manifest.xml
bindebugFlexListViewerMoss.dll FlexListViewerMoss.dll
bindebugCore.dll Core.dll
FlexListViewerCabFeature.xml FlexListViewerCabFeature.xml

The first lines tell makecab how it needs to create the cabinet file. Notice the fact that I put down the name FlexListViewerMOSS.wsp instead of .cab. The .WSP file extension is only used so you can tell you are dealing with a Web Solution Package, it does not change the file format in any way. It still is a normal cabinet file.

The last lines are there to target the sourcefile and tell it where to store it in the cabinet.

When you are done, feed this ddf file to makecab like this:

Makecab /f

Solution deployment
The command described above will create the FlexListViewerMOSS.wsp file. Now we need to add this to WSS. We need the STSADM tool for this with the following parameters:

Stsadm –o addsolution –filename “flexlistviewermoss.wsp”

Now you can check the Central Administrations Solution Management section to see a non deployed solution is added to your webfarm. From here you start deployments to your web applications (or you can use STSADM for this as well)

Download flexlistviewermoss.wsp
You want to have a copy and test it yourself? Get it here -> click J

I hope this post shows you how to apply a few of the new concepts of WSS v3 ‘in the real world’. Good luck using it for your own webpart / site definition / features / etc. solutions!