Blog

You are browsing the archive for For Developers.

SharePoint 2010 Lab Environment Part 2 – Bootable vhd Files

November 4, 2009

The problem:  Having to install SharePoint on a server OS has been a consistent cause of complaint for years within the SharePoint community, especially for developers.  The proliferation of virtualization technologies (such as the free Virtual PC and VMWare Server for client OS’s, and Virtual Server and Hyper-V for server OS’s) have helped to soothe the pain – but didn’t make it all better for many.  The picture has gotten more complicated with SharePoint 2010.  Now 64-bit hardware and operating systems are required for SharePoint 2010 all SKUS, which significantly narrows the options for desktop lab environments.  Hyper-V is the only Microsoft virtualization technology capable of running 64-bit guest machines, but it only runs on a Windows 2008 Server host machine. 

I have so far been running my Win2k8 SharePoint 2010 guest virtual servers on a spare desktop machine running Win2k8 with Hyper-V.  This is a more traditional development environment for SharePoint, and it is still nice from several perspectives.  1) I have snapshots to do the ‘I was never here’ trick easily if (when) I mess something up, 2) I can give the VMs more RAM than I could on my laptop, and 3) I can run more than one VM to simulate an actual farm.  However, it’s not a very portable environment.  It would be very handy as I travel to have a simple single-server farm that I could boot my laptop into wherever and whenever I felt the need. 

Even if your laptop or desktop is 64-bit, most of us probably aren’t running a server OS on it.  I did try using Windows 2008 Server as my laptop OS for a couple of months, but the performance load of Hyper-V and the SharePoint guest resource requirements caused a significantly slower environment than I was prepared to accept for my everyday use.  I know there are low-cost alternatives using VMWare’s free product, but that still would still have the duplicate host / guest resource issue.  I also wanted to see if it was practical to use Microsoft software because of my familiarity level with it. 

Two solutions:  There are two new developments (one in SharePoint 2010 and the other in Windows 7) that open some new doors to the desktop / laptop dev environment.  TechNet now documents that 1) SharePoint 2010 offers an option for installing on a client OS – at least for development use, and 2) that a pre-installed and configured vhd can be mounted as a secondary bootable drive on a Windows 7 PC.

In this post, I will document my experience mounting a pre-installed Win2k8 R2 server vhd as a bootable drive on my Windows 7, x64, 4gb RAM laptop.  In a previous post, I documented my experience installing SharePoint 2010 directly on Windows 7.

Now Windows 7 natively allows us to boot into vhd files instead of just the physical drive partitions.  That’s pretty significant and will probably have big implications for many admins and developers.  It is not as simple as installing SharePoint 2010 directly into Windows 7, but it has distinct advantages.  For instance, we can have multiple versions of the server stored as separate vhd files for different testing scenarios.  We can also make a temporary copy of any vhd file before booting into it to maintain kind of a quasi-snapshot capability.  It also offers me more of an ‘apples to apples’ comparison to a production farm (since it’s on a server OS) and allows me to use hardware on the PC that doesn’t work in HyperV – like wireless network cards, for instance.

Mounting a bootable vhd drive in Windows 7 – The nitty gritty

  1. Log into your existing SharePoint virtual machine, and run the following sysprep command within the virtual server:
    c:\windows\system32\sysprep\sysprep.exe /generalize /shutdown
    cmdSysprep
  2. Once the sysprep command completes and the virtual machine shuts down, copy the server’s vhd file onto the physical drive of your PC.  Mine was copied to C:\VHD\2010AllinOne.vhd.
  3. BCDEdit is a command-line utility new to Windows 7 that allows you to edit the Boot Configuration Data, including creating a boot menu for multiple operating systems or at least disks. 
    Open a command prompt with administrative privileges, and type bcdedit /enum.  This will print out to the screen the current setup of your Windows 7 bootloader, which probably has only a single boot option.
    startCMDAdmin
    cmdBCDEditEnum
    You’ll notice that there is a Windows Boot Manager section, and currently only one Windows Boot Loader entry.  That’s about to change. 
  4. Type the following command to create a new item in the boot menu named “2010 All In One” that we will use for our 2010 lab environment by copying the existing one:
    bcdedit /copy {current} /d “2010 All In 1”
      cmdBCDEditCopy  
    The /copy command created another boot menu entry and assigned it a new GUID.  (Every Windows Boot Loader entry has its own GUID, even though you have to look very closely to see the difference).  However, the new boot menu entry is not wired up to our VHD file.  So, we need to add another two related commands to tell the new menu entry where to point.  The GUID can be typed if you really want to, but I suggest copying it. 
  5. If you right-click on the GUID in the last line output to the command prompt and choose Mark, then you can highlight the GUID with your mouse.  The ENTER key copies it to the clipboard.
    cmdMark
    cmdHighlight
    cmdPaste
    The following are the complete commands to type and paste into the command prompt.

    bcdedit /set {pasted guid} device vhd=[C:]\VHD\2010AllInOne.vhd
    bcdedit /set {pasted guid} osdevice vhd=[C:]\VHD\2010AllInOne.vhd
    cmdBCDEditDevice 

  6. Finally, we need to force the new bootloader entry to auto-detect the VM’s Hardware Abstraction Layer.
    cmdBCDEditDetectHAL 

The end result should be a dual-boot menu with a choice for Windows 7, your native OS, and 2010 All In One, your SharePoint lab VM.  In my case, I have SharePoint 2010 installed on both Windows 7 and Windows 2008 R2 – all running natively on my 64-bit HP laptop with 4 gb of RAM.  So far, things are working very well for me.

NOTES: 

  • If you get a BSOD when you try to boot into the VHD, it’s probably because you didn’t use the Generalize option when you did the sysprep command.  (I, um, have ‘a friend’ that did that once…)
  • This boot to vhd trick allegedly will work with a Windows Vista client OS too – with a little hacking.  I won’t go into it here, but Google “windows 7 vhd dual boot vista bootmgr bcdedit” and you’ll find several brave adventurers who can take you down that path if you wish.
  • I worked under the assumption that many developers / admins would already have a test server built as a VM by the time they stumbled across this procedure.  So these instructions show how to repurpose an existing VM onto your client PC in a dual-boot scenario.  If you do not have an existing SharePoint 2010 vhd file, here’s a link to a TechNet blog post with a webcast that describes how to create the vhd dual-boot environment with nothing more than a blank hard drive, a Windows 7 DVD, a Windows 2008 R2 DVD, and a dream…
  • You can use a dynamically-expanding vhd file, but it does something at boot time that may surprise you.  It automatically expands to its full size.  Interestingly, it contracts again to it’s smaller size when you shut it down.  That means you don’t have to maintain enough space for the full drive, but you do have to free up enough space for the entire drive before you try to boot into it.

SharePoint 2010 Lab Environment Part 1 – Installing SharePoint on Windows 7

October 29, 2009

The problem:  Having to install SharePoint on a server OS has been a consistent cause of complaint for years within the SharePoint community, especially for developers.  The proliferation of virtualization technologies (such as the free Virtual PC and VMWare Server for client OS’s, and Virtual Server and Hyper-V for server OS’s) have helped to soothe the pain – but didn’t make it all better for many.  The picture has gotten more complicated with SharePoint 2010.  Now 64-bit hardware and operating systems are required, which significantly narrows the options for desktop lab environments.  Hyper-V is the only Microsoft virtualization technology capable of running 64-bit guest machines, but it only runs on a Windows 2008 Server host machine.  Even if your laptop or desktop is 64-bit, most of us probably aren’t running a server OS on it.  I did try using Windows 2008 Server as my laptop OS for a couple of months, but the performance load of Hyper-V and the SharePoint guest resource requirements caused a significantly slower environment than I was prepared to accept for my everyday use.  I know there are possibilities for running 64-bit guest machines on a client host OS via VMWare, but I wanted to see if it was practical to use Microsoft software because of my familiarity level with it. 

Two solutions:  However, there are some new developments in SharePoint 2010 and Windows 7 that open some new doors to the desktop / laptop dev environment.  TechNet now documents that 1) SharePoint 2010 offers an option for installing on a client OS – at least for development use, and 2) that a pre-installed and configured vhd can be mounted as a secondary bootable drive on a Windows 7 PC.

In this post, I will document my experience installing SharePoint 2010 directly on my Windows 7, x64, 4gb RAM laptop while I’m home fighting the flu this week.  In another post, I will look at mounting a pre-installed Win2k8 server vhd as a bootable drive.

Installing SharePoint 2010 on a client OS – The nitty gritty

This is the simplest solution for creating a desktop lab environment for SharePoint 2010.  There is no longer a need for a virtualization product, which means fewer resources are needed with no guest OS to provide for.  Bamboo Solutions created a helpful utility for installing WSS 3.0 and MOSS2007 on Windows XP / Vista – so this is not a new idea.  However, this tool doesn’t work on SharePoint 2010.  Fortunately, there is a native (although not obvious) way to accomplish this in the 2010 product line that is documented in the first link above.  It basically boils down to editing a config file and manually installing the pre-reqs.  Here’s the procedure I followed.

****  UPDATED:  This is now confirmed to work for both MSS 2010 and SharePoint Foundation (the replacement for WSS) in the public beta released to MSDN on 11/16/2009.  However, step 4 below is now a necessary addition to the process.****

  1. Extract all files from the SharePoint.exe installer file from which you intend to install SharePoint (for any other SharePoint 2010, the replacement for WSS, the filename will likely be OfficeServer.exe instead of SharePoint.exe).  This is done with the /extract:directoryname switch, as shown below.  This may prompt you with one of the wonderful UAC ‘are you sure’ boxes.  If so, just click Yes and move on.
     cmdExtract
  2. The result will be a folder with the entire set of installation files for SharePoint 2010.  Go to ExtractedDirectoryName\Files\Setup, and open the Config.xml file using Notepad.
    wxConfig.xml 
  3. Insert a new line in the <Configuration> section, as shown below:
    <Setting ID=”AllowWindowsClientInstall” Value=”True” />
    npConfig.xml 
  4. While you have the file open, change to the key in the PIDKEY Value entry from the ‘Please enter key…’ text to your actual MSS 2010 license key.
    (If you don’t do this, you will likely get an error message in step 12 below that says your ‘config.xml is not valid, run setup again without using a setup configuration file, or fix the configuration file’.)
    image
  5. Close and save the file.
  6. Now we must install the prerequisites manually.  (The fancy new pre-req installer doesn’t work on a client OS.) 
    First, run all of the installer files found in the subfolders under the ExtractedDirectoryName\PrerequisiteInstallerFiles directory with the exception of the Speech and SpeechLPK folders (ChartControl (for Office Servers only), FilterPack, sqlncli, sync):
     wxPreReqInstallers
  7. Download and install the Microsoft Geneva Framework Runtime for x64.
    (This is a tricky one.  Most of the downloads you find with Google are not the correct version for the public Beta, and the one you may have used with the SharePoint 2010 Technical Preview doesn’t work either.  If you don’t have the correct version, you won’t be able to complete the SharePoint 2010 Products Configuration Wizard in step 13 below.  The download available at the link above worked for me with the public Beta.  The key is to have the following DLL version in your c:\Windows\Assembly folder:  Microsoft.IdentityModel 1.0.0.0) 
    image
  8. Download and install the ADO.NET Data Services v1.5 (runtime only), or whatever is the most current version when you’re reading this.
  9. Download and install the SQL Server Analysis Services – ADOMD.Net, or whatever is the most current version when you’re reading this.
  10. Install the IIS pre-reqs by entering (or, lets be honest – copying and pasting) the following command without any line breaks:
    start /w pkgmgr /iu:IIS-WebServerRole;IIS-WebServer;IIS-CommonHttpFeatures;
    IIS-StaticContent;IIS-DefaultDocument;IIS-DirectoryBrowsing;IIS-HttpErrors;
    IIS-ApplicationDevelopment;IIS-ASPNET;IIS-NetFxExtensibility;
    IIS-ISAPIExtensions;IIS-ISAPIFilter;IIS-HealthAndDiagnostics;
    IIS-HttpLogging;IIS-LoggingLibraries;IIS-RequestMonitor;IIS-HttpTracing;IIS-CustomLogging;
    IIS-Security;IIS-BasicAuthentication;IIS-WindowsAuthentication;IIS-DigestAuthentication;
    IIS-RequestFiltering;IIS-Performance;IIS-HttpCompressionStatic;IIS-HttpCompressionDynamic;
    IIS-WebServerManagementTools;IIS-ManagementConsole;IIS-IIS6ManagementCompatibility;
    IIS-Metabase;IIS-WMICompatibility;WAS-WindowsActivationService;WAS-ProcessModel;
    WAS-NetFxEnvironment;WAS-ConfigurationAPI;WCF-HTTP-Activation;
    WCF-NonHTTP-ActivationcmdIISPreReqInstall
  11. Restart your PC.
  12. Run the SharePoint installer file setup.exe in the root of your ExtractedDirectoryName.

    (Microsoft recommends configuring only a ‘Stand-Alone’ SharePoint instance on Windows 7, but it will allow you to choose advanced and Complete in order to specify a SQL Server if you wish.)

  13. When the installer finishes and you begin the ‘SharePoint Products and Technologies Configuration Wizard’, a popup will warn you that this use is not supported for production environments.  Click OK and proceed through the wizard.
  14. NOTE:  If you need to install SharePoint in using the ‘Complete’ option to be able to use the full version of SQL Server, you will not be able to use a local user account in the config wizard.  This is possible with the New-SPConfigurationDatabase PowerShell cmdlet, though.  I’ll blog about using that cmdlet in a later post.

    wizWin7Warning

Changes in SharePoint DesignerTypes for workflow activity parameters

October 23, 2009

Creating a workflow in SharePoint Designer consists of selecting Conditions and Activities to build the logic and determine what actions the workflow performs. When you select an activity or condition a sentence appears in the WorkFlow Designer screen with underlined phrases that allow you click on them to set the workflow’s parameters. These parameters can be selecting a column on a list item and a value to give it, or they can be a user’s account name, a url to a site or something more complex like an email definition that includes a To address, CC address, a subject and a body.

When creating custom workflow activities and conditions for SharePoint in Visual Studio, you create a code class to build its functionality as well as a .actions file, both of which define the parameters. SharePoint Designer uses the .actions to be able to add the activity or condition to a workflow. You must specify the type for each parameter within both the class and the .actions file as well as the DesignerType in the .actions file. When a user clicks on a parameter, different windows open to allow the user to input the values according to the DesignerType given to the parameter. The DesignerType is simply an enumeration that SharePoint Designer uses to determine what type of form to display to gather information on each parameter. For example, a DesignerType of DropDown will present a drop down menu at the location of the parameter phrase in the sentence, whereas a DesignerType of Email will open a pop up window with fields for the To address, CC address, Subject and Body where each of these fields is defined as a parameter of different types in code and returned from the Designer form as an object of that type.

For an activity to send an email, the simple class definition may look something like this:


public partial class SendAnEmail : SequenceActivity
{
   #region Dependency Properties

   public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(SendAnEmail));
   public static DependencyProperty RecipientCCProperty = DependencyProperty.Register("RecipientCC", typeof(ArrayList), typeof(SendAnEmail));
   public static DependencyProperty RecipientFromProperty = DependencyProperty.Register("RecipientFrom", typeof(string), typeof(SendAnEmail));
   public static DependencyProperty RecipientTOProperty = DependencyProperty.Register("RecipientTO", typeof(ArrayList), typeof(SendAnEmail));
   public static DependencyProperty SubjectProperty = DependencyProperty.Register("Subject", typeof (string), typeof (SendAnEmail));
   public static DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(string), typeof(SendAnEmail));

   #endregion

   public SendAnEmail()
   {
      InitializeComponent();
   }

   #region Activity Parameters

   [Description("Recipient address")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public ArrayList RecipientTO
   {
      get { return ((ArrayList) (base.GetValue(RecipientTOProperty))); }
      set { base.SetValue(RecipientTOProperty, value); }
   }

   [Description("Carbon copy recipient")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public ArrayList RecipientCC
   {
      get { return ((ArrayList) (base.GetValue(RecipientCCProperty))); }
      set { base.SetValue(RecipientCCProperty, value); }
   }

   [Description("Subject")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string Subject
   {
      get { return ((string) (base.GetValue(SubjectProperty))); }
      set { base.SetValue(SubjectProperty, value); }
   }

   [Description("HTML Body")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string Body
   {
      get { return ((string) (base.GetValue(BodyProperty))); }
      set { base.SetValue(BodyProperty, value); }
   }

   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public WorkflowContext __Context
   {
      get { return ((WorkflowContext) (base.GetValue(__ContextProperty))); }
      set { base.SetValue(__ContextProperty, value); }
   }

   [Description("Sender address. If this value is not specified, default sharepoint sender address will be used")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string RecipientFrom
   {
      get { return ((string) (base.GetValue(RecipientFromProperty))); }
      set { base.SetValue(RecipientFromProperty, value); }
   }

   #endregion

   protected override ActivityExecutionStatus OnExecute(ActivityExecutionContext executionContext, Microsoft.SharePoint.Workflow.ISharePointService service)
   {
   }
}

The .actions file would look like:


<?xml version="1.0" encoding="utf-8"?>
<WorkflowInfo Language="en-us">
   <Actions Sequential="then" Parallel="and">
      <Action Name="Send E-mail Extended" ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities.SendEmailExtended" Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=08a33cc09f006379" AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
         <RuleDesigner Sentence="Send a %1 e-mail to %2 and display %3 as the sender">
            <FieldBind Field="IsMessageUrgent" DesignerType="Dropdown" Text="choose" Id="1">
               <Option Name="urgent" Value="true"/>
               <Option Name="non urgent" Value="false"/>
            </FieldBind>
            <FieldBind Field="RecipientTO,RecipientCC,Subject,Body" Text="this address" DesignerType="Email" Id="2"/>
            <FieldBind Field="RecipientFrom" Text="this address" Id="3" DesignerType="stringbuilder" />
         </RuleDesigner>
         <Parameters>
            <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/>
            <Parameter Name="IsMessageUrgent" Type="System.String, mscorlib" Direction="In" InitialValue="false" />
            <Parameter Name="RecipientTO" Type="System.Collections.ArrayList, mscorlib" Direction="In" />
            <Parameter Name="RecipientCC" Type="System.Collections.ArrayList, mscorlib" Direction="Optional" />
            <Parameter Name="RecipientFrom" Type="System.String, mscorlib" Direction="In" />
            <Parameter Name="Subject" Type="System.String, mscorlib" Direction="In" />
            <Parameter Name="Body" Type="System.String, mscorlib" Direction="In" />
         </Parameters>
      </Action>
   </Actions>
</WorkflowInfo>

In terms of SharePoint 2010, there are several new DesignerTypes and some of the existing ones have changed slightly in the types of parameters that they return. Below is an overview of most, if not all, of the DesignerTypes included in 2010.

 Designer Type 
   
 New to 2010 
   
 Parameter(s) returned
(example parameter name) 
   
 Parameter type 
   
 Description 
 Assignment       Yes       AssignedTo       System.String       
             CC       System.Collections.ArrayList       
             Comments       System.String       
             Subject       System.String       
             Duration       System.Double       
             DurationUnit       Microsoft.Office.Workflow.Actions.DurationUnit       
             DueDate       System.DateTime       
 Boolean       No       Yes/No       System.Boolean       
 ChooseDocLibItem       No       DocumentLibrary
ItemName 
     System.String       Selects list item from a Document Library based on a field value. 
 ChooseListItem       Changed       ListId       System.String       Selects List Item from list based on a field value. 
             ListItem       Microsoft.SharePoint.Workflow.SPItemKey       
 ContentType       Yes       ContentTypeID       System.String       
 CreateListItem       No                   
 DataSourceDropDown       Yes       DataSourceName       System.String       Drop Down list of DataSources for list associated with workflow. 
 Date       No       Date       System.DateTime       Date Time Selector 
 Dependent       Yes            S ystem.String       Based on TextArea DesignerType 
 DropDown       No             System.String       
 Email       No       To       System.Collection.ArrayList       
             CC       System.Collection.ArrayList       
             Subject       System.String       
             Body       System.String       
 Hide       No                   Used to hide parameter from users in Designer 
 FieldNames       No       FieldName       System.String       Select field column from list associated with workflow. 
 Float       No             System.Float       
 HyperLink       No       Link       System.String       
 Integer       No             System.Int32       
 ListItems       Yes             System.String       
 ListNames       No       ListTitle       System.String       Drop Down with list of list names from current site 
 Operator       No                   Drop-down list box control that includes operators used to evaluate each side of the RuleDesigner sentence. Operators are static and must be added in Options elements. 
 ParameterNames       No             System.String       Allows the creation of a new variable for the workflow. 
 Person       No       Users       System.Collections.ArrayList       Allows selection of multiple users 
 SinglePerson       Changed             System.Object       Allows selection of a single user 
 StringBuilder       No             System.String       
 Survey       No                   Creates a task in the workflow to gather data from users. 
 TaskSummary       Yes       TaskProcessName       System.String       
 Text       No             System.Object       
 TextArea       No             System.String       
 UpdateListItem       No       ListItemToUpdate             
 WritableFieldNames       No             System.String       Drop down including list of fields on list that are writable 

So far, the main changes appear in the return types of the ChooseListItem and SinglePerson DesignerTypes. In SharePoint 2010, the SinglePerson form returns a generic System.Object rather than a string, and the ChooseListItem’s ListItem parameter returns a new type of SPItemKey instead of a string.

To accommodate the return of an Object from the SinglePerson DesignerType form, simple define the parameter as System.Object in the .actions file and the DependencyProperty in code, then define the activities property as a String and explicitly convert it from object to string in the get statement.

The new .actions file section would now look like:

<Action Name="myNewActivity"
 ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities. myNewActivity "
 Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral,
 PublicKeyToken=08a33cc09f006379"
 AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
   <RuleDesigner Sentence="Get %1">
     <FieldBind Field="SharePointUser" DesignerType="SinglePerson" Text="this person" Id="1" />
   </RuleDesigner>
   <Parameters>
     <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,
      Microsoft.SharePoint.WorkflowActions" Direction="In"/>
     <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
     <Parameter Name="SharePointUser" Type="System.Object, mscorlib" Direction="In" />
   </Parameters>
 </Action>

The new declaration in the class for parameters returned from the ChooseListItem DesignerType would now look like:

public static DependencyProperty SharePointUserProperty =
DependencyProperty.Register("SharePointUser", typeof(object), typeof(myNewActivity));
[Description("SharePoint User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string SharePointUser
{
   get { return ((string) (base.GetValue(SharePointUserProperty))); }
   set { base.SetValue(SharePointUserProperty, value); }
}

The SPItemKey type appears to be a wrapper for returning an instance of the list item. It has two public properties: Id as Int32 and Key as String where the Id is the selected ListItem’s Id and Key is the name. You can programmatically get an instance of the SPListItem by passing the SPList object as a parameter to SPItemKey.GetItemByIdFromList(SPList).

Public Members for Microsoft.SharePoint.Workflow.SPItemKey

Constructors
 SPItemKey()       Returns object with Key = string.Empty, Id = -1 
 SPItemKey(Int32 id)       Returns object with Key = id.ToString(), Id = id 
 SPItemKey(string key)       Returns object with Key = key, Id =Int32.Parse(key) 
Methods
 Equals(object rhs)       Boolean       Determines if current object equals object passed in 
 Equals(object objA, object objB)       Boolean       Determines if two objects are equal 
 Finalize()       Void       Empty override of base System.Object.Finalize() 
 FromItem(SPListItem listItem)       SPItemKey       Returns SPItemKey object given SPListItem 
 GetHashCode()       Int32       Generated from Exclusive OR operation between Id and Key.GetHashCode() 
 GetItemByIdFromList(SPList)       SPItemKey       Returns SPListItem from given list from Key or Id property 
 GetType()       Type       Returns Type for current SPItemKey 
 IsEmpty(SPItemKey)       Boolean       Static. Returns true if both Id and Key properties are null or if Id = -1 and Key is null or string.Empty 
 MemberwiseClone()       Object       Creates a shallow copy of the current SPItemKey 
 op_Equality(SPItemKey lhs, object rhs)       Boolean       Static. Determines if SPItemKey and Object are both null or equal 
 op_Equality(SPItemKey lhs, SPItemKey rhs)       Boolean       Static. Determines if two SPItemKey objects are both null or equal 
 op_Inequality(SPItemKey lhs, object rhs)       Boolean       Static. Determines if SPItemKey and Object are both not null or not equal 
 op_Inequality(SPItemKey lhs, SPItemKey rhs)       Boolean       Static. Determines if two SPItemKey objects are both not null or not equal 
 ReferenceEquals(object objA, object objB)       Boolean       Static. Determines if two objects are references to the same object 
 ToString()       String       Comma separated string: Key, Id 
Properties
 Empty       SPItemKey       Static. Returns empty object using empty constructor 
 Id       Int32       Read/Write. Id of SPItemKey 
 Key       String       Read/Write. Key of SPItemKey 

To access the new type in your class, be sure to reference the new assemblies for SharePoint 14 including C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.dll and C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.WorkflowActions.dll.

The new .actions file section would now look like:

<Action Name="myNewActivity"
 ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities. myNewActivity"
 Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral,
 PublicKeyToken=08a33cc09f006379"
 AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
   <RuleDesigner Sentence="Get %1">
     <FieldBind Field="ListId, ListItem" DesignerType="ChooseListItem" Text="List Item" Id="1" />
   </RuleDesigner>
   <Parameters>
     <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,
      Microsoft.SharePoint.WorkflowActions" Direction="In"/>
     <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
     <Parameter Name="ListItem" Type="Microsoft.SharePoint.Workflow.SPItemKey, Microsoft.SharePoint" Direction="In" />
   </Parameters>
</Action>


The new declaration in the class for parameters returned from the ChooseListItem DesignerType would now look like:

public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(myNewActivity));
[Description("List Id")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string ListId
{
   get { return ((string) (base.GetValue(ListIdProperty))); }
   set { base.SetValue(ListIdProperty, value); }
}

public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(SPItemKey), typeof(myNewActivity));
[Description("List Item")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public SPItemKey ListItem
{
   get { return ((SPItemKey) (base.GetValue(ListItemProperty))); }
   set { base.SetValue(ListItemProperty, value); }
}

Looking at the SharePoint 14 codebase, there are several new activities included in the namespace Microsoft.SharePoint.WorkflowActions.WithKey that use the SPItemKey object includng the same ListItem property as well as additional properties such as TaskId. It appears that the workflow activities in the new version of SharePoint uses this object extensively for List Items, probably as a smaller object to pass around instead of the full SPListItem object. It will be interesting to see how, if at all, this object changes in the beta release.

Externalizing BLOB Storage in SharePoint 2010

October 21, 2009

These are some notes from a helpful session today at the SharePoint Conference 2009 in Las Vegas delivered by Srini and Burzhin (I typed too slowly to get their last names), product engineers from Microsoft.  The notes are as organized as I can make them while I’m sitting here in the room, but they will of course not be as polished as I’d like them to be.  I’ve decided to err on the side of more information – less polish. In the interest of full-disclosure, this is a pretty new topic for me personally.  Therefore, it is possible that some of these notes represent things a bit differently than how the presenters intended.  The RBS team blog is available here: http://blogs.msdn.com/sqlrbs to find things in their own words.

BLOBs are Binary Large OBjects – a container of unstructured bytes of data.  SharePoint data that is not meta-data (documents – most other list items are completely meta-data) is stored in BLOBs in SQL databases.  BLOBs typically account for 60-70% of all content storage.  Most SharePoint operations act against the meta-data, not the BLOB data – until you go to click on the link and open the document.  By default, BLOB data is stored in the content database with the meta-data.

This model works well, but it does have some pain points.  SQL storage is inherently expensive, especially if it’s on a SAN.  The more data existing in SQL, the more performance load there to retrieve it.  Large data sets are slow to backup and recover.  SQL data is difficult to guarantee retention and deletion for compliance.  So…, Remote BLOB Storage (RBS) will solve all of our problems and bring about world peace by allowing us to store BLOB data outside of our content databases.

Previously with 2007, EBS (External BLOB Storage) meant that third-party providers were responsible for both managing external BLOB storage and creating the API libraries to interface with SharePoint.  The objective now is for SharePoint, itself to provide a common set of API libraries to do so.  The result is a downloadable add-in component that can be registered for a SharePoint farm via the SQL 2008 R2 Feature Pack (see below).  EBS is supported in 2010, but is deprecated.  Migration from EBS to RBS can be performed via PowerShell commands.

RBS is fully managed code, can be scoped to individual content databases (instead of at the farm level), can be configured and managed via PowerShell, supports many providers (including third-party), and supports migration both ways.  It ships with a native RBS FileStream store provider.

From the user’s perspective, SharePoint 2010 does all of the dancing transparently.  They’ll never know something is different.

From the administrator’s perspective, there are new PowerShell cmdlets that talk to the relevant SQL stored procedures for installing, configuring, provisioning, and maintaining RBS.

From the third-party provider view ,there is now no need to write the BLOB store libraries. 

Implementation

The RBS add-in must be installed first in SQL (the SQL RBS 2008 R2 with FILESTREAM Provider)

RBS and Provider DLLs must be installed on all WFEs

RBS must be enabled and configured using PowerShell:

  • site.contentdatabases.rbssettings.enabled
  • GetProviderNames
  • SetActiveProvider (1 BLOB store to many content database)
  • Migrate (copy entire BLOBs in or out of the db with no downtime)

Backup and Restore

This will by necessity be more complicated with multiple stores for SharePoint.  However, it is workable by following some simple restores.

  1. Always start SQL backups first (the windows can overlap)
  2. Always start BLOB restores first (the windows can overlap)

A longer BLOB retention policy can make it realistic to back it up less frequently than your SQL backups.  The RBS Maintainer keeps track of deletions and propagates them to the BLOB store.  Deletions don’t have to be concurrent from SharePoint to BLOB.  You should retain BLOBs long enough to allow you to restore the previous version of the content database without also restoring the BLOB store.

Performance

RBS seems to add little to no performance overhead in internal Microsoft testing with 128 users.  In fact, with larger files – it may have a slight advantage.  Third party providers may vary a bit, but are expected to cause no more than a 5 – 10% degradation and less for larger files.

Deploying SharePoint 2010 Extranet

October 21, 2009

These are some notes from a session today at the SharePoint Conference 2009 in Las Vegas delivered by Ryan McMinn, an Access Services guy at Microsoft.  It was nice to get more specific information about getting FBA to work, but it was also a little frustrating to not get much information about setting up SharePoint to trust external claims providers.  It’s touted as the best answer for partner collaboration, and I anticipate it to be a big winner for sites the interact with large numbers of individual contributors (think LiveID users), and earlier sessions pointed to this one as having all of the implementation details – but it seems like most of we get are concepts and generalities so far.  The notes are as organized as I can make them while I’m sitting here in the room, but they will of course not be as polished as I’d like them to be.  I’ve decided to err on the side of more information – less polish. 

Design Considerations and Business Requirements

  • Account Management
  • Network Access and entry points
  • Single Sign On
  • Information Disclosure
  • Antivirus
  • Rich Client Experience

Target Audiences

Remote Employees – Need to use their internal identity.  Need access to Line of Business apps, collaboration, and publishing content.

Partners – Need to use both internal and / or external identities.  Need access to limited sites and data (no other partner data).

Vendors and Customers – Need to use external identity.  Need access to targeted and segmented content for collaboration and / or publishing content.

We must also think about zones and Alternate Access Mappings (or host named site collections).  The Default zone should be the most secure (SSL), because it is the fallback zone in case of problems

Authentication Issues

Claims Based Authentication can use Windows Integrated, Forms Based (ASP.Net or LDAP), or SAML.  When you create a web application, you pick between Windows Classic or Claims Based.  You can still use separate zones for different authentication methods.  However, if you choose Claims, then multi authentication can be used in the same zone (as long as they use the same protocol – HTTP or HTTPS).  This is much like what Outlook does with RPC over HTTP (using Windows Integrated when possible, and prompting when not).  The authentication page first asks which method you want to use for login.  This happens in the browser or in the rich Office clients.

There is not yet any documentation about how to configure the SharePoint STS to trust external claims providers such as LiveID or external federated domains.  The short version is that they must be installed into the store, and then PowerShell commands are used to register them for use.  Microsoft requests us not to go into production with Beta2 Claims Based functionality, but will provide instructions to test it there and wants us to do so.

There are some specific steps necessary to make FBA work in 2010.

  1. Setup the authentication provider
  2. Setup the web app to use the authentication provider
  3. Add authentication provider to the web.config files of:
    • Central Admin
    • Web Application
    • STS

This can be done via PowerShell (if you are upgrading an existing web application you should do this BEFORE attaching the database for upgrade).

  1. new-spauthenticationprovider –aspnetmembershipprovider “membership” –aspnetroleprovidername “rolemanager”
  2. new-spwebapplication –name “my web app” –applicationpool “claims app pool” –applicationpoolaccount “domain\appool” –url http://servername –port 80 –authenticationprovider “membership”

ForeFront Unified Access Gateway 2010 (formerly IAG, Intelligent Application Gateway, which apparently is the yet again renamed replacement for ISA 2006) allows you to leverage existing servers without replication, a DMZ, or more servers.  It uses wizards to publish sites, do link translation, supports AAM, and path blocking.  It can also apply more specific rules (upload, download, edit…) based on identity, role, and endpoint device (corporate desktop vs. home PC).  It can also handle authentication with multiple directories and 2-factor tools, and provides excellent single-sign-on.

Forefront Identity Manager 2010 synchronizes identities and passwords across systems, automates user provisioning and management, and can be used to delegate this ability to partners.

Forefront Protection for SharePoint 2010 scans for viruses and malware, filters inappropriate content, and notifies administrators for infractions.

Develop Advanced Access Web Databases and Publish to SharePoint

October 21, 2009

These are some notes from a REALLY great session today at the SharePoint Conference 2009 in Las Vegas delivered by Ryan McMinn, an Access Services guy at Microsoft.  Lots of good, detailed information here.  The notes are as organized as I can make them while I’m sitting here in the room, but they will of course not be as polished as I’d like them to be.  I’ve decided to err on the side of more information – less polish.

This is a follow-up to a more basic session on building apps yesterday (which I didn’t attend).  Access has long been valued by business users for its rapid application development capabilities.  It’s also been hated by many IT people for its lack of security, management, and disaster recovery.  Since the 2007 version, Access and SharePoint have been friendly with each other.  Now however,fully integrating Access via SharePoint 2010’s Access Services addresses IT’s concerns and actually makes it more powerful for business users at the same time.

A big emphasis has been put on providing database templates to help people get started, including community templates uploaded to Microsoft from you and me.  One of the OOTB ones is a ‘Web database’.

Miscellaneous Access Client Improvements

Building table schema in datasheet view is easier now, as the column headings allow you to pick the data type on the fly.

Data Models are groups of fields you can create and insert as a group.

Data Types allow you to insert common calculated fields along with the fields they reference.

The Macro writer has been amped up to be almost like working in the VBA editor, but still maintaining the low-security-required environment for web publishing.  This adds enhanced capabilities to do full If Then Else structures, comments, parameters with full Intellisense.

The new Web Browser Control allows you to show web content in your forms by parameter-based URLs.

Publishing to Access Services

You do this in Backstage (Office menu > Info; or Office menu > Share)

Tables turn into lists, forms turn into aspx pages, reports turn into rdl files (Rptg Svcs), and macros turn into workflows.

It creates all of this in its own sub-site.

Full web functionality is only available on native Access lists that are moved up to SharePoint.  External lists are usable in the full Access client, but not via web forms.  This is true even if you are leveraging BCS to bring that data into SharePoint.

You can also save your database design as templates that get saved into SharePoint as wsp solution files.

Macros are great for:

Change validation

Change tracking

Notification

Workflow

Aggregates (doing them this way gives better performance that queries)

Bulk updates

Custom calculations

There are Before * data macros that trigger before the database is updated.  They are meant to be quick, and are good for validation.

After * data macros trigger after the change is committed to the database.  They can be much longer, looping, firing other macros…

Named data macros are not triggered automatically, but are called by other macros or button clicks.  Functionality is expanded like the After * data macros.

Using Enterprise Content Types and Managed Taxonomies in SharePoint 2010

October 21, 2009

These are some notes from a REALLY great session today at the SharePoint Conference 2009 in Las Vegas delivered by Daniel Kogan, the Metadata Service Program Manager at Microsoft.  Lots of good, detailed information here.  The notes are as organized as I can make them while I’m sitting here in the room, but they will of course not be as polished as I’d like them to be.  I’ve decided to err on the side of more information – less polish.

Our content types are now free to roam throughout the enterprise!  We also now get the ability to standardize and manage our meta-data tagging easily across different content types, usage scenarios, and storage locations.  Now, tags can be hierarchical just like your site or folder structure.  They can also be localized by language.

There are several questions we need to consider when we begin to contemplate this type of standardization.  They are similar concerns to what we had to consider when planning content types and site columns within a site collection, but obviously the issues can be far more complex when the scope increases across the enterprise.

Is it the same?

Does this have the same structure, policies, defaults everywhere in the enterprise?  Are things of content type “A” always the same?

What is it?

Do I trust it, recognize it?

Where is it?

Searching, navigating…

What happens to it?

Retention, workflow…

 

Terminology:

Hub – A site collection designated as a “souce” from which we share content types

CT Syndication – Publishing, sharing, pushing one or more content types across site collection, web app, and farm boundaries

Taxonomy – a hierarchical tree

Folksonomy – informal flat list of adhoc values

Term Store – DB that contains taxonomies

Groups – a security boundary within the term store and above the term set

Term set – a hierarchical section in the term store that contains many individual terms – e.g. Months, or Regions. (max 1000 total per store)

Term – a node in the taxomy with an ID and many text labels (30,000 per term set, max 1million total)

Tagging – applying metadata to an item (authoritative or social)

Keywords – not just a text string, a reference to a node in the hierarchical term store.  This is particularly powerful, standardizing tags for future use.  As you enter keywords, a suggestion list displays showing the entries in the hierarchy.

 

Content Type Syndication

  • Each Metadata Service app can publish through a maximum of 1 hub
  • It is not a requirement to syndicate or consume from the service
  • Content Type with all corresponding columns, policies, and workflow association
  • From the hub, you can publish, unpublish, republish, and roll up errors
  • From the consuming side you can extend, derive, view errors, refresh from the hub

If you are working on the service in Central Admin, it is created with whatever name you like – configuring where the hub site collection is.  Then a connection service is used to consume from the original service.

If you are working in the hub, you can simply go to the Content Type gallery, click the type and choose to Manage publishing…  In the background, the Metadata Service creates a cab file that is versioned.  So the consuming web apps, site collections, and farms can check regularly for new versions of subscribed content types.

On the consuming side, it shows up like a normal content type – but it’s read-only.

Applying Metadata

Web Browser – Edit Properties, by a business process, location-based (inherit by virtue of where it is stored)

Rich Client – DIP, Backstage (Office menu > Info).  The Office client fetches the term set when it opens the document, so that recently added terms are available.

Once the meta-data has been entered using the term store, the column headings AND left-hand navigation displays the tag taxonomy as a means of filtering or pivoting the library listing.  If that doesn’t create a mental picture for you, it’s kind of like automatic, faceted, dynamic folder trees based on tags.

Managed Metadata columns are like a ‘super choice’ field that looks up in the hierarchical term store and filters exclusively or inclusively.  The user can even add entries to an ‘open term set’, while ‘closed term sets’ are owned by someone and closed to others.

Managed Keyword columns are like a ‘super text’ field where the user can type, and they are given suggestions from the term store.  If their entry doesn’t exist, the system will add it automatically.

 

The Term Store Management Tool

You find this at Home > Site Settings > Site Administration > Term Store Management

This tool allows you to access  all available term stores, to copy, reuse, merge, delete… individual terms.  Merges ripple through all the millions of documents that use them, and the two are now synonyms of each other (including any natural abbreviations).

Claims Based Identity in SharePoint 2010

October 20, 2009

These are some notes from a conceptual session today at the SharePoint Conference 2009 in Las Vegas delivered by Venke Veeraraghavan from Microsoft.  The notes are as organized as I can make them while I’m sitting here in the room, but they will of course not be as polished as I’d like them to be.  I’ve decided to err on the side of more information – less polish.  There is a later session that focuses on implementation details, so there will be more specific notes to follow.

Claims Based Identity is similar to Kerberos in many respects, but it extends similar benefits (and more) to non-Windows accounts.  It involves a trusted authority issuing a token (like a ticket) to a user as they log in.  This token can then be used to authorize access to whatever other system trusts the same authority.  From a SharePoint perspective, it is basically a way to offload / delegate the management of user accounts, profiles, and authentication for your portal users to a third-party.  It is a not a replacement for FBA, but a framework under which FBA can be one of the methods used to authenticate and authorize users.  Since Claims Based Identity is a flexible, framework based on standard SAML tokens – SharePoint doesn’t have to write compatibility with external protocols or identity providers. 

SharePoint 2010 is also now able to assign access permissions based on claims (roughly parallel to attributes) as read from the token.  That’s a lot more flexibility than we used to have.  It seems similar to what we found when working with the Audience Targeting features in 2007, where we could dynamically filter items based on profile properties.  Those prior features were not truly for security – just filtering.  Now, claims allow us to apply actual permissions based on similar criteria instead of strictly using users and groups.

Office client applications are now also able to support non-Windows Integrated Authentication.

There are 2 Important Identity Problems in SharePoint

Sign-In

There are 2 modes for authentication in SharePoint 2010:

  • Classic (NT Token) or
  • Claims (NT Token | FBA, SAL, LDAP… | SAML Token)

Claims creates a SAML token based on the sign-in, that contains the user’s identity

An IP-STS (Identity Provider Security Token Service) processes logins and manages attributes.  It creates a token and passes it to the user for them to present to the SharePoint STS.

The SharePoint STS (Security Token Service) verifies that the IP-STS creating the token (or FBA login) is trusted by SharePoint as configured by the farm administrators.  It then issues its own token incorporating the identity information from the first, and also adds whatever SharePoint-specific attributes might be necessary or desired.

Services

How do we use the identity outside of SharePoint?

  • LOB systems
  • External partner services
  • Separate SharePoint farms

Claims allow us to accomplish more portability than Kerberos does.  Especially now with the Service Application Architecture, this enables much easier and more efficient ways to share services granularly across farms.  The SharePoint STS runs on every WFE and App server, and examines / trusts the STS on other servers as configured.

Other notes

In Beta2, Claims will be partially supported.  Here’s the list of what IS included:

  • Windows-Classic
  • FBA-Claims
  • Anonymous
  • FBA-Claims + Anonymous

 

The following modes will NOT be ready yet:

  • Windows Claims
  • SAML-Claims

These modes should be included in the RTM version.

Building a SharePoint Service Application to Provide Auto-completion Services for AJAX-enabled Rich User Controls – Part 2

October 18, 2009

Part One – The Service Application
Part Two – The Service Application’s Admin Interface
Part Three – The WCF Service Endpoint
Part Four – The User Application Page

Browse Complete Source Code
Download Visual Studio 2010 Solution

Update 10/29/09: Added Powershell cmdlets to create, retrieve and update properties of the demo service application.  Refer to the accompanying sample project for details.

Part Two – The Service Application’s Admin Interface

The Create and Manage Application Pages

In the project, I’ll add a SharePoint Mapped Folder to the [14 Hive]\TEMPLATE\ADMIN directory.

In Solution Explorer, I’m going to expand the newly created ADMIN mapped folder, right-click the AutocompletionDemo subfolder, and from the context menu Add > New Item. I select a SharePoint Application Page and name it ServiceCreate.aspx. Then, I repeat the process to add one more page named ServiceManage.aspx.

The ServiceCreate page will be a popup dialog box, and as such should be modified to inherit from SharePoint’s ~/_layouts/dialog.master master page. This page will implement place holders for its master page’s PlaceHolderDialogHeaderPageTitle , PlaceHolderDialogDescription and PlaceHolderDialogBodyMainSection content sections. Refer to the accompanying sample project for the complete listing.

Inside the PlaceHolderDialogBodyMainSection, I add the necessary controls to gather user input before creating the service application. This page will ask for the service application’s name, application pool identity, and a check box to set this instance as the default.

Inside the ServiceCreate page’s code-behind, within the CreateNewServiceApp method is where the new Auto Completion service application is actually created. All of the heavy lifting for creating the service application resides with a SPLongOperation. Refer to the accompanying sample project for the complete listing.

The ServiceManage page is where developer’s are free to add any user configurable settings for the service application. The Auto Completion service application has no user configurable options, so this page is largely left blank for the purposes of our demo. Note that this page’s master page is ~/_admin/admin.master.

At this point, the Auto Completion service application can actually be deployed to SharePoint, and instances of the service application can be provisioned in Central Administration. Of course, the application doesn’t actually do anything yet, but the core infrastructure pieces have been defined. To verify this, right-click on the AutocompleteDemo project in Solution Explorer and select Deploy. The solution will deployed, and after a few seconds, you should see a "Deploy succeeded" message in the bottom left corner of Visual Studio.

To verify deployment, I can open SharePoint’s Central Administration site and click on Manage service applications under the Application Management menu heading.

Selecting any item in the list of services will cause the Service Applications ribbon to appear. I’ll click the New button to see the Auto Complete Service Application list there. Now I can go ahead and click it to create a new service application instance.

If all is well, I’m presented with a dialog box to create a new Auto Completion service application instance.

Congratulations! If everything works on this next step, most of the hard part is over. I can go ahead and complete the form by entering an instance name and selecting an application identity. When finished, I click OK to provision the service application. If the provisioning succeeded, a pair of listings for the new service application and its proxy should now be available on the Manage Service Applications Page. I haven’t added any user configuration options for this demonstration, but clicking the listing’s link to will visit the ServiceManage page.

One more step to verify the provisioning was successful is to check that the service application’s virtual application was created in IIS. To do so, I can open Internet Information Services (IIS) Manager from Administration Tools on the Start menu of the Windows Server running SharePoint 2010. Next, I’ll expand the Sites node and then expand the SharePoint Web Services node below that. I right click on one of the virtual applications below SharePoint Web Services and select Switch to Content View.

I’m looking through the list of virtual applications which have guids for names. Notice SharePoint’s built-in service applications such as MetadataWebService.svc and WebAnalyticsService.svc. I’m looking for the virtual application with a guid for a name that that contains our Service Host file YouCompleteMeService.svc. If everything checks out, the empty WCF service has been provisioned.

Next:
Part Three – The WCF Service Endpoint

Building a SharePoint Service Application to Provide Auto-completion Services for AJAX-enabled Rich User Controls – Part 1

October 18, 2009

Part One – The Service Application
Part Two – The Service Application’s Admin Interface
Part Three – The WCF Service Endpoint
Part Four – The User Application Page

Browse Complete Source Code
Download Visual Studio 2010 Solution

Update 10/29/09: Added Powershell cmdlets to create, retrieve and update properties of the demo service application.  Refer to the accompanying sample project for details.

Introduction

With each new release of SharePoint, Microsoft has managed to further improve this platform’s programmability, extensibility and manageability. Among many other exciting new features and capabilities, the new 2010 release of SharePoint now provides developers with ASP.NET AJAX as a first-class tool in our proverbial toolbox. AJAX has been around for some time now, and it is great to finally see both native and custom SharePoint applications will be enabled with the same rich, interactive user controls we’ve come to expect from quality browser-based applications. Yet another exciting technology that ships with SharePoint 2010 is the Service Application Framework. The Service Application Framework allows developers to create robust and scalable shared services which can be consumed by multiple SharePoint web applications.

In this article, I’ll show you how to create and provision a SharePoint Service Application. Within the service application I’ll define a WCF service endpoint which provides auto-completion services to ASP.NET AJAX-enabled controls. Finally I’ll leverage this WCF service and the ASP.NET AJAX Toolkit to provide users with a simple Geo-locator page. The Geo-locator will prompt a user for a city and state, suggesting known values in real-time as the form’s fields are completed. Once a city and state have been keyed, the user will be shown the specified location on a satellite map.

 

Author’s Notes

Admittedly, the use case set forth in this demonstration in somewhat contrived. Using SharePoint’s Service Application Framework to simply provide AJAX controls with auto-completion services is really beating a small nail with a big hammer. In most real-world production scenarios, such trivial functionality could probably be achieved with a simpler site-level web service. I’ve chosen such a simple use case so as to not distract from the primary purpose of the article, which is to illustrate how to create and provision the skeleton of a simple SharePoint Service Application.

The topic of SharePoint Service Applications is broad and technically advanced. Areas such as scalability, fault-tolerance, external service publishing, security, database provisioning and data backup are left for another demonstration. That being said, in this article I will get you started by showing the basics of creating, provisioning and hooking into the Central Administration management interface for SharePoint Service Applications.

This demonstration is accompanied by a complete Visual Studio solution. All code artifacts covered in this narrative are included in the solution. I will walk you through the process of creating the solution from scratch. As I add each artifact, I will highlight its salient points, but I will assume you also have the Visual Studio solution open to view complete code listings. There are a few utility and helper classes in the project which I don’t cover in this narrative, as I believe these artifacts are self-evident. The Visual Studio solution is meant to be a starting point for you to create your own SharePoint Service Applications. I hope you will be able to take the work done here and refactor it to a launching point for your own real-world use cases.

What You’ll Need

To follow along with this demonstration, I assume you have the following requirements installed and functioning properly.

Required

  • SharePoint 2010 – WSS only will do.
  • Visual Studio 2010
  • Visual Studio 2010 SharePoint Tools

Optional

  • WSS 2010 SDK
  • .NET Reflector
  • Fiddler

I also assume that you are an intermediate to advanced SharePoint developer familiar with the SharePoint object model and the latest ASP.NET, Visual Studio and SharePoint development tools.

Part One – The Service Application

In SharePoint 2010, the Service Application Framework provides you with the ability to create hosted, middle-tier services. These shared services can then provide data or processing resources to other SharePoint features. Native SharePoint applications such as search and Excel Services are built by using this platform. The platform is now available in SharePoint 2010 for third parties to also build upon.

Among other things, the Service Application Framework provides:

  • Built-in support for building applications using the Windows Communications Framework (WCF).
  • Integration with the standard SharePoint management experience, including Administration and configuration using SharePoint Central Administration.

Anatomy of a SharePoint Service Application

SPService

A service provides a very narrow range of functionality that usually does not include end-to-end functions that are valuable in themselves. Services typically run invisibly and have little or no UI.

Every SPService object has an Instances property that holds all the instances of the service that are running on various servers in the farm. No more than one instance of each service runs on any one server, but some services have multiple instances, each one running on a different server. Each instance is represented by an object of a class derived from SPServiceInstance.

SPServiceInstance

SPServiceInstance represents an instance of a service on a server in the farm. A service instance is independent from, and identical in functionality, to all other server instances of the same type. As long as one service instance of a given service remains online, the service is fully functional. Service instances may be in the ’started’ or ’stopped’ state. A service instance provides the host process for service applications.

SPServiceApplication

A service application is hosted by a service instance. Service applications are generally created by administrators. They provide the service interface, containing the administrator settings. Service applications may own user data.

SPServiceProxy

A SPServiceProxy is simply the parent of the SPServiceApplicationProxy. It is the equivalent of a SPService on the server side, which is the parent of a SPServiceApplication. You can also think of these parent objects as class factories for the child objects, if that makes more sense to you.

SPServiceApplicationProxy

Service application proxies provide the public (front-end) interface to a service application. They allow client code to consume remote service applications. Service applications may not be installed locally and therefore cannot be called directly.

Implementing the Service Application

In Visual Studio 2010 I start out by creating a new Empty SharePoint project.

When prompted by the SharePoint Customization Wizard, I’m going to target the Central Administration web, as this is where the service application will be deployed. Also in the wizard, I’ll select the option to Deploy as a full-trust solution.

Next, I add a new class to then project and name it AutoCompletionService.cs. As with all code artifacts in this demonstration, I’ll cover the highlights of this class, but refer to the accompanying Visual Studio 2010 sample project for the complete listing. The AutoCompletionService class inherits the SPIisWebService class and implements the IServiceAdministration interface. Because this class is a persisted object, it must also be decorated with the System.Runtime.InteropServices.Guid attribute and assigned a unique guid.

For serialization purposes, the AutoCompletionService class must have a default, parameter-less constructor. This class also implements a singleton pattern to provide the means for acquiring an instance of the local service.

I’ll add three more classes to the project. I’m going to name the new classes AutoCompletionServiceProxy.cs, AutoCompletionServiceApplication.cs and AutoCompletionServiceApplicationProxy.cs respectively.

AutoCompletionServiceApplication inherits from SPIisWebServiceApplication and implements IFormattable. As a persisted object, the AutoCompletionServiceApplication class must be decorated with the System.Runtime.InteropServices.Guid attribute and assigned a unique guid. AutoCompletionServiceApplication overrides the abstract InstallPath and VirutalPath properties of its parent SPIisWebServiceApplication. AutoCompletionServiceApplication also overrides the ManageLink virtual property of SPServiceApplication.

AutoCompletionServiceApplication needs two methods to both provision and unprovision the service application and its instance. These methods will be called from the UI when an administrator creates or tears down a service application instance.

AutoCompletionServiceProxy inherits from SPIisWebServiceProxy and implements the IServiceProxyAdministration interface. IServiceProxyAdministration requires the GetProxyTypes, GetProxyDescription and CreateProxy methods to be implemented. Also of note, AutoCompletionServiceProxy is decorated with the SupportedServiceApplication attribute which tightly couples it to AutoCompletionServiceApplicationProxy. Refer to the accompanying sample project for the complete class listing.

AutoCompletionServiceApplicationProxy inherits from SPIisWebServiceApplicationProxy.

Add another class titled AutoCompletionServiceInstance.cs to your Visual Studio 2010 project. AutoCompletionServiceInstance inherits from SPIisWebServiceInstance. This class overrides the DisplayName and TypeName properties. Again, refer to the accompanying sample project for the complete class listing.

In SharePoint 2010, WCF web services are stored at the path [14 Hive]\WebServices. On most systems the full path to this location is C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\WebServices. In Visual Studio 2010, I’ll create a SharePoint Mapped Folder to this location by right-clicking on the AutocompleteDemo project in Solution Explorer and selecting Add > SharePoint Mapped Folder. Note the 14 hive’s WebServices folder at the bottom of the list.

Next, I’m going to expand the newly created WebServices mapped folder and right-click on the AutocompleteDemo folder below. From the context menu, I select Add > New Item. In the Add New Item dialog, I select the WCF Service template and name the new file YouCompleteMeService.cs.

I’m going to move the App.config file that was added automatically to be in the same folder as YouCompleteMeService.cs. Then I rename App.config to web.config and delete its contents. I’m going to create my own configuration file. In the web.config file I’ll turn on aspNetCompatibilityEnabled, define a default endpoint for our WCF service, and also turn on enableWebScript for AJAX compatibility. Refer to the accompanying sample project for the complete web.config listing.

For some reason, Visual Studio 2010 doesn’t automatically add a WCF Service Host declaration file to the SharePoint Project for me. At least in the VS2010 Beta, I’ll have to add this file manually. To do so, I just add another file to the AutocompleteDemo folder below WebServices mapped folder in the project. I select a Text file as the file type and name it YouCompleteMeService.svc. This Service Host file will only contain a few lines declaring the service and its factory.

I’m going to delete the YouCompleteMeService.cs, as I won’t be using it.

Now, I’ll add two more classes named AutoCompletionServiceApplicationHostFactory and AutoCompletionServiceApplicationHost to the root of the project. AutoCompletionServiceApplicationHostFactory inherits from ServiceHostFactory and overrides the CreateServiceHost method.

AutoCompletionServiceApplicationHost inherits from System.ServiceModel.ServiceHost and implements both the IFormattable and IDisposable interfaces.

Next, I expand the Features folder of the AutocompleteDemo Visual Studio project and right-click on Feature1. From the context menu, I click Add Event Receiver. In the newly created Feature1.EventReceiver.cs class, only the FeatureActivated method is salient to this application. In the FeatureActivated method, I check to see if an AutoCompletionService object has ever been created, and if not create it. Only one local AutoCompletionService will ever be needed. After an AutoCompletionService has been created for the first time, SharePoint’s service application management will become aware of the new service application and allow administrators to create or manage instances of the Auto Completion Service Application from Central Administration. I’ll make the admin pages to create and manage our service application in Part 2.

Next:
Part Two – The Service Application’s Admin Interface