Custom Actions to Calculate Document Size in Sharepoint 2010

In this scenario we are using the Custom Actions infrastructure of SharePoint 2010.

Scenario

Our aim is to provide user interface controls to display the Document Size at:

  • Site level Calculate Document Size for all Libraries
  • Library level Calculate Document Size for all Documents
  • Document level Calculate Document Size for selected Document

Solution

We can use Custom Actions to address the preceding scenario.

What is Custom Action?

Custom Actions are special purposed actions integrated into the SharePoint user interface. A custom action could be:

  • A menu item in the Site Actions menu
  • A button in the ribbon tool bar
  • A menu item in the context menu of list or library item

Please find some custom action samples (we are going to create these actions now):

custom-action-samples.jpg

Why do we need Custom Action?

In the development life cycle using SharePoint, we may encounter scenarios where the user prefers a special user control for a particular context. Some of the examples are:

  • Calculate Document Size in site level, library level, item level
  • Convert a particular document to PDF file
  • Display button to open Bing Search
  • Display the Audit History on site level, list level, item level

How to create Custom Actions?

We can create custom actions using Visual Studio 2010 and SharePoint project templates. The custom actions can be represented using XML Element files which are deployed as Features. The associated images can also be included in the project and get deployed automatically.

Custom Action Element

We use the XML tag CustomAction to specify custom action elements like menu item, button etc.

The custom action element defines an extension to the User Interface. A sample custom action element contains the following tags and values:

Custom-Action-Element.jpg

The following are the properties which we are interested in:

  • ID to provide a unique Identifier
  • Title to display the caption
  • Description to provide information on the UI element
  • ImageUrl to specify the relative image path
  • Sequence to specify the order of listing
  • Location to specify the container

Our Aim

Our aim is to create 3 custom actions as shown in the preceding image. For starting with create a new Visual Studio 2010 > Empty SharePoint project.

Empty-SharePoint-project.jpg

Now your Solution Explorer looks as in the following:

solution-explorer.jpg

Create Site Actions menu item

Now we can try creating the first Custom Action:

  • Site Document Size

On clicking this menu item an application page will be shown. This page should display the total size of documents summing up all libraries and the items inside it.

To create the custom action, right-click on the Solution Explorer and use the Add New Item and choose the Empty Element option.

Create-Site-Actions-menu-item.jpg

Enter the name as SiteActionsMenuItem. Replace the contents of the file with the following.

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

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

  <CustomAction Id="SiteActionsMenuItem"

    Description="Displays the Total Documents Size of the Site"

    Title="Site Document Size"

    GroupId="SiteActions"

    Location="Microsoft.SharePoint.StandardMenu"

    ImageUrl="/_layouts/images/CustomActionsExample/red.png"

    Sequence="10">

    <UrlAction Url="/_layouts/CustomActionsExample/DocSizeInfoPage.aspx?scope=web"/>

  </CustomAction>

</Elements>

The preceding Custom Action element specifies the following:

  1. Set the Location as Microsoft.SharePoint.StandardMenu. We need to specify the exact location for each custom action element. Here we are specifying the Standard Menu which is displayed on clicking the Site Actions link. You will see the GroupId set as SiteActions.

    Set-Location-Microsoft.SharePoint-StandardMenu.jpg
     
  2. Set the Title as Site Document Size. The title is used to specify the caption of the menu item.
  3. Set the ImageUrl, Sequence. These properties we can explore later.

Create Ribbon button

For creating the ribbon button you can add a new Empty Element. Set the name as LibraryRibbonButton.

Create-Ribbon-button.jpg

Replace the XML content with following:

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

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

  <CustomAction Id="LibraryRibbonButton" Location="CommandUI.Ribbon.ListView" RegistrationId="101" RegistrationType="List" Title="Library Document Size">

    <CommandUIExtension>

      <CommandUIDefinitions>

        <CommandUIDefinition Location="Ribbon.Documents.Share.Controls._children">

          <Button Id="DocSizeButton" Image32by32="/_layouts/images/CustomActionsExample/green.png" Command="DocSizeButton" Description="Displays the Total Documents Size of the Library" LabelText="Library Document Size" TemplateAlias="o2"

                  Sequence="93"

                  />

        </CommandUIDefinition>

      </CommandUIDefinitions>

      <CommandUIHandlers>

        <CommandUIHandler Command="DocSizeButton" CommandAction="/_layouts/CustomActionsExample/DocSizeInfoPage.aspx?scope=library&amp;ListId={ListId}" />

      </CommandUIHandlers>

    </CommandUIExtension>

  </CustomAction>

</Elements>

To make the preceding button visible only for Document Libraries we are using the Registration Id attribute as 101. 101 represent the template Id for Document types. The CommandAction is pointing to an application page with ListId as the parameter set through runtime.

Create Document menu item

Here we are going to add a new menu item to the document context menu. This menu is called Edit Control Block.

To do this create a new Empty Element and use the name DocumentMenuItem; see:

Create-Document-menu-item.jpg

Replace the XML content with the following:

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

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

  <CustomAction

    Id="DocumentMenuItem"

    RegistrationType="List"

    RegistrationId="101"

    Location="EditControlBlock"

    Sequence="301"

    Title="Document Size"

    ImageUrl="/_layouts/images/CustomActionsExample/blue.png">

    <UrlAction

      Url="/_layouts/CustomActionsExample/DocSizeInfoPage.aspx?scope=item&amp;ListId={ListId}&amp;Itemid={ItemId}"/>

  </CustomAction>

</Elements>

The Location specifies the container in which the custom action should occur. In this case it is EditControlBlock. The ImageUrl is set to a file which we will be adding later. The URL contains the application page which process the request.
You will see that {ListId} and {ItemId} are the parameters resolved in the Runtime. It should contain the List GUID and the Item Id when invoked.

Creating Application Page

Here we are using a common application page to process all the 3 requests. The requests are differentiated using the query parameters.

Create a new Application Page and name it DocSizeInfo.aspx; as in:

Creating-Application-Page.jpg

In the page load event invoke a RefreshData() method as follows:

protected void Page_Load(object sender, EventArgs e)

{

    if (!IsPostBack)

        RefreshData();

}

 

private void RefreshData()

{

    if (this.Request.QueryString["scope"] != null)

    {

        string scope = this.Request.QueryString["scope"];

 

        if (scope == "web")

        {

            CalcDocSizeForWeb();

        }

 

        else if (scope == "library")

        {

            CalcDocSizeForLibrary();

        }

 

        else if (scope == "item")

        {

            CalcDocSizeForItem();

        }

    }

}

Modify the Application Page HTML code to include a Label control.

<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">

    <h1>

        Document Size Information</h1>

    <asp:Label ID="InfoLabel" runat="server" Font-Size="Small" ForeColor="Blue">

    </asp:Label>

</asp:Content>

 

<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">

    Document Size Information

</asp:Content>

 

<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea"

    runat="server">

    Document Size Information

</asp:Content>

Please note that I have updated the Title in various places to Document Size Information. These updates are reflected in various places as shown below:

Document-Size-Information.jpg

Application Pages & Site Pages

In this example we have used Application Pages. The Application pages are residing in the File System and are not editable like the Site Pages.

Calculation Methods

Now we can try completing the calculation methods for document size.

Method 1

private void CalcDocSizeForWeb()
{

    long total = 0;

    int count = 0;

 

    foreach (SPList list in SPContext.Current.Web.Lists)

    {

        if (list is SPDocumentLibrary)

        {

            count += list.Items.Count;

 

            foreach (SPListItem item in list.Items)

            {

                total += item.File.Length;

            }

        }

    }

 

    InfoLabel.Text = "Number of Documents in Web: " + count.ToString() + "</br>Total Documents Size of Web: " + total.ToMBString();

}

Method 2

private void CalcDocSizeForLibrary()

{

    long total = 0;

    int count = 0;

 

    // ListId assigned by SharePoint runtime

    Guid listGuid = new Guid(this.Request.QueryString["ListId"]);

    SPList list = SPContext.Current.Web.Lists[listGuid];

 

    if (list != null)

    {

        if (list is SPDocumentLibrary)

        {

            count = list.Items.Count;

            foreach (SPListItem item in list.Items)

            {

                total += item.File.Length;

            }

        }

    }

 

    InfoLabel.Text = "Number of Documents in Library: " + count.ToString() + "</br>Total Documents Size of Library: " + total.ToMBString();

}

Method 3

private void CalcDocSizeForItem()

{

    // ListId assigned by SharePoint runtime

    Guid listGuid = new Guid(this.Request.QueryString["ListId"]);

    SPList list = SPContext.Current.Web.Lists[listGuid];

 

    if (list != null)

    {

        int itemId = Int32.Parse(this.Request.QueryString["ItemId"].ToString());

        SPListItem item = list.GetItemById(itemId);

        if (item != null)

        {

            InfoLabel.Text = "Documents Size: " + item.File.Length.ToMBString();

        }

    }

}


You will see that an Extension Method is used. Create a class for the extension method and place the following code in it:

namespace CustomActionsExample

{

    public static class ExtensionMethods

    {

        public static string ToMBString(this long size)

        {

            double result = (double)(((double)size / 1024) / 1000);

 

            return string.Format("{0:0.00}", result) + " MB";

        }

    }

}

The preceding extension method ToMBString converts the long value to Mega Bytes and returns a formatted string.

Now you are ready with the Methods; try building the project. Fix errors if there are any, and we can proceed to the next section to set Images for our custom actions. 

Setting Images for Custom Actions

Setting the Images are a little tricky. We need to map them to the correct folder. Copy the images from the source (or create 3 images of your own).

Right-click on the solution and use the Add > SharePoint "Images" mapped folder.

Setting-Images-for-Custom-Actions.jpg

This will create an Images folder with a sub folder inside it. Now add the images into it.

create-an-Images-folder.jpg

You need to place the image files inside this folder. The preceding folder is mapped to:

imagefiles-inside-this-folder.jpg

After deployment the preceding image files will be copied to the SharePoint Front End Server > 14 HIVE > Template > Images > CustomActionsExample folder; see:

CustomActionsExample-folder.jpg


You will see the same folder inside IIS (Internet Information Services)

Open IIS > Select SharePoint site > Expand _layouts folder

Expand-layouts -folder.jpg


The _layouts folder is a Virtual folder which is resolving into the 14 HIVE folder of SharePoint. You can try clicking the Explore button from the right side to see the Images folder.

Pointing the Images from Custom Actions

Inisde the custom action file we are pointing to the image as shown below:
 

Site Actions Menu Item > ImageUrl="/_layouts/images/CustomActionsExample/red.png"

Library Ribbon Button > Image32by32="/_layouts/images/CustomActionsExample/green.png"

Document Menu Item > ImageUrl="/_layouts/images/CustomActionsExample/blue.png"

Deployment

You can try deploying the solution. Right-click on the project and use the Deploy menu item.

Deployment.jpg

Seeing in Action

Now going back to your site, you will see the custom actions there. On clicking them you will see the result. Please note that the result changes according to the context.

Site Actions -> Custom Action

Site-Actions-Custom-Action.jpg

Library -> Ribbon -> Custom Action

Library-Ribbon-Custom-Action.jpg

Document -> Custom Action

Document -Custom-Action.jpg

Creating Test Documents

To verify the tests you can create 2 libraries in the Site. Each library can have a 2 one MB file inside it.

The results should be:

  • Site Document Size as 4 MB

  • Library Document Size as 2 MB

  • Document Size as 1 MB

Security Trimming Custom Actions

We can show or hide a custom action based on the user's permission level. The attribute rights can be used for this purpose. It takes comma-separated values and is treated as an AND operation.

For example:

<CustomAction Rights="Approve,Read">
</CustomAction>


You will see a user permission level by going to the Site Actions > Site Permissions page.

Security-Trimming-Custom-Actions.jpg

The setting of Permission Levels using Rights attribute is referred to as Security Trimming for Custom Actions.

References

http://tinyurl.com/sp2010-sactn
http://tinyurl.com/sp2010-caecm
http://tinyurl.com/sp2010-csact

Summary

In this scenario we have explorer the Custom Actions feature of SharePoint and using it in the Site level, Library level and Item level.

I hope this will give you good grounds for a more complex scenario in future.

The source code contains the example we have discussed.