SharePoint 2007 Deployment: Creating Solutions

Summary

This fourth post is about creating and using Solutions in a general sense, just as the previous one was about Features. Check the first post SharePoint 2007 Deployment: Overview for an introduction and the series index.

The Solution File

A solution file is a cabinet (.cab) file with a .wsp extension which contains a manifest file and, additionally, can contain several other files like:

  • Site definitions
  • Feature definitions (with their element manifests and element files)
  • Web part files (.dwp and .webpart)
  • Template files
  • Root files
  • Assemblies
  • Code access security policies

The solution file has a hierarchical structure where the manifest file is placed in its root and each feature and other components are placed in dedicated folders.

Note: one very important consideration that must be taken into account when creating a solution is that, the folder structure inside the .wsp file determines the final folder structure on the SharePoint server when the solution is deployed.

Creating a Solution

Creating a solution is a multiple step process:

  1. Create the solution manifest file (Manifest.xml file)
  2. Create the folder structure with all the components
  3. Create a Diamond Directive File (.ddf file which specifies the .wsp internal folder structure)
  4. Build the Solution Package (.wsp file)

The next sections detail each one of these steps.

Solution Manifest File

The solution manifest file is an XML file that must be named Manifest.xml and must be placed in the root folder of the .wsp file. This file references all the components of the solution and defines their locations in the target machine (and consequently in the .wsp internal folder structure).

This is a sample manifest file for a solution. To make it easier to explain its contents, I will separate the description in sections as indicated by the comments in the file below.

<?xml version="1.0" encoding="utf-8" ?>
<Solution
    xmlns="http://schemas.microsoft.com/sharepoint/"
    SolutionId="{A2E6B7EA-8D64-4a23-80B7-8104A82DF1C1}"
    DeploymentServerType="ApplicationServer"
    ResetWebServer="True">

  <!-- Resources -->
  <ApplicationResourceFiles>
    <ApplicationResourceFile Location="MyFiles\AppResources.pt-PT.resx"/>
  </ApplicationResourceFiles>
  <Resources>
    <Resource Location="MyFirstFeature\MyFeatureResources.pt-PT.resx"/>
  </Resources>

  <!-- Web Parts -->
  <DwpFiles>
    <DwpFile Location="MyWebPart.webpart"/>
  </DwpFiles>

  <!-- Assemblies -->
  <Assemblies>
    <Assembly DeploymentTarget="GlobalAssemblyCache" Location="GAC\MyFirstAssembly.dll">
      <SafeControls>
        <SafeControl
          Assembly="MyFirstAssembly, Version=1.0.0.0, 
                    Culture=neutral, PublicKeyToken=5968549632b337ff"
          Namespace="MyNamespace"
          TypeName="MyClassName"
          Safe="True"/>
      </SafeControls>
      <ClassResources>
        <ClassResource Location="MyLogo.jpg"/>
      </ClassResources>
    </Assembly>
    <Assembly DeploymentTarget="WebApplication" Location="MySecondAssembly.dll" />
  </Assemblies>

  <!-- Features -->
  <FeatureManifests>
    <FeatureManifest Location="MyFirstFeature\Feature.xml"/>
    <FeatureManifest Location="MySecondFeature\Feature.xml"/>
  </FeatureManifests>

  <!-- Root Files -->
  <RootFiles>
    <RootFile Location="Resources\MyResources.pt-PT.resx"/>
  </RootFiles>

  <!-- Template Files -->
  <TemplateFiles>
    <TemplateFile Location="Layouts\MyProduct\CustomPage.aspx"/>
    <TemplateFile Location="Layouts\MyProduct\MyLogo.jpg"/>
  </TemplateFiles>

  <!-- Site Definition Manifests -->
  <SiteDefinitionManifests>
    <SiteDefinitionManifest Location="STS">
      <WebTempFile Location="1033\STS\webtempSTS.xml"/>
    </SiteDefinitionManifest>
  </SiteDefinitionManifests>

  <!-- Code Access Security -->
  <CodeAccessSecurity>
    <PolicyItem>
      <PermissionSet
        class="NamedPermissionSet"
        Description="This code group grants code signed with
                     the Microsoft strong name full trust"
        Name="Microsoft_Strong_Name"
        version="1">
        <IPermission />
      </PermissionSet>
      <Assemblies>
        <Assembly
          Name="System.Security.NamedPermissionSet"
          PublicKeyBlob="00000000000000000400000000000000"
          Version="1"/>
      </Assemblies>
    </PolicyItem>
  </CodeAccessSecurity>
</Solution>

Solution Element

The root element of the manifest file is the <solution> element which has four possible attributes:

  • xmlns – The namespace. This attribute is mandatory.
  • SolutionId – Unique ID of the solution. This attribute is mandatory.
  • DeploymentServerType – Indicates which type of server is the target for the deployment of this solution. Can be ApplicationServer or WebFrontEnd. This attribute is optional (if not used, the solution is deployed to all the servers in the farm).
  • ResetWebServer – Indicates if web server should be restarted after the deployment of the solution. Can be True or False. This attribute is optional.

Resources

There are several ways to add resource files to a solution. One of them is through the <ApplicationResourceFiles> element. This element can have one or more <ApplicationResourceFile> elements which have a single mandatory attribute Location. This attribute defines the location of the .resx file in the internal structure of the solution file.

Resource files added to the solution using this element will be copied to the web application folder inside the IIS folder structure. In the sample above, assuming the solution was deployed to the web application in port 80, it would be placed in:

C:\Inetpub\wwwroot\wss\VirtualDirectories\80\Resources\MyFiles\AppResources.pt-PT.resx

Another way of adding resource files to a solution is through the <Resources> element. Like the previous element, this one can have one or more <Resource> elements which have a single mandatory attribute Location. This attribute defines the location of the .resx file in the internal structure of the solution file.

The difference between the <ApplicationResourceFiles> element and the <Resources> element, is that the last one must be used in the context of a feature specifying the location of the file inside the FEATURES folder. In the sample above, the file would be placed in:

C:\...\12\TEMPLATE\FEATURES\MyFirstFeature\MyFeatureResources.pt-PT.resx

Notes:

  • To add generic resource files (not packed in .resx files) associated with an assembly, you must used the <Assembly> element.
  • To add resource files to SharePoint, independently of a Feature, and Assembly or an Application, use the <RootFiles> element.

Web Parts

Web parts are one of the most common components that developers need to deploy to a SharePoint farm. There are several methods to deploy web parts to SharePoint, one of them is using the <DwpFiles> element. This element can have one or more <DwpFile> elements which, in turn, have a single mandatory attribute Location. This attribute determines the location of the .webpart or .dwp file that contains the web part specification.

This method copies the web part specification file (.webpart or .dwp) to the web part gallery of all the site collections of a web application. One important aspect is that this is not enough to deploy a web part. You'll also need to deploy the assembly and optional resource files to SharePoint to get the web part to work.

Assemblies

Creating a solution package is the only way to deploy an assembly to a SharePoint farm. For that, you use the <Assemblies> element. This element can have one or more <Assembly> elements, each one bearing two mandatory attributes:

  • DeploymentTarget – Specifies if the assembly should be copied to the GAC (if its value is GlobalAssemblyCache) or to the BIN folder of the web application (if its value is WebApplication).
  • Location – Specifies the path to the assembly inside the solution package. This value is relevant because, when placed in the BIN folder of the web application, the assembly will be placed in the same folder structure that exists inside the solution package. This means that, if you want to place the assembly in the BIN folder (and not in any subfolder), you must put it in the root of the solution package.

Additionally, there are two optional child elements for the <Assembly> element: SafeControls and ClassResources.

The <SafeControls> element allows you to add one or more lines to the SafeControls section of the web application's web.config file. This is an essential step if you are deploying a web part or a web control to SharePoint, because without it SharePoint will not allow it to be used. This element can have one or more <SafeControl> elements, each one with four mandatory attributes:

  • Assembly – The full qualified name of the assembly.
  • Namespace – The namespace of the type to be marked as a safe control.
  • TypeName – The name of the class that implements the control to be marked as safe. You can use the asterisk (*) character to specify that all types in the assembly are safe.
  • Safe – Boolean flag that indicates if the type is to be marked safe or unsafe.

If you look closely, you'll see that each <SafeControl> element has exactly the same format as the line added to the web application's web.config file.

The <ClassResources> element allows you to add unpackaged resource files (such as images or XML files) that are used in a particular assembly but weren't embedded in it. This element can have one or more <ClassResource> elements, each one with a mandatory attribute Location. This attribute defines the path to the file used as a resource in the assembly.

In the above sample, two assemblies are added:

  • The assembly MyFirstAssembly.dll is installed in the Global Assembly Cache, and the class MyClassName, with the namespace MyNamespace, is added to the web.config as a Safe Control. Additionally, the file MyLogo.jpg is added as a resource of this assembly.
  • The assembly MySecondAssembly.dll is copied to the BIN folder of the web application.

Features

To deploy features to a SharePoint farm, you only need to use the <FeatureManifests> element. This element can have one or more <FeatureManifest> elements, each one with a single mandatory attribute Location. This attribute specifies the path to the Feature.xml file (the feature manifest) inside the solution package (and inside the FEATURES folder in the SharePoint folder structure).

When the solution is deployed, the feature manifest file and all the files referenced in it (element manifests and element files) are copied to the folder specified in the Location attribute, and the feature is installed in the farm.

In the above sample, two features are installed:

  • A folder named MyFirstFeature is created inside the FEATURES folder, and the Feature.xml (and all other element manifests and element files) are copied to it.

C:\...\12\TEMPLATE\FEATURES\MyFirstFeature\Feature.xml

  • The same happens to the feature MySecondFeature.

Note: you don't need to add the files referenced inside the feature manifest (element manifests and element files) to the solution manifest. During the deployment of the solution, SharePoint will open the feature manifests of each of the features and add the files that are referenced in them.

Root Files

If you wish to copy a certain file to any of the folders in the SharePoint folder structure, you can use the <RootFiles> element. This element can have one or more <RootFile> elements, each one with a single mandatory attribute Location. As in previous elements, this attribute specifies the path to the file inside the solution package (and in the destination folder structure).

Files added using this method are placed inside the root of the SharePoint folder structure:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12

In the above sample, the resource file MyResources.pt-PT.resx is copied to the global SharePoint resources folder:

C:\...\12\Resources\MyResources.pt-PT.resx

Template Files

If you wish to copy a certain file to the TEMPLATE folder (or any of its subfolders) in the SharePoint folder structure, you can use the <TemplateFiles> element. This element can have one or more <TemplateFile> elements, each one with a single mandatory attribute Location. Like in root files, this attribute specifies the path to the file inside the solution package (and its destination path).

Files added using this method are placed inside the folder C:\...\12\TEMPLATE. It's rather common to use this method to place files in the /_layouts virtual directory, since it is mapped to the folder C:\...\12\TEMPLATE\LAYOUTS.

In the above sample two files are copied to:

C:\...\12\TEMPLATE\LAYOUTS\MyProduct\CustomPage.aspx
C:\...\12\TEMPLATE\LAYOUTS\MyProduct\MyLogo.jpg

This makes the available inside any SharePoint web site through the URLs:

/_layouts/MyProduct/CustomPage.aspx
/_layouts/MyProduct/MyLogo.jpg

Site Definition Manifests

The <SiteDefinitionManifests> element allows you to include site definitions in the solution. This element can have one or more <SiteDefinitionManifest> elements, each one with a single mandatory attribute Location and child element <WebTempFile>.

The Location attribute of the <SiteDefinitionManifest> element specifies the name of the root folder inside C:\...\12\TEMPLATE\SiteTemplates where the the Site Definition will be placed.

The <WebTempFile> element also has a Location attribute that specifies the path to the web template specification file associated with this site definition.

In the above sample, a site definition is deployed to the folder:
C:\...\12\TEMPLATE\SiteTemplates\STS

and its specification is included in the file copied to:
C:\...\12\TEMPLATE\1033\STS\webtempSTS.xml.

Code Access Security

The last optional section in the solution manifest is the <CodeAccessSecurity> element, which allows you to set a Code Access Security policy for the solution. This element can have one or more <PolicyItem> elements, and each one of these has two child elements: <PermissionSet> and <Assemblies>.

The <PermissionSet> element defines the permissions for this CAS policy, and contains four attributes:

  • class – A mandatory attribute that must have the value NamedPermissionSet.
  • version – A mandatory attribute that defines the version of the permission set.
  • Name – An optional attribute that specifies the name of the permission set.
  • Description – An optional attribute that specifies a description for the permission set.

Additionally, the <PermissionSet> element has one or more <IPermission> child elements. These elements have several optional attributes and child elements, which will not be discussed in the context of this post.

The <Assemblies> element is composed of one or more <Assembly> elements, which specify the assemblies associated with this policy item. The <Assembly> element has three optional attributes:

  • Name – The assembly name.
  • PublicKeyBlob – The public key of the assembly in binary format.
  • Version – The version of the assembly.

Solution Package Folder Structure

Like it was referred in the beginning of this post, the internal folder structure of a solution package will be reproduced in the destination machine. For that reason, you should follow some simple rules:

  • Place the solution manifest (Manifest.xml) in the root folder of the package.
  • Create a folder for each feature, in the root of the solution package. Don't forget each feature must have a feature manifest (Feature.xml) in that folder. The same goes for Site Definitions.
  • All the assemblies that will be copied to the BIN folder of the web application should be placed in the root folder of the solution package, so that no subfolders are created in the destination BIN folder.
  • Assemblies that will be copied to the GAC can be placed anywhere since there are no subfolders in the GAC. However, a good practice is to create a folder named GAC in the root of the solution package and place the assemblies inside.
  • When using custom web pages or images, create a LAYOUTS folder in the root of the solution package. Inside that folder create a folder structure of your choice ([Company Name]\[Product Name] for instance) and place the files inside. In the solution manifest use the <TemplateFiles> element specify the deployment destination.

The Diamond Directive File

To build a solution package (which is essentially a .cab file) you'll need to define a Diamond Directive File (.ddf file) which defines its internal folder structure. You can find several tools that help you this, but knowing how to do it manually can always come handy.

The DDF is a text file with a specific syntax that defines the folder into which each file will be placed when the package is generated. See below a sample of a DDF that goes with the above solution manifest.

; HEADER
.OPTION EXPLICIT
.Set CabinetNameTemplate=MySolution.wsp
.Set DiskDirectoryTemplate=CDROM
.Set CompressionType=MSZIP
.Set UniqueFiles=Off
.Set Cabinet=On
.Set DiskDirectory1=Package

; ROOT FOLDER
manifest.xml
MyWebPart.webpart
MyLogo.jpg
MySecondAssembly.dll

; GAC FOLDER
.Set DestinationDir=GAC
GAC\MyFirstAssembly.dll

; MyFiles FOLDER
.Set DestinationDir=MyFiles
MyFiles\AppResources.pt-PT.resx

; MyFirstFeature FOLDER
.Set DestinationDir=MyFirstFeature
MyFirstFeature\Feature.xml
MyFirstFeature\MyFeatureResources.pt-PT.resx

; MySecondFeature FOLDER
.Set DestinationDir=MySecondFeature
MySecondFeature\Feature.xml

; Resources FOLDER
.Set DestinationDir=Resources
Resources\MyResources.pt-PT.resx

; Layouts\MyProduct FOLDER
.Set DestinationDir=Layouts\MyProduct
Layouts\MyProduct\CustomPage.aspx
Layouts\MyProduct\MyLogo.jpg

; 1033\STS FOLDER
.Set DestinationDir=1033\STS
1033\STS\webtempSTS.xml

When creating the DDF file, take the following notes into account:

  • The instruction .Set CabinetNameTemplate=MySolution.wsp is defining the name of the package to be generated.
  • The instruction .Set DiskDirectory1=Package is defining the destination folder where the generated package will be placed.
  • The instructions .Set DestinationDir=FolderName specify that the files listed below it, will be placed inside that folder, in the package. This allows you to compose any internal folder structure, even if the original files are not physically stored with that structure.
  • Lines that start with the semi-colon (;) are comments.

After creating this file, save it with the .ddf extension (with the name solution.ddf for instance) in the same folder where you placed the solution manifest (this will be the root folder of the solution package).

Building the Solution Package

Building the solution package is the final and easier part. Just open a command line prompt, and run the following command in the same folder where the DDF file is:

makecab /f solution.ddf

Assuming that your DDF file is named solution.ddf, this will create a subfolder named Package and place a MySolution.wsp file inside it.

Solution Management

Adding a Solution

Adding a solution to SharePoint can only be executed from the command line, using the stsadm tool. You should copy the .wsp file to the SharePoint server that hosts the Central Administration web application and run the following command:

stsadm -o addsolution -filename MySolution.wsp

This adds the solution to the Solution Store, but does not deploy its components to the SharePoint servers.

Deploying a Solution

To deploy the solution's components to the SharePoint servers you can use one of two methods. The easier one is accessing the Central Administration web site, go to the Operations section, and select the Solution Management option. In the Solution Management screen you will see all the solutions that were added to the Solution Store, and their current state. Clicking the name of the solution you just added, you will have the option to deploy it immediately or at a scheduled time.

The other method is also using the stsadm command line tool. You can run the following command in the server that hosts the Central Administrator web site:

stsadm -o deploysolution -name MySolution.wsp -immediate -allcontenturls

This command creates a deployment timer job (which executes immediately), that will deploy the solution to all the servers in the farm, and all web applications in SharePoint. This command allows some additional options, that might be necessary depending on the contents of the solution package:

  • If the solution contains assemblies that must be placed in the GAC, you must specify the option -allowgacdeployment (or -allowgac for short).
  • If you have a single-server farm, you can execute the deployment without creating a timer job, changing the -immediate option for the -local option. Note that this means that the contents will not be propagated to additional servers in a multiple-server farm.
  • You can also specify a time for the deployment to take place, replacing the -immediate option for the -time <time to deploy> option.
  • If you wish to deploy a solution to a specific web application, rather than to all the web applications (present and future), you must remove the -allcontenturls option and add the -url http://webapplicationurl:port option.
  • The -allcontenturls or -url options can only be used if the solution contains at least one component that is web application-specific. Examples of such components are:
    • Assemblies that must be copies to the BIN folder of a web application.
    • Assemblies that must be added to the Safe Controls section of a web applications web.config file.
    • Application resource files specified through the <ApplicationResourceFiles> element.
  • If the solution contains Code Access Security policies, you must specify the -allowcaspolicies option.

Retracting a Solution

Retracting a solution is the opposite action of the deployment of the solution. It removes all the components included in the solution (except objects that are in use, such as site columns, site content types or lists) from the SharePoint web sites, but does not remove the solution from the Solution Store.

Like in deployment, you can retract a solution accessing the Central Administration web site, going to the Operations section and selecting the Solution Management option. In the Solution Management screen, clicking on the solution's name will allow you to retract it (if it is deployed) completely or partially (from a specific web application) and schedule a time for the retraction process.

You can also perform these actions through the stsadm command line tool, executing the following command in the machine that hosts the Central Administrator web site:

stsadm -o retractsolution -name MySolution.wsp -immediate -allcontenturls

This command creates a timer job that will run immediately and retract the solution's components from all the web application in SharePoint. Like in the deploy operation, there are some additional options that can be specified:

  • If you have a single-server farm, you can execute the retract without creating a timer job, changing the -immediate option for the -local option. Note that this means that the contents will not be retracted from additional servers in a multiple-server farm.
  • You can also specify a time for the retraction to take place, replacing the -immediate option for the -time <time to retract> option.
  • If you wish to retract a solution from a specific web application, rather than to all the web applications, you must remove the -allcontenturls option and add the -url http://webapplicationurl:port option.
  • The -allcontenturls or -url options can only be used if the solution contains at least one component that is web application-specific. Examples of such components are:
    • Assemblies that must be copies to the BIN folder of a web application.
    • Assemblies that must be added to the Safe Controls section of a web applications web.config file.
    • Application resource files specified through the <ApplicationResourceFiles> element.

Deleting a Solution

Deleting a solution from the Solution Store is just as easy as adding it. You can do it using the Central Administration web site, going to the Operations section and choosing the Solution Management option. In the Solution Management screen, if you click the solution's name you will be presented with the option of deleting it from the Solution Store (if the solution is not deployed to any web application).

Additionally, you can use the stsadm command line tool to do the same, executing the following command:

stsadm -o deletesolution -name MySolution.wsp

Upgrading a Solution

There is an additional and very important action that you can perform on a solution package, and that is upgrading it. When you upgrade a solution, SharePoint compares the new version with the older version and upgrades all the components, without deactivating any features (even if their elements have been updated).

The solution upgrade can only be performed using the stsadm command line tool, using the following command:

stsadm -o upgradesolution -name <Solution Name> -filename <New Solution File> -immediate

This command creates a timer job that executes immediately and upgrades an existing (and deployed) solution with a new version of itself, packed in a new .wsp file. Like the deploy and retract operations, the upgrade operation has additional options that might be considered:

  • If you have a single-server farm, you can execute the upgrade without creating a timer job, changing the -immediate option for the -local option. Note that this means that the contents will not be upgrade on additional servers in a multiple-server farm.
  • You can also specify a time for the upgrade operation to take place, replacing the -immediate option for the -time <time to upgrade> option.
  • If the solution contains assemblies that must be placed in the GAC, you must specify the option -allowgacdeployment (or -allowgac for short).
  • If the solution contains Code Access Security policies, you must specify the -allowcaspolicies option.

Helper Tools

There are several tools that can help you create solutions (and features). Check the following links for some of them: