Tuesday, December 29, 2009

Building and Deploying Solution Packages

Hello Guys,

First let's be clear on exactly what a Solution package is. Note I'm using 'Solution' with a capital S  in this article to distinguish between what we are discussing here and the general idea of a technical solution built using SharePoint. A Solution is a package of SharePoint items for deployment - in physical terms it is a cabinet file (.cab) which is given the extension of .wsp to differentiate it from standard .cab files. Other articles on this blog cover the idea of using SharePoint Features to deploy functionality, so let's also be clear on the relationship between Features and Solutions. In general terms, some of the tasks which cannot be done with a Feature alone but can be done with a Solution include:

  • Deployment of certain files to the filesystem, e.g. an assembly for workflow or web parts, custom files which will reside in the ‘12’ folder 
  • Deployment of web part definition files (.webpart)
  • Web.config modifications e.g. the ‘SafeControls’ entry required for a custom web part
  • Code Access Security config modifications e.g. those required for custom web parts not running from the GAC
In addition to being able to do these things, Solutions can also contain Features. The way I think of it is that the Solution wraps the Feature. In actual fact, I always recommend that even if they don't need to be (e.g. we're not doing anything in the list above), Features are always deployed as part of a Solution.  The reason for this is that the Solution framework takes care of deploying all required files to all Web Front End (WFE) servers in a SharePoint farm. This alone is incredibly useful in working towards repeatable deployments, and ensures your WFEs stay synchronized.


How Solutions are specified
The key file used to specify what a Solution package consists of is the manifest.xml file. Going back to my earlier post on deploying web parts, the manifest.xml file for that scenario looks like this:

<Solution xmlns="http://schemas.microsoft.com/sharepoint/" SolutionId="122C0F04-78B7-4d42-9378-6F8B4F93ADD1">
  <FeatureManifests>
   
    <FeatureManifest Location="COB.Demo.WebPartDeployment.WriteToFileWebPart\feature.xml" />
  FeatureManifests>
  <Assemblies>
    <Assembly     Location="COB.Demo.WebPartDeployment.WriteToFileWebPart\COB.Demo.WebPartDeployment.WriteToFileWebPart.dll"
        DeploymentTarget="GlobalAssemblyCache">
      <SafeControls>
        <SafeControl Assembly="COB.Demo.WebPartDeployment.WriteToFileWebPart, COB.Demo.WebPartDeployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5"
                    Namespace="COB.Demo.WebPartDeployment"
                    Safe="True"
                    TypeName="*" />
        SafeControls>
    Assembly>
  Assemblies>
  <DwpFiles>
    <DwpFile
     Location="COB.Demo.WebPartDeployment.WriteToFileWebPart\COB.Demo.WebPartDeployment.WriteToFileWebPart.webpart"
      FileName="COB.Demo.WebPartDeployment.WriteToFileWebPart.webpart" />
  DwpFiles>
Solution>

This is assuming the web part is being deployed to the GAC - for this illustration this is a simpler scenario than deploying to the web application's bin directory, where Code Access Security (CAS) policy would also be required. Effectively, the manifest specifies that the Solution package consists of the following:
  • a Feature with a header file named 'feature.xml'
  • an assembly for deployment to the GAC named 'COB.Demo.WebPartDeployment.WriteToFileWebPart.dll'
  • an entry in the SafeControls section of the application's web.config file, specifying all types in the specified assembly should be treated as safe
  • a web part definition file named 'COB.Demo.WebPartDeployment.WriteToFileWebPart.webpart' - this will be deployed to the web part gallery on the site
Importantly, all these details in the manifest.xml file are only used by SharePoint when the generated Solution package is deployed. They are effectively the instructions which say "go and get this item from the .wsp file and put it here". The actual process for generating the .wsp file is another task.

Building Solution packages
There are 2 options for building the actual package - build it manually using makecab.exe, or use an automated solution - there are several community-developed tools/techniques available. Since it's always good practise to understand what's actually happening in such processes, we'll cover how to do it manually here.
The first step is to write a .ddf (Diamond Directive File). This is a set of instructions for makecab.exe on how to build the folder hierarchy inside the .cab file. For my web part example, my file looks like:

.OPTION Explicit
.Set CabinetNameTemplate="COB.Demo.WebPartDeployment.WriteToFileWebPart.wsp" 
.Set DiskDirectory1="Package"
;***

manifest.xml

;** this directory name is used for the folder name under 12\TEMPLATE\Features, so should
;** match up with what you want to call the feature!
.Set DestinationDir=COB.Demo.WebPartDeployment.WriteToFileWebPart
elements.xml
feature.xml

.Set DestinationDir=COB.Demo.WebPartDeployment.WriteToFileWebPart
WebPart\COB.Demo.WebPartDeployment.WriteToFileWebPart.webpart
WebPart\COB.Demo.WebPartDeployment.WriteToFileWebPart.dll

;***

This file tells makecab.exe to do the following:
  • create a .cab file named 'COB.Demo.WebPartDeployment.WriteToFileWebPart.wsp'
  • put the 'manfest.xml' file at the root of the hierarchy
  • put the 'elements.xml' and 'feature.xml' files in a subfolder called 'COB.Demo.WebPartDeployment.WriteToFileWebPart'
  • also put the 2 other files (with extensions .webpart and .dll) in this same subfolder, but that makecab.exe should look for these files in a subfolder on the main filesystem called 'WebPart'
This instructions file is then passed to makecab.exe with the following command-line command:
D:\SolutionDeployment\Development\COB.Demo.WebPartDeployment>"C:\Program Files\Microsoft Cabinet SDK\BIN\MAKECAB.EXE" /f COB.Demo.WebPartDeployment.ddf

Couple of things to note here. At the command prompt we have ensured the current directory is the directory where all our Solution files are kept. This ensures that our relative references in the .ddf file above can be resolved. We pass the /f parameter to indicate we are passing a directives file, and also pass the location of this file.
Assuming all the files/references are OK, this results in a .cab file with a .wsp extension which will be created in a subfolder under the current directory called 'Package' (the folder will be created for you if it doesn't exist). We now have a Solution package which can be deployed to another SharePoint server. But first let's take a peek inside - this can be done by temporarily renaming the extension to .cab. You should then see something like:


No comments:

Post a Comment