Installing Office Web Apps for SharePoint 2010 Step by Step

We continue our journey in configuring our SharePoint 2010 farm and today we shift our focus to one of the many exciting new inclusions in SharePoint 2010, “Office Web Apps”. Office Web Apps was first introduced with SharePoint 2010 and soon after released to the public integrating with Windows Live SkyDrive (currently in beta form) to compete with Google Docs. Office Web Apps is an online version of Microsoft Word, Excel, PowerPoint and OneNote allowing users to access these applications and their respective documents from any Internet connection and most notable web browsers. For those running SharePoint 2010, you can deploy Office Web Apps onto your SharePoint farm providing your users with the same functionality as the online version of Office Web Apps. Deploying Office Web Apps on your SharePoint farms will add the following service applications;

  • Word Viewing Service Application
  • Excel Calculation Service
  • PowerPoint Service Application

Today I will be extending my step by step SharePoint 2010 configuration articles and by the end of this post you will be able to open and edit Office documents from within your web browser without the requirement of having Microsoft Office installed locally. This is a huge productivity gain for those that might be accessing their SharePoint sites from an Airport Kiosk where Office is usually not available.

Installation

You will need to download Office Web Apps from the Microsoft Download Site. This download is available to Volume licensing customers or those with TechNet and MSDN subscriptions. Let’s begin by launching the setup.exe and entering our product key;

Installing Office Web Apps for SharePoint 2010 Step by Step

Accept the licensing terms.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Continue

Choose a file location for installation. Ensure you select a drive with adequate free space for your Data partition which stores the Office Web Apps search index files.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Install Now

Upon successful installation, you will be greeted with the “Run Configuration Wizard” window. We will immediately run the configuration wizard by leaving the checkbox ticked and clicking close. You can also achieve the same by running PSConfig. Both methods will register the Office Web Apps services.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Close to Run the SharePoint Configuration Wizard.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Next and click Yes to acknowledging the restart of the IIS, SharePoint Administration and Timer Services.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Next

Installing Office Web Apps for SharePoint 2010 Step by Step

Click Finish to acknowledge the successful configuration.

Installing Office Web Apps for SharePoint 2010 Step by Step

You will then receive the below Central Administration screen regarding configuring your SharePoint farm. Because we have been configuring each service application one by one as needed (best practice) we will click cancel and proceed to activate the Office Web Apps services individually.

Installing Office Web Apps for SharePoint 2010 Step by Step

Provisioning the Office Web Apps Service Applications

Let’s begin by starting the relevant Office Web Apps services located under Central Administration / System Settings / Manage services on server.

Scroll down until you locate all of the Office Web Apps specific services, namely Excel Calculation Services, PowerPoint Service and Word Viewing Service. Click Start for each respective service.

Installing Office Web Apps for SharePoint 2010 Step by Step

Let’s now navigate to Central Administration / Application Management / Manage service applications.

Click on New / Word View Service

Enter the following details to complete the creation of the Word Viewing Service Application. Ensure that you select “SharePoint Web Services System” from the Use existing application pool option.

Installing Office Web Apps for SharePoint 2010 Step by Step

Click OK

Your service application will then proceed with the creation process and will be listed with our previously provisioned service applications.

Installing Office Web Apps for SharePoint 2010 Step by Step

You can now further provision the “Excel Services Application” and “PowerPoint Service Application” in the same manner following the above steps. Please note that there isn’t a separate service application for OneNote.

Activating Office Web Apps

Depending on where you want the feature activated, you will venture to your Site Collection(s) and activate each one individually or you can utilise PowerShell to activate multiple site collections at once within a single script.

From within your SharePoint Site, click on Site Actions / Site Settings.

Under Site Collection Administration, click on Site Collection Features.

Navigate down the page until you find Office Web Apps and click on Activate.

Installing Office Web Apps for SharePoint 2010 Step by Step

You should now be able to open a Microsoft Word document from a document library on your SharePoint site and it should launch within the browser by default.

To ensure the best experience possible for your end users, you should install Silverlight. The below warning will be will be displayed if Silverlight is not detected.

Installing Office Web Apps for SharePoint 2010 Step by Step

By default, your browser will open the document in view mode and it’s only until you click on Edit in Browser that you will receive the Office Web Apps editing toolbar.

Installing Office Web Apps for SharePoint 2010 Step by Step

Things to note

  • Silverlight installed on client computers will enhance the end user experience for Word and PowerPoint Web App and improve speed with regards to page loading. There’s no benefits for Excel or OneNote Web App.
  • Installing Office Web Apps will change the default behaviour when opening documents from open in client application to open in browser.
  • There is no service application for OneNote.
  • Service Application Proxies are utilised to provide location information of a service instance within a farm.
  • You can load balance and install Office Web Apps on multiple servers to optimise performance.
  • When installing on a SharePoint farm (i.e not a standalone installation), you will need to install Office Web Apps on every server.
  • Current list of supported browsers include Internet Explorer 7 and 8, Firefox 3.X, Google Chrome and Safari 4.X.

Resources

Office Web Apps (Installed on SharePoint 2010 Products) – TechNet http://technet.microsoft.com/en-us/library/ee855124.aspx

Configuring Enterprise Search in SharePoint 2010 step by step

We all have to agree that search plays an integral part of any successful SharePoint deployment and is an area that Microsoft continues to invest in with each new release of SharePoint. Microsoft went as far as acquiring FAST 2 years ago which it now offers as a separate add-on to SharePoint for those willing to invest in high end enterprise search. In addition to FAST, SharePoint 2010 search comes in a number of flavors each offering their own feature set and capabilities which I have duplicated at the end of this article as an Appendix for convenience.

Today we will introduce SharePoint Server 2010 Search and eventually work our way up to Microsoft’s latest and greatest FAST Search Server in a near future article. Before we deep dive into the step by step guide I will begin by listing some of the new features that you will come to expect from SharePoint Server 2010 Search. These are as follows;

  • Boolean query syntax has finally been introduced. These include AND, OR and NOT operators in your search queries.
  • Suggestions whilst typing and after running search queries, a feature that we have come to love with major search engines such as Google and Bing.
  • Integrating SharePoint enterprise search with Windows 7, allowing end users to utilise the Windows 7 search box to locate SharePoint 2010 content.
  • Results display has been refined to provide filters for search results such as document type, categories and managed properties.
  • View in Browser capabilities, allows end users to view documents within their own browser utilising Office Web Apps and not having to rely on launching the necessary Microsoft Office Application, or even the need of having it installed on their local machine. This is handy when browsing your SharePoint site via Kiosks and Internet Cafes that may not be running the Microsoft Office Suite.
  • Last but not least, there have been a number of improvements to People Search, including phonetic name and nickname matching, and improved relevance and self search.

Now that we have a taste for what’s to come, let’s begin our configuration.

SharePoint Server Search is a service application which we have come to learn about over the past few articles that it is independent of other services and is no longer tied to the Shared Services Provider (SSP) that was introduced in SharePoint 2007.

SharePoint 2010 search architecture is made up of the Crawler, Indexing Engine, Query Engine and the User Interface and Query Object Model. We now have greater flexibility and expandability with our search design in 2010 and can setup not only multiple Query Servers but can now scale out our Index server and add multiple instances.

Below is a logical overview of the components that will make up our SharePoint 2010 search configuration.

Configuring Enterprise Search in SharePoint 2010 step by step

Configuring the Service Application

As always we begin our journey in Central Administration / Application Management / Manage Service Applications.

Click New / Search Service Application.

Name: Enter a name for your Service Application.

FAST Service Application: Select “None” (we will leave the configuration of FAST for a future article)

Configuring Enterprise Search in SharePoint 2010 step by step

Search Service Account: Click on Register new managed account and ensure your domain account has already been provisioned in Active Directory. I have created a separate search account; e.g. DOMAIN\sp_search

Configuring Enterprise Search in SharePoint 2010 step by step

Application Pool for Search Admin Web Service: Create a new application pool for your search admin web service application.

Configuring Enterprise Search in SharePoint 2010 step by step

Application Pool for Search Query and Site Settings Web Service: Create a new application pool for your search query web service application.

Configuring Enterprise Search in SharePoint 2010 step by step

Click Create

The search service application will begin its configuration process.

Configuring Enterprise Search in SharePoint 2010 step by step

You will eventually be presented with confirmation that the search service application was created successfully.

If we now navigate back to Application Management / Manage Service Applications, you will notice that 2 additional services have been added to our list. These are;

  1. Search Service Application (Typical Search Administration page which is similar to that in SharePoint 2007. From here we can create content crawl rules, reset indexes, setup content sources etc).
  2. WSS_UsageApplication (This is a new service in SharePoint 2010 that specifically handles our Usage and Health Data Collection Service Application. This service application handles web analytics such as usage, search query usage, rating usage etc More on this in a future article).

Let’s now launch the Search Administration page by clicking on our Search Service Application.

Configuring Enterprise Search in SharePoint 2010 step by step

Our Default content access account should be set to the account that we had specified at the time of provisioning the Search Service Application; i.e. DOMAIN\sp_search

Confirming Permissions

There are a couple of areas to note that we should check to ensure that our Default content access acount (sp_search) has been provided with the appropriate access permissions. Let’s first begin by checking our User Profile Service Application by Navigating to Service Applications / User Profiles. Just highlight the User Profiles and select Administrators from the ribbon.

Configuring Enterprise Search in SharePoint 2010 step by step

Our newly provisioned sp_search account should have “Retrieve People Data for Search Crawlers” selected as a permission.

Configuring Enterprise Search in SharePoint 2010 step by step

We will also confirm that our sp_search account has the necessary “Read” permissions against the Web Applications being crawled.

Navigate to Central Administration / Application Management / Manage Web Applications. Again, highlight the Web Application in question and from the ribbon select User Policy.

Configuring Enterprise Search in SharePoint 2010 step by step

Ensure that the Search Crawling Account is set to the sp_search domain account.

Configuring Enterprise Search in SharePoint 2010 step by step

Content Sources

Let’s venture into our content sources listed in the Quick Launch navigation bar under Crawling.

As was the case with SharePoint 2007, our Local SharePoint sites will be detected by default, albeit without a crawl schedule.

Configuring Enterprise Search in SharePoint 2010 step by step

Check to see that your Start Addresses are located within your content source via editing the content source from the drop down menu. These includes all SharePoint Web Applications and the sps3 “User Profiles” address.

Configuring Enterprise Search in SharePoint 2010 step by step

You can easily create your crawl schedule by clicking on Local SharePoint sites and scrolling down to Crawl Schedules.

Configuring Enterprise Search in SharePoint 2010 step by step

Let’s initiate a Full Crawl by clicking on Start all Crawls from the Manage Content Sources page.

Once your crawl has completed, you should confirm that there were no errors encountered during the initial crawl. Usually any errors noted are most likely due to incorrect permission assignments.

Creating a “Basic Search Center” Site

If you haven’t done so already, from your top level site, click on Site Actions / New Site.

Select “Basic Search Center”

Configuring Enterprise Search in SharePoint 2010 step by step

Enter a Name and URL and click on Create.

This will provision the Search Center similar to the below.

Configuring Enterprise Search in SharePoint 2010 step by step

Creating an “Enterprise Search Center” Site

Let’s also create an Enterprise Search Center for comparison. The key difference here is that we are provided with two tabs for searching, one for Sites and the other for People. The “Enterprise Search Center” will be the search site of choice for most organizations running SharePoint Server.

From Central Administration / Application Management / Site Collections, click on Create site collections. Ensure you are creating the Site Collection below the relevant Web Application.

Enter your Title, Description etc and select the Enterprise Tab under Template selection. Select the Enterprise Search Center, specify your site collection administrators and click OK.

Configuring Enterprise Search in SharePoint 2010 step by step

This will provision the Enterprise Search Center similar to the below.

Configuring Enterprise Search in SharePoint 2010 step by step

As we have already completed an initial Full crawl earlier, I can now test my new search centers by performing a couple of searches.

Searching Content

Configuring Enterprise Search in SharePoint 2010 step by step

Searching People

Configuring Enterprise Search in SharePoint 2010 step by step

Now I ran into an issue when trying to search for content located in My Sites. The crawl log displayed the following warning;

“This item and all items under it will not be crawled because the owner has set the NoCrawl flag to prevent it from being searchable”

In order to fix this issue (and this is true for any Site Collection), is to navigate to your My Site host and click on Site Actions / Site Settings.

Click on “Search and offline availability” under Site Administration, and ensure that you have Indexing Site Content, Allow this site to appear in search results? set to “Yes”.

Configuring Enterprise Search in SharePoint 2010 step by step

After enabling the indexing of My Sites, I was able to successfully perform My Site Content searches and the warning disappeared from the Crawl Log.

That’s all that is to it in setting up a search center in its most basic form. From here you can expand your service applications over multiple servers providing you with redundancy, scalability and increased performance . Until next time, happy searching

References:

TechNet :: Getting Started with Enterprise Search in SharePoint 2010 Products

How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)

1.) Create a Managed Property from a Crawled Property

Managed Properties are great! FAST pulls and indexes Managed Properties for multitudes of things, including boosting and search scopes. They are core to your FAST User Experience and an essential part to configuration

When a FAST crawl runs, it will pick up site column data and create a crawled property for that site column (given that there is data associated with this site column). In order to query this site column directly in search, first we will created a managed property from this site column.

Generally, most out of the box SharePoint site columns are already mapped to a managed property in FAST. However, custom site columns usually are not, and these are the ones that we need to target to map to a managed property.

First we will need to make sure that our site column was indeed picked up as a crawled property. In this example, we are using a custom site column called “country”. Make sure you have already executed a crawl and that there is data associated with this site column.

From PowerShell: Executing the command Get-FASTSearchMetadataCrawledProperty in the FAST PowerShell will return the entire list of crawled properties in FAST. This can get quite verbose in your PowerShell window, so if you would like to print that out to a text file for easier viewing, execute the following simple script in PowerShell:

   1:  Get-FASTSearchMetadataCrawledProperty | Out-File “C:\crawledproperty.txt”


If you know the name of your column, you can shorten the search by adding –Name.



   1:  Get-FASTSearchMetadataCrawledProperty -Name 'country'




Basic Troubleshooting: If you get an error that the cmdlet Get-FASTSearchMetadataCrawledProperty doesn’t exist, make sure that you are FAST’s PowerShell. If the error continues, add the FAST PowerShell snap-in by typing in the command: Add-PSSnapin Microsoft.FASTSearch.Powershell



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)



From the UI: In Central Admin, go to Service Applications –> <Your FAST Query SSA> –> FAST Search Administration –> Crawled Property Categories –> SharePoint. From here you can do a search to find your site column. In general, SharePoint site columns will be preceded with “ows_”, so our returned crawled property looks like this: ows_country().



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)





Creating Managed Property



Now that we know our site column exists as a crawled property, we need to create or find a managed property to map it to. In this case, we will simply create a new managed property.



From PowerShell:



Here, ‘-type 1’ is the type of information that we are storing in the property. Make sure you make it Queryable!




# Create New Managed Property
$nmp = New-FASTSearchMetadataManagedProperty –Name “country” –type 1 –description “Managed Property for country content type”
Set-FASTSearchMetadataManagedProperty –Name “country” –Queryable $true –StemmingEnabled
$false –RefinementEnabled $false
$cp = Get-FASTSearchMetadataCrawledProperty –name 'ows_country'
New-FASTSearchMetadataCrawledPropertyMapping –Managedproperty $nmp –crawledproperty $cp







m the UI: Go to Service Applications –> <Your FAST Query SSA> –> FAST Search Administration –> Managed Properties. Click Add Managed Property. We will create a new managed property called “country”, type in a short description, and then click “Add Mapping”. This will bring up a menu where you will search for your crawled property. Once you find the managed property, add it and click ok. Finally, we will check “Query property”, which will allow you to use this managed property in search queries. There are also the options to make this managed property a sort property and deep refiner.



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)



Either way we choose to create our managed property, we should be able to see it in our list of managed property names.



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)



Crawl it!



In order to use this new managed property in search and see filtered results, we must do a content crawl. Service Applications –> <Your FAST Connector> and execute an incremental or full crawl of your content source.



After your crawl, you can query directly on this column by using it as a scope in your search. For example “country:USA”.



How To Map a Crawled Property to Managed Properties By PowerShell (FAST for SharePoint 2010)

Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007 – Part 2

SharePoint Products and Technologies provide an extensible framework for implementing and extending policy features for information management policy. The existing policy features in Microsoft Office SharePoint Server 2007 provide functionality for document bar codes, document labels, auditing, and expiration.

In Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007 – Part 1, you learn how to extend the existing expiration policy feature in Office SharePoint Server 2007 by creating a policy resource and implementing a custom expiration formula. In this Microsoft Office Visual How To, you find out how to implement logic within the expiration formula to expire records based on information that is contained in a secondary list. The expiration is calculated based on a shared event among multiple records. When a project is defined as complete, all the related project records start their expiration based on the project completion date. This enables the project records to expire as a batch, and multiple expirations can be triggered based on a single action, such as project completion.

The scenario for this Visual How To involves retrieving information from a secondary list for use in the expiration formula. Specifically, the goal is to create a formula that causes project records to expire two years after the project completion date. The issue is that the project completion date is stored in a secondary list that contains information about the project and is not on the project records. Instead, the project records contain a metadata field that defines the project to which they are related. To correctly compute the expiration date, a custom formula is created to identify the project for the record, retrieve the project completion date from the project information list, and compute the correct expiration date.

Several items are set up in the records center for this example.

  • First, in a records center site, a custom list named Policy Info is created, and a DateTime field named Completion Date is added. The list is populated with the items shown in Table 1.
    Table 1. Policy Info list items

    Title Completion Date

    Project A12/31/2007

    Project B12/31/2004

  • Next, a library named Project Records is created, and a lookup field named Project is added. The Project field is set to retrieve information from the Policy Info list in the Title field.
  • Two documents are uploaded to the library. The Project field of one document is set to Project A, and the Project field of the second document is set to Project B.
  • Finally, the custom expiration formula from the example in Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007 – Part 1 is implemented, and an expiration policy that uses this formula is created on the Project Records library.

The logic for the custom expiration calculation is implemented in the ComputeExpireDate method of the CustomExpirationFormula class. In the method, the first step is to ensure that the record that is being processed contains a Project field that contains a value. If it does, you continue to retrieve the project completion date. To obtain this date, you determine which list the Project lookup field is using as a lookup list. You obtain a string representation of the GUID that identifies the lookup list by casting the Project field as an SPFieldLookup object and retrieving the LookupList property. You convert this string to a GUID and use it to retrieve the lookup list (the Project Info list).

The next step is to retrieve the corresponding item from the lookup list that contains the completion date for the project. The value of the Project lookup field contains the ID of the corresponding item in the Project Info list. You use this ID value to retrieve the corresponding item by passing it into the GetItemById method on the lookup list.

Finally, you retrieve the value of the Completion Date from the corresponding list item, and add two years. The method returns this value.

public Nullable<DateTime> ComputeExpireDate(SPListItem item, System.Xml.XmlNode parametersData)
{
DateTime? expirationDate = null;

// Make sure the project field has a value.
if (item["Project"] != null && (!string.IsNullOrEmpty(item["Project"].ToString())))
{

// Get the value from the corresponding list item.
using (SPWeb web = item.Web)
{

// Get the lookup list.
string lookupListId
= ((SPFieldLookup)item.Fields["Project"]).LookupList;
SPList lookupList
= web.Lists[new Guid(lookupListId)];

// Get the corresponding item in the lookup list.
SPFieldLookupValue lookupValue
= new SPFieldLookupValue(item["Project"].ToString());
SPListItem correspondingItem
= lookupList.GetItemById(lookupValue.LookupId);
if (correspondingItem["Completion Date"] != null
&& (!string.IsNullOrEmpty(correspondingItem["Completion Date"].ToString())))
{

// Get the completion date.
DateTime? completionDate
= Convert.ToDateTime(correspondingItem["Completion Date"].ToString());

// Add 2 years to the completion date.
expirationDate = completionDate.Value.AddYears(2);
}
}
}

return expirationDate;
}







The scenario used in this Microsoft Office Visual How To involves calculating the expiration date of a record based on information that is contained in a secondary list. A custom expiration formula is implemented to retrieve this information and use it when calculating the expiration date.



This scenario is also similar to determining the expiration of content based on an event that occurs. The event in this example is the completion of a project. Records related to a specific project do not have an expiration date until the project completion date is set. As soon as this event occurs, all related records start their retention period and must have their expiration date calculated.



The expiration date is calculated automatically by the Expiration timer job and also by event handlers that are automatically registered by Office SharePoint Server on the library. Recalculation is done by the event handlers that are automatically registered and fired when changes occur to the record, such when the record metadata is modified.



This raises an interesting problem with the event-based expiration scenario. The first time the project completion date is defined, the Expiration timer job calculates the expiration date on all related records because they do not have an expiration date set. However, any later changes to the completion date do not initiate recalculation on the related records. This is because the project completion date exists in a secondary list, and modifications to this date do not cause the recalculation event handlers to occur on the record.



You have several options available to handle this; however, the exact implementation is highly dependent on the situation. Because the expiration formula could potentially be executed many times, you must ensure that the code is highly efficient and does not do any unnecessary processing, such as instantiate unnecessary SPWeb objects or process duplicate items.



One way that you can trigger a recalculation efficiently is to make a change and update the policy that is associated with the content type or library. All items that use the policy are then marked as “dirty” and are reprocessed, having their expiration date recalculated.




SPList list = web.Lists["Project Records"];
SPContentType contentType = list.ContentTypes[0];
Policy policy = Policy.GetPolicy(contentType);
policy.Update();






In the example, there is only one content type in the document library, which is based on Document. To update the policy, you retrieve this content type from the list, obtain the policy for the content type, and finally, update the policy.

Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007 – Part 1

SharePoint Products and Technologies provide an extensible framework for implementing and extending policy features for information management policies. The existing policy features in Microsoft Office SharePoint Server 2007 provide functionality for document bar codes, document labels, auditing, and expiration. In this Microsoft Office Visual How To, you learn how you can extend the existing expiration policy feature by creating a policy resource to implement a custom expiration formula.

The first step in creating a custom expiration formula is to reference the Microsoft.SharePoint and Microsoft.Office.Policy assemblies in your project, as shown in the following code example. The Microsoft.Office.Policy assembly provides access to the Microsoft.Office.RecordsManagement namespace and the Microsoft.Office.RecordsManagement.Policy namespace.

using Microsoft.SharePoint;
using Microsoft.Office.RecordsManagement;
using Microsoft.Office.RecordsManagement.PolicyFeatures;







The next step is to create a class that derives from the IExpirationFormula interface in the Microsoft.Office.RecordsManagement.Policy namespace. In this class, you need one public method named ComputeExpireDate. This method accepts an SPListItem object and an XMLNode object, and it returns a nullable DateTime object. This class is invoked when the custom formula is executed. In this example, the logic is very simple and returns a DateTime object set to Now. This logic is extended to meet a specific scenario in Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007 – Part 2.



To make this class available for use in Office SharePoint Server 2007, you must compile it with a strong name and put in a location from which it can be accessed, such as in the global assembly cache or in the _app_bin directory of the Office SharePoint Server Web application.




namespace CustomExpiration
{
public class CustomExpirationFormula : IExpirationFormula
{

public Nullable<DateTime> ComputeExpireDate(SPListItem item,
System.Xml.XmlNode parametersData)
{
return System.DateTime.Now;
}

}
}







To prepare the custom formula class so it can be used by the expiration policy feature, you must describe it as a policy resource and add it to the collection of available policy resources. In this example, you use a PowerShell script to perform these actions. The Microsoft.Office.Policy assembly is used and is loaded by the script. Next, you create an XML string to describe the policy resource. The PolicyResource element contains attributes for the following:




  • Id Fully qualified name of our custom expiration formula policy resource


  • featureId Fully qualified name of the expiration policy feature


  • type The resource type for the expiration formula policy resource



The XML string contains information for the name and description of the policy resource, and also information about the assembly and class. Before you add this policy resource to the collection, you validate the PolicyResource xml string by using the ValidateManifest method in the PolicyResource class. You then add the policy resource to the collection of policy resources by using the Add method of the PolicyResourceCollection class.




[System.Reflection.Assembly]::Load("Microsoft.Office.Policy, Version=12.0.0.0, `
Culture=neutral, PublicKeyToken=71e9bce111e9429c"
)

$policyResource = "<PolicyResource xmlns='urn:schemas-microsoft-com:office:server:policy' "
$policyResource += " id = 'CustomExpiration.CustomExpirationFormula' "
$policyResource += " `
featureId='Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration' "

$policyResource += " type = 'DateCalculator'>"
$policyResource += "<Name>Expire Now</Name>"
$policyResource += "<Description>Custom Expiration Calculation</Description>"
$policyResource += "<AssemblyName>CustomExpiration, Version=1.0.0.0, Culture=Neutral, `
PublicKeyToken=5f8dea7214264d83</AssemblyName>"

$policyResource += `
"<ClassName>CustomExpiration.CustomExpirationFormula</ClassName>"
$policyResource +="</PolicyResource>";

[Microsoft.Office.RecordsManagement.InformationPolicy.PolicyResource]::ValidateManifest($policyResource)
[Microsoft.Office.RecordsManagement.InformationPolicy.PolicyResourceCollection]::Add($policyResource)





The result is that your expiration formula is made available to the expiration policy feature as a policy resource and is visible to users when creating a new expiration policy on a list of content types.



Figure 1. Custom expiration for new policy



Creating a Custom Expiration Formula Based on Metadata in SharePoint 2010/SharePoint 2007



The final step is to test things to make sure the custom expiration formula is properly registered and can be invoked. To do this, create an expiration policy on a library, as follows.



To create an expiration policy on a library




  1. In a document library, click Settings, and then click Document Library Settings.





  2. Under Permissions and Management, click Information Management Policy Settings.





  3. Select Define a policy, and then click OK.





  4. On the Edit Policy page, select the Enable Expiration check box.





  5. Select the Set by a custom retention formula installed in this server option, and select the name of the custom expiration formula created in the example: Expire Now.





  6. Select the Perform this action option, and then click Delete.





  7. Click OK.





  8. Next, set a breakpoint within the ComputeExpireDate method, and upload a document to the library.



    This invokes the ComputeExpireDate method and hits the breakpoint. If this occurs, you have successfully set up the expiration formula, and you can now extend it with specific formula logic.





The expiration policy feature is part of the information management policy functionality provided by Microsoft Office SharePoint Server 2007. The expiration policy feature defines rules for how long content is retained and the action that occurs when the retention period expires. This Microsoft Office Visual How To shows how to extend the expiration formula by creating a policy resource and making it available to the expiration policy feature. In addition, you can also extend the expiration action.



An alternative approach to the custom expiration formula and action is to create a timer job to perform the calculation and action. However, implementing a timer job that evaluates and takes action on every item is not an easy development task. By using a custom formula, you can take advantage of the information-management policy infrastructure, which has already solved this problem.



This example shows how to use a PowerShell script to describe the functionality as a policy resource, and then add the resource to the collection of policy resources that are available in the records center. You can also remove the resource from the policy resource collection in a PowerShell script by calling the Delete method of the PolicyResourceCollection class, passing in the fully qualified class name of the policy resource, as shown here.




[System.Reflection.Assembly]::Load("Microsoft.Office.Policy, Version=12.0.0.0, Culture=neutral, `
PublicKeyToken=71e9bce111e9429c"
)

$id = "CustomExpiration.CustomExpirationFormula"

[Microsoft.Office.RecordsManagement.InformationPolicy.PolicyResourceCollection]::Delete($id)






Although PowerShell scripts are used here, you should use best practices when deciding how to deploy this functionality to an environment outside of a single development computer. You can convert the functionality in these scripts to Microsoft Visual C# or Microsoft Visual Basic and use it in callout code of a SharePoint Feature.

Displaying a SharePoint Modal Dialog from Ribbon Button and Getting Selected Item Context

Another really cool new feature in SharePoint 2010 is the new dialog framework provided by the JavaScript client object model. Inside the new client object model is a JavaScript static class called “SP.UI.ModalDialog” that provides a number of helpful methods for working with the dialog framework. In this blog post, I will discuss the process for displaying a SharePoint Dialog using the client object model and wiring it up to a custom ribbon button and also showing how to get context to selected items in a list or library at the time the ribbon button was clicked.

Also I need to mention that I am using version 14.0.4605.1000 of SharePoint 2010, this version is newer than Beta 1 but not quite full Beta 2. I am hoping that as we get closer to RTM, upcoming versions still work with my examples in this post. If you do encounter any weirdness with the samples shown here, please let me know by leaving a comment on this post and I will do my best to investigate and see what’s up.

Displaying a SharePoint Modal Dialog from Ribbon Button and Getting Selected Item Context

Looking at "SP.UI.ModalDialog.showModalDialog()"

The method in the SP.UI.ModalDialog class that launches the dialog is SP.UI.ModalDialog.showModalDialog() and it takes a parameter of an object called “options”. The “options” parameter is really quite important because it communicates to the dialog all the settings for it such as the URL to be displayed inside the dialog, its dimensions and other settings. The pattern I’ve used and seen so far is just to declare a literal object called “options (could be any name you like though of course) with the correct members specified, then pass this object along to “showModalDialog()”. To see this in action, check out the custom ribbon button code sample below. In this code we are defining the the properties of a custom ribbon button. It is inside the “CommandAction” attribute that is inside the “CommandUIHandler” that we specify the JavaScript that is executed when the button is clicked. In our case, we are launching a dialog. If you would like to learn more about adding a custom button to the SharePoint 2010 ribbon, please have a look  How to add Custom Button to the SharePoint 2010 Ribbon

I should also mention that in order for the dialog to be completely useful, you will need to deploy a custom page such as an application page first to your SharePoint web application that you can use to render in your dialog.

Something else cool to mention is that you may notice that OOB in SharePoint the pages in the dialogs seem to have some smartness with their masterpage chrome. It turns out that now in SharePoint 2010, masterpages won’t show all the top and left nav stuff if they are being displayed inside a dialog launched using the showModalDialog() function. The masterpages do this because now if any content in SharePoint is marked up using the CSS class “s4-notdlg” it will render when viewed normally in a browser, but when rendered through a client object modal dialog, the content marked with this CSS class will not be displayed.

One last side note to point out is that because the “showModalDialog()” function is simply part of the SharePoint 2010 client object model we could actually call it from anywhere, such as a context menu item click or a button on the screen, it doesn’t necessarily have to be a custom ribbon button. But I am suspecting that launching dialogs from custom ribbon buttons might be a pretty common pattern as more custom applications are written on SharePoint 2010.

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

<CustomAction

Id="SkynetCustomRibbonButton"
RegistrationId="101"
RegistrationType="List"
Location="CommandUI.Ribbon"
Sequence="5"
Title="Move Documents">

<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.Documents.Manage.Controls._children">
<Button
Id="Ribbon.Documents.New.SkynetTestButton"
Alt="Move Documents"
Sequence="5"
Command="Skynet_Test_Button"
Image32by32="/_layouts/images/Skynet/WinEarth32x32.png"
Image16by16="/_layouts/images/Skynet/WinEarth16x16.png"
LabelText="Move Documents"
TemplateAlias="o1" />

</CommandUIDefinition>

</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="Skynet_Test_Button"
CommandAction="javascript:

function demoCallback(dialogResult, returnValue)
{
SP.UI.Notify.addNotification('Operation Successful!');

SP.UI.ModalDialog.RefreshPage(SP.UI.DialogResult.OK);
}

var ctx = SP.ClientContext.get_current();
var items = SP.ListOperation.Selection.getSelectedItems(ctx);
var myItems = '';
var k;

for (k in items)
{
myItems += '|' + items[k].id;
}

var options = {
url: '/_layouts/Skynet/ShowItems.aspx?items=' + myItems + '&amp;source=' + SP.ListOperation.Selection.getSelectedList(),
tite: 'Move Documents',
allowMaximize: false,
showClose: false,
width: 800,
height: 600,
dialogReturnValueCallback: demoCallback };

SP.UI.ModalDialog.showModalDialog(options);"
/>

</CommandUIHandlers>

</CommandUIExtension>

</CustomAction>

</Elements>







Code Analysis



To delve a little deeper into the code sample above, on line 39 we are declaring our literal object called “options” that we create along with the required members. The code above covers a number of all the possible fields available to be used in the option class, but there are a few more too. If you are curious, and would like to dig in further to see all the possible fields for the options object, and how the options object is parsed inside the showModalDialog() function, check out the .js file named “SP.UI.Dialog.debug.js” located in the folder “{14 Hive}\TEMPLATE\LAYOUTS\” – on lines 24 to 93 you can see the actual code that is processing this object.



One of the members of the options object that is, I think, particularly important to point out is “dialogReturnValueCallback”. This field takes a user defined delegate function which subsequently will be called after the dialog is closed. This could be useful for a lot of reasons, one I’ve already ran into is wanting to refresh the originating list or library if the dialog is doing something that updates the items. Also, another cool new feature of the SharePoint 2010 client object mode and good use for the callback function is a function called “SP.UI.Notify.addNotification()”. This function is shown in my “demoCallback” delegate function above and when called displays a friendly, subtly fading message on the top right of the screen. This is an attractive way to display some kind of feedback to an end user after the dialog is closed.



I mentioned refreshing the list as a reason to use the callback function. The function I found for doing this (after digging around in the OOB .js files for inspiration) is “SP.UI.ModalDialog.RefreshPage()”. RefreshPage takes a couple of different parameters, but the one that I found works best to gracefully refresh the list without a full postback was to use the built-in enumeration of “SP.UI.DialogResult.OK” as seen above on line 36.







Getting Selected Item Context



The other big concept illustrated in the code sample above is getting context on the items selected in the list or library the user launched the dialog from. This was something that took me a little while to figure out because I could not find too many examples of it yet. In the end I actually ended up interrogating the OOB features of “Document Sets” and “In Place Records Management” to see inside their .js files how they accomplished getting item context when their dialogs are launched.



The key function I found I needed to use was “getSelectedItems()”, as shown on line 40 in the above code sample, which lives in the static JavaScript class “SP.ListOperation.Selection”. This function takes in a context object so first I had to get context using the “SP.ClientContext.get_current()” function then pass the resulting object as the single parameter of “getSelectedItems()”. The function “getSelectedItems()” then returns a loosely typed collection object (well, everything is loosely typed in JavaScript!) of the selected items in the list or library that I then iterate through using a “for” loop, where in each iteration of the loop I snag the ID of the item and build up a string of all the IDs using a pipe symbol as a delimiter (this will come in handy shortly).



From there, on line 50 in the above code sample, I append query string parameters onto my URL field of my options object of the built-up string of IDs, delimited with pipe symbols, and also the ID GUID of the current list. The key reason for employing the query string for this, as I am sure you’ve guessed by now, is that on my ShowItems.aspx application page, I parse these query string parameters server-side, performing a string.Split(‘|’) call on the string of IDs and using the ID GUID of the list to get context of the items that were selected client-side. Once you get to this point, your options are endless with our old friend the SharePoint server-side API. The code sample below is from the code behind of my ShowItems.aspx application page and illustrates the server-side aspect discussed:




using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.WebControls;

namespace Skynet.CustomRibbonButton
{
public class DemoPage : LayoutsPageBase
{
protected Label LabelItems;
protected TextBox TextDestination;

protected System.Collections.Generic.List<SPListItem> ListItems;

protected override void OnLoad(EventArgs e)
{
if (Request.QueryString["items"] != null && Request.QueryString["source"] != null)
{
string source = Request.QueryString["source"];
string[] items = Request.QueryString["items"].ToString().Split('|');

LabelItems.Text = "You have selected the following items to move:<br><br>";

source = source.Substring(1, source.Length - 2).ToLower();

Guid sourceID = new Guid(source);

SPDocumentLibrary sourceDocLib = (SPDocumentLibrary)SPContext.Current.Web.Lists[sourceID];

ListItems = new System.Collections.Generic.List<SPListItem>();

for (int i = 1; i < items.Length; i++)
{
SPListItem currentListItem = sourceDocLib.GetItemById(int.Parse(items[i]));

ListItems.Add(currentListItem);
LabelItems.Text += currentListItem.Name + "<br>";
}
}
}

// more stuff here, omitted for simplicity
}
}







Some Further Visuals



After you add the the CommandAction code as shown in the code sample above and redeploy your feature, you can have a dialog appear that looks like the following below. As you can see we are hiding the maximize button and close button as specified in the options object, along with rendering the custom application page as the URL value. Also, due to getting context of the selected items from the originating library, I am then rendering the names of the files on the server-side code, using the IDs of each item to get context to the actual SPListItem object.



Displaying a SharePoint Modal Dialog from Ribbon Button and Getting Selected Item Context



As mentioned earlier, below is an example of what happens when you close the dialog. Because we make a call to “SP.UI.Notify.addNotification()” on the callback function delegate, the attractive yellow message appears on the top right of the page.



Displaying a SharePoint Modal Dialog from Ribbon Button and Getting Selected Item Context



Well that’s it for now. I hope to be posting more on the topic of the dialog framework and the SharePoint 2010 client object model overall since I find these topics really interesting and also because I am working with them for my current project and it’s nice to keep track of what I’ve been working on for future reference.