Introduction
Knit is a Visual Studio add-in tool that allows a developer to apply multi-step patterns to solution and assembly meta-data.
Although originally created to stitch projects together into SharePoint 2007 solutions, Knit is flexible and expandable enough to handle almost any post build meta-data processing.
The meta-data of Visual Studio solutions, projects, and project files are exposed as XML to a knitting pattern via a “Skein” file. In addition, each project in the Skein file also contains its .NET reflected meta-data. The Skein file is available to each pattern step, including the powerful “Stitch” step that applies an XSLT transform.
New patterns are easily created in XML, and several powerful step processes are built-in to allow the developer complete autonomy to create post-build knitting patterns.
Background
The whole concept of distributing SharePoint Web Parts and other customizations has been greatly simplified, by the addition of the solution CAB file. The solution CAB file contains all the necessary files, including a manifest.xml file which defines how and where SharePoint will install each component. Installing a packaged solution on a SharePoint site is just a single command line instruction using the stsadm.exe tool supplied. The structure of the CAB file and the manifest.xml file is fairly straightforward, and is better explained by the CodeProject article: Fundamentals of SharePoint Web Parts (Part II: Deployment Methods) by _alank, and by the Microsoft MSDN article: Solutions Overview.
SharePoint solution files are not to difficult to create when your Visual Studio solution is relatively simple, containing, for instance, a single project with one or two Web Parts. Keeping the solution and manifest.xml file in sync with a VS solution that spans several projects, including custom fields, .ASCX user controls, .ASPX pages, and other SharePoint template files can be trying even for the most dedicated developer. Luckily, most of the information needed to create these solutions is contained in the structure and meta-data inside Visual Studio solutions, the projects, and the assemblies. Why not create a tool to access the meta-data and make it more accessible for packaging?
Since the complexity of the SharePoint solutions I was creating varied from assignment to assignment, I needed a tool that could be updated and extended relatively easily; a way to expose all the meta-data of Visual Studio and make it easy to manipulate. Using the Visual Studio add-in technology (see the Microsoft MSDN article Creating Add-ins and Wizards), I created the Knit add-in. At the time of this article, the source code for the Knit add-in remained copyrighted by Hitachi Consulting; they have however, kindly agreed to allow the binaries of the tool to be distributed as part of this article. The main thrust of this article is to explain the use of Knit, how it exposes Visual Studio meta-data, and how to create patterns, with a specific example for packaging SharePoint 2007 solutions.
Installing Knit
Download and install the Knit binaries. Knit requires that Visual Studio 2005 or 2008 be installed. Download and unzip the Knit.zip file, and execute Setup.exe. The setup wizard has three options:
- Install Knit for Visual Studio 2005
- Install Knit for Visual Studio 2008
- Install Knit Pattern Examples
Getting started with Knit
Once installed, Knit should appear at the top of the Tools menu in Visual Studio, the next time that Visual Studio is launched. Knit can be executed by either clicking on the "Knit" menu item or by executing the Visual Studio command "knit".
The Knit dialog box will be displayed, allowing you to select a pattern to start knitting with.
When Knit executes, it produces output to an output pane labeled "knit".
Executing Knit as a Visual Studio command requires that the label of the pattern be specified as its argument. For example: Knit Share Point 2007 - Solution. Executing Knit as a command does not invoke the Knit dialog box.
Knit architecture
The following diagrams depict how Knit examines meta-data and applies pattern steps to product output.
Knitting machine: Pass 1
The first pass of the knitting machine,examines the Visual Solution meta-data and processes each project and each project file. For each project that produces an assembly file, if the assembly file exists, it is opened, and .NET Reflection is used to extract the assembly meta-data. All meta-data is combined with the user inputted options, converted to XML tags, and added to the Skein document.
Knitting machine: Pass 2
The knitting machine then applies each step of the selected pattern, using the Skein document of Pass 1 as input. The step executes, resulting in one or more output files being created in Visual Studio or in the solution directory.
Finally, if the user selected to produce a skein file, the Skein document is output as a file.
The Skein file
The heart of the knitting machine is the "Skein" file. The Skein file is an XML representation of the entire Visual Studio project as well as all selected knitting options and the assembly meta-data. In short, it contains everything about your solution, except the code itself! As the pattern is executed, each step appends information to the Skein file, making it available to the next step of the pattern; an example of this can be seen at the bottom of the example, between the <outputs>...<outputs/>
tags.
Below is an abbreviated example of a Skein file for a simple solution (note that much of the file has been abbreviated using ellipses "...", including file paths, to conserve screen space):
<skein xmlns="http://hitachiconsulting.com/namespaces/visualstudio/knit/skein">
<options>
<option name="AutoSaveFiles">true</option>
<option name="CreateSkeinFile">true</option>
<option name="SolutionID">ac468818-e45b-4e17-b453-b4b437b273cf</option>
<option name="GenerateWebPartFiles">true</option>
</options>
<solution name="Hitachi.VisualStudio.Knit.UnitTest"
path="C:\Users\...\VisualStudio\Knit\UnitTest">
...
<project name="UnitTest" unique-name="UnitTest\UnitTest.csproj">
<assembly name="Hitachi.Sharepoint.SolutionBuilder.UnitTest"
full-name="Hitachi.Sharepoint.SolutionBuilder.UnitTest,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=dda93a23bface736"
location="C:\Users\...\UnitTest\bin\Debug\Hitachi.
Sharepoint.SolutionBuilder.UnitTest.dll"
version="1.0.0.0" culture="neutral"
public-key-token="dda93a23bface736">
<type name="TestWebPart"
full-name="Hitachi.Sharepoint.SolutionBuilder.UnitTest.TestWebPart"
namespace="Hitachi.Sharepoint.SolutionBuilder.UnitTest"
base-type="System.Web.UI.WebControls.WebParts.WebPart">
<attribute name="Public" type="System.Reflection.TypeAttributes" />
...
<attribute name="Bindable"
type="System.ComponentModel.BindableAttribute"
Bindable="True" Direction="OneWay" />
<member-property name="Title" property-type="System.String">
<attribute name="WebBrowsable"
type="System.Web.UI.WebControls.WebParts.WebBrowsableAttribute"
Browsable="True" />
<attribute name="Personalizable"
type="System.Web.UI.WebControls.WebParts.PersonalizableAttribute"
IsPersonalizable="True"
IsSensitive="False" Scope="User" />
<attribute name="DefaultValue"
type="System.ComponentModel.DefaultValueAttribute"
Value="Knit Test Web Part" />
</member-property>
...
<member-property name="Description" property-type="System.String">
...
</member-property>
<member-method name="DoSomeStuff" return-type="System.Void">
<attribute name="FamANDAssem" type="System.Reflection.MethodAttributes" />
<attribute name="Family" type="System.Reflection.MethodAttributes" />
<attribute name="Public" type="System.Reflection.MethodAttributes" />
<attribute name="HideBySig" type="System.Reflection.MethodAttributes" />
<parameters>
<parameter name="a" type="System.Int32" />
<parameter name="b" type="System.String" />
<parameter name="c" type="System.Boolean" />
</parameters>
</member-method>
<member-method name="Render" return-type="System.Void">
...
</member-method>
</type>
</assembly>
<folder name="_layouts">
<folder name="HitachiConsulting">
<folder name="KnowledgeManagement">
<folder name="Rating">
<file name="Comments.aspx">
<properties>
<property name="Extension">.aspx</property>
<property name="FileName">Comments.aspx</property>
...
<property name="DateCreated">11/15/2007 4:16:30 PM</property>
<property name="LocalPath">C:\Users\...\Comments.aspx</property>
</properties>
</file>
<folder name="Images">
<folder name="Rating">
<file name="0.png">
...
</file>
...
<file name="none.png">
...
</file>
<properties>
...
</properties>
</folder>
<properties>
...
</properties>
</folder>
...
</folder>
...
</folder>
</solution>
<outputs>
<step-outputs from-step="Step_0">
<output name="disposition">continue</output>
</step-outputs>
<step-outputs from-step="webparts">
<output name="disposition">manifest</output>
</step-outputs>
<step-outputs from-step="manifest">
<output name="file-name">C:\Users\...\manifest.xml</output>
<output name="disposition">fail</output>
</step-outputs>
</outputs>
</skein>
The SharePoint-SolutionBuilder Pattern
The SharePoint Solution-Builder Pattern included with the Knit tool is designed to create a solution CAB file, a manifest.xml file, and all .webpart definition files directly from the meta-data of the Visual Studio Solution and of the .NET assembly files.
="1.0" ="utf-8"
<pattern xmlns="http://hitachiconsulting.com/namespaces/visualstudio/knit/pattern"
name="SharePoint-SolutionBuilder" label="Share Point 2007 - Solution">
<description> Generates a complete Share Point 2007 Solution,
including all web part definition files. </description>
<options>
<option type="guid" required="true" persist="true"
name="SolutionID" label="Share Point Solution GUID">
<description>Uniquely identifies a Share Point solution.</description>
</option>
<option type="check-box" persist="true" name="GenerateWebPartFiles"
label="Generate .webpart files" default-value="true">
<description>Generate .webpart files by scanning each
assembly for web parts Note that the values
of properties are extracted from the [DefaultValue] attribute.
To supply a value for Title and Description, override the base property and
supply a [DefaultValue] attribute.
</description>
</option>
</options>
<steps>
<if expression="/ns:skein/ns:options/ns:option[@name='GenerateWebPartFiles']='true'"
on-false="no-webparts"/>
<stitch name="webparts" label="generating webpart file(s)"
uri="$(PatternPath)\Transforms\webparts.xslt"
on-success="manifest"
on-failure="manifest"/>
<message name="no-webparts"
text="Web Part definition file generation disabled by user" popup="false"/>
<stitch name="manifest" label="generating manifest file"
uri="$(PatternPath)\Transforms\manifest.xslt"
output-path="$(SolutionPath)\manifest.xml"/>
<stitch name="cabinet-definition" label="generating cabinet definition file"
uri="$(PatternPath)\Transforms\cabinetDefinition.xslt"
output-path="$(SolutionPath)\wsp_structure.ddf"/>
<execute name="makecab" window="Normal" label="generating cabinet file"
command="MAKECAB.EXE" directory="$(SolutionPath)"
arguments="/f "$(SolutionPath)\wsp_structure.ddf""/>
<message text="Sharepoint-SolutionBuilder knitted!" popup="true"/>
</steps>
</pattern>
Note that the key steps in this pattern are the <stitch>
steps. Each stitch step uses the Skein file as input, applying an XSLT transform to produce an output file. For more information on the XLST style sheet standards, visit w3.org for the article: XSL Transforms (XSLT) Version 1.0. I've also found that w3schools.com has a fairly good XSLT tutorial for developers just starting out.
The first stitch step, labeled "webparts", applies the XSLT file "webparts.xslt" to scan the Skein file for any assembly type that has properties using the SharePoint [WebBrowsable]
attribute. Each type found with a [WebBrowable]
property is used to generate a .webpart file for the solution.
The second stitch step, labeled "manifest", applies the XSLT file "manifest.xslt" to scan the Skein file and create a SharePoint solution manifest file (manifest.xml).
The third and final stitch step, labeled "cabinet-definition", creates the cabinet definition (.ddf) file that is used as input to the makecab step.
For additional details on how to create a pattern definition, including details on creating custom steps, please refer to the Knit user's guide that is installed as part of the Knit Add-In download.
Using the SharePoint-SolutionBuilder Pattern
The SharePoint-SoutionBuilder Pattern comes with the installed version of Knit. To apply the SharePoint-SoutionBuilder knitting pattern to your solution, select "Knit" from the Tools menu and select the SharePoint 2007 solution from the pattern selection drop-down list. The first time you select the pattern, you will need to either supply or generate a GUID for the solution ID from the Knit dialog box. Knit expects a little structure to your SharePoint solution before it can generate a valid solution file. If you are including files to be placed in the shared TEMPLATE directory of SharePoint, you need to structure your project as follows:
- Solution
- Project (or Web)
- TEMPLATE
- template-folder (optional)
- template-folder (optional)
- file (with a build action set to "content")
- file (with a build action set to "content")
Any file with a build action property of "content" under the "TEMPLATE" folder will be copied into the appropriate place in the SharePoint common TEMPLATE folder when the solution is installed. A good example of this is to create a project that installs a SharePoint custom field type (see the Microsoft MSDN article on custom field types for more info). To install the custom field definition file, set up your solution structure as follows:
- Solution
- Project (or Web)
- TEMPLATE
- Xml
- fldtypes_myfield.xml (with a build action set to "content")
To simplify referencing resources located with the SharePoint common URL, http://{share point site}/_layouts/{resource-path}, the pattern also expects to find resources with the project structure, as follows:
- Solution
- Project (or Web)
- _layouts
- resource-folder (optional)
- resource-folder (optional)
- file (with a build action set to "content")
- file (with a build action set to "content")
Download the sample Web Part project to see an example of these structures.
Points of interest
The Knit tool does a great job of exposing all of the meta-data Visual Studio maintains about a solution. I envision expanding this tool in the future to include a number of different structure and assembly inspection patterns.
History
- December 30, 2007 - First version.