Quantcast
Viewing all articles
Browse latest Browse all 3

Contributing SPIs for CKSDev

As I’ve mentioned in many recent posts, I believe that all developers working with SharePoint 2010 should have CKSDev installed. The new SPI (SharePoint Project Item) structure that Visual Studio facilitates means that developers can easily create templates for every conceivable SharePoint artefact. CKSDev is a CodePlex project that consolidates all of these SPI’s into a single, easily installed, extension that makes it easy to get and SharePoint development project moving quickly. Wherever possible, I intend to make CKSDev SPI’s for all of the code posted on this site and to encourage other developers to do the same, and to show how easy it is to create a simple SPI, I’ve prepared this step by step guide.

Step 1 – Get the latest version of the source

First things first, get the latest CKSDev source from http://cksdev.codeplex.com/SourceControl/list/changesets . In the interests of ensuring quality and keeping some control over the project the CKSDev team doesn’t allow direct TFS access to the source. Instead developers need to download the latest version and develop their extension locally before submitting it to the team for testing and integration into the codebase. Once we get into the code, it’s easy to see why this approach is vital. There’s a lot of code in there and there’s no way that developers could be allowed to make ad-hoc changes without breaking the code.

Step 2 – Disable Strong Name Verification

With the latest code downloaded, we need to make a few tweaks to get the code to properly build on our dev machine. Only team members can create properly signed builds, if we open the CKS Development Tools Edition.sln and try to create a local build we’ll see errors like:

Error    124    Could not load file or assembly ‘CKS.Dev, Version=1.2.0.0, Culture=neutral, PublicKeyToken=487fd6341a5c701f’ or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)   

To get round this problem we need to follow the instructions found in CKS Developer EditionSigningReadme.txt:

CKSDEV – Strong Name Signing

CKSDEV allows non project members to create local builds of the product. This enables non-members to
add features and fix bugs without first consulting with the CKSDEV team. Features which at a later
point in time may be merged into the main codebase.

To ensure that these builds can be differentiated from the ‘real’ product compiled by the CKSDEV team
the strong name key file used by CKSDEV is password protected. A second key file containing only the
CKSDEV public key can be used to create delay signed builds. These builds will run as the real product
as long as key verification is skipped for the CKSDEV assemblies.

The Debug and Release builds are delay-signed and can be compiled on any machine without needing a
password. The DebugSigned and ReleaseSigned builds are signed and password protected.

In order to compile and run CKSDEV, first run the DisableStrongNameVerification.bat in a Visual Studio
command prompt (sn.exe must be in the %PATH% environment variable). Then you can use either the Debug
or Release build configuration to perform a local build.

If we open a Visual Studio command prompt and navigate to the Signing folder, executing DisableStrongNameVerification.bat will resolve the problem and we’ll now be able to create local builds.

Step 3 – Get to know the Solution Structure

With the solution file open in Visual Studio we’ll see something akin to this:

Image may be NSFW.
Clik here to view.
image

As we can see the solution is made up of 6 projects split into two areas: CKS for Foundation and CKS for Server. I’m sure it’ll come as no surprise to learn that SPI’s that target functionality only found in the SharePoint 2010 Server SKU exist in the CKS for Server projects whereas everything else exists in the CKS for Foundation projects! Both areas are structured in the same manner and contain three projects a piece, for the sake of simplicity we’ll focus on the CKS for Foundation area for the remainder of the article.

Visual Studio Extension Packaging

Before we go any further, it’s worthwhile developing an understanding of how Visual Studio Extension are packaged and deployed. The key to deploying and packaging a VS extension is the VSIX manifest file. As SharePoint developers, we’re completely comfortable with the idea of a manifest file so I won’t get into detail about how it works it’s magic, all we need to know is that the extension is deployed as a Zip file containing a manifest that describes it’s contents. For more on VSIX packaging see this MSDN article. The manifest file is named source.extension.vsixmanifest and can be found in the CKS.Dev project. Double-click on the file to view the VSIX Manifest Editor. The important section of this page is the Content list, we can see that different output groups have been created to correspond to the various VSIX Content types. What this means is that we don’t need to think about VSIX packaging. There is nothing in here that we should ever need to change since the guys in the CKSDev team have set it all up already for us. However, for those that like nuts and bolts, here’s a bit more info on VSIX.

So back to the solution structure. We have three projects. the first, CKS.Dev,contains the VSIX manifest and most of the SPI related code and artefacts. In this post all of the work we need to do will be in here. The other two projects, CKS.Dev.Commands and CKS.Dev.Commands.Implementation.V4, work hand-in-hand and probably warrant some further explanation. Visual Studio is a 32-bit application whereas SharePoint 2010 is exclusively 64-bit. This difference presents a problem when communicating with the SharePoint Server Object Model as you’ll see if you create a console application using the default build target of x86. Basically, it’s not possible to use the Server Object Model from a 32-bit process. Because of this limitation, when creating a Visual Studio extension that targets SharePoint, it’s not possible to execute code within the Visual Studio process that directly accesses the server object model. To get round this limitation, a 64-bit host process named VSSPHost4.exe is used. This 64-bit process makes the necessary SharePoint API calls on behalf of Visual Studio. The mechanism whereby a Visual Studio extension makes a call into the server object model via the 64-bit host process is known as a SharePoint command. I won’t get into the details here because it’s not relevant to what we need to do in this post, but for more info see this page on MSDN. All we need to know for now is that a SharePoint command has two components: an Id, which is used to call the command from Visual Studio and an Implementation which is the actual Server Object Model code that will execute in the 64-bit host process. CKS.Dev.Commands contains the command ID’s and CKS.Dev.Implementation.V4 contains the implementation code.

We’re looking good so far, we’ve started with a pretty complicated looking solution and have discovered that we really only need to concern ourselves with a single project, either CKS.Dev for SharePoint Foundation SPI’s or CKS.Dev.Server if we’re creating an SPI that targets SharePoint Server. With that knowledge, we’ll move on and look at creating an SPI. A while back I added this post on using the dialog framework. The techniques discussed in there are a good candidate for an SPI that will allow a developer to easily create dialog pages. The remainder of this post will discuss how I went about converting the same code in that article into the final SPI that was submitted to the CKSDev team.

Step 4 – Create a Project Item Type Provider

The first step when creating a new SPI is to define a project item type provider. At it’s most basic, the type provider allows us to specify a custom solution explorer icon for items created using our item template. The type provider is also where we can define any properties that we want to show in the Properties pane when an item created from our custom type is selected in the Solution Explorer. Maybe we’ll cover more advanced functionality in a later post but for now we’ll stick with adding an Icon. For more info on type providers see this MSDN page.

In the CKS.Dev project file, type providers are created in the Content folder. Each provider class must be decorated with the SharePointProjectItemType attribute. This attribute accepts a string value that uniquely identifies the SPI. To prevent any magic string problems, unique identifiers are defined as constants in the ProjectItemIds.cs file in the projects file. Our first step is to add a unique identifier for our SPI in there.

Add code similar to this to ProjectItemIds.cs:

/// <summary>
/// The Dialog Page project item name
/// </summary>
public const string DialogPage = "CKS.Dev.SharePoint.DialogPage";

With this constant defined, we can make use of it to create a custom project item type provider. Add a new class in the Content folder with a name similar to DialogPageTypeProvider.cs and then add the following code:

using System.ComponentModel.Composition;
using Microsoft.VisualStudio.SharePoint;

namespace CKS.Dev.VisualStudio.SharePoint.Content
{
    /// <summary>
    /// Dialog Page item provider.
    /// </summary>
    [Export(typeof (ISharePointProjectItemTypeProvider))]
    [SharePointProjectItemType(ProjectItemIds.DialogPage)]
    [SharePointProjectItemIcon(
        "CKS.Dev.VisualStudio.SharePoint.Resources.SolutionExplorerIcons.DialogPage_SolutionExplorer.ico")]
    internal class DialogPageTypeProvider : ISharePointProjectItemTypeProvider
    {
        #region ISharePointProjectItemTypeProvider Members

        public void InitializeType(ISharePointProjectItemTypeDefinition typeDefinition)
        {
            //throw new NotImplementedException();
        }

        #endregion
    }
}

Notice the use of our constant in the SharePointProjectItemType attribute. As you can see this code doesn’t do much, in fact the only thing it does is to associate an icon with our SPI via the SharePointProjectItemIcon attribute. Before we move on, we need to add an icon as an embedded resource. In the Resources > SolutionExplorerIcons folder, add a new icon named similar to DialogPage_SolutionExplorer.ico. In the Properties pane for the icon, be sure to set the Build Action to embedded resource.

As an aside, You may have heard about MEF and the joy that it brings to developing Visual Studio add-in’s. The Project Item Type Provider is an example of MEF at work. The Export attribute makes it possible to load the class dynamically. For more on MEF see this MSDN article by Ted Pattison.

Step 5 – Create the Item Template

As the name suggests, an Item Template is simply a template that will be used to create items of our custom type. These templates may consist of one or more tokenized files that will be added to the Visual Studio project when the user selects our API from Add New Item dialog. Each template has it’s own folder in the ItemTemplates directory of the CKS.Dev project. Create a new folder for our custom extension named DialogPage, as shown:

Image may be NSFW.
Clik here to view.
image

As well as tokenized files, a template usually consists of:

  • An icon that will represent our custom item in the Add New Item dialog.
  • A .spdata file that dictates how the various files added by our SPI will be packaged for deployment to SharePoint
  • A .vstemplate file that contains metadata about our SPI together with details of tokens to be replaced and files to be deployed.

Creating the .vstemplate file

We’ll deal with the .vstemplate file first since it’s the most complex. Create a new file named similar to DialogPage.vstemplate and add the following XML:

<VSTemplate Version="2.0.0"
            Type="Item"
            xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:vssdk="http://schemas.microsoft.com/developer/vssdktemplate/2007">
  <TemplateData>
    <Name>Dialog Page (CKSDev)</Name>
    <Description>A Dialog page rendered using the SharePoint Dialog Framework.</Description>
    <Icon>DialogPage.ico</Icon>
    <ProjectType>CSharp</ProjectType>
    <SortOrder>200</SortOrder>
    <DefaultName>DialogPage</DefaultName>
    <TemplateGroupID>SharePointItemTemplateGroupID</TemplateGroupID>
    <ShowByDefault>false</ShowByDefault>
    <vssdk:OutputSubPath>SharePointSharePoint14</vssdk:OutputSubPath>
  </TemplateData>
  <TemplateContent>
  </TemplateContent>
  <WizardExtension>
  </WizardExtension>
</VSTemplate>

Note: Be sure to set the Build Action to VSTemplate

There are a few things to note about this XML:

  • <Name>  – This is the display name that appears in the ‘Add New Item’ dialog. By convention all CKSDev SPI’s have the suffix (CKSDev). This prevents conflicts with any SPI’s provided by Microsoft.
  • <Description> – Pretty self-explanatory. Again, this text appears in the ‘Add New Item’ dialog.
  • <Icon> – this is the name of the icon file to use in the Add New Item dialog. The icon file is usually stored in the same location as the .vstemplate file.
  • <ProjectType> – In the Add New Item dialog, we can select which type of project item we’re looking for. All SharePoint project items are stored under Visual C# Items and should therefore have a project type of CSharp
  • <SortOrder> – This value determines where the SPI appears on the list of SPI’s in it’s category. The lower the number the closer to the top of the list.
  • <DefaultName> – This is the default name of the item created by the SPI. Users can enter a different name in the Add New Item dialog.
  • <TemplateGroupID> – This is the name of the group that will contain our SPI. For SharePoint SPI’s the group should always be SharePointTemplateGroupID.
  • <ShowByDefault> – If this value is set to True or unspecified, our SPI will appear when the user select’s any category that is a parent of the category that contains our SPI. So for example, if teh user selected the root Visual C# Items and ShowByDefault was true, our SPI would appear in the list. Since SharePoint project items are only useful in SharePoint projects, we only want out SPI’s to appear when the user has selected the correct category. Accordingly for all SPI’s this value should be set to false.
  • <vssdk: OutputSubPath> – When extensions are deployed to Visual Studio, item templates are stored as Zip files in the file system. The root path is: C:Users<Username>AppDataLocalMicrosoftVisual Studio10.0Extensions<Extension Name>ItemTemplates<ProjectType><OutputSubPath><Locale ID>

Creating the .spdata file

The spdata file is one of the the core elements of the deployment and packaging framework for SharePoint 2010. Effectively it acts as a mapping file between artefacts that are present in the Visual Studio project and their final deployment locations in SharePoint. With previous versions of SharePoint, when using any of the community tools for packaging and deployment, we generally maintained a Visual Studio project structure that mirrored the file deployment locations in SharePoint. For example, if we were using WSPBuilder (my tool of choice for MOSS development), it was common practice to have a folder structure similar to this:

Image may be NSFW.
Clik here to view.
image

With the new tooling in Visual Studio 2010, we no longer need to organise our artefacts to fit the deployment location. We can now group our files in a more logical manner, keeping all our source files together in functional packages, each represented by an SPI.

Note: For those of use who spent a lot of time with WSPBuilder and it’s contemporaries, the new way of working will seem a bit weird at first. Maybe we’ll be tempted to organize our files in the same old way. However, for developers that are new to SharePoint, being able to completely disregard the final deployment location certainly eases the learning curve. Embrace the new functionality, life doesn’t need to be so difficult these days!

Create a new file named similar to dialog.spdata and add the following XML:

<?xml version="1.0" encoding="utf-8"?>
<ProjectItem Type="CKS.Dev.SharePoint.DialogPage"
             SupportedTrustLevels="All"
             SupportedDeploymentScopes="Web, Site"
             xmlns="http://schemas.microsoft.com/VisualStudio/2010/SharePointTools/SharePointProjectItemModel">
  <Files>
    <ProjectItemFile Source="$ProjectItemName$.aspx" Target="Layouts$rootnamespace$" Type="TemplateFile" />
  </Files>
</ProjectItem>

Note: Be sure to set the Build Action to Content

I won’t get into the contents of this file in detail, there’s a lot of excellent information on MSDN. However, a few things to note are:

The ProjectItem element is the top level element and represents a unit of deployable functionality. It may contain many child elements but they will be deployed as part of an overall project item.

Project items generally contain a Files element with one or more ProjectItemFile elements. A ProjectItemFile represents a file that will be deployed to SharePoint. The Type attribute determines the type of file and therefore the location that it will be deployed to. In this example, we’re deploying a TemplateFile, this means that the deployment location will be %SPROOT%Template<value of the Target attribute>. See this page for a complete list of possible values for the Type attribute.

Creating an Icon file

As we saw when creating the vstemplate file, we have the option of specifying an icon. Following the procedure described earlier, we can create an icon with the correct name (in this example, DialogPage.ico) and save it in the template folder (in this case, DialogPage). This time, leave the build action for the icon file as Content. The file will be physically copied to our template location.

Add Tokenized template files

We’ve now added the basics of our SPI. To make it do anything useful we need to add some template files that will allow users to create items that implement our intended functionality. IN thsi example we’re adding an SPI that will allow users to create a dialog page that uses the Dialog Framework to show and hide the page. Our template will consist of three files:

  1. Dialog.aspx – An aspx page that references the dialog.master masterpage and contains appropriate JavaScript to deal with the Dialog Framework
  2. Dialog.aspx.cs – A code-behind page that users can add any custom code to.
  3. Dialog.aspx.designer.cs – A partial code-behind file that will be used by Visual Studio to manage references to controls added from the toolbox.

I won’t cover the contents of these files in detail since they’re not relevant to the topic and are covered in more detail here. However,It is worthwhile looking at the tokens that we commonly use for SPI’s such as this.

In the Dialog.aspx file we have the following markup:

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="$fileinputname$.aspx.cs"
    Inherits="$rootnamespace$.$safeitemname$" MasterPageFile="~/_layouts/dialog.master" %>

The token $SharePoint.Project.AssemblyFullName$ is a standard token and will be replaced when the project is built. The other tokens, $fileinputname$, $rootnamespace$ and $safeitemname$ will be replaced when an instance of our SPI is created in Visual Studio.

In Dialog.aspx.cs we have the following:

namespace $rootnamespace$
{
    public partial class $safeitemname$ : LayoutsPageBase

Again, $rootnamespace% and $safeitemname$ will be replaced when an instance of our SPI is created. There’s one thing to note about code-behind files though. If we try to build our project with code files similar to this in it, the compiler will throw an error. Since the file shoudl be treated as a template, and therefore just a standard text file, as opposed to a code file that should be compiled, we need to change the Build Action to Content.

Updating .vstemplate to include template files

With our template files in the project and suitably tokenized, the last thing that we need to do is to update our vstemplate file to include them. Within the TemplateContent element in our .vstemplate file, add the following XML:

<References>
  <Reference>
    <Assembly>System.Web</Assembly>
  </Reference>
</References>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$$fileinputname$.aspx">Dialog.aspx</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$$fileinputname$.aspx.cs">Dialog.aspx.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$$fileinputname$.aspx.designer.cs">Dialog.aspx.Designer.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$SharePointProjectItem.spdata">Dialog.spdata</ProjectItem>
<CustomParameters>
  <CustomParameter Name="$ProjectItemName$" Value="$fileinputname$"/>
  <CustomParameter Name="SharePointProjectTemplateAttributes" Value="ProjectItem"/>
  <CustomParameter Name="SharePointProjectParentFilter" Value="General;ProjectItem"/>
</CustomParameters>
 

There are a few things to note about this XML. Firstly there References element. If our template requires a specific reference is included in the Visual Studio project, we can add it here. IN the case of this example, our code-behind picks up a reference to the Master property of System.Web.UI.Page and therefore requires a reference to System.Web.

The ProjectItem elements each represent a file that should be included. Not that this ProjectItem is not the same as the ProjectItem used in the .spdata file. More information on it’s attributes and child elements can be found here. Each ProjectItem has a TargetFileName attribute that determines the file name once an instance of the SPI has been added to Visual Studio. Notice that we’re using tokens here, allowing the filename to be dynamically generated. The ReplaceParameters attribute should be set to True if we’re using tokens either in our ProjectItem element or in the file that it refers to.

The CustomParameter elements allow us to define arbitrary parameters that can be passed to the Visual Studio project item templating framework. Those that are defined in this sample are used by the SharePoint tooling and should be included with all SPI’s.

With these final changes made, we can now build and deploy our extension. By default, Visual Studio will start what is known as an Experimental instance that has our extension activated. Using this experimental instance we can check that our extension works as expected. In the case of this sample, when creating an SPI using our experimental instance we’ll see the following:

Image may be NSFW.
Clik here to view.
image

We have a DialogPage4 SPI that’s using the icon that we defined as an attribute on eth Project Item Type Provider. Our template files have been added and named according to the TargetFileName attribute on our ProjectItem elements and if we open any of the files, we can see that our tokens have been replaced appropriately. We can now deploy our SPI to SharePoint and it should function as expected.

Conclusion

Although there’s a fair bit of reading in this post, it really only scratches the surface of what’s possible with the extensibility capabilities of Visual Studio 2010 and SharePoint. Hopefully it provides useful links and a decent basis to aid would-be contributors to get started in developing more complex SPI’s for CKSDev. All that remains to be done now is to submit the completed SPI to the CKSDev team. Full contact details can be found at http://cksdev.codeplex.com/team/view.

Feel free to post any questions/comments or criticisms. If there’s any interest in diving into this in more detail, I’ll be more than happy to write a few more advanced posts.


Viewing all articles
Browse latest Browse all 3

Trending Articles