Features in Office SharePoint Server 2007: Overview
Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 are known
for their template framework which uses the XML files for customizations. By
this exiting and enhanced template framework customizations to the Microsoft
Office SharePoint Server 2007 / WSS 3.0 site are so much easy. Among this template
framework Features are one of the major contributor. Features allow the facility
to test, deploy and activate custom functionality inside WSS or Office SharePoint
Server 2007. This also provides the facility to make the functionality available
across the server farm as well. The functionalities may be a custom workflow,
creating new custom content types, or adding new custom action to list tool bar
or to add new page link to Site Actions menu. For example, you can package a
custom list definition and deploy to any number of site as Feature, complete
with its metadata in the schema or you can add a custom developed workflow to
the site packaged in feature and later activating the feature. You can package
the Feature as a SharePoint solution like .wsp and provide it to the system administrator
to install and deploy it.
Other benefit of using the Features is that, it helps out to reduce the complexity
of site definition (ONET.xml) files. ONET.xml files are the main site definition
files which are used to create new sites in SharePoint. These files can be modified
to meet the requirements. These files include the definition and default implementation
information about lists and document libraries being included in new provisioned
site, its navigation pattern, the features to be activated when the site is provisioned.
With the use of features, the ONET.xml file shrinks because features can contain
the information in separate file and referenced in the ONET.xml file. So this
reduces the complexity of the ONET.xml file and makes it more manageable.
In this article we will create a custom Feature, which will add a new action item
to the Actions menu of the Custom List and provides the functionality to redirect
the user to the custom page where he will be provided with the functionality
to move the list item attachments to a new document library. Before diving in
to the custom feature development and implementation, we will discuss the basics
of Features.
Internal Structure of a Feature
Feature is stored on the SharePoint Server at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES directory. As you can see in the below image each and every feature has its own
directory under the FEATURES directory. Each individual directory for feature
at least contains two files: one is features.xml which guides the SharePoint
for where to find the XML data and code that defines the Feature. The feature.xml
file contains the Feature element that has the information about location of
assemblies, files, dependencies or properties that support the Feature. Generally,
the feature.xml file points to the element XML file that contains the definition
of components and types that make the Feature. This file is generally stored
with name as elements.xml. Most of the feature definitions have these two files
and with name feature.xml and elements.xml. So to avoid lost of information of
the other feature and to avoid overwriting of the information each feature has
its own directory.

The Feature.xml file
The metadata associated with Feature are stored in the feature.xml file. The structure
of the feature.xml file used for our example is as follows:
<?xml version="1.0" encoding="utf-8"?>
<Feature Id="f5702592-4b51-4759-9eda-a4e6b12e566c"
Title="Copy or Move Attachments to Document Library"
Description="Provides the facility to move or copy attachments from custom
list items to document library."
Version="12.0.0.0"
Hidden="FALSE"
Scope="Web"
DefaultResourceFile="core"
ReceiverAssembly="CopyMoveAttachmentsFeature, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=79f97b311651d47e"
ReceiverClass="CopyMoveAttachmentsFeature.CopyMoveAttachmentsFeature"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>
And the following is the sort but useful information of metadata items which are contained in the <Feature> element in the Feature.xml file.
The ID attribute is used to uniquely identify the Feature among other features on the server.
The Title is displayed on the page for Site Features in the Site Settings section for a SharePoint
site. The Description provides details about its functionality and displayed below the Title on Site Features
Page. Generally in SharePoint provisioned site this description value is retrieved
from the resource file. This helps in localization of the site. The Version is the current implemenation or development version of the feature. Generally 12.0.0.0
is used to match the current version of other SharePonit assemblies and SharePoint
provided feature. But you can provide it of yours as well. Now, the Scope defines the context in which the Feature can be activated or deactivated. The scope
value Web allows the Feature to activated or deactivated within the context of the site. The
scope value Site allows the Feature to be activated or deactivated at the Site Collection context.
The feature with scope of Site is displayed on the Site Collection Features page.
There are also two other scope value: WebApplication and Farm. The Hidden indicates the features visibility on the Site Features page. If it is set to TRUE,
the the feature will be displayed on the Site Features page, otherwise not. This
is the Boolean value property and the allowed values are TRUE or FALSE. The optional
but useful DefaultResourceFile attribute indicates the resource file used for the feature. The ImageUrl contains
the relatiev path of the image which will be displayed next to the Feature Title
on the Site Features page. The <ElementManifests> node houses the <ElementManifest> elements or nodes, where each <ElementManifest> element has the location, mostly relative, of the manifest file generally named
elements.xml.
The following lines are from the elements.xml manifest file which is used for our
example. The manifest file contains details of the different components or actions
that make the real Feature. For example, the manifest to add a custom action
item to the Actions Menu of a custom list and the UrlAction element for where
to redirect when that custom action item is clicked.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="CopyMoveAttachmentsToDocumentLibrary"
GroupId="ActionsMenu"
Location="Microsoft.SharePoint.StandardMenu"
Sequence="100"
Title="Copy or move attachments to document library"
Description="Copy or move attachments of list items to document library"
ImageUrl="_layotus/images/CREATE.GIF">
<UrlAction Url="_layouts/CopyMoveAttachmentsToDocLib.aspx?ListId={ListId}"></UrlAction>
</CustomAction>
<Module Path="PageTemplate" Url="_layouts">
<File Url="CopyMoveAttachmentsToDocLib.aspx" />
</Module>
</Elements>
One more functionality provided by features is the EventHandlers which provide the
developer to write code against the WSS/MOSS object model for applying changes
to the site. For example, when the Feature is activated, the site title can be
changed or a new list can be created. Generally, Features provide following main
four Events:
1. FeatureActivated: This event is triggered when the feature is activated on the site or site collection.
2. FeatureDeactivating: This event is triggered when the feature is being deactiated from the site.
3. FeatureInstalled: This event is triggered when the feature is successfully installed on the server.
4. FeatureUninstalling: This event is triggered when the feature is being uninstalled from the server.
To use this events in your feature development, you have to create a class which
inherit from SPFeatureReceiver base class, and the have to override the above said four method of the base class.
In the overridden method you can wrap your logic of changes to be applied to
the site. The following code snippet shows you the structure of the CopyMoveAttachmentsFeature
class which is inherited from SPFeatureReceiver.
public class CopyMoveAttachmentsFeature : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb _web = SPContext.Current.Web;
_web.Properties["OldTitle"] = _web.Title;
_web.Title = _web.Title + " with Copy or move attachments feature activated";
_web.Update();
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWeb _web = SPContext.Current.Web;
_web.Title = _web.Properties["OldTitle"];
_web.Update();
}
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
//To do code
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
//To do code
}
}
The above code also shows you the example how to change the web site title when the
feature is activated and also to restore the old title when the feature is deactivated.
Install the Feature
When the development of the feature is completed you need to install and activate the
feature. You can install and activate the feature by two ways. You have to perform
the below steps to install and activate the feature on the server. Here the directory
name is the one which is going to be developed later. You need to change it as
per your feature directory name.
1. Coyp the folder which contains the feature files, i.e. feature.xml and elements.xml
to C:\PROGRAM FILES\COMMON FILES\MICROSOFT SHARED\WEB SERVER EXTENSIONS\12\TEMPLATE\FEATURES directory.
2. Open the Command prompt.
3. Execute “stsadm –o installfeature –filename CopyMoveAttachmentsFeature\feature.xml –force” to install the feature on the server.
4. Execute “stsadm –o activatefeature –name CopyMoveAttachmentsFeature –url http://localhost:2000
–force” to activate the feature for the particular site as shown in command.
Now we will see the real world example as a case study.
Case Study: Creating Custom Feature to move or copy attachments to document library
Requirements: We need the functionality which provide the user to move or copy the attachment
documents which are attached while create list item. So, we need a menu item
in Actions menu of the list which will redirect the user to the page where he
can select the attachment documents from the list. He can also have the option
to select the existing document library or to craete a new document library.
Also, he will be provided the option to move all the attachment documents or
to move just selected documents to the new or existing document library. For
our purpose we are using Custom Lists. So, we need this functionality on ever
custom lists which are created in the site. Also, this functionlity will be activated
and deactivated when needed and limited to the single site as well.
Development scenario: To fullfill the requirements the best way is to create a feature which provide
the functionality, that when it is activated on the particular site, a new menu
item is being added to the Actions menu of the each instances of the Custom List
type. So, we perform the following steps to reach to our goal.
1. Create a class library project in Visual Studio 2005 or Visual Studio 2008.
2. Add reference of Microsoft.SharePoint.dll to the project.
3. Next, create the folder heirarchy like 12\TEMPLATE\FEATURES in the project. See
below image.
4. Now, create a new folder under FEATURES folder in project and name it CopyMoveAttachmentsFeature.
This is the folder which is copied to the Windows SharePoint Services FEATURES
directory when installing the feature.
5. Now in the CopyMoveAttachmentsFeature folder, add a new xml file and name it feature.xml.
6. Now, in the feature.xml file, write the following text to define the Feature element.
7. As per the above xml file content, you can see that the Feature element has several
attributes like ID – a GUID to uniquely identify the feature on the server, Title
– valid descriptive name of the feature which will be displayed on Site Features
page, Version – the version of the feature, generally, 12.0.0.0, Scope – here
“Web” which defines the context where the feature be activated or deactivated.
Other attributes ReceiverAssembly and ReceiverClass are optional and required
if you want to attach the Event handler for the feature to you feature. The ElementManifest
node of ElementManifests element points the location of the elements.xml file
which will be creaed in the next point.
8. Now create one new xml file in the same CopyMoveAttachmentsFeature folder and
name it elements.xml. If you provide different name then you have to change the
Location attribute value of the ElementMainfes element in the feature.xml file
to avoid any error.
9. Now, open the elements.xml file, if not an write the below text to craete Elements.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="CopyMoveAttachmentsToDocumentLibrary"
GroupId="ActionsMenu"
Location="Microsoft.SharePoint.StandardMenu"
Sequence="100"
Title="Copy or move attachments to document library"
Description="Copy or move attachments of list items to document library"
ImageUrl="_layotus/images/CREATE.GIF">
<UrlAction Url="_layouts/CopyMoveAttachmentsToDocLib.aspx?ListId={ListId}"></UrlAction>
</CustomAction>
<Module Path="PageTemplate" Url="_layouts">
<File Url="CopyMoveAttachmentsToDocLib.aspx" />
</Module>
</Elements>
10. As seen in the above text, the CustomAction element in Elements node, has Id
– an id of custom action, GroupId – the id of the group where to display the
CustomAction item, here we have provided “ActionsMenu”, Title – a valid descriptive
name of the action to be displaed in the Actions menu item, ImageUrl – relative
url of the image for the menu item. The UrlAction element of CustomAction provide
the relative path to the page where the user is being redirected when he clicks
the item in Actions menu.
11. Now our feature is ready to install and to be activated. But our main functionality
resided in the page CopyMoveAttachmentsToDocLib.aspx.
12. To create a custom page, first create a new folder under the TEMPLATE directory.
13. In that folder add a new aspx page with name CopyMoveAttachmentsToDocLib.aspx.
14. Add the below lines to the page which you just created. Please download the working
sample to see the full code of the example.
<%@ Assembly Name="CopyMoveAttachmentsFeature, Version=1.0.0.0, Culture=neutral,PublicKeyToken=79f97b311651d47e"
%>
<%@ Page Language="C#" MasterPageFile="~/_layouts/application.master"
EnableViewState="true" AutoEventWireup="true" Inherits="CopyMoveAttachmentsFeature.CopyMoveAttachmentsToDocLibForm"
%>
<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
%>
<%@ Register TagPrefix="Utilities" Namespace="Microsoft.SharePoint.Utilities"
Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
%>
<%@ Register TagPrefix="jatin" TagName="ucCopyMoveAttachments"
Src="~/_controltemplates/CopyMoveAttachmentsToDocLib/ucCopyMoveAttachmentsToDocLib.ascx"
%>
<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
<%= PageTitle %>
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"
runat="server">
<%= PageTitleInArea %>
</asp:Content>
<asp:Content ID="PageDescription" ContentPlaceHolderID="PlaceHolderPageDescription"
runat="server">
<%= PageDescription %>
</asp:Content>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
<jatin:ucCopyMoveAttachments ID="control1" runat="server"></jatin:ucCopyMoveAttachments>
</asp:Content>
15. Now, as shown in the above code line, the page uses the user control named ucCopyMoveAttachments.
This is the main user control that performs all the required actions.
16. So, using the user control in the custom page, is one of the ways to develope
the custom pages for SharePoint. Others are using Web Part, using inline coding
for custom page and using custom controls.
17. Now add a new folder in the project named CONTROLTEMPLATES under the TEMPLATE
folder. And in that add a new user control and name is "ucCopyMoveAttachmentsToDocLib.ascx". See the below image.

18. We will not see each and every line of the code. But you can download the full
working source code of this sample.
19. The method GetListItemAttachments() given below get the all attachments attached with each item of the list. The list
information is based on the query string parameter ListId. This ListId value
is passed from out custom menu item added in the Actions Menu of the list.
private void GetListItemAttachments()
{
SPQuery query = new SPQuery();
query.Query = "<OrderBy><FieldRef Name='Title' /></OrderBy>";
SPListItemCollection items = _list.GetItems(query);
foreach (SPListItem item in items)
{
SPAttachmentCollection attachments = item.Attachments;
for (int i = 0; i < attachments.Count; i++)
{
DataRow dr = Attachments.NewRow();
dr["ItemID"] = item.ID;
dr["ItemTitle"] = item.Title;
dr["AttachmentName"] = attachments[i];
dr["AttachmentUrl"] = string.Format("{0}{1}", attachments.UrlPrefix, attachments[i]);
Attachments.Rows.Add(dr);
}
}
gvItems.DataSource = Attachments;
gvItems.DataBind();
}
20. Below image will give the idea about how the custom page works for moving
or copying the attachments.

21. As shown in the above image, the user is provided with the options to move
or copy the attachments, also that he wants to move / copy all the attachments
or only selected. The user is also presended with the list of existing document
libraries in the current site to selected for moving or copying the attachment.
If the user want to created the new document library the he can select the option
for that and provide the name of the document library as well. For out example,
by default a new document library is being created with the provided name.
22. When the user clicks "Ok" button, based on the selection of this options,
the remaing operations are performed. The method MoveSelectedAttachments() ,as
shown below, moves or copies the selected attachments to the existing or new
document library. If the user has selected "Move" action, then selected
attachment(s) are deleted from the item's attachments collection.
private void MoveSelectedAttachments(string newDocLibName, string newDocUrl)
{
bool found = false;
foreach (GridViewRow row in gvItems.Rows)
{
CheckBox cb = row.FindControl("chkSelect") as CheckBox;
if (!cb.Checked)
continue;
found = true;
string fileName = ((Label)row.FindControl("lblAttachmentName")).Text;
string filePath = string.Format("{0}/{1}/{2}", _web.Url.Trim('/'), newDocLibName, fileName);
SPFile attachment = _web.GetFile(((Label)row.FindControl("lblAttachmentUrl")).Text);
_web.Files.Add(filePath, attachment.OpenBinary(), true);
if (rblAction.SelectedItem.Text.Equals("Move"))
{
SPListItem item = _list.GetItemById(Convert.ToInt32(((Label)row.FindControl("lblItemID")).Text));
item.Attachments.RecycleNow(fileName);
}
}
if (found)
{
lblResult.Text = string.Format("Selected attachment(s) are {0} to {1}",
rblAction.SelectedItem.Text.Equals("Copy") ? "Copied" : "Moved", string.Format("<a href='{0}'>{1}</a>", newDocUrl, newDocLibName));
}
else
lblResult.Text = "Please select attachment(s) to " + rblAction.SelectedItem.Text.ToLower();
}
23. The method MoveAllAttachments(), as shown below, moves or copies all the attachments
to the existing or new document library. In this method also, if the user has
selected "Move" action, then all the attachments for all the items
are deleted and sent to the recycle bin.
private void MoveAllAttachments(string newDocLibName, string newDocUrl)
{
foreach (DataRow dr in Attachments.Rows)
{
string fileName = dr["AttachmentName"].ToString();
string filePath = string.Format("{0}/{1}/{2}", _web.Url.Trim('/'), newDocLibName, fileName);
SPFile attachment = _web.GetFile(dr["AttachmentUrl"].ToString());
_web.Files.Add(filePath, attachment.OpenBinary(), true);
if (rblAction.SelectedItem.Text.Equals("Move"))
{
SPListItem item = _list.GetItemById(Convert.ToInt32(dr["ItemID"]));
item.Attachments.RecycleNow(fileName);
}
}
lblResult.Text = string.Format("All attachment(s) are {0} to {1}",
rblAction.SelectedItem.Text.Equals("Copy") ? "Copied" : "Moved", string.Format("<a href='{0}'>{1}</a>", newDocUrl, newDocLibName));
}
Installing the working feature using .bat file
Before going to the process of creating and executing the batch file, we must need
to sign our assembly with strong name. So, to do that, right click the project
name in the Solution explorer and click properties. On the properties page click
"Signing" tab, see below image. Check the "Sign the assembly"
and from the "Choose a strong name key file:" drop down, select <New...>.
This will open a new dialog to create Strong Name Key. There provide proper name
for the file, clear the "Protect my key file with a password" check
box and click Ok. Now, save the project and build.

Using the batch command file, you can execute multiple command at the cost of single
command. So, add a new batch file named "install.bat" at the project
level. See, the above image of the project structure for more information. In
that file write the following lines.
@SET STSADM="c:\program files\common files\microsoft shared\web server extensions\12\bin\stsadm"
@SET GACUTIL="c:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe"
Echo Installing HelloWorld.dll in GAC
%GACUTIL% -if bin\debug\CopyMoveAttachmentsFeature.dll
Echo Copying files to TEMPLATE directory
xcopy /e /y 12\TEMPLATE\* "c:\program files\common files\microsoft shared\web server extensions\12\Template"
Echo uninstalling feature if installed previously
%STSADM% -o uninstallfeature -name CopyMoveAttachmentsFeature -force
Echo Installing feature
%STSADM% -o installfeature -filename CopyMoveAttachmentsFeature\feature.xml -force
IISRESET
Now, execute the batch file. This will first adds, the assembly / dll, CopyMoveAttachmentsFeature.dll,
to the GAC. the copies all the content of the TEMPLATE folder to the TEMPLATE
directory of 12 hive, of SharePoint. Then it tries to uninstall the feature,
if it is installed previously using "STSADM -o uninstallfeature -name CopyMoveAttachmentsFeature
-force" command. Then using the "STSADM -o installfeature -filename CopyMoveAttachmentsFeature\feature.xml
-force" command it installs the feature to the SharePoint Server. This is
the actual operation that informs the SharePoint Server about our custom feature.
And at the last IISRESET is performed, to take chagnes in the effect.
Experience the Feature working in real SharePoint Site
To see actual working of the feature, Navigate to your SharePoint site or create
a new site.
Now, go to Site Settings page. There click on "Site Features". This will
take you to the Site Features page, as shown below.

There, locate the Feature with name "Copy or Move Attachments to Document Library"
or which you provided, and Activate it.
Now, if there is any existing custom list, then go to there or create a new custom
list. There click the Action menu from the list's tool bar, There you can see,
that our custom action with name "Copy or Move Attachments to Document Library".

For testing, add couple of item to the list with the attachments.
After that by clicking "Copy or Move Attachments to Document Library" on
the Actions menu, you will be redirected to our custom page. And there you can
test the functionality. Rest is leaved to the reader.........
I hope you have enjoyed the article and learned about features, custom pages and
working with document library and lists as well as working with attachments of
the list. You can download the fully working code from below link.
Source code for CopyMoveAttachmentsFeature.