Saturday, October 28, 2006

Presenting Two Sessions at SharePoint Information Worker Conference 2007

In January I'll be presenting two sessions at the SharePoint Information Worker Conference 2007 in Orlando, FL. IWC07 is a three-day SharePoint conference designed specifically for business, web and application professionals who need to stay on the leading edge of Microsoft’s Office System and SharePoint technologies.
Here's a summary of the two sessions which I'll be presenting:

Enabling SharePoint for Extranet Collaboration

Thousands of organizations worldwide are turning to Microsoft's SharePoint Product and Technologies for sharing critical business data with partners, customers and suppliers over the Internet. To achieve business advantage by effectively collaborating with business partners, organizations need to provide access to proprietary content while still maintaining security, audit ability and accountability.
Along with security concerns, companies are facing the challenging process of working with IT resources to get collaborative extranet sites provisioned and accessible. Once online, the ongoing tasks for user management of these collaborative applications must be identified and assigned.
In this session, attendees will be hear about enhancements in SharePoint 2007 and third-party add-ons that open new doors in terms of the possibilities and feasibility of using SharePoint as an Extranet collaboration tool.

Integrating data from business applications using the new Business Data Catalog in SharePoint 2007

The Business Data Catalog (BDC) provides a means to surface business data from line-of-business (LOB) systems into SharePoint 2007 without the need to write custom code. The BDC bridges the gap between SharePoint 2007 and business applications by bringing in key data for use in SharePoint sites, lists, search, and user profiles.
In this session, the I'll demonstrate the use of Business Data web parts and show how these web parts are used to display business data within a SharePoint application. Attendees will also learn about leveraging the Business Data field type to display business data in any SharePoint list and see how SharePoint's Search Center can gather and index data from BDC applications to provide full-text search ability.
Categories: , , , , , ,

Automation in Visual Studio 2005 for WSS v3 Feature Development

I'm anxiously awaiting Microsoft's release of Visual Studio Extensions for SharePoint Services as mentioned by Mathew Cosier here, Mart Muller here, and Wes Preston here. When released, these new extensions should make our lives as SharePoint developers a bit simpler. In the meantime, if you follow a consistent approach when laying out the structure and outputs of your WSS v3 Feature project, it becomes possible to create useful and time-saving tools for automation inside the Visual Studio 2005 IDE. In my development environment I've defined and frequently use tools to add, deploy, upgrade, retract, and delete a WSS Solution Package (wsp). My favorite of these tools is the upgrade operation, as it allows for a quick "build and test" iterative development cycle. Behind the scenes, each of these tools call the appropriate stsadm.exe operation and display the command's result in Visual Studio 2005's Output Window.

As I previously mentioned, for these external tools to be useful across all of your WSS Feature projects requires consistency in how you structure the artifacts and outputs of your project. In an earlier post, I walked you through the anatomy of a WSS v3 Feature project. Three key factors of my example Feature project's anatomy allow my external tools to function and be re-used. Please take a look at my earlier post for the specifics on how these are implemented:

  1. Makecab.exe is called from the Visual Studio project's AfterBuild target to create the WSS Solution Package including the project's freshly compiled assembly.
  2. The WSS Solution Package (wsp) is placed in the Package subfolder by Makecab.exe each time it is rebuilt.
  3. The WSS Solution Package's name is defined by the Visual Studio 2005 $(TargetName) variable.

Let's take a look at specific implementation for each of the external tools I'm using. To define these tools, from Visual Studio 2005 go to Tools->External Tools on the menu bar.

WSP Solution Add

Command: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE

Arguments: -o addsolution -filename "$(ProjectDir)Package\$(TargetName).wsp"

WSP Solution Deploy Global

Command: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE

Arguments: -o deploysolution -local -allowgacdeployment -allcontenturls -name $(TargetName).wsp

WSP Solution Upgrade

Command: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE

Arguments: -o upgradesolution -local -allowgacdeployment -name $(TargetName).wsp -filename "$(ProjectDir)Package\$(TargetName).wsp"

WSP Solution Retract

Command: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE

Arguments: -o retractsolution -local -allcontenturls -name $(TargetName).wsp

WSP Solution Delete

Command: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.EXE

Arguments: -o deletesolution -name $(TargetName).wsp

As a bit of review, remember that the WSS Solution Package framework involves two-stage operations for both deployment and retraction. WSP packages must first be added to the solution store and then forward deployed to the Farm. Conversely, WSP packages must be retracted from the Farm and then deleted from the solution store in order to be removed.

Keeping the WSS v3 Solution Framework's deployment mechanisms in mind, doing a WSP Solution Add command followed by WSP Solution Deploy would get your project initially deployed into the SharePoint Farm. Running WSP Solution Retract then WSP Solution Delete would remove your project from the Farm and the solution store. As I mentioned earlier, the command I use most frequently is WSP Solution Upgrade. Upgrade allows me to iteratively cycle my code changes into SharePoint and simply hit refresh in my browser to see the updates.

Having these stsadm.exe call available directly from Visual Studio 2005's IDE has saved me a lot of clicking, typing and time. I'll finish up with a few "where do I go from here" thoughts. If desired, a developer could completely automate the package upgrade process by adding stsadm.exe's upgrade operation to the AfterBuild target of the project. Taking things a step further, stsadm.exe's extensibility can be leveraged to create additional external tools such as AC's WCM Custom Commands for STSADM.EXE.

Categories: , , , , , ,

Tuesday, October 17, 2006

Anatomy of a SharePoint WSS v3 Feature Project in Visual Studio 2005

In a previous post, I published the source code to a WSS v3 Feature which illustrates how to add sub menus to SharePoint's Site Actions menu. In this follow-up post, I'll walk through the anatomy of the Visual Studio 2005 project for this feature.

Artifact 1 - Modified class library project

This is a standard C# Class Library project modified to include the project (artifact 4) and call's BuildFeaturePackage target from the AfterBuild target. Note that this project references Microsoft.SharePoint.dll and System.Web.dll.

1 <Import Project="" />
2 <Target Name="AfterBuild">
3 <CallTarget Targets="BuildFeaturePackage" />
4 </Target>

Artifact 2 - Inclusion of SharePoint's XML Schema Definitions

References to these SharePoint XML Schema Definitions add Intellisense for Elements.xml (artifact 3), Feature.xml (artifact 5) and Manifest.xml (artifact 7).

Artifact 3 - Elements.xml

Element manifest file containing definitions to the feature's elements. This manifest file is referenced from Feature.xml (artifact 5). See this blog post for details on the contents of Elements.xml.

Artifact 4 -

Custom MSBuild project used to create the WSS Solution Package for deployment of the feature. calls MakeCab.exe, which can be downloaded with the Microsoft Cabinet SDK. For the Exec call (line 6) to work, MakeCab.exe is expected to be located in the system path.

1 <?xml version="1.0" encoding="utf-8" ?>
2 <Project DefaultTargets="BuildFeaturePackage" xmlns="">
4 <Target Name="BuildFeaturePackage">
5 <Copy SourceFiles="$(TargetPath)" DestinationFolder="bin" ContinueOnError="false"/>
6 <Exec Command="makecab.exe /F package.ddf /D CabinetNameTemplate=$(TargetName).wsp" />
7 </Target>
9 </Project>

Artifact 5 - Feature.xml

Defines the feature and specifies the location of assemblies, files, dependencies, or properties that support the Feature. See this blog post for details on the contents of Feature.xml.

Artifact 6 - Public/Private key pair

Signs the feature's code-behind assembly so that the assembly can be placed into the Global Assembly Cache (GAC).

Artifact 7 - Manifest.xml

Defines the list of features, site definitions, resource files, web part files, and assemblies to be included in the Solution package. In this case, just a feature and its code-behind assembly are defined.

1 <?xml version="1.0" encoding="utf-8" ?>
3 <Solution SolutionId="{5DA74A52-818A-4bba-B268-AD5E29361489}"
4 xmlns="">
6 <FeatureManifests>
7 <FeatureManifest Location="SiteActionsSubMenuDemo\Feature.xml"/>
8 </FeatureManifests>
10 <Assemblies>
11 <Assembly DeploymentTarget="GlobalAssemblyCache"
12 Location="SiteActionsSubMenuDemo.dll">
13 <SafeControls>
14 <SafeControl Assembly="SiteActionsSubMenuDemo, Version=, Culture=neutral, PublicKeyToken=e9db3057acd9c0f6"
15 Namespace="SiteActionsSubMenuDemo"
16 TypeName="*"
17 Safe="True" />
18 </SafeControls>
19 </Assembly>
20 </Assemblies>
22 </Solution>

Artifact 8 - Package.ddf

Package.ddf is a MakeCab diamond directive file used to define the structure and contents of the solution package.
1 ;*** MakeCab Directive file
2 ;
3 .OPTION Explicit ; Generate errors
4 .Set DiskDirectoryTemplate=CDROM
5 .Set CompressionType=MSZIP
6 .Set UniqueFiles=Off
7 .Set Cabinet=On
8 .Set DiskDirectory1=Package
9 ;
10 ; \
11 ;**************************************************
12 manifest.xml
13 bin\SiteActionsSubMenuDemo.dll
15 .Set DestinationDir=SiteActionsSubMenuDemo
16 Feature.xml
17 Elements.xml
18 ;
19 ;***End

Artifact 9 - SiteActionsSubMenuCustomizer.cs

Referenced from the CustomAction located in Elements.xml (artifact 3), this C# class defines the structure of the sub menus which will be added to the Site Actions Menu. See this blog post for details on the contents of SiteActionsSubMenuCustomizer.cs.

The complete Visual Studio 2005 solution can be download here:

Source: (21.5KB)

For a basic step-by-step walk through on creating, installing and activating custom actions that will be located on the Site Actions dropdown menu, see Darrin Bishop's post Custom Actions - Simple Steps to Add Your Touch to Site Actions.

Categories: , , , , , ,

Thursday, October 12, 2006

Custom Feature: Link to WSS Central Admin from SharePoint Site Actions Menu

This post has been moved to a new location.

Compiling HTML Help Workshop Projects in Visual Studio 2005

Like many other software development shops, we use Microsoft HTML Help Workshop to create compiled HTML help files (.chm) for distribution with our packaged software applications. Although we add the .hhp project files, index files, pages and other help related artifacts to our Visual Studio solution so that they get vaulted along with our application source code into Team Foundation Server, I've always relied on the HTML Help Workshop UI itself to do the actual help file compilation.

In the interest of saving some time and having a few less apps open while I'm developing, I wanted to be able to compile the help project from within Visual Studio itself. Initially, I considered adding a call to hhc.exe from my Visual Studio project's post build event. The downside to this approach would be wasted CPU cycles (and compile time) for all those times when I'm compiling the code but no changes have been made to the help file content. Of course, I could mitigate the wasted cycles by putting some incremental build logic into my Visual Studio project with a bit of MSBuild code, but I really just wanted an on-demand method for compiling the HTML Help Workshop projects when I need to. The solution that seems to meet my requirements the best has been to configure an External Tool from Visual Studio 2005 to call hhc.exe on-demand when I have the .hhp project open. Here's how:

1. In Visual Studio 2005, select Tools->External Tools.

2. When the External Tool dialog pops up, fill-in the values as shown. Note that the macro $(ItemPath) indicates the item currently open in Visual Studio 2005's source editor pane.

3. Now that hhc.exe is configured as an external tool, you can open the .hhp project file.

4. And Select Tools->Compile Html Help.

The output from HTML Help Workshop's compiler will be displayed in Visual Studio 2005's Output window.

Categories: , , , ,

Wednesday, October 11, 2006

Using LINQ with SharePoint List Data

Ever since I sat in on one of Anders Hejlsberg's TechEd sessions about LINQ a while back, I've been wanting to take a look at how to use LINQ with SharePoint List data. Well, timing and priorities have kept me from diving in, but Kevin Hoffman has started the ball rolling with this post about using LINQ with SharePoint.

What is LINQ and why use it with SharePoint List data? Well, LINQ stands for Language Integrated Query, and what LINQ does is add a native querying syntax reminiscent of SQL to .NET Framework programming languages. To illustrate why using LINQ with SharePoint is a compelling approach to programming against List data, I'll borrow a few code snippets from Kevin Hoffman's post:

First, the usual method for enumerating List data:

1 SPSite site = new SPSite("http://server/site");
2 SPWeb web = site.AllWebs[0];
4 List<SPList> hiddenLists = new List<SPlist>(); // Do not use an SPListCollection here
5 foreach (SPList list in web.Lists)
6 {
7 if (list.Hidden)
8 hiddenLists.Add(list);
9 }

Now, the same thing with LINQ:

1 SPSite site = new SPSite("http://server/site");
2 SPWeb web = site.AllWebs[0];
4 var hiddenLists = from list in web.Lists where list.Hidden select list;

Half the code, and good-bye foreach loop! Elegant, no? Take a look at Kevin's post for more details. Thanks for the info Kevin. I'm not sure what book you're working on, but good luck!

Categories: , , , , , ,

Programmatically Manipulating WSS v3 Solution Packages Part 1: Adding a Package to the Solution Store

This is the first installment in a multi-part tutorial I'll be publishing on the topic of how to pragmatically add, deploy, retract and delete Windows SharePoint Services v3 Solution packages. Each installment in this series will be kept very simple and focused on a particular task. These articles are intended for intermediate level SharePoint developers and as such will rely heavily on the code examples themselves to illustrate the necessary patterns and practices. Why keep it short and simple? Because when I'm surfing the web for a code snippet to get a particular job done, I usually don't want to read a bunch of background information. I just want to see some code, grab it, and then move on!

In this first article we'll take a look at how to add a Solution package to the WSS v3 Solution store. If you'd like to build the complete solution along with me as I publish these articles, then create a new C# console application in Visual Studio 2005 and copy/paste the code below into your Program.cs file. If you are just looking for the snippet of code to accomplish adding a Solution package to the WSS v3 Solution store, then skip down to the AddSolution() method listed below (reference line 38) and grab it.

Here's the code:

[Listing 1]

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.IO;
5 using System.Text.RegularExpressions;
6 using Microsoft.SharePoint.Administration;
8 namespace solmgr
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 try
15 {
16 Arguments cli = new Arguments(args);
18 if (cli["add"] != null && cli["lcid"] != null)
19 AddSolution(cli["add"], uint.Parse(cli["lcid"]));
20 else if (cli["add"] != null)
21 AddSolution(cli["add"], 0);
22 else
23 PrintUsage();
24 }
25 catch (Exception ex)
26 {
27 Console.WriteLine("solmgr encountered an error:\r\n");
28 Console.WriteLine(ex.Message);
29 }
30 }
32 /// <summary>
33 /// Adds a solution to the store
34 /// </summary>
35 /// <param name="fname">Solution package file</param>
36 /// <param name="lcid">Locale</param>
37 /// <returns>Newly added SPSolution package</returns>
38 internal static SPSolution AddSolution(string fname, uint lcid)
39 {
40 if (ValidateSolutionName(Path.GetFileName(fname)))
41 return SPFarm.Local.Solutions.Add(fname, lcid);
42 else
43 throw new ArgumentException(
44 string.Format("The solution name {0} was invalid.",
45 Path.GetFileName(fname)));
46 }
48 /// <summary>
49 /// Validates solution package name
50 /// </summary>
51 /// <param name="name">Solution package file name</param>
52 /// <returns>true if solution file name is valid</returns>
53 internal static bool ValidateSolutionName(string name)
54 {
55 Regex regex1 = new Regex("[\\\\/\\*\\?\"<>|]");
56 return !regex1.Match(name).Success;
57 }
59 /// <summary>
60 /// Prints usage information
61 /// </summary>
62 internal static void PrintUsage()
63 {
64 Console.WriteLine("solmgr usage:\r\n");
65 Console.WriteLine("\t-add <solution package>\tAdd solution to store");
66 Console.WriteLine("\t[-lcid <LCID>]\t\tLocale of solution");
67 Console.WriteLine("\r\nexample: solmgr -add mypackage.wsp\r\n");
68 }
69 }
70 }

To handle the parsing of command line arguments in the example above (reference line 16), I'm using R. Griffon's Command Line Parser for C# as published on The Code Project.

In you have any questions, please add a comment to this post and I'll try to answer it as soon as I can. In part 2, I'll illustrate how to remove a WSS v3 Solution from the store.

Categories: , , , , ,