Search

rafelo

Advancing Productivity and Operational Efficiency through Cloud Services and Apps

Category

CustomActions

Submitting Items to Lists from Custom Application Pages

This posting is in response to a comment I had on a previous posting; “Using the InputFormSection and InputFormControl to build Custom Application Pages that look like OOTB Pages”. One of the readers posted a comment asking how to go about using the submit button to post to a list. Needless to say, I didn’t feel that answering his question by replying to his comment would be the best response. So I’ve decided to post my response here, where its a little bit easier to elaborate on the subject.

Application pages can in fact be used to create list items, but there are a number of things to consider. The first and probably most important thing, is that application pages can be accessed from any site in your SharePoint farm. If the list the form is meant to write to is accessible globally this may not be much of a problem, but I’d have to question how that list was created and where it is stored. Application pages are part of what I consider to be a fairly modular development framework in SharePoint, and the scenario mentioned doesn’t sound very modular at all; a page that is deployed or accessible from every site, but the list it writes to is only deployed to one. What if the site containing the list is deleted? Or certain fields changed? The site administrator would likely be able to do either, but he/she wouldn’t be able to update the Application Page, which would likely break.

So how do I recommend using Application Pages to write to lists? There are many ways, most (if not all) of which would involve Features. The following is a sample approach:

1. Develop a site or site collection Feature that creates a list. Since we will be writing to this list from a Custom Application Page, I recommend that the list be hidden. This recommendation stems from the fact that we don’t want anybody accidentally deleting or modifying the list, which may impact the Application Page. Of course this would probably mean creating another page to view and/or edit list items; this could be a Content Page or Application Page.

2. Develop the Application Page that writes to the list created by the feature, including logic in it that checks if the feature is activated. If the logic determines that the feature is not activated, the page should display a message stating that the feature needs to be activated for the page to work.

3. Use Custom Actions and Custom Action Groups to create a link to the Application Page(s) from the “Site Settings”, or “Site Actions” menu.

I don’t mean to imply that an Application Page shouldn’t be used to save items to a single globally accessible list. But it requires even more consideration and planning than the scenario mentioned above. Actually, I’ve had to develop such pages; in one example the list resides in Central Administration and is created as part of a Feature scoped at the Farm level.

In another scenario, the list may not be hidden, or even created by the feature. The list may be manually created (to capture very specific criteria) by a site or farm administrator, in which case another Application Page may be used to capture the location of the list, and save it in the property bag of the site or site collection. The Application Page that writes to the list, fist looks at the property bag to determine its location, if the property has not been set, the page simply returns a friendly error.

Like the above mentioned scenarios, I’m sure there are hundreds more. The point is all of them require some thought. Unless strictly used to display information that you know is always available, an Application Page is rarely a solution as a whole. Take time to carefully plan and design your Application Pages, examine your solution from multiple angles making sure it doesn’t easily break. Remember, if you fail to plan you are planning to fail.

digg_url = “https://blog.rafelo.com/2009/05/submitting-items-to-lists-from-custom.html”;digg_title = “Submitting Items to Lists from Custom Application Pages”;digg_bgcolor = “#FFFFFF”;digg_skin = “compact”;digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

Custom SharePoint Application Pages and the Menu System

Last night in Houston’s SharePoint Users Group (HSPUG) I gave a short presentation / introduction on Custom Application Pages and how to add items to the SharePoint menu system. During the presentation we discussed what application pages are, when to use them, and demonstrated how to create a simple application page and add it to the site settings menu. All of the information is contained in the presentation which can be downloaded here.

digg_url = “https://blog.rafelo.com/2009/03/custom-sharepoint-application-pages-and.html”;digg_title = “Custom SharePoint Application Pages and the Menu System”;digg_bgcolor = “#FFFFFF”;digg_skin = “compact”;digg_url = undefined;digg_title = undefined;digg_bgcolor = undefined;digg_skin = undefined;

Apply Site Features Globally from Central Administration via a custom Application Page.

This posting covers a subset of a more general subject; Using Custom Application Pages to Extend the Capabilities of the Central Administration Site. Perhaps I will elaborate on the subject another time. For now, I will cover how to create a custom application page to activate or deactivate site-scoped (web) features globally.

Not much of an explanation is needed in regards to the purpose or practicality of this posting, as I’m sure most of you have been there, but for the sake of being thorough here is a brief description of a problem it helps address:

With just about every SharePoint project I’ve worked on, there has been some level of custom branding, usually involving new themes, master pages, and page layouts. Ultimately, and preferably, these get deployed via site-scoped (web) features. While these features can be automatically activated during the site provisioning process for new sites via Feature Stapling, there are often existing sites that we need to activate the feature on. Activation of these features can generally be narrowed down to specific types of sites, that is sites created from specific templates or site definitions, and generally target specific web applications. Out of the box, SharePoint only allows activation of site scoped features per site via the Site Settings page or stsadmin.exe. Global activation of such features targeting sites of a specific type/definition requires the creation of custom scripts or batch files. The solution; create a custom application page for the Central Administration site that allows farm administrators to activate site features across all sites in a given web application and of a specific site definition.

WARNING: Great care should be taken when applying Features globally. A poorly developed feature, or one that is targeted towards one type of site and applied to another, may render the site inoperable. Make sure you test your features thoroughly with each applicable site definition/template before activating features globally using this or any other technique.

The first step is to create a page that inherits from the GlobalAdminPageBase class, which is in the Microsoft.SharePoint.ApplicationPages.Administration assembly. This is the class that most of your Central Administration Pages should inherit from as it implements security and other related logic with the Central Administration site.


Additionally, you’ll need to include references to the following Namespaces and SharePoint Controls as they will be used throughout the page:

<%@ 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="wssawc"
Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”%>

The “Administration” namespace will be used, amongst other things, to obtain a reference to the SharePoint farm. The “Utilities” namespace will be used for security reasons when validating the page request. The “WebControls” namespace and additional “ascx” controls are used in rendering certain controls on the page.

Add the following Content Placeholders for the title, description, and main content area.


    Global Site Feature Management


    Global Site Feature Management


    Use this page to activate or deactivate site-scoped Features across all sites based on the selected site definition for the selected Web Application.


Next we will add an InputForm, ButtonSection, and a WebApplicationSelector controls to the page. This will allow the user to select the Web Application on wish to activate the feature. We use the same controls SharePoint uses on its Central Administration pages to provide a consistent look and feel. We will also add; a RadioButtonList control to display the features, a CheckBox to indicate if the action should be forced, a DropDownList to specify the action (activate or deactivate), and a CheckBoxList to display the Site Definitions. We will encapsulate all of this in an ASP Panel control to toggle the visibility of the form when the user clicks OK.


   
       

       

         

                   

               

               
                       
          

            <!– ****************************************
                 DISPLAY THE AVAILABLE FEATURES
                 USING THE InputFormSecton AND ASP:RadioButtonList CONTROLS –>
            <wssuc:InputFormSection runat="server"
                Title=”Site Feature”
                Description=”Select a site feature from the list” >
               
               

                   

               

           
               
           
           

            <!– *******************************************
                 DISPLAY A SECTION TO SPECIFY THE ACTION TO
                 PERFORM WITH THE FEATURE–>
            <wssuc:InputFormSection runat="server"
                Title=”Action”
                Description=”Specify if activating or deactivating the selected Feature.” >
               
               

                   

               

           
               
           
           

            <!– *******************************************
                 DISPLAY A SECTION TO SPECIFY IF THE FEATURE ACTIVATION
                 SHOULD BE FORCED –>
            <wssuc:InputFormSection runat="server"
                Title=”Force Feature Activation / Deactivation”
                Description=”Check here to force feature activation or deactivation.” >
               
               

                   

               

           
               
           
           

            <!– *******************************************
                 DISPLAY THE AVAILABLE SITE DEFINITIONS
                 USING THE InputFormSecton AND ASP:CheckBoxList CONTROLS –>
            <wssuc:InputFormSection runat="server"
                Title=”Site Definitions”
                Description=”Select the site definitions to which the
                                 feature will be applied” >
               
               

                   

               

           
               
           
                       

            <!– ****************************
                 OK AND CANCEL BUTTON SECTION –>
            <wssuc:ButtonSection runat="server" TopButtons="false" 
                BottomSpacing=”5″ ShowSectionLine=”true”>
               
                    <asp:Button UseSubmitBehavior="false" runat="server"
                       class=”ms-ButtonHeightWidth” OnClick=”BtnSubmit_Click”
                       Text=”” 
                       id=”BtnSubmitBottom”
                       accesskey=”” 
                       Enabled=”true”/>
               
           
           
         

       

       

  
            <!– *****************************************
                 USE SHAREPOINT THE ButtonSection CONTROL
                 TO DISPLAY THE “OK” AND “CANCEL” BUTTONS –>
            <wssuc:ButtonSection runat="server" TopButtons="true"
                BottomSpacing=”5″ ShowSectionLine=”false”>
               
                    <asp:Button UseSubmitBehavior="false" runat="server"
                        class=”ms-ButtonHeightWidth” OnClick=”BtnSubmit_Click”
                        Text=””
                        id=”btnSubmitTop”
                        accesskey=””
                        Enabled=”true”/>
               
           
           

            <!– **************************************
                 DISPLAY THE WEB APPLICATION SELECTOR
                 USING THE InputFormSecton AND WebApplicationSelector CONTROLS.
                 THE TITLE AND DESCRIPTION ARE SPECIFIED IN THE CORRESPONDING
                 ATTRIBUTES OF THE InputFormSection CONTROL, WHILE THE CONTROLS
                 THEMSELVES ARE PLACED INSIDE THE InputFormControl SECTION –>

            <wssuc:InputFormSection runat="server"
                Title=”Web Application”
                Description=”Select a Web Application” >
               
               

                    <SharePoint:WebApplicationSelector id="Selector" runat="server"
                            TypeLabelCssClass=”ms-listheaderlabel”
                            AllowAdministrationWebApplication=”true” />
                   
                    <!– Use a SharePoint Required Field Validator to ensure
                         that a web application is selected –>
                    <wssawc:InputFormRequiredFieldValidator
                            ID=”ReqValAppPoolPassword”
                            ControlToValidate=”rdSiteFeatures”
                            ErrorMessage=”You must select a Feature to activate”
                            Runat=”server” />
                    <asp:RadioButtonList ID="rdSiteFeatures" runat="server"
                            CssClass=”ms-listheaderlabel” EnableViewState=”true” />
                   
                    <asp:DropDownList ID="lstAction" runat="server"
                         EnableViewState=”true”>
                    
                    
                   
                   
                    <asp:CheckBox ID="chkForce" runat="server" 
                          EnableViewState=”true” Text=”Force
                          CssClass=”ms-listheaderlabel”  />
                   
                         
                       <asp:CheckBox ID="chkSelectAll" runat="server"
                            CssClass=”ms-listheaderlabel” 
                            Text=”Select All
Click here to select all site
                                    definitions.”
                            OnCheckedChanged=”chkSelectAll_Changed”
                            AutoPostBack=”true”  />

                        <asp:CheckBoxList ID="chkListSiteDefinitions" runat="server"
                            CssClass=”ms-listheaderlabel” AutoPostBack=”false” />
                   

   


   

Next we’ll need to populate the list of features. Check the PostBack state of the page, if false, get the available features from the FeatureDefinitions property of the SPFarm object. Iterate through each of the features and add a list item the the feature radio button list for each one that is scoped at the site(web) level.

//Get the regional localeID and Culture Information (Regional Settings)
//these will be used to retrieve the list of features and
//site definitions
int localeID = (int)SPContext.Current.RegionalSettings.LocaleId;
System.Globalization.CultureInfo cInfo = new System.Globalization.CultureInfo(localeID);

//Get a reference to the farm object we will use it
//to retrieve the feature definitions
SPFarm thisFarm = SPFarm.Local;
foreach (SPFeatureDefinition featureDefinition in thisFarm.FeatureDefinitions)
{
//Check that each feature is scoped at the web level and
//that it is not hidden before adding it to the list
if ((featureDefinition.Scope == SPFeatureScope.Web) && !(featureDefinition.Hidden))
{
ListItem siteFeatureItem = new ListItem("" + featureDefinition.GetTitle(cInfo) + "
"
+ featureDefinition.GetDescription(cInfo), featureDefinition.Id.ToString());
rdSiteFeatures.Items.Add(siteFeatureItem);
}
}

To populate the list of site definitions obtain a reference to the SPWebTemplateCollection of the current site definition via the GetWebTemplates method.

//Get the list of available Site Definitions / WebTemplates
foreach (SPWebTemplate webTemplate in SPContext.Current.Site.GetWebTemplates(SPContext.Current.RegionalSettings.LocaleId))
{
//Skip "GLOBAL", it has an ID of 0
if (webTemplate.ID != 0)
{
ListItem webTemplateItem = new ListItem("" + webTemplate.Title + " - ID: " + webTemplate.ID + " Name: " + webTemplate.Name + "
"
+ webTemplate.Description,webTemplate.Name);
chkListSiteDefinitions.Items.Add(webTemplateItem);
}
}

Finally, you’ll need to write the code that adds or removes the feature from each site. Use the CurrentItem of WebApplicationSelector to get a reference to the selected web application and the underlying site collections. Iterate through each site(web) checking the WebTemplate and Configuration properties of each against the list of selected site definitions. If the web template and configuration of the site are in the list of selected site definitions, call the Add method of SPWeb.Features to activate the feature and the Remove method to deactivate it based on the “action” the user selected.

//*************************************************************
// This method is called when the user clicks the "OK" button
// to activate the site feature.
protected void BtnSubmit_Click(object sender, EventArgs e)
{
//Prepare a string object to display the result
//of the feature activation for each site
string strMessages = "";

//Hide the form
inputForm.Visible = false;

//Get the GUID of the selected Feature to activate
Guid featureID = new Guid(rdSiteFeatures.SelectedValue);

try
{
//Iterate through each of the site collections
//in the selected web applications
foreach (SPSite site in Selector.CurrentItem.Sites)
{
//Disable the CatchAccessDeniedException
//of the site collection to avoid being redirected
//to the "Access Denied" page if access is denied.
site.CatchAccessDeniedException = false;

//Iterate through each site in the site collection
//and activate the selected feature
foreach (SPWeb web in site.AllWebs)
{
//Use a try statement to trap any errors that
//may occur during activation. Errors may occur
//due to feature dependencies, features that
//may already be active, permissions, etc.
//Consider Refactoring this code for better error
//handling
try
{
//Check if the site definition/configuration of the
//current site is included in the list of site definitions
//that the feature will be applied to.
ListItem item = chkListSiteDefinitions.Items.FindByValue(web.WebTemplate + "#" + web.Configuration.ToString());
if ((item != null) & (item.Selected))
{
//Activate the feature
if (lstAction.SelectedValue == "Activate")
{
web.Features.Add(featureID, chkForce.Checked);
strMessages += "
Feature Successfully Activated: "
+ web.Url + "
"
;
}
else
{
web.Features.Remove(featureID, chkForce.Checked);
strMessages += "
Feature Successfully Deactivated: "
+ web.Url + "
"
;
}

}
}
catch (Exception featureActivationError)
{
//if an error occurs during activation;
//capture the message to display it to the user
//after iterating through all the sites
strMessages += "
Feature Activation Error: "
+ web.Url + " ERROR:" + featureActivationError.Message + "
"
;
}
}
//Allow the site collection to continue handling
//access denied exceptions
site.CatchAccessDeniedException = true;
}
}
catch (Exception featureActivationError)
{
//if an error occurs write the error message to
//an error element
strMessages += featureActivationError.Message + "hhhhhh
"
;
}
}

Save the application page to the “ADMIN” folder in the 12 hive’s template directory, usually C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\ADMIN\. The complete code sample of the application page includes additional error handling and security logic to validate the users roles and page request.
With the application page created and saved to the ADMIN folder, it can be called and ran from the browser via the Central Administration site’s URL followed by “_admin/pagename.aspx” (i.e. http://centraladminsite/_admin/sitefeaturemanagement.aspx).
image
To add a link to the page from the Application Management Section of the Central Administration Web Site, we’ll need to create a farm feature. Create a new folder in the feature directory and name it “SiteFeatureAdministration”. Create a Feature.xml file in the newly created folder with the following code:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Id="4D4F4516-DDEC-4ea8-82F4-124D1B743984"
Title="Site Scoped Feature Management"
Hidden="FALSE"
Scope="Farm"
ActivateOnDefault="TRUE"
Version="12.0.0.0">

<ElementManifest Location="Elements.xml" />

This file tells SharePoint that the feature is scoped at the farm level and is to be activated by default. The elements.xml file referenced will contain the instructions of what the feature should do.
Next create an elements.xml file in the SiteFeatureAdministration folder with the following code:

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomActionGroup
Id="BDDBB947-CBC6-47f7-B57A-6C8BEB0E19D7"
Location="Microsoft.SharePoint.Administration.ApplicationManagement"
Title="Utilities"
Sequence="1000"/>
<CustomAction
Id="E57ECD33-91FD-4fc3-A4E8-E1B932178CB4"
GroupId="BDDBB947-CBC6-47f7-B57A-6C8BEB0E19D7"
Location="Microsoft.SharePoint.Administration.ApplicationManagement"
Sequence="20"
Title="Site Scoped Feature Management"
Description="">
<UrlAction Url="_admin/SiteFeatureManagement.aspx"/>

The “CustomActionGroup” element tells SharePoint to create a new section titled “Utilities” in the Application Management Section of the Central Administration site. The “CustomAction” element gives the link a name and adds it to the CustomActionGroup. The “UrlAction” element specifies the URL of the link.
Deploy the feature using your preferred method. Go to the Application Management page in the Central Administration, you should see the Utilities Section with a link to the Site Feature Management page.
image
When creating custom solutions for SharePoint its always a good idea to use Solution Packages. They provide ease of deployment and upgrading capabilities for your custom application pages, features, web parts, and custom site definitions to all of the servers in the farm. For more information on how to create, deploy, and work with solution packages, reference: http://msdn.microsoft.com/en-us/library/ms413687.aspx
You can download the full code samples from: http://www.rafelo.com/SiteFeatureManagmentCode.zip
You can download the solution package from:

http://www.rafelo.com/SiteFeatureManagementWSP.zip

SharePoint Site Enumeration Page: Get a list of all the sites in your SharePoint farm from Central Administration

Updated 8/25/2008: Updates to formatting in code blocks and removed recursive call that was causing duplication.

In my previous post “Iterating through SharePoint Web Applications, Site Collections, and Sites (Webs)” I provided a simple script to iterate through all web applications, sites and site collections. In this post, I will use much of that code to create an application page that returns a list of all the sites in the farm in XML. I will also create a feature to display a link to the application page from the Application Management section in Central Administration.

Click here to download the Solution Package (WSP)
Click here to download the source files

First I create a new file called EnumerateSites.aspx in c:\program files\common files\microsoft shared\web server extensions\12\template\admin. I will be accessing the page from the Central Administration site; I prefer to put such pages in the “admin” folder which is not accessible from regular SharePoint sites, as opposed to the “layouts” folder.

Since this file will be returning a list of all the sites in XML, we need to make sure the browser renders it properly. To do so we change the content type of the page to “application/xml”

Next,we create references to the necessary SharePoint and XML assemblies:

Since we are only displaying XML we wont need to reference a master page; so the rest is pretty much the same code from the previous post executing in the OnLoad event of the page. I use the XMLTextWriter class to build the XML document, and incorporate a number of “try catch” statements throughout the code to ensure that any errors that may be encountered are properly displayed in the XML. I’ve pasted all of the code for the application page (including the 2 previous excerpts) below:

    protected override void OnLoad(EventArgs e){
        // Get references to the farm and farm WebService object
        // the SPWebService object contains the SPWebApplications
        SPFarm thisFarm = SPFarm.Local;
        SPWebService service = thisFarm.Services.GetValue(“”);

        // Prepare the XML Writer
        XmlTextWriter xmlWriter = new XmlTextWriter(Response.OutputStream, Encoding.UTF8);

        //Start the XML Document
        xmlWriter.WriteStartDocument();

        //Create a Web Applications Element
        xmlWriter.WriteStartElement(“webapplications”);

        //**********************************************
        // NOTE: From here on everything is executed in
        //       “try catch” blocks. This is done to
        //       facilitate troubelshooting in case any
        //       errors surface. The error is caught and
        //       rendered in an xml “error” element.
        //       since the pages MIME type has been
        //       changed to XML, allowing the error
        //       to surface would render the xml document
        //       unreadable in IE.
        //***********************************************
        try
        {
            //Iterate through each web application
            foreach (SPWebApplication webApp in service.WebApplications)
            {
                //Create an XML Element for each web application
                //and include the name in the “name” attribute
                xmlWriter.WriteStartElement(“webapplication”);
                xmlWriter.WriteAttributeString(“name”, webApp.DisplayName);
                try
                {
                    //Create a sites element for the site collections
                    xmlWriter.WriteStartElement(“sites”);

                    //Iterate through each site collection
                    foreach (SPSite siteCollection in webApp.Sites)
                    {

                        //Create an XML Element for each site collection
                        //and include the url in the “url” attribute
                        xmlWriter.WriteStartElement(“site”);
                        xmlWriter.WriteAttributeString(“url”, siteCollection.Url);

                        //call the recursive method to get all the sites(webs)
                        GetWebs(siteCollection.AllWebs, xmlWriter);

                        //close the site element
                        xmlWriter.WriteEndElement();

                    }
                    //close the site collection element
                    xmlWriter.WriteEndElement();

                }
                catch (Exception siteError)
                {
                    //if an error occurs write the error message to
                    //an error element
                    xmlWriter.WriteElementString(“error”, siteError.Message);
                }
                //close the web application element
                xmlWriter.WriteEndElement();
            }
        }
        catch (Exception webAppError)
        {
            //if an error occurs write the error message to
            //an error element
            xmlWriter.WriteElementString(“error”, webAppError.Message);
        }

        // close the web applications element and document
        xmlWriter.WriteEndElement();
        xmlWriter.WriteEndDocument();
        xmlWriter.Close();
    }
    //*************************************************
    // This method is used recursively to display all
    // webs in a site collection. The Web Collection
    // from the site collection is passed in along with
    // the XML writer to continue writing the XML Document
    // where the calling method left off
    public void GetWebs(SPWebCollection allWebs, XmlTextWriter xmlWriter)
    {
        //create a webs element to contain all sites(webs)
        xmlWriter.WriteStartElement(“webs”);
        try
            {
            //iterate through each site(web)
            foreach (SPWeb web in allWebs)
            {
                if (web.Permissions.DoesUserHavePermissions(SPRights.FullMask));
                {
                    //Create an XML Element for each site(web)
                    //and include attributes for the url, title,
                    //and template information
                    xmlWriter.WriteStartElement(“web”);
                    xmlWriter.WriteAttributeString(“url”,web.Url);
                    xmlWriter.WriteAttributeString(“title”, web.Title);
                    xmlWriter.WriteAttributeString(“WebTemplateID”, web.WebTemplateId.ToString());
                    xmlWriter.WriteAttributeString(“WebTemplateName”, web.WebTemplate);

                    //close the site(web) element
                    xmlWriter.WriteEndElement();
                }
            }       
            }
        catch (Exception webError)
            {
                //if an error occurs write the error message to
                //an error element   
                xmlWriter.WriteElementString(“error”, webError.Message);
            }
        //close the webs element   
        xmlWriter.WriteEndElement();     
    }

With the page saved in the admin folder, you could just access it via the URL of your central administration site:
(i.e. http://centraladminsite/_admin/enumeratesites.aspx)

I personally prefer to build a Custom Action which adds a link to the page from Application Management in Central Administration. The steps to do this are relatively simple:

  1. Create a new folder for the feature and call it “EnumerateSites”. We will use the feature to add a link to the page from Central Administration.
  2. Open the folder and create a new empty file naming it FEATURE.xml
  3. Open the file and paste the following XML, replacing NEWGUID with a newly generated GUID.


    <Feature xmlns="
    http://schemas.microsoft.com/sharepoint/
    Id=”NEWGUID”
    Title=”Enumerate Sites in XML”
    Hidden=”FALSE”
    Scope=”Farm”
    ActivateOnDefault=”TRUE”
    Version=”12.0.0.0″>

  4. Save and close the file.
  5. Create another file, this time naming it “Elements.xml” and paste the following XML, replacing GROUPGUID and ACTIONGUID with newly generated GUIDs (use the same GUID in both occurrences of GROUPGUID):


    <Elements xmlns="http://schemas.microsoft.com/sharepoint/“>
    <CustomActionGroup Id="GROUPGUID
    Location=”Microsoft.SharePoint.Administration.ApplicationManagement
    Title=”Application Management Utilities” Sequence=”1010” />
    <CustomAction
    Id=”ACTIONGUID
    GroupId=”GROUPGUID
    Location=”Microsoft.SharePoint.Administration.ApplicationManagement
    Sequence=”10” Title=”Enumerate Sites in XML” Description=”“>

    <UrlAction Url="_admin/enumeratesites.aspx” />

  6. Save and close the file
  7. Package the EnumerateSites.aspx page and feature using your method of choice. Don’t have one? Checkout WSPBuilder by Carsten Keutmann
  8. Deploy your solution and you are done!

You can access the page from the Application Management section of Central Administration, you’ll see a new section titled Application Management Utilities with a link to Enumerate Sites in XML.

image

Click on the link to get an XML page enumerating all of the sites in your farm, it should look similar to the following

image

Click here to download the Solution Package (WSP)
Click here to download the source files

How to Add Menu Items to SharePoint with Features, Custom Actions, and Custom Action Groups

In my previous post, “Hidden SharePoint Lists, Fields, and Other Advanced List Settings”, I demonstrated how we can develop a custom application page to easily expose and modify list and field settings. But once the custom application page has been created, how do we expose it to our users? Ideally we would create links to our Application Pages by adding new menu item entries to the SharePoint Site Settings and Site Actions menus. Fortunately, SharePoint allows us to do just that via Features and the CustomActionGroup and CustomAction elements.

The CustomAction element refers to the actual link or menu item.

image

The CustomActionGroup element, as Microsoft puts it, “contains the core definition for a grouping of custom actions.” Such as when you see a group of links or menu items grouped together in the “Operations” and “Application Management” pages of the Central Administration site.

image

What about the “Site Actions”, list or library “Actions” and “Settings” menus? These, like most other SharePoint menus, can also be configured via CustomActions. 

image image

The following steps demonstrate how we can use features and CustomActions to add a new menu item to the Site Settings page.

Creating the Feature

  1. Browse to the file system Feature folder located in “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\”
  2. Create a new folder for your feature. In my case I will call it “AdvancedListSettings” as I will use the feature to add a link to the Custom Application Page I created in my previous post; Hidden SharePoint Lists, Fields, and other Advanced List Settings
  3. Open the folder and create a new empty file naming it FEATURE.xml

    image

  4. Open the file and paste the following XML, replacing NEWGUID with a newly generated GUID. 

    <Feature xmlns="http://schemas.microsoft.com/sharepoint/”
      Id=”NEWGUID”
      Title=”Advanced List Settings Menu”
      Description=”This Feature adds a new menu item to the Site Settings page”
      Hidden=”FALSE”
      Scope=”Web”
      Version=”1.0.0.0″>
       
           
       

    I like to call this file the “feature definition file”. It contains the general settings of our feature such as; title, description, feature scope, and whether or not the feature is hidden; but it doesn’t necessarily contain any of the “meat” or instructions for the feature, we’ll put those in our Elements Manifest file which we’ll create next.

     

  5. Save and close the file
  6. Create another file and name it “CustomMenuItem.xml”, we’ve specified this as an Elements Manifest file in our feature definition.
  7. Open the file and paste the following XML

    <Elements
        xmlns=”http://schemas.microsoft.com/sharepoint/”>
        <CustomAction
            Id=”AdvancedListSettings”
            GroupId=”SiteAdministration”
            Location=”Microsoft.SharePoint.SiteSettings”
            RequireSiteAdministrator=”TRUE”
            Sequence=”1″
            Title=”Advanced List Settings”>
            <UrlAction
                Url=”_layouts/AdvancedListSettings.aspx” />
       

     

  8. Looking at out CustomAction element the attributes break down as follows:
    • ID – The ID specifies a unique identifier for the custom action, keep in mind that it must be unique, you may want to use a GUID.
    • GroupID – Identifies an action group that contains the action, for example, "SiteManagement". If contained within a custom action group, the value of the GroupId attribute must equal the group ID of the CustomActionGroup element.
    • Location – Specifies the location of this custom action. In this example we specified “Microsoft.SharePoint.SiteSettings", which tells SharePoint to create the custom action in the Site Settings Page.

      Note: Click here for the default list of Locations and ID’s

    • Sequence – Indicates what position the custom action should be placed in regards to other custom actions that may be in the same group.
    • Title – Gives it the text to display
  9. Save and close the file.
  10. Open the command prompt and execute the following command to install the feature:

    stsadm -o installfeature -file AdvancedListSettings

    Where “AdvancedListSettings” is the name of the new feature folder in “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\FEATURES\”

  11. Browse to the Site Settings page of one of the SharePoint sites in Internet Explorer and click on the “Site Features” link

     image

  12. Click the “Activate”  button next to the new feature

    image

  13. Go back to the Site Settings page to see your new menu item / custom action.

    image 

To create a new section in the site settings page and have the link appear in that new section, the elements manifest file (i.e. CustomMenuItem.xml in this example) would have too look as follows:

<Elements
    xmlns=”http://schemas.microsoft.com/sharepoint/”>
    <CustomActionGroup
        Id=”SiteListandLibrarySettings”
        Location=”Microsoft.SharePoint.SiteSettings”
        Title=”Site List and Library Settings”
        Sequence=”1″ />
    <CustomAction
            Id=”AdvancedListSettings”
            GroupId=”SiteListandLibrarySettings”
            Location=”Microsoft.SharePoint.SiteSettings”
            RequireSiteAdministrator=”TRUE”
            Sequence=”1″
            Title=”Advanced List Settings”>
            <UrlAction
                Url=”_layouts/AdvancedListSettings.aspx” />
   

Notice the new CustomActionGroup element, it uses many of the same attributes of the CustomAction element. The GroupID attribute of the CustomAction element now references the ID of newly created CustomActionGroup.

For additional information see Custom Action Definitions in the SharePoint General Reference section of the MSDN:
http://msdn.microsoft.com/en-us/library/ms465980.aspx

Technorati Tags: SharePoint, WSS, MOSS, FEATURES

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: