Archive

Archive for the ‘sharepoint’ Category

HiSoftware Accessibility Foundation Module

First look at the Accessibility Foundation Module from HiSoftware:

The other day I wrote a post that HiSoftware announced their Accessibility Foundation Module. Shortly after that the CEO from HiSoftware contacted me and asked if I would like a walkthrough of the module. Of course, I jumped at the opportunity.

The Accessibility Foundation Module is an add-on to HiSoftware’s Compliance Sheriff. Compliance Sheriff is a tool that checks the accessibility of a SharePoint site. Since SharePoint is a Content Management tool, many people can enter content. But, that content isn’t always accessible. Among other things, Compliance Sheriff checks the accessibility of content being add by end-users into a SharePoint site. It can do this with custom workflows and reports.

The Accessibility Foundation Module is an add-on ontop of Compliance Sheriff. This module uses the same idea of the Accessibility Toolkit from HiSoftware (custom master pages, css sheets and control adapters). The Accessibility Foundation Module does look like a final product that can be installed onto a SharePoint site. It uses a feature to install (very nice compared to the installation of the Accessibility Toolkit). It also uses the “common” master page/look and feel for SharePoint (the Accessibility Toolkit only worked with the external/extra master pages).  Also, it takes care of a lot of the common problems with SharePoint accessibility.

One of the features I really liked was the ARIA support (http://www.w3.org/WAI/intro/aria).

The pricing model seems to be a CAL/server based license. It looks like this can get pretty expensive for large implementations. Truthfully, I didn’t get a full understanding of the pricing model based on the conversation (I need to talk more to them about that). But, regardless of the price, I think accessibility is worth it (especially in government space). So, all government agencies working with SharePoint 2007 should look into this when pricing out their implementations.

I haven’t had a chance to use this tool yet (I only got the walkthrough). So, once I get my hands on it I will be able to write another review. Until then, I’m going to encourage my clients to look into this because it “seems” to be far and away the best implementation I’ve seen for accessibility and SharePoint.

For anyone who is on the SharePoint 2010 bandwagon already, I did ask them about it. HiSoftware says that SharePoint 2010 isn’t as accessible as Microsoft wants us to think. I’d like to get a few instances from them, but that was very interesting to hear. So, HiSoftware is making this for SharePoint 2010 too. After I do a full assessment of SharePoint 2010 and accessibility I will be able to see whether the HiSoftware price is justified for this version.

Categories: Accessibility, sharepoint

HiSoftware announces Accessibility Foundation Module

March 5, 2010 1 comment

HiSoftware just announced their AFM (Accessibility Foundation Module). http://www.hisoftware.com/products/CS_AFM.html.

“The optional Accessibility Foundation Module (AFM) provides users with a set of tools to create an accessible platform/framework for a SharePoint portal or intranet site. AFM is integrated into the Compliance Sheriff offering to provide a more complete and easy-to-deploy method of addressing SharePoint framework accessibility. The most significant advantage of AFM is the enterprise-friendly installation method that allows a SharePoint Server Administrator to easily apply a master configuration to multiple SharePoint Applications.”

I was never really a fan of the “completeness” of HiSoftwares Accessibility Kit for SharePoint. The ideas were good, but the implementation seemed incomplete to me. I did use their ideas and extend that kit for accessible SharePoint projects. But, could never use it out-of-the-box and the amount of work involved was always very high. Hopefully this new Module is more of an out-of-the-box approach to accessibility (I’d rather pay vs build for this).

I don’t know too much about the details of this Kit yet, but as soon as I get my hands on it I will post my thoughts.

Categories: Accessibility, sharepoint

Approve all items button in a SharePoint View

January 14, 2010 2 comments

Situation: You’ve been tasked with building a mechanism for an approver to approve all the pending items in a SharePoint list. 

Implementation: Single “Approve All” button WebPart that only shows for approvers. This WebPart can be shown on one of the view pages of the list. 

Concepts:

  1. Place the WebPart on a View of the List
    • Go to the list
    • Click Edit Page
    • Add the WebPart in the top zone
  2. Loop through the items in the current list and set the approve flag
    • This is in the bgnApprove_click event handler below
    • This checks if the item is in pending status and approves the item
    • This will cancel approval workflows currently running on the item
 
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow; 

namespace ApproveAll
{
[Guid("a73bd0c2-a842-4c37-8021-447f550428b5")]
public class ApproveAll : Microsoft.SharePoint.WebPartPages.WebPart
{
private bool _error = false; 

public ApproveAll()
{
this.ExportMode = WebPartExportMode.All;
} 

///
/// Create all your controls here for rendering.
/// Try to avoid using the RenderWebPart() method.
///
protected override void CreateChildControls()
{
if (!_error)
{
try
{
base.CreateChildControls(); 

//get the list
SPList list = SPContext.Current.List; 

//Show the approve button for users with approve permissions to this list
if (list.DoesUserHavePermissions(SPBasePermissions.ApproveItems))
{
Button btnApprove = new Button();
btnApprove.Text = "Approve All";
btnApprove.CssClass = "ApproveAllButton";
btnApprove.Click += new EventHandler(btnApprove_Click);
this.Controls.Add(btnApprove);
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
} 

///
/// Loops through all items in the current list and approves them.
///
///
///
void btnApprove_Click(object sender, EventArgs e)
{
//get the list
SPList list = SPContext.Current.List; 

//approve all items
foreach (SPListItem item in list.Items)
{
if (item.Level == SPFileLevel.Published)
continue; 

SPFile sourceFile = item.File;
if (sourceFile != null)
{
//Update files
if (sourceFile.Item.ModerationInformation.Status == SPModerationStatusType.Pending)
{
CancelWorkflows(list, item);
sourceFile.Approve("Bulk Approval by" + SPContext.Current.Web.CurrentUser.LoginName);
}
}
else
{
//Update simple list items
if (item.ModerationInformation.Status == SPModerationStatusType.Pending)
{
CancelWorkflows(list, item);
item.ModerationInformation.Status = SPModerationStatusType.Approved;
item.ModerationInformation.Comment = "Bulk Approval by" + SPContext.Current.Web.CurrentUser.LoginName;
item.Update();
}
}
}
} 

private static void CancelWorkflows(SPList list, SPListItem item)
{
if (list.DefaultContentApprovalWorkflowId != Guid.Empty)
{
SPSecurity.RunWithElevatedPrivileges(delegate{
foreach (SPWorkflow workflow in item.Workflows)
{
if (workflow.ParentAssociation.Id == list.DefaultContentApprovalWorkflowId)
SPWorkflowManager.CancelWorkflow(workflow);
}
});
}
} 

///
/// Ensures that the CreateChildControls() is called before events.
/// Use CreateChildControls() to create your controls.
///
///
protected override void OnLoad(EventArgs e)
{
if (!_error)
{
try
{
base.OnLoad(e);
this.EnsureChildControls();
}
catch (Exception ex)
{
HandleException(ex);
}
}
} 

///
/// Clear all child controls and add an error message for display.
///
///
private void HandleException(Exception ex)
{
this._error = true;
this.Controls.Clear();
this.Controls.Add(new LiteralControl(ex.Message));
}
}
} 

Sorry for the lack of proper indentation in the code. The blog did it 🙂

Now, build and deploy the custom WebPart. Then, go to any view in your List. Edit the page and drop the custom Approve All WebPart in the WebZone (right above the list view). 

*Just remember: this only works if you put the WebPart on a view “in the list” because it infers the list object from the current context. Also, if you want this on multiple views for the list, you must place it on all the views. 

Happy hacking!

Categories: sharepoint, webpart

MOSS Project Tasks Gantt Chart size issue in Firefox

October 5, 2009 1 comment

When you use a Gantt Chart web part, from the project tasks list in MOSS, you get a scroll bar at the bottom so that it fits in the screen (in Internet Explorer). This is done with a div tag and an overflow style of auto in the ms-ganttDiv of the core.css file in SharePoint.

gantt

However, in any other browser (other than IE), you don’t get the scroll bar. Instead, the Gantt Chart is set to the full width and your browser page becomes very wide.

This happens because SharePoint uses a different style for browsers other than IE. For other browsers ms-ganttDiv is replaced with ms-ganttDivNonIE. So, using my trusty developer toolbar in IE and Firebug in Firefox, I decided to check out these two styles.

The difference between the two is the “position” property. In IE, the position is set to absolute. In the other browsers, the position is set to inherit.

So, I decided to switch the position to absolute in Firefox to see what happens. And, of course, it looked horrible (I knew the SharePoint developers did this for a reason).  It makes the Gantt Chart overflow over the size of the webpart.

ganttFirefox

I tried playing around with different css settings to see if I could fix this. But, I think I found the same thing the SharePoint developers found, it is very hard to fix this issue in non-IE browsers (no wonder they hacked this up).

Thus, my conclusion is to make this a fix width Gantt Chart. All I did was set my WebPart to fixed width (instead of 100% height). Then I added a css style to my site to set the width of the ms-ganttDivNotIE.

.ms-ganttDivNotIE{ width:800px; }

Note: making the WebPart width the same size as the .ms-ganttDivNotIE is important. If you don’t do this, the user could see space between the end of the Gantt Chart and the border of the WebPart.

It’s not the perfect solution, but it makes the site act consistent in Firefox and IE (that was my requirement).

Categories: sharepoint

Inheriting Themes for SharePoint publishing sites

September 12, 2009 2 comments

SharePoint themes do not inherit when creating a site/sub-site structure. Try it, set a theme to the root site in your site collection, set the theme to something other than the default, then create a sub-site under that site. Notice that this sub-site automatically gets set to the default theme again. Now your users have a different design experience as they navigate through your site. That might be ok if you are creating different team sites, but it doesn’t create a cohesive experience when building a portal structure. Of course, you can always set the theme every time you create a sub-site, but wouldn’t it be nice if you didn’t have to do that (especially if you have an environment where less experienced SharePoint administrators are adding sub-sites).

I’ve never  been a big fan of themes in the past. I usually create my own css and put it in the layouts folder and access it in the master page. But, that is only when I have time to customize my site. Every once in a while I have to put a quick SharePoint site together using out-of-the-box functionality and I need to use the out-of-the-box themes to give a distinct look to a particular site collection.

The following technique shows a way to gain that theme inheritance behavior for SharePoint publishing sites.

Note: The following directions are for MOSS publishing sites because you can set the alternate css in MOSS through the interface. In addition, you must make sure that all of your sub-sites are set to inherit the alternate css.  And lastly, you must have the publishing features turned on. Of course, all these settings are set by default when you use one of the publishing templates to create your site and sub-sites. It works really nice with the Collaboration Portal template for the site collection and the Publishing Site templates for the sub-sites.

  • Set the theme you want to on the home page of your site collection (Site Settings – Look and Feel – Site Theme – Choose a theme)
  • Go to the site collection home page and view the source (right-click on the page in your browser and choose view source)
  • Do a search for the word _themes and copy the link from the href tag. For example: a tag on my site looks like this – <link rel=”stylesheet” type=”text/css” id=”onetidThemeCSS” href=”/_themes/Jet/Jet1011-65001.css?rev=12%2E0%2E0%2E6421″/>. I copied: /_themes/Jet/Jet1011-65001.css?rev=12%2E0%2E0%2E6421
  • Go to the master page settings of your site collection (Site Settings – Look and Feel – Master page)
  • Check the radio button to “Specify a CSS file to be used by this publishing site and all sites that inherit from it”
  • Paste the link we copied previously into the text box
  • Check the checkbox “Reset all subsites to inherit this alternate CSS URL” if you already have subsites created in your site collection.
  • Click OK

Note: If these steps do not work, there is a posibility you do not have the alternate css inhertence setup on your sites. Or, it might mean that you are creating a non-publishing site (like a team site) off of your publishing site collection. Also, if you don’t see some of the links I mentioned in the steps, then that means you either do not have MOSS or you don’t have the publishing features turned on.

Why does this work

SharePoint dynamically creates a _theme folder for a site when you set the theme. Then it associates the theme, through a stylesheet link, in a tag on the sites page. For more information on this process please visit Heather Solomons blog.

The problem is, SharePoint only creates the stylesheet link in the particular site you create the theme at.

Thus, this technique takes advantage of the fact that if you create the theme at the top level site, you can access it through relative paths from any sub-site. So, by creating the theme at the top level site, it will create that _themes folder at that level. Then, luckily, the alternate CSS does inherit through all the sub-sites in SharePoint. So, we can just use a simple relative path, in the alternate CSS, to inherit the theme down through our sub-sites.

Caveat: This is a “no-code” solution for a particular situation (MOSS Publishing Sites). For production systems I always like to do my customizations through solutions, features, custom master pages and custom css. If you don’t have the environment described in this post (MOSS Publishing), then you might have to use other techniques – such as a full customization technique with a solution or by setting the css through designer: Heather Solomons post on CSS Options with Master Pages

Categories: sharepoint

Developing SharePoint WebParts using User Controls and Web Applications

May 18, 2009 79 comments

If you’ve read my blogs before, then you probably know I am a fan of WSPBuilder (http://www.codeplex.com/wspbuilder). I like the intuitive nature and flexibility of the product. It really helps with the deployment aspects of SharePoint features and functionality. However, in the end, it is really just a structured way to create a deployment/feature project that will create the wsp install file for SharePoint. It really doesn’t help much when building UI functionality. For example: if you want to build a Web Part in SharePoint, you still have to build the Web Part code out programmatically (instead of using the WYSIWYG features of Visual Studio). The same issue comes up with building master pages, application pages or anything that requires html and a code behind.

In this article I am going to show you how you can utilize the flexible nature of WSPBuilder, ASP.Net Web Applications and post build scripts in order to utilize WSPBuilder as your deployment project for your UI. 

Solution Overview

SharePoint is a dynamically generated website that pulls information out of a database. It also utilizes files on the server and uses those files as templates or actionable files. The combination of these static files on the server and the information in the database creates the web page we see. This architecture is what allows us to create pages, add webparts, modify navigation, etc… all within the SharePoint site itself.

So, when developing against SharePoint, we need to deploy files to this static place on the server and register the files in the database. This static place on the server is called the 12 hive. It is usually found at: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12. A lot of stuff goes on in the 12 hive. You have the templates for the website, images, themes, etc… You also have very special items called Features. Features allow us to deploy custom functions to SharePoint and then activate/deactivate them at our leisure.

WSPBuilder allows us to “mimic” the 12 hive, within a Visual Studio project. As long as you have the same 12 hive structure setup, it can create the SharePoint deployment file (i.e.: the wsp). You do not need WSPBuilder to create wsp files; you can do the same thing by building extra files in your solution called manifest.xml and ddf files. However, for rapid application development, it is easier to use a third party solution like WSPBuilder because it creates those extra deployment files for you.

While WSPBuilder is a great tool to help us build the deployment files, it is not a web application project in Visual Studio. Web application projects help us build code behind and designer files for our server side controls.

Thus, the ideal solution for building UI elements in SharePoint consists of:

  1. ASP.Net Web Application project to build the UI elements
  2. WSPBuilder project to create our deployable wsp file

The ASP.Net Web Application project will contain the UI elements (such as User Controls). The build process will move the appropriate elements from the ASP.Net Web Application project to the WSPBuilder deployment project. Then the deploy will move the files from the wsp to the SharePoint Server.

Deploy

The key to this solution is seperation of concerns. You should build all UI related functionality in the ASP.Net Web Application project. All SharePoint specific functionality (ex: features), should be built in the WSPBuilder project.

 

Create the WSPBuilder deployment project

  1. Create your project in Visual Studio (File – New – Project)
    • Choose the WSPBuilder project. I am utilizing the one under c# for this example.
    • Give it a good name. I am using DemoProject for this example.
    • Make sure it creates a new solution when creating the project.
  2. Add a folder under the 12 folder called “Template”.
  3. Add a folder under the Template folder called “LAYOUTS”.
  4. Add a folder under the Template folder called “FEATURES”.
  5. Add a folder under the Template folder called “CONTROLTEMPLATES”.
  6. Add a folder under the project called “GAC”.

Note: The “GAC” folder in WSPBuilder is a special folder. We can place external dlls in this folder the the resulting WSP will deploy those dlls to the GAC for us.

DemoProject

 

Create the UI project

As I mentioned in the beginning of this article, the point is to create our UI elements in an ASP.Net Web Application project. So, we need to create another project, in the same solution, so that we can develop our UI elements.

  1. Create the UI project (File – Add – New Project)
    • Choose the ASP.NET Web Application Template. I am utilizing the one under c# for this example.
    • Give it a good name. I am using DemoProjectUI for this example.
  2. Delete the Default.aspx
  3. Sign the project (this is because we are going to deploy to the GAC)
    • Go to the properties (right-click the project and choose properties).
    • Go to the Signing tab.
    • Choose “Sign the assembly”.
    • Under the “Choose a strong name key file” – choose <New>
      • Give it a strong name – I usually use the name of my project (for example: DemoProjectUI).
      • Uncheck “Protect my key with a password”.
  4. Add in the post build commands
    • Go to the properties (right-click the project and choose properties).
    • Go to the Build Events tab.
    • Add the following into the post build section:
      xcopy "$(TargetPath)" "$(SolutionDir)DemoProject\GAC\" /Y /s
      xcopy "$(ProjectDir)*.ascx" "$(SolutionDir)DemoProject\12\TEMPLATE\CONTROLTEMPLATES\" /s /Y /R

Let’s recap what we did in the steps above. First we created a WSPBuilder project called DemoProject. This is our deployment project. It will create wsp files that we can deploy to SharePoint. Then we created an ASP.Net Web Application project called DemoProjectUI. This is where we will create all our UI elements. This will allow us to create user controls with html and code behind files. Lastly, we made sure that we moved the dll and ascx files, from the DemoProjectUI project, to the appropriate place in the DemoProject project.

 

Create a Web Part

Our next step is to create a Web Part. As anyone who has developed in SharePoint before knows, Web Parts are complete code files. They are not the html with code behind files we are used to when developing in ASP.Net. Some people are fine with developing Web Parts completely programmatically. However, it is much easier to create UI elements when you have WYSIWYG editors, html and code behind.

One way to get the normal ASP.Net web development experience, when developing Web Parts, is to use the SmartPart. The SmartPart is a very clever Web Part, developed by Jan Tielens, which can render .Net user controls in Web Parts. I really like the SmartPart, especially for people learning to build SharePoint Web Parts as user controls. However, I like more control over what I do and there are some limitations to the SmartPart. It is not my intent to go over those limitations in this article, but you can read them here: http://weblogs.asp.net/erobillard/archive/2008/03/04/what-to-know-about-smartpart-and-loadcontrol.aspx

In the end, you can accomplish the same thing as the SmartPart using the “LoadControl” method in .Net. Thus, this article will show how to create a Web Part, which will load the user control from our UI project.

  1. Create the Web Part using WSPBuilder
    • Right-click on the DemoProject project
    • Go to Add – New Item
    • Choose WSPBuilder – Web Part Feature
    • Give it a good name. For this example I am going to use DemoFeature
    • A popup will come up with Title, Description and Scope. Since we are developing a Web Part, you must choose “Site” for the scope. This is because we need the Web Part to deploy to the Web Part gallery of our Site Collection.

    Notice that WSPBuilder did two things for you:
    – It created the feature in the features folder
    – It created the Web Part code in a folder called WebPartCode

  2. Modify the Web Part code to use “LoadControl”
    • Open up the DemoFeature.cs file in the WebPartCode folder
    • Remove the MyProperty property and attribute for now. This is just WSPBuilder showing you how you can use properties. We aren’t going to use them for this demo.
    • Find the CreateChildControls method and find the comment that says “Your code here…”
      • Remove the line under it.
      • Replace it with this: this.Controls.Add(Page.LoadControl("~/_controltemplates/DemoControl.ascx"));

      Your CreateChildControls method should look like this:
      protected override void CreateChildControls()
      {
          if (!_error)
          {
             try
             {
                base.CreateChildControls();
                this.Controls.Add(Page.LoadControl("~/_controltemplates/DemoControl.ascx"));
             }
             catch (Exception ex)
             {
               HandleException(ex);
             }
          }
      }

  3. Add the control to the UI project
    • Right-click on the DemoProjectUI project
    • Go to Add – New Item
    • Choose Web – Web User Control
    • Give it a good name. For this example I am going to use DemoControl.ascx

Now, when you build your solution, the DemoControl.ascx will move to the ControlTemplates folder in the DemoProject project. The SharePoint Web Part will look for the control by using the _controltemplates path.

Note: SharePoint can find any control in the ControlTemplates folder by using the _controltemplates path because of a mapping it creates in IIS. SharePoint maps the _controltemplates path to the servers 12 hive at 12/Template/ControlTemplates.

 

Utilizing the Code Behind

We now have our basic solution setup. We have our UI project and can build our user control there. We have our WSPBuilder deployment project that will create our SharePoint install file. But, we aren’t ready to deploy just yet. We still need to tell our user control how to talk to its code behind. Because we are utilizing the GAC for our assemblies, we need to put a fully qualified domain in our ascx file. There are a couple of techniques for figuring out this fully qualified domain. What I like to do is deploy the project and go to the GAC to get the properties.

  1. Deploy the WSP, so that the assembly gets added to the GAC, so that we can pull out the assembly information.
    • Right-click on the DemoProject project
    • Click WSPBuilder – Build WSP (wait for it to finish)
    • Right-click on the DemoProject project
    • Click WSPBuilder – Deploy WSP (wait for it to finish)
    • Get the assembly information from the GAC
      • Usually found at C:\Windows\assembly
      • Right-click on the DemoProjectUI assembly and click properties
      • Note the public key token and version ( I suggest copying the public key token at this point because we are going to use this information in the next step).
  2. Add the assembly information to the ascx
    • Go to the DemoControl.ascx file in the DemoProjectUI project
    • Add an Assembly reference as the first line in this file. Below is an example. However, you cannot copy this example. Your assembly reference must have the correct information about your assembly (including your public key information).


<%@ Assembly Name="DemoProjectUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=772ab5f02712b819"%>

 Now we are ready to test our solution!

 

Deploy the Solution

Now that we are finished setting everything up, we can deploy the solution. This is real easy with the use of WSPBuilder as long as we are developing on a SharePoint server.

Note: Please make sure you have a web application and site collection setup in SharePoint before doing the following steps. When you deploy the WSP solution, it will deploy to all web applications on your development server. Thus, the web application must exist before you deploy.

  1. Right-click the DemoProject project
  2. Click WSPBuilder – Build WSP (wait for it to finish)
  3. Right-click on the DemoProject project
  4. Click WSPBuilder – Deploy WSP (wait for it to finish)
  5. Open up your SharePoint site.
  6. Note: if you go to the SharePoint site at this point and it says “Server Not Available”, then just keep refreshing the page until it shows up. The WSP install recycled the application pools because it needs to every time a dll in the GAC is added or modified. It sometimes takes a few seconds for this process to finish.

  7. Go to Site Actions – Site Settings
  8. Go to Site Collection Features
  9. Activate the DemoFeature
  10. Go back to the site
  11. Go to Site Actions – Edit Page
  12. Click “Add a Web Part” in one of your web zones
  13. Find your WebPart. It should be under “MyGroup” unless you changed the group name in your feature. The elements.xml file in the feature folder of the DemoProject lets you configure this information. I
  14. Add your Web Part to the page

At this point your Web Part is empty because we didn’t add any html or code to it. However, you solutions architecture is ready to go. Now you can go back to your User Control, do your development, deploy the solution and it will show up on your page. Let’s give it a try.

  1. Go to the DemoProjectUI project
  2. Open the DemoControl.ascx
  3. Put a label tag on the control
  4. <asp:Label runat="server"  ID="test" />

  5. Go to the code behind (i.e.: DemoControl.ascx.cs)
  6. In the Page_Load type the following
    protected void Page_Load(object sender, EventArgs e)
     {
          test.Text = "Hello World";
     }
  7. Right-click the DemoProject project
  8. Click WSPBuilder – Build WSP (wait for it to finish)
  9. Right-click on the DemoProject project
  10. Click WSPBuilder – Deploy WSP (wait for it to finish)
  11. Open your SharePoint site and see your Web Part. It should say “Hello World”.

Remember: if it says “Server Not Available”, then keep refreshing the page until the site shows up again.

Wow, that was a lot of setup just to create a user control that can render in a Web Part. But, the great thing is, you only have to do the setup once. As a SharePoint Architect, I set this up for my team and they can just concentrate on building the user controls. It runs very smooth!

Per popular demand, here is the demo solution from the walkthrough. I used Visual Studio 2008, WSPBuilder Extenstions 1.0.5 and .net 2.0 for this solution (I used 2.0 so it can work for a client of mine, it can be upgraded to 3.5 easily)
DemoProject

Categories: sharepoint, webpart, wspbuilder

Cleaning up your WebPart Gallery

March 21, 2009 16 comments

Deploying webparts in SharePoint can be difficult (when you are learning) because of the many ways to do it. You can manually add webparts to the WebPart gallery, you can add WebParts through features and you can even manually add them to certain file system folders.

If you have developed extensively in SharePoint, you probably choose the feature way to deploy WebParts. I am not going to go into this conversation right now, but it is well known that the best practice for building webparts is to deploy them with features. However, one thing that nobody really talks about is removing the WebPart from the WebPart Gallery. If a WebPart is placed in the WebPart gallery when the feature is activated, shouldn’t it be removed from the WebPart gallery when the feature is de-activated? In this article we are going to go over the basics of how WebParts are added to the WebPart gallery during activation of the feature and then we are going to show how you can clean up your gallery when the feature is deactivated.

Overview of WebParts and Features

The premise of WebParts is simple – you are adding an xml file to a special list in SharePoint. This special list is called the Web Part Gallery and the xml file you add is called a .webpart file or a .dwp file. The .webpart or .dwp file “describes” the properties of the WebPart and points to a code file where the .net code runs that builds the WebPart controls. If you want to visit this special WebPart Gallery you can go to your SharePoint site and put “/_catalogs/wp” after your url (i.e.: http://server:port/_catalogs/wp). If I have already confused you at this point, you probably want to start looking into some beginner guides to WebParts in SharePoint. I will do a small overview of WebParts in this article (that might be helpful for beginners), but the point of this article is to show some advanced techniques to how to clean up your WebPart Gallery.

When deploying webparts in SharePoint I always use a Feature to deploy the WebPart to the WebPart gallery. Then I always wrap these features up in a WSP solution in order to deploy a single solution to my SharePoint farm. This is best practice and is really easy once you have done it a couple of times. Personally, I choose to use WSPBuilder to build my WSP solutions (but the process is the same if you use Visual Studio Extensions or if you build your WSPs manually).

If you are using WSPBuilder you can just click Add – New Item – WSPBuilder – WebPart Feature. This will create a .webpart file, feature.xml, element.xml  and code file for you. And, I choose “Site” scope so that the WebPart is added to my Site Collection WebPart Gallery. If you don’t use WSPBuilder, the process is the same, you still have to build the .webpart file, feature.xml, element file and code file (WSPBuilder just does it for you).

So, let’s talk about what these files do:

1.       Feature.xml – this file defines “how” the feature will get deployed and the general settings for the feature. Technically, this is the only file required for a feature to work.

 

The important part of this file is the “Scope”. The scope defines where the feature will be deployed (Site, Web, Web Application, Farm). For webparts, we usually choose “Site” in order for the WebPart to be added to the WebPart Gallery. The other important part of this file is the “ElementManifest”. This tells the feature where the element file is located. The element file is the actually actionable file in a feature.

<?xml version=1.0 encoding=utf-8?>

<Feature  Id=7801227a-326a-4a65-8769-6e56ade76b66

          Title=Custom Webpart

          Description=This is my custom webpart Webpart

          Version=12.0.0.0

          Hidden=FALSE

          Scope=Site

          DefaultResourceFile=core

          xmlns=http://schemas.microsoft.com/sharepoint/ >

  <ElementManifests>

    <ElementManifest Location=elements.xml/>  

  </ElementManifests>

</Feature>

 

2.       Elements file – usually we call this file elements.xml, but you can call it whatever you want. You just need to make sure it is an xml file and you need to make sure that the name you call it is the same as the reference in the feature.xml.

 

This file tells SharePoint “what” to do with the feature. There are a lot of different things you can do with SharePoint Features. So, you have to do your research to understand the different xml combinations. In the case of the WebPart, we are using a “Module” action. Module actions move files to different galleries (or lists) in SharePoint. With webparts, we want to move the .webpart gallery to the WebPart gallery list. We do this by setting the “url” property to the “_catalogs/wp” path. That is the path for the WebPart gallery list. The other thing to notice in this file is the “Group” and “QuickAddGroups”. These define the grouping when you click “Add New Webpart” on your SharePoint site.

<?xml version=1.0 encoding=utf-8 ?>

<Elements xmlns=http://schemas.microsoft.com/sharepoint/>

  <Module Name=WebPartPopulation Url=_catalogs/wp RootWebOnly=TRUE>  

         <File Url=CustomWebpart.webpart Type=GhostableInLibrary>

                <Property Name=Group Value=RDA></Property>

                <Property Name=QuickAddGroups Value=RDA />

         </File>    

  </Module>

</Elements>

 

3.        .webpart file – this is the file that “describes” the properties of the WebPart. This could also be a .dwp file (it all depends on the version of the WebPart you are using). SharePoint supports .net webparts and SharePoint webparts. That is why you can have .dwp and .webpart files. So, any property you can set in your WebPart, can be set in this file. I am not going to show an example here because the set of properties is different for every WebPart.

 

This file also contains the assembly path to the code file. This is important, because if you ever change information about the Code file (name, version, etc…), then you need to change the path in your .webpart file.

 

4.       Code file – this is the file that actually runs the webpart code. These files inherit from one of two classes depending on the version of WebPart you are building (.net webpart or SharePoint webpart). For example, a .net framework webpart will inherit from Microsoft.SharePoint.WebPartPages.WebPart. Once again, I am not going to show an example of this, because it is different for every customization. The basis of this class is that you build out your html controls programmatically and add them to the Control collection.

 

Side Note: On a side note that is not really part of this article, don’t think the SharePoint webpart (i.e.: dwp) is better to use than the .net webpart (i.e.: .webpart) just because one is labeled a SharePoint webpart. If you don’t plan on using SharePoint webpart connections or part caching, I actually recommend using a .net webpart in SharePoint. Also, you might hear .dwp webparts referred to as Version 2 webparts and .webparts referred to as Version 3 webparts. This is because .dwp webparts were originally built just for SharePoint 2.0 and are backwards compatible. But, in SharePoint 3.0 we got the ability to use the asp.net webparts.

 

Cleaning up your WebPart Gallery

Ok, so you know how to deploy a WebPart to the WebPart Gallery. But, you notice that when you de-activate your Feature the WebPart is still hanging around in the Gallery. Some developers don’t really care about this. But, other than the obvious problem of keeping a clean Gallery for maintaince, there is another big issue. Let’s say you are using versioning for your assembly for the WebPart code. The reference for the assembly is located in the .webpart file. Thus, if you don’t remove the WebPart from the gallery before you make version changes, then your new assembly version will never make it to the gallery.

So, the easiest way to do this is to just go to the WebPart Gallery and remove it before you install and activate your updated feature. However, as most SharePoint developers know, you want to stay away from manual processes as much as possible. That makes your customizations almost impossible to maintain as your code base grows.

But, the answer to this problem is easy. Create a feature receiver to remove the webpart from the WebPart Gallery when the feature deactivates. I saw this done for the first time when I was reviewing the code for the Forms Based Authentication project in the Community Toolkit for SharePoint:  http://www.codeplex.com/CKS. I modified the code a little to meet my needs, but it is basically the same. Here is how you do it.

Create a Generic Class

This class is a generic class that will work for any WebPart feature receiver. The idea behind this class is to implement the Feature Deactivating event and remove the WebPart. Here is the code for this class:

     class GenericWebPartFeatureReceiver : SPFeatureReceiver

    {

 

        /// <summary>

        /// Remove the webpart from the webpart gallery. This is to fix a shortcoming of SharePoint

       ///       that it doesn’t remove

        /// the webpart when the feature gets deactivated (even though it adds it when the feature

       ///       gets activated).

        /// </summary>

        /// <param name=”properties”></param>

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

        {

            SPSite site = null;

            try

            {

                site = properties.Feature.Parent as SPSite;

                using (SPWeb web = site.RootWeb)

                {

                    SPList list = web.Lists[“Web Part Gallery”];

 

                    // go through the items in reverse

                    for (int i = list.ItemCount – 1; i >= 0; i–)

                    {

                        // format name to look like a feature name

                        string webpartName = list.Items[i].Name;

                        webpartName = webpartName.Substring(0, webpartName.IndexOf(‘.’));

 

                        // delete web parts that have been added

                        if (properties.Feature.Definition.DisplayName == webpartName)

                        {

                            list.Items[i].Delete();

                            break;

                        }

                    }

                }

            }         

            finally

            {

                if (site != null)

                    site.Dispose();

            }

        }

 

        public override void FeatureActivated(SPFeatureReceiverProperties properties){ }

 

        public override void FeatureInstalled(SPFeatureReceiverProperties properties){ }

 

        public override void FeatureUninstalling(SPFeatureReceiverProperties properties) { }

    }

 

Call Feature Receiver

After your Generic Feature Receiver is built, then you just need to call it from the feature.xml file for all your WebParts. Here is some sample code. It is the same as the feature.xml file I showed above, except for the fact that I placed a reference to a RecieverAssembly and a ReceiverClass.

<?xml version=1.0 encoding=utf-8?>

<Feature  Id=7801227a-326a-4a65-8769-6e56ade76b66

          Title=Custom Webpart

          Description=This is my custom webpart Webpart

          Version=12.0.0.0

          Hidden=FALSE

          Scope=Site

          DefaultResourceFile=core

          xmlns=http://schemas.microsoft.com/sharepoint/

   ReceiverAssembly=MySolution, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3cbe19ecf7353dae

   ReceiverClass=MySolution.GenericWebPartFeatureReceiver>

  <ElementManifests>

    <ElementManifest Location=elements.xml/>  

  </ElementManifests>

</Feature>

Note: You cannot just copy the xml above. The reference to the features ReceiverAssembly and ReceiverClass is specific to my implementation. When you deploy the assembly that contains the “GenericWebPartFeatureReceiver” to your BIN or GAC, then you need to get the information necessary to build out these two lines. Make sure the name of the Assembly and Namespaces match your implementation. And, make sure that the PublicKeyToken matches your public key for your assembly.

 

That’s it; you now have a Generic WebPart Feature Receiver that will remove the WebPart from the WebPart Gallery whenever your WebPart Feature is deactivated. This should help you keep your gallery clean and will help eliminate possible issues with assembly versioning.

Categories: sharepoint, webpart