Saturday, February 5, 2011

Archiving with MOSS Records Center

Introduction

In this article, I’ll try to show how you can use MOSS Team Site and MOSS Records Center Site for archiving your documents.
Basically active documents which are kept in Team Site (TS) will be archived to Records Center (RC). Here actually ‘Archiving’ means not copying but moving document to RC.
Also, in order to keep the link to the archived documents, a back link will be left in the document library from where the document was archived.


Scenario

Sites: There are 2 MOSS sites, Team Site and Records Center.
Users: There are 2 users: Joe User, Rachel Record.
Joe User can only access TS and has no access to RC.
Rachel Record is Records Manager and she can access both to TS and RC.
Username: joe
Password: joeuser
Username: rachel
Password: rachel
Desired action: Archiving TS documents to RC.
  

Sample Archiving

Before I start explaining how to implement archiving solution for MOSS, firstly I want to show what we’ll get at the end.
1.      Joe uploads a contract document to Contracts folder in TS.
Upload Document 
Image_1 
2.      Then, he archives this document to RC using ‘Archive’ edit menu item.
 Archive Document
Image_2
3.      Once the document has been archived, its name is changed to {DocumentName}_Archived and link to archive destination is also provided as seen below.
Document Archived 
Image_3 
4.      Since Joe User doesn’t have access to RC, he can’t see the archived document anymore. If he tries to click the archive link, he’ll get an access denied error.
 Access Denied for Joe
 Image_4
5.      However, Rachel can access the archived document since she’s Records Manager.
 Rachel can access to RC
 Image_5
6.      Now, let’s see RC folder where this document has been archived to.
Destination Folder
Image_6

Documents are being routed to Archive folder. Within that folder, separate folders are being created based on archived documents content types.
Since we just archived a document of ‘Contract’ content type, the destination folder structure is Archive à Contract à Date (Month-Year).

Requirements

There are 2 main requirements for this archiving functionality.
Firstly, we need an ECB item, Archive, in our edit menu.
ECB Item 
 Image_7
Secondly, we need a custom router feature in order to route archived documents to corresponding folders in RC. Also this custom router will be responsible from sending the back link of the archived document to TS.
Archiving Site Feature 
Image_8

Archive ECB Item

In order to have ‘Archive’ ECB Item in Edit menu, we need basically 2 elements.
First thing we need is Archive feature definition. This feature will be deployed under TEMPLATE\FEATURES\.
Feature folder needs to have feature definition file, feature.xml, and also elements.xml file which will have the custom action URL in it.

 

Feature.xml

 
            Id=”{576182EA-1351-4932-A6BD-56687E78984A}” 
            Title=”Archive ECB Item” 
            Description=”This feature enables Archiving feature for MOSS – developed by Oguz Demirel” 
            Scope=”Web” 
            Hidden=”FALSE” 
            ImageUrl=”menuprofile.gif” 
            xmlns=”http://schemas.microsoft.com/sharepoint/”>

           
                       
           

Elements.xml

  
    Id=”UserInterfaceLightUp.ECBItemToolbar”
    RegistrationType=”List”
    RegistrationId=”101″
    Location=”EditControlBlock”
    Sequence=”106″
    Title=”Archive”>
   
 

Reading ListId and ItemId for an Application Page

Here at this point, we have our Archive ECB item and now we need to implement the code that will execute when this item is clicked.
In the above UrlAction tag, Url attribute determines which page will be executed for Archive ECB Item.
When you write a CustomAction entity to create a menu item for an entry control block to redirect the user to a custom application, you should use dynamic tokens to configure the Url attribute that Windows SharePoint Services replaces at run time. In particular, you should assign the value of the Url attribute within the UrlAction element in the following form.
Url=”~site/_layouts/ArchiveListItem.aspx?ItemId={ItemId}&ListId={ListId}”
However, we need to pass additional information to this page, since we are interested in the item we are working on. In order to point this item to this page, we use query string parameters ItemId and ListId.
Archive ListItem 
 Image_9
Please see this MSDN article for more details: http://msdn.microsoft.com/en-us/library/bb418733.aspx

 

Custom Application Page

Now let us examine the code that is required to extract the list item ID and the GUID for either the containing list or the document library from the query string.
The following code uses a standard programming technique that involves the QueryString property of the ASP.NET Request object to accomplish this.
        SPWeb oWeb = SPContext.Current.Web;
        // Get ItemId and ListId from querystring
        SPList oList = oWeb.Lists[new Guid(Context.Request["ListId"])];
        SPListItem oItem = oList.GetItemById(int.Parse(Context.Request["ItemId"]));

        // Get Item URL
        SPFile file = oWeb.GetFile(oItem.Url);

        String recordSeries = “Records Archive”;
        String additonalInformation;
        OfficialFileResult returnValue;

        // Send item to Records Center
        returnValue = file.SendToOfficialFile(recordSeries, out additonalInformation);

        // Item sent successfully
        // Apply custom logic
        if (returnValue == OfficialFileResult.Success)
        {
            // Delete this item
            oWeb.AllowUnsafeUpdates = true;
            oItem.Delete();

            // Redirect back to library
            Context.Response.Redirect(oWeb.Url + “/” + oList.RootFolder.Url);
        }
In the above code, our aim is as follows:
1.      Get the item based on ListId and ItemId.
2.      Send Item to RC using SPFile.SendToOfficialFile method.
At this point, Custom Router Feature (will be explained in next section) starts its execution and routes submitted document to the directory which is determined based on its content type. After doing so, a dummy back link is created in TS source folder. Doing so, we don’t lose the link to the archived document.
3.      Once item is sent successfully and routed to its corresponding folder, delete this item.
4.      Finally, redirect back to document library.
In case you have trouble to figure out which directives to add to the page, here they are.
<%@ Page language=”C#”     %>
<%@ 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=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages” Assembly=”Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %> 
<%@ Assembly Name=”Microsoft.SharePoint.ApplicationPages” %>
<%@ Import Namespace=”Microsoft.SharePoint” %>

Custom Router Feature

The other main part in implementing archiving functionality for MOSS is the Custom Router Feature.
Mainly this feature will be responsible from:
1.      Routing incoming document to the corresponding destination folders. The destination folder is determined based on content type.
2.      Creating a back link in Team Site source folder for the archived document.
Record Routing
For the implementation, you can use the sample files and procedure described in this article:
Creating a custom router is relatively straight forward in MOSS. All you need to do is create a class which implements the IRouter interface and register the router with the records center.
The IRouter interface has only one method called OnSubmitFile.
You can copy the sample project from this link:

Creating Back Link

Here at this point, I want to concentrate on the part we create a back link in TS for the archived document.
Idea is very simple. All we need to do is just to create a dummy file and assign destination link to its title.
// Create Link in source folder
            String SiteUrl = “http://delorean:55555/sites/teamsite/“;

            using (SPSite mySite = new SPSite(SiteUrl))
            {
                using (SPWeb myWeb = mySite.OpenWeb())
                {
                    string strTargetFile = Path.GetFileNameWithoutExtension(sourceUrl);
                    strTargetFile = strTargetFile.Replace(” “, string.Empty) + “_Archived”;

                    string linkToRC = “http://delorean:55555/sites/rm/” + oFile.Url;
                    string wikiContent = String.Empty;
                   
                    string folderName = Path.GetDirectoryName(sourceUrl.Replace(SiteUrl, string.Empty));
                    SPFileCollection files = myWeb.Folders[folderName].Files;

                    SPFile spf = files.Add(files.Folder.Url + “/” + strTargetFile, SPTemplateFileType.StandardPage);
                    SPListItem newItem = spf.Item;
                    newItem["Title"] = linkToRC;
                    newItem.Update();
                }
            }
The above code also appends ‘_Archived’ to the original file name, so that TS user knows that this file has been archived.
Since, the back link will be stored in title property, you might need to modify document library’s view and enable title property in that view.
If there are space characters in original file’s name, those will be removed for link to be clickable in Title property.
Back Link to Team Site 

Conclusion

In this article I tried to show how to modify MOSS Records Center and Team Site in order to get a basic archiving functionality.
This can be extended in many ways. For instance, dummy file can be improved and locked, back link can be provided in a new property. IMPs can be applied to archived documents … etc.

No comments:

Post a Comment