Microsoft SharePoint Developer Documentation Team Blog
The Official Blog of the SharePoint Developer Documentation Team

  • Microsoft SharePoint Developer Documentation Team Blog

    Customizing Alert Notifications and Alert Templates in Windows SharePoint Services 3.0

    • 41 Comments

    Hello.  My name is Albert Meerscheidt and I’m one of the Programming Writers on the Windows SharePoint Services SDK team.

    In the coming months I will be posting about the content that’s on the publishing horizon.  The first topic that I'd like to discuss is how to customize alert notifications and alert templates in Windows SharePoint Services 3.0. The following is a somewhat abridged version of what you will see in the upcoming SDK update.

       Overview

    Alerts are an e-mail subscription notification service in Windows SharePoint Services 3.0. Users can create alerts to be notified of changes to list items (item level alert), documents, lists (list level alert), or document libraries. Alerts in Windows SharePoint Services 3.0 are quite flexible; when you create an alert you have options such as when to be notified and what kind of changes will trigger the alert. Alerts can be managed by users and administrators and customized by developers.

    After an alert has been created, changes that fit the criteria specified in the alert are recorded in an event log. Alerts are generated by a timer job that reads the event log, formats the alert email using an alert template, and then sends that email out to the user.

    Alert templates are stored in Alerttemplates.xml. Alerttemplates.xml defines the format, contents, and properties used to create alert messages from each list type in Windows SharePoint Services 3.0. Developers can customize alerts by modifying a copy of Alerttemplates.xml and then loading the customized alert templates using the stsadm -o updatealerttemplates command.

    Note   Do not modify Alerttemplates.xml itself. Doing so may result in loss of functionality when upgrading or installing service packs.

    The <filters> element in each template allows you to create custom triggers for events by using Collaborative Application Markup Language (CAML) queries.

    The default timer interval can be changed to adjust the latency of 'immediate' alerts.

       Default Timer Interval

    Alert emails can be sent immediately or in a daily or weekly summary. Immediate alerts are not actually immediate; they are sent out after a delay determined by the timer interval. This is done for performance reasons.

    The default timer interval is 5 minutes. Thus, if this interval has not been changed you could notice a delay of up to 5 minutes (the default timer interval) before an alert message is generated. Changes are recorded as they occur in an event log (discussed later in this article) and then alert messages are rendered from that log when the next timer job runs.

    The default timer interval can be determined using the stsadm command.

    stsadm -o getproperty -pn job-immediate-alerts -url<url> command.

    The timer interval property can be set using stsadm. In this example I set the interval to 3 minutes.

    stsadm -o setproperty -pn job-immediate-alerts -url<url> -pv "every 3 minutes"

    For more information about STSADM, see http://technet2.microsoft.com/Office/en-us/library/188f006d-aa66-4784-a65b-a31822aa13f71033.mspx?mfr=true.

       Alert templates

    Alert templates are stored in the configuration database and are available at the web application level. Alert templates are defined in Alerttemplates.xml.

    Windows SharePoint Services 3.0 ships with the following templates:

    Table 1. Predefined alert templates

    Alert Template Name

    Description

    SPAlertTemplateType.GenericList

    The first alert template in Alerttemplates.xml. GenericList is used unless there is a match to one of other event types.

    SPAlertTemplateType.DocumentLibrary

    Notification of changes in document libraries

    SPAlertTemplateType.Survey

    Notification of changes in surveys

    SPAlertTemplateType.Links

    Notification of changes in links

    SPAlertTemplateType.Announcements

    Notification of changes in announcements

    SPAlertTemplateType.Contacts

    Notification of changes in contacts

    SPAlertTemplateType.Events

    Notification of changes in events

    SPAlertTemplateType.Tasks

    Notification of changes in tasks

    SPAlertTemplateType.DiscussionBoard

    Notification of changes in discussion boards

    SPAlertTemplateType.PictureLibrary

    Notification of changes in picture libraries

    SPAlertTemplateType.XMLForm

    Notification of changes in XML form

    SPAlertTemplateType.DataConnectionLibrary

    Notification of changes in data connection libraries

    SPAlertTemplateType.AssignedtoNotification

    Assigned to task / issue list notifications

     

    Alerttemplates.xml is located at: Local_Drive\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Template\XML directory.

    Note   Do not modify Alerttemplates.xml itself. Make changes to a working copy.

     

       Alert Template Format

    Alert templates have the following format:

    <AlertTemplates>

     <AlertTemplate Type="List" Default="True" Name ="Default Template">

     </AlertTemplate>

    <AlertTemplate Type="List" Name="SPAlertTemplateType.GenericList">

      <EventTypes IsVisible="True"/>

      <Format>

      </Format>

      <Filters>

        <FilterDefinition>

        </FilterDefinition>

      </Filters>

      </AlertTemplate>

    </AlertTemplates>

     

    Table 2. Alert Template Attributes

    Attribute

    Description

    Name

    The name of the template. Searching on the template names provides an easy way to locate a particular template.

    Type

    The type attribute can be set to List, Item, or Custom.

    Default

    Default="True" sets the default alert template.

    Filters

    If IsVisible = "True", then the filter fields are displayed when creating the alert.

    Filter Definitions

    Define a filter (query).

    Format

    Formatting of the email is defined in the <Format> element.

    Fields

    Specify which fields to render in the alert email.

     

       Filters and Filter Definitions Elements

    Filters enable you to create new triggers for an event such as 'the priority of a task has changed'. To modify existing filters or create additional filters modify the <FilterDefinition> element of the appropriate template. Define the query element using inside the filter using Collaborative Application Markup Language (CAML).  This query will create an alert event if the event date, end date, or location changes.

     

    <FilterDefinition>

       <FriendlyName>$Resources:Alerts_4_filter;</FriendlyName>

       <ShortName>$Resources:Alerts_4_filter_shortname;</ShortName>

       <Query>

       <Or>

          <Or>

          <Neq><FieldRef name="EventDate/New"/>

          <FieldRef name="EventDate/Old"/>

          </Neq>

          <Neq>

             <FieldRef name="EndDate/New"/>

             <FieldRef name="EndDate/Old"/>

          </Neq>

       </Or>

          <Neq>

             <FieldRef name="Location/New"/>

             <FieldRef name="Location/Old"/>

          </Neq>

       </Or>

       </Query>

    </FilterDefinition>

     

    Resource variables listed in AlertTemplates.xml, such as $Resources:Alerts_anything_filter_shortname, can be found in core.resx; located in the Local_Drive\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Resources directory.

    Note   The Query element in the Alerts schema contains no Where element.

     

    For more information about CAML query schema, see http://msdn2.microsoft.com/en-us/library/ms467521.aspx.

       

       Format Element

    Use the format element of an alert template to modify the look of the alert email. You can also customize the formatting of the alert email by using embedded styles.

    <Format>

    <Digest> - digest format

        <Subject>

        </Subject>

        <Header>

        </Header>

        <HeaderFieldsHeader>

        </HeaderFieldsHeader>

        <HeaderFields>

        </HeaderFields>

        <HeaderFieldsFooter>

        </HeaderFieldsFooter>

        <RowHeader> - each row’s header (row refers to each item level change in the digest notification)

        </RowHeader>

        <RowFields> - each row’s fields

        </RowFields>

        <RowFooter> - each row’s footer

        </RowFooter>

        <Footer>

        </Footer>

    </Digest>

    <Immediate> - immediate notification format

        <Subject> - email subject

        </Subject>

        <Header>

        </Header>

        <Fields> - the html for the fields. CAML will go over all the fields and render this part of the template. The field itself should be referenced using <GetVar Name=”OldValue#{Field}” /> or <GetVar Name=”NewValue#{Field}” />

        </Fields>

        <Footer>

      </Footer>

    </Immediate>

    </Format>

     

        Fields Element

    Specify the fields to be rendered in the email.

    For example you can specify <GetVar Name="NewValue#{Field}"> inside the <Fields> section. More examples can be seen in AlertTemplates.xml.

    To exclude some fields from being rendered in the email, you should include them in the <DigestNotificationExcludedFields> and <ImmediateNotificationExcludedFields> section. DigestNotificationExcludedFields and ImmediateNotificationExcludedFields give you the flexibilty to render different fields for immediate alerts and summary (digest) alerts.

     

    In addition to these, CAML is supported. For example you can specify <GetVar Name="NewValue#{Field}"> inside the <Fields> section. More examples can be seen in AlertTemplates.xml.

     

    To exclude some fields from being rendered in the email, you should include them in the <DigestNotificationExcludedFields> and <ImmediateNotificationExcludedFields> section.

       Properties Element

    The properties element allows you to include or exclude fields from the list that would be shown in the email notification. The example below demonstrates how to exclude fields for both the immediate and summary (digest) alerts.

    <Properties>

    <ImmediateNotificationExcludedFields>ID;Author;Editor;Modified_x0020_By;Created_x0020_By;_UIVersionString;ContentType;TaskGroup;IsCurrent;Attachments;NumComments;</ImmediateNotificationExcludedFields>

                <DigestNotificationExcludedFields>ID;Author;Editor;Modified_x0020_By;Created_x0020_By;_UIVersionString;ContentType;TaskGroup;IsCurrent;Attachments;NumComments;</DigestNotificationExcludedFields>

            </Properties>

       Customizing the Alert Email

    Alert UI elements

    In addition to the formatting styles defined in the <format> element, alert templates include formatting instructions for user interface elements, such as the Modify my alert settings, Mobile View, and View <list> buttons, which can be modified or removed.

    Modify my alert settings button

    The following code displays the Modify my alert settings button:

    <GetVar Name="MySubsUrl" URLEncodeAsURL="TRUE"/>

                <HTML><![CDATA[">$Resources:Alerts_link_modify;</a></td>

            <td class="toolbarsep">|</td>]]></HTML>

    View list URL button

    The following code displays the List URL button:

    <GetVar Name="ListUrl" URLEncodeAsURL="TRUE" />

                    <HTML><![CDATA[">$Resources:Alerts_link_view; ]]></HTML><GetVar Name="ListName" HTMLEncode="TRUE" />

    Mobile View button

    The following code displays the Mobile View button:

    <Switch>

            <Expr><GetVar Name="MobileUrl"/></Expr>

              <Case Value = "NULL"/>

              <Default>

                  <HTML><![CDATA[

            <td class="toolbarsep">|</td>

            <td class="toolbarbutton"><a href="]]></HTML><GetVar Name="MobileUrl" />

         <HTML><![CDATA[">$Resources:Alerts_mobile_view;</a></td>]]></HTML>

             </Default>

    </Switch>

    Steps to Modify Alerts

    You can use any XML editing tool to edit the templates.

    1.      Create a working copy of AlertTemplates.xml.

    Note   Remember to always modify a copy of Alerttemplates.xml, not Alerttemplates.xml itself.

    2.      Edit the working copy that you just created.

    3.      Use the stsadm command to read the changed templates into the database.
    STSADM -o updatealerttemplates -url <http://urlname> -filename <your working copy filename>.

    4.      Restart IIS.

    Note   It may be necessary to restart SharePoint Timer Services.

    Creating your own alert template

    If you want, you can create your own template, and then use the stsadm command to load that template. Pattern your template after one of the templates in Alerttemplates.xml.

     

    A particular instance of a list can use a specific alert template by setting the SPList.AlertTemplate property with the desired template. Any new alert created for this list through the subnew.aspx or through the object model using SPAlerts.Add(SPList / SPItem, SPEventType, SPAletFrequency) will pick up the alert template defined for the list.

     

    To assign a custom alert template to a specific list

    1.      Create a new custom template with a unique Name attribute in your working copy of AlertTemplates.xml (You can copy paste the entire section with Name SPAlertTemplateType.GenericList, change the name and modify the sections you want to). Modify the template as necessary. After restarting IIS, write object model code to set the list alert template

    SPAlertTemplateCollection ats = new SPAlertTemplateCollection((SPWebService)(WebApplication.Parent)); //give appropriate values for WebApplication

    list.AlertTemplate = ats[“name from above”];

    list.Update();

     

       Event Logs

    Rendering of alert emails occurs some time after the change that generated the alert. Data in the EventCache and EventLog tables is used for rendering the alert since the changed item may no longer exist, or exist in the same form, at the time the email is sent.

    The event log uses a SQL table called the EventCache to record SQL level events as they occur.  Each row in the table corresponds to an event.  The events can be read using the WSS object model.  In general, the number of rows written to the table is the minimum necessary to capture the semantics of the event.  The assumption is that the reader of the event knows how to use the event row to calculate all the implications of a given event.  For example, when a folder is deleted, the folder delete event is the only event written to the change log.  No events are written for the files and sub-folders that are contained in the folder.  The reader of the folder delete event needs to understand that it implies the deletion of the entire contents of the folder.

    By default, the change log retains 15 days worth of data.  You can configure this using the “web application general settings” page.  There is a timer job that runs daily to delete all expired change log entries.

    Change Events

    Change events are returned as objects in an SPChangeCollection.  Each change object is a subclass of the SPChange object.  Depending on the type of SPChange object, different properties are available.  The change collection is created by calling SPSite.GetChanges(), SPWeb.GetChanges(), SPList.GetChanges(), or SPContentDatabase.GetChanges().  An SPChangeToken object is passed into GetChanges() to specify where in the log to begin reading.  An SPChangeToken can be serialized to a string format by calling the ToString() method. 

    Use the SPList.CurrentChangeToken property to get the current change token for that list object.  There is a similar property on the SPSite, SPWeb, and SPContentDatabase objects.  In general, the SPChangeToken from one object cannot be used in the GetChanges() method of another object.  The only exception is that the SPChangeToken from an SPContentDatabase can be used in any object contained in that content database.  There is also an object called an SPChangeTokenCollection which can be used to store multiple change tokens together, that can then be serialized to one single string.

    Change Log Event Types

    The following is a description of the event types recorded in the change log.

    Table 3. Event Types

    Event Type

    Description

    Add

    An object was added.  For items, files and folders, the TimeLastModified in the log should be the same as the Created datetime of the object.

    Modify

    An object was modified.  For items, files and folders, the TimeLastModified in the log should be the same as the modified date time of the object.

    Delete

    An object was deleted.

    Rename

    An object was renamed.  This means that the file name portion of the URL was changed.

    MoveInto/MoveAway

    An object was renamed.  This means that the path portion of the URL was changed.  The leaf portion may or may not have been changed also.

    Restore

    An object was restored from the recycle bin or from a backup. This event signals to a sync client change log reader that it needs to re-sync the object and all its children.

    Role Add

    A role was added at the scope of the object.

    Assignment Add

    A role assignment was added at the scope of the object.

    System Modify

    An object was modified without its Modified date time or Modified By property changing.  The TimeLastModified in the log should be the time that the update took place, not the Modified date time property.

    Member Add

    A member is added to a SharePoint group.

    Member Delete

    A member is deleted from a SharePoint group.

    Role Delete

    A role was deleted at the scope of the object.

    Role Update

    A role was updated at the scope of the object.

    Assignment Delete

    A role assignment was deleted at the scope of the object.

    Navigation

    The navigation nodes were updated at the scope of the object.

     

    Object Types

    The following is a list of the object types that may have changes recorded in the change log.  Not all event types are possible on all object types.

    Table 4. Object Types

    Object Type

    Description

    Item

    This object type applies to all objects that exist in a list: list items, files and folders

    List

    List object type

    Web

    Web object type

    Site

    Site object type

    File

    This object type applies to files that exist outside of a list and don’t have a corresponding item.

    Folder

    This object type applies to folders that exist outside of a list and don’t have a corresponding item.

    Alert

    Alert object type

    User

    User object type

    Group

    Group object type

    ContentType

    Content object type

    Field

    Field object type

    SecurityPolicy

    A security policy change has been made at the web application level that affects the entire content database.  This event was added late in the development cycle, so it and the content database level restore event are logged as a site level event with a SITEID of “00000000-0000-0000-000000000000”

     

       Conclusion

    Alerts are quite flexible; when you create an alert you have options such as when to be notified and what kind of changes will trigger the alert. Alerts can be managed by users and administrators and customized by developers.

    Alerts are generated by a timer job that reads the event log, formats the alert email using an alert template, and then sends that email out to the user.Developers can customize these alert emails by modifying alert templates. Alert templates are stored in Alerttemplates.xml. Alerttemplates.xml defines the format, contents, and properties used to create alert messages from each list type in wssversion3. The <filters> element in each template allows you to create custom triggers for events by using Collaborative Application Markup Language (CAML) queries. Developers can customize alerts by modifying a copy of Alerttemplates.xml and then loading the customized alert templates using the stsadm -o updatealerttemplates command.

     

    In my next post I'll talk about how to use the IAlertNotifyHandler interface to customize alerts. 

     

     

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    How To: Customizing alert emails using IAlertNotifyHandler

    • 22 Comments

    In my post last week I talked about customizing alert notifications and alert templates. Sometimes you need to go further and create an alert handler.  This week I’d like to share a code sample from Rashid Aga, one of our escalation engineers.  His sample demonstrates how to intercept and modify alert mails using the IAlertNotifyHandler interface.

     

    Problem:

    ==============

    There are issues with particular field names like ItemName which will be truncated in an alert email at 70 characters. There can also be situations where you want to embed additional content in the email or change the layout and email appearance altogether.

     

    Solution:

    ==============

    Make use of the IAlertNotifyHandler interface to intercept the email and modify it.

     

    We can create our own class that inherits from the IAlertNotifyHandler interface and uses the OnNotification method. This will allow you to intercept the outgoing alert emails and modify them. We can access most of the properties for the alert and with some xml parsing and SharePoint object model code, we can extract all the information we need to build up the email. We can then construct the HTML stub to display the email based on your requirements and send the email out using SharePoint’s SendMail functionality.

     

    Steps:

    I have included the sample code below along with the steps to set up the scenario. I have formatted the output of my code to resemble the default alert template emails as close as possible, you can customize it further to suit your needs.

     

    1      Create a class project that inhertits from the IAlertNotifyHandler interface. Include the Microsoft.SharePoint and Microsoft.SharePoint.Utilities namespaces in the project.

                        This is the code for the class:

        public class Class1:IAlertNotifyHandler

        {

     

            #region IAlertNotifyHandler Members

     

            public bool OnNotification(SPAlertHandlerParams ahp)

            {

                try

                {

                    SPSite site = new SPSite(ahp.siteUrl+ahp.webUrl);

                    SPWeb web = site.OpenWeb();

                    SPList list=web.Lists[ahp.a.ListID];

                    SPListItem item = list.GetItemById(ahp.eventData[0].itemId) ;

                   

                    string FullPath=HttpUtility.UrlPathEncode(ahp.siteUrl+"/"+ahp.webUrl+"/"+list.Title+"/"+item.Name);

                    string ListPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl + "/" + list.Title);

                    string webPath=HttpUtility.UrlPathEncode(ahp.siteUrl+"/"+ahp.webUrl);

                    

                    string build = "";

                     if (ahp.eventData[0].eventType==1)

                     eventType="Added";

                     else if(ahp.eventData[0].eventType==2)

                     eventType="Changed";

                     else if(ahp.eventData[0].eventType==3)

                     eventType="Deleted";

     

                    build = "<style type=\"text/css\">.style1 {              font-size: small; border: 1px solid #000000;"+

                        "background-color: #DEE7FE;}.style2 {               border: 1px solid #000000;}</style></head>"+                    

                        "<p><strong>"+ item.Name.ToString() +"</strong> has been "+eventType +"</p>"+

                        "<table style=\"width: 100%\" class=\"style2\"><tr><td style=\"width: 25%\" class=\"style1\">"+

                        "<a href="+ webPath +"/_layouts/mysubs.aspx>Modify my Settings</a></td>"+

                        "<td style=\"width: 25%\" class=\"style1\"> <a href="+ FullPath +">View "+item.Name+"</a></td>"+

                        "<td style=\"width: 25%\" class=\"style1\"><a href=" + ListPath + ">View " + list.Title + "</a></td>" +

                        "        </tr></table>";

                    string subject=list.Title.ToString() ;              

                    SPUtility.SendEmail(web,true , false, ahp.headers["to"].ToString(), subject,build);

                    return false;

                }

                catch (System.Exception ex)

                {

                    return false;

                }

            }

     

            #endregion

        }

     

    2.            GAC the dll. 

    3.            Make a copy of the alertTemplates.xml file found at this location: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML. Always work with a copy of AlertTemplates.xml, not the original.

    4.            Call this new file CustomAlertTemplates and save the file. Edit the file and search for the keyword properties:

    Include these additional lines into the properties block:

     

              <NotificationHandlerAssembly>AlertHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d59ecf2a3bd66904</NotificationHandlerAssembly>

              <NotificationHandlerClassName>AlertHandler.Class1</NotificationHandlerClassName>

        <NotificationHandlerProperties></NotificationHandlerProperties>

     

    The entire stub should look like this now:

            <Properties>

                <ImmediateNotificationExcludedFields>ID;Author;Editor;Modified_x0020_By;Created_x0020_By;_UIVersionString;ContentType;TaskGroup;IsCurrent;Attachments;NumComments;</ImmediateNotificationExcludedFields>

                <DigestNotificationExcludedFields>ID;Author;Editor;Modified_x0020_By;Created_x0020_By;_UIVersionString;ContentType;TaskGroup;IsCurrent;Attachments;NumComments;</DigestNotificationExcludedFields>

                <NotificationHandlerAssembly>AlertHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d59ecf2a3bd66904</NotificationHandlerAssembly>

                    <NotificationHandlerClassName>AlertHandler.Class1</NotificationHandlerClassName>

                    <NotificationHandlerProperties></NotificationHandlerProperties>

      </Properties>

     

    Include this xml stub in each alert template section you want in the alert template file.

     

    5.            Run this command from C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN:  stsadm -o updatealerttemplates -filename "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML\customalerttemplates.xml" -url <your sharepoint site url>

    6.            Run this command:  stsadm -o setproperty -pn job-immediate-alerts -pv "every 1 minutes" so that you can see the log file come back in one minute. Be sure to set the time back after testing.

    7.            Make sure you have SharePoint already configured for outgoing emails.

    8.            Make sure that you have alerts for the document library turned on if you are testing with the document library. 

    9.            Run this command from the command prompt: iisreset

    10.         Run this command from the command prompt: services.msc

    11.         From the services window, restart the Windows SharePoint Services Timer.

     

    Your custom email alert handler should be configured at this point. Create a new alert and you should get the updated custom email.

     

    Once again, my thanks to Rashid for this sample.

     

  • Microsoft SharePoint Developer Documentation Team Blog

    Application Lifecycle Management in Microsoft SharePoint 2010

    • 14 Comments

    Update, February 10, 2011: See the MSDN version of this article: Application Lifecycle Management in Microsoft SharePoint 2010.

    November 2010

    Applies to: Microsoft SharePoint Foundation 2010, Microsoft SharePoint Server 2010, Microsoft Visual Studio 2010 SharePoint Developer Tools, Microsoft Visual Studio 2010 Team Foundation Server and Microsoft SharePoint Designer 2010

    Summary: Learn how to plan and manage Application Lifecycle Management (ALM) in Microsoft SharePoint 2010 projects using Visual Studio 2010 and Microsoft SharePoint Designer 2010. Also learn what things should be considered when setting up team development environments, establishing upgrade management processes, and creating a standard development model.

    Introduction to Application Lifecycle Management in SharePoint 2010

    The Microsoft SharePoint 2010 development platform, which includes SharePoint Foundation 2010 (SPF2010) and SharePoint Server 2010 (SPS2010), contains many capabilities to help you develop, deploy, and update customizations and custom functionalities for your SharePoint sites. The activities that take advantage of these capabilities all fall under the category of Application Lifecycle Management (ALM).

    Key considerations when establishing ALM processes include not only the development and testing practices that you use before the initial deployment of a single customization, but also the processes that you must implement in order to manage updates and integrate customizations and custom functionality on an existing farm. This article discusses the capabilities and tools that you can use when implementing an ALM process on a SharePoint farm, and also specific concerns and considerations to take into account when you create and hone your ALM process for SharePoint development.

    This article assumes that each development team will develop a unique ALM process that fits its specific size and needs, so its guidance is necessarily broad. It also assumes, however, that regardless of the size of your team and the specific nature of your custom solutions, you will need to address similar sets of concerns and utilize capabilities and tools that are common to all SharePoint developers. The guidance in this article will help you as create a development model that exploits all the advantages of the SharePoint 2010 platform and addresses the needs of your organization.

    SharePoint Application Lifecycle Management: An Overview

    Figure 1 depicts a sample ALM process for a midsize or large SharePoint 2010 deployment. Obviously the process and required tasks depend on the project size.

    image

    These are the steps illustrated in figure 1:

    1. Initial requirements are collected and turned into tasks.

    2. Developers use Visual Studio 2010 Team Foundation Server or other tools to track the development progress and store custom source code.

    3. Since source code is stored in a centralized location, you can create automated builds for integration and unit testing purposes. You can also automate testing activities to increase the overall quality of the customizations.

    4. In larger projects, there could also be an additional build verification or user acceptance testing (UAT) farm, which is used by QA personnel to test and verify the builds in an environment that more closely resembles the production environment. Typically a build verification farm has multiple servers to ensure that custom solutions are deployed properly. Figure 2 illustrates a potential model for relating development integration and testing environments, build verification farms, and production environments. In this particular model, the pre-production or QA farm and the production farm switch places after each release. This model minimizes any downtime related to maintaining the environments.

    image

    5. After custom solutions have successfully undergone acceptance testing, you can continue to the pre-production or quality assurance environment.

    6 and 7. The pre-production environment should resemble the production environment as much as possible. This often means that the pre-production environment has the same patch level and configurations as the production environment. The objective of this environment is to ensure that your custom solutions will work in production. The production database can be copied to this environment occasionally, so that you can imitate the upgrade actions that will be performed in the production environment.

    8 and 9. After the customizations are verified in the pre-production environment, they are deployed either directly to production or to a production staging environment and then to production.

    10. The production environment is used by end users, who give feedback and ideas concerning the different functionalities. Issues and bugs are reported and tracked through established reporting and tracking processes.

    11. Feedback, bugs, and other issues in the production environment are turned into requirements, which are prioritized and turned into developer tasks. Figure 3 illustrates how multiple developer teams can work with and process bug reports and change requests received from end users of the production environment. The model in this figure also illustrates how development teams might also coordinate their solution packages. For example, the framework and the functionality development teams might follow separate versioning models that need to be coordinated as they track bugs and changes.

    image

    Another significant consideration in your ALM model is SharePoint Designer 2010. SharePoint 2010 is an excellent platform for no-code solutions, which can be made and deployed directly to the production environment by using SharePoint Designer 2010. These customizations are stored in the content database and are therefore not stored in your source code repository. Designer activities in general are another consideration. Will you be creating new page layouts directly within your production environment, or will you deploy them as part of your packaged solutions? There are advantages and disadvantages to both options.

    Your own ALM model depends completely on the custom solutions and the customizations that you plan to make, and on your own policies. Your ALM process does not have to be as complex as the one described in this section. However, you will need to establish a firm ALM model early in the process as you plan and create your development environment and before you start creating your custom solutions.

    The following section discusses specific tools and capabilities related to SharePoint 2010 development that you can use when considering how to create a model for SharePoint ALM that will work best for your development team.

    Solution Packages and the SharePoint Tools Continuum

    One major advantage of the SharePoint 2010 development platform is that it provides the ability to save sites as solution packages. A solution package is a deployable, reusable package stored in a .cab format file with a .wsp extension. You can create a solution package either by using the SharePoint 2010 user interface in the browser, SharePoint Designer 2010, or Microsoft Visual Studio 2010. In the browser and SharePoint Designer 2010 user interfaces, solution packages are also called templates. This flexibility allows you to create and design site structures in a browser and/or in SharePoint Designer and then import these customizations into Visual Studio 2010 for further development. Figure 4 illustrates this continuum.

    image

    When the customizations are complete, you can deploy your solution package to SharePoint and use it there. After modifying the existing site structure with a browser, you can start the cycle all over again by saving the updated site as a solution package.

    This tools continuum also enables you to use other tools. For example, you can design a workflow process in Microsoft Visio 2010 and then import it to SharePoint Designer 2010 and from there to Visual Studio 2010. For instructions on how to do this, see Create, import, and export SharePoint workflows in Visio.

    For more information on creating solution packages in SharePoint Designer 2010, see Save a SharePoint Site as a Template. For more information on creating solution packages in Visual Studio 2010, see Creating SharePoint Solution Packages.

    Using SharePoint Designer 2010 as a Development Tool

    SharePoint Designer 2010 differs from Microsoft SharePoint Designer 2007 in that its orientation has shifted from the page to features and functionality. The improved user interface provides greater flexibility for creating and designing different functionalities. It provides rich tooling for building complete, rich, reusable and process-centric applications. For more information about the new capabilities and features of SharePoint Designer 2010, see Getting Started with SharePoint Designer.

    You can also use SharePoint Designer 2010 to modify modular components developed with Visual Studio 2010. This means, for example, that you can create web parts and other controls with Visual Studio 2010, deploy them to a SharePoint farm, and then edit them in SharePoint Designer 2010.

    The primary target users for SharePoint Designer 2010 are IT personnel and information workers who can use this application to create customizations in a production environment. For this reason, you will need to decide on an ALM model for your particular environment that defines which kinds of customizations will follow the complete ALM development process and which customizations can be done by using SharePoint Designer 2010. Developers are secondary target users. They can use SharePoint Designer 2010 as a part of their development activities, especially during initial creation of customization packages and also for rapid development and prototyping. Your ALM process also needs to define where and how to fit SharePoint Designer 2010 into the broader development model.

    A key challenge of using SharePoint Designer 2010 is that when you use it to modify files, all of your changes are stored in the content database instead of the file system. For example, if you customize a master page for a specific site by using SharePoint Designer 2010 and then design and deploy new branding elements inside a solution package, the changes will not be available for the site with the customized master page, since that site is using the version of the master page that is stored in the content database.

    To minimize these kinds of challenges, SharePoint Designer 2010 contains new features that enable you to control usage of SharePoint Designer 2010 in a specific environment. You can apply these control settings at the web application or site collection level. If you disable some action at the web application level, that setting cannot be changed at the site collection level.

    SharePoint Designer 2010 makes the following settings available:

    • Allow site to be opened in SharePoint Designer 2010.
    • Allow customization of files.
    • Allow customization of master pages and layout pages.
    • Allow site collection administrators to see the site URL structure.

    These settings are ignored if you use the farm administration account.

    Since the primary purpose of SharePoint Designer 2010 is to customize content on an existing site, it does not support source code control. Pages that you customize by using SharePoint Designer 2010 are by default stored inside a versioned SharePoint library. This provides you with simple support for versioning, but not for full-featured source code control.

    Importing Solution Packages into Visual Studio 2010

    When you save a site as a solution package in the browser (from the Save as Template page in Site Settings), SharePoint 2010 stores the site as a .wsp file and places it in the Solutions Gallery of that site collection. You can then download the solution package from the Solutions Gallery and import it into Visual Studio 2010 by using the Import SharePoint Solution Package template, as illustrated in figure 5.

    image

    SharePoint 2010 solution packages contain a number of improvements that take advantage of new capabilities that are available in its feature framework. The following list contains some of the new feature elements that will be helpful to you in managing your development projects and upgrades (many of which are discussed later in this article).

    • SourceVersion for WebFeatures and SiteFeatures
    • WebTemplate feature element
    • PropertyBag feature element
    • $ListId:Lists
    • WorkflowAssociation Feature Element
    • CustomSchema attribute on ListInstance
    • Solution Dependencies

    After you have imported your project, you can start customizing it any way you like. Note that since this capability is based on the WebTemplate feature element, which is based on a corresponding site definition, the resulting solution package will contain definitions for everything within the site. See Web Templates for more information about creating and using web templates.

    Visual Studio 2010 supports source code control (as shown in figure 6), so you can store the source code for your customizations in a safe and secure central location and enable easy sharing of customizations among developers.

    image

    The precise manner in which your developers will access this source code and interact with each other depends on the structure of your team development environment. The next section of this article discusses key concerns and considerations that you should consider when you build a team development environment for SharePoint 2010.

    Team Development Environment for SharePoint 2010: An Overview

    As any ALM planning process, your SharePoint 2010 planning should include the following steps:

    1. Identify and create a process for initiating new projects.
    2. Identify and implement a versioning system for your source code and other deployed resources.
    3. Plan and implement version control policies.
    4. Identify and create a process for work item and defect tracking and reporting.
    5. Write documentation for your requirements and plans.
    6. Identify and create a process for automated builds and continuous integration.
    7. Standardize your development model for repeatability.

    Visual Studio 2010 Team Foundation Server (illustrated in figure 7) provides a good potential platform for many of these elements of your ALM model.

    image

    When you have established your model for team development, you will need to choose either a collection of tools or Microsoft Visual Studio 2010 Team Foundation Server to manage your development. Team Foundation Server provides direct integration into Visual Studio, and it can be used to manage your development process efficiently. It provides many capabilities, but your actual usage of it will depend on your projects.

    You can use the Team Foundation Server for the following activities.

    • Track work items and report the progress of your development. Team Foundation Server provides tools to create and modify work items that are delivered not only from Visual Studio 2010, but also from the Visual Studio 2010 web client.
    • Store all source code for your custom solutions.
    • Log bugs and defects.
    • Create, execute and manage your testing with comprehensive testing capabilities.
    • Enable continuous integration of your code by using the automated build capabilities.

    Visual Studio 2010 Team Foundation Server also provides a basic installation option that installs all required functionalities for source control and automated builds. These are typically the most heavily used capabilities of Team Foundation Server and this helps you set up your development environment more easily.

    Setting up a Team Development Environment for SharePoint 2010

    SharePoint 2010 must be installed on a development machine in order to take full advantage of its development capabilities. If you are developing only remote applications, such as solutions that use SharePoint web services, the client object model or REST, you could potentially develop solutions on a computer where SharePoint 2010 is not installed. Even in this case, however, your developers' productivity would suffer, since they would not be able to take advantage of the full debugging experience that comes with having SharePoint 2010 installed directly on the development computer.

    The design of your development environment will depend on the size and needs of your development team. Your choice of operating system will also have a significant impact on the overall design of your team development process. You have three main options for creating your development environments.

    You can run SharePoint directly on your computer's client operating system. This option is available only when you use the 64-bit version of Windows 7, Windows Vista Service Pack 1, or Windows Vista Service Pack 2.

    You can use the boot to VHD option, which means that you start your laptop using the operating system in VHD. This option is only available when you use Windows 7 as your primary operating system.

    You can use virtualization capabilities. If you choose to take advantage of virtualization capabilities, you have a choice of numerous options, but from an operational point of view, the option that is most likely to be the easiest to implement is a centralized virtualized environment that hosts each developer's individual development environment.

    The following sections take a closer look at these three options.

    SharePoint on a Client Operating System

    If you are using the 64-bit version of Windows 7, Windows Vista Service Pack 1, or Windows Vista Service Pack 2, you can install SharePoint Foundation or SharePoint Server. See Setting Up the Development Environment for SharePoint 2010 on Windows Vista, Windows 7, and Windows Server 2008 for more information on installing SharePoint 2010 on supported operating systems.

    Figure 8 illustrates how a computer running a client operating system would operate within a team development environment.

    image

    A benefit of this approach is that you can take full advantage of any existing hardware that you own that is running one of the targeted client operating systems. You can also take advantage of pre-existing configurations, domains, and enterprise resources that your enterprise supports. This could mean that little or no additional IT support would be required. Your developers would also face no delays (such as booting up a virtual machine, accessing an environment remotely, etc.) in accessing their development environments.

    If you take this approach, however, you will need to make sure that your developers have access to sufficient hardware resources. In any development environment, you should use a computer with an x64-capable CPU, and at least 2 gigabytes (GB) of RAM to install and run SharePoint Foundation; 4 GB of RAM is preferable for good performance. You should use a computer with 6 GB to 8 GB of RAM to install and run SharePoint Server.

    A disadvantage of this approach is that your environments will not be centrally managed, and it will be difficult to keep all of your project-dependent environmental requirements in sync. It might also be advisable to write batch files that start and stop some of the SharePoint-related services so that when your developers are not working with SharePoint, these services will not consume resources and degrade the performance of their computers.

    The lack of centralized maintenance could hurt developer productivity in other ways. For example, this might be an unwieldy approach if your team is working on a large SharePoint Online project that is developing custom solutions for multiple services (for example, the equivalents of http://intranet, http://mysite, http://teams, http://secure, http://search, http://partners, and http://www.internet.com) and deploying these solutions in multiple countries. If you are developing on a computer that is running a client operating system in a corporate domain, each development computer would have its own name (and each local domain name would be different, such as http://dev 1, http://dev2, etc.). If each developer is implementing custom functionalities for multiple services, you will have to use different port numbers to differentiate each service (for example, http://dev1 for http://intranet and http://dev1:81 for http://mysite ). If all of your developers are using the same Visual Studio 2010 projects, the project debugging URL will have to be changed manually whenever a developer takes the latest version of a project from your source code repository. This would create a manual step that could hurt developer productivity, and it would also diminish the efficiency of any scripts that you have written for setting up development environments, since the individual environments are not standardized. Some form of centralization with virtualization is preferable for large enterprise development projects.

    Windows 7 and Boot to VHD

    If you are using Windows 7, you can also create a virtual hard drive (VHD) out of an existing Windows Server 2008 image on which SharePoint is installed in Windows Hyper-V, and then configure Windows 7 with BDCEdit.exe so that it boots directly to the operating system on the VHD. See Deploy Windows on a Virtual Hard Disk with Native Boot and Boot from VHD in Win 7 to learn more about this kind of configuration.

    Figure 9 illustrates how a computer running Windows 7 and booting to VHD would operate within a team development environment.

    image

    An advantage of this approach is the flexibility of having multiple dedicated environments for an individual project, enabling you to isolate each development environment. Your developers will not accidently cross reference any artifacts within their projects, and they can create project-dependent environments.

    This option also comes with considerable hardware requirements, though, since you are directly utilizing the available hardware and resources on your computers.

    Centralized Virtualized Environments

    In a centralized virtualized environment, you host your development environments in one centralized location, and developers access these environments through remote connections. This means that you use Windows Hyper-V in the centralized location and copy a VHD for every developer as required. Each VHD is configured to be accessible from the corporate network, so that when it starts, it can be accessed using remote connections.

    Figure 10 illustrates how a centralized virtualized team development environment would operate.

    image

    An advantage of this approach is that the hardware requirements for individual developer computers are relatively light since the actual work happens in a centralized environment. Developers could even use computers with 1 GB of RAM as their clients and then connect remotely to the centralized location. You can also easily manage environments from one centralized location, making adjustments to them whenever necessary.

    Your centralized host will have significantly high hardware requirements, but developers can easily start and stop these environments. This enables you to use the hardware that you have allocated for your development environments more efficiently. Additionally, this approach provides a ready platform for more extensive testing environments for your custom code (such as multi-server farms).

    Once you have set up your team development environment, you can start taking advantage of the deployment and upgrade capabilities that come with the new solution packaging model in SharePoint 2010. The following sections describe how to take advantage of these new capabilities in your ALM model.

    Models for Solution Lifecycle Management in SharePoint 2010

    The SharePoint 2010 solution packaging model provides a number of useful features that will help you plan for deploying custom solutions and managing the upgrade process. You can implement assembly versioning by applying binding redirects in your web application configuration file. You can also apply versioning to your feature upgrades, and feature upgrade actions enable you to manage changes that will be necessary on your existing sites in order to accommodate feature upgrades. These upgrade actions can be handled declaratively or programmatically.

    The feature upgrade query object model enables you to create queries in your code that look for features on your existing sites that can be upgraded. You can use this object model to get relevant information about all of the features and feature versions that are deployed on your SharePoint 2010 sites. You can also configure in your solution manifest file the type of IIS recycling that you want to be performed during a solution upgrade.

    The following sections go into greater details about these capabilities and how you can use them.

    Assembly BindingRedirect

    The BindingRedirect feature element can be added to your web applications configuration file. It enables you to redirect from older versions of installed assemblies to newer versions. The XML configuration from the solution manifest file in figure 11 instructs SharePoint to add binding redirection rules to the web application configuration file. These rules forward any reference to version 1.0 of the assembly to version 2.0. This is required in your solution manifest file if you are upgrading a custom solution that uses assembly versioning and if there are existing instances of the solution and the assembly on your sites.

    image

    It is a best practice to use assembly versioning, since it gives you an easy way to track the versions of a solution that are deployed to your production environments.

    Feature Versioning

    The support for feature versioning in SharePoint 2010 provides a large number of capabilities that you can use when you are upgrading features. For example, you can use the SPFeature.Version property to determine which versions of a feature are deployed on your farm, and which features therefore need to be upgraded. See SPFeature.Version Property for a code sample that demonstrates how to do this.

    Feature versioning in SharePoint 2010 also allows you to define a value for the SPFeatureDependency.MinimumVersion property to handle feature dependencies. For example, you can use the MinimumVersion property to ensure that a particular version of a dependent feature is activated. Feature dependencies can be added or removed in each new version of a feature.

    The SharePoint 2010 feature framework has also enhanced the object model level to support feature versioning more easily. You can use the QueryFeatures method to retrieve a list of features, and you can specify both feature version and whether a feature needs an upgrade. The QueryFeatures method returns an instance of SPFeatureQueryResultCollection instance, which you can use to access all of the features that need to be updated. This method is available from multiple scopes, since it is available from the SPWebService, SPWebApplication, SPContentDatabase and SPSite classes. For more information about this overloaded method, see SPSite.QueryFeatures, SPWebService.QueryFeatures, SPWebApplication.QueryFeatures, and SPContentDatabase.QueryFeatures. For an overview of the feature upgrade object model, see Feature Upgrade Object Model.

    The following section summarizes many of the new upgrade actions that you can apply when you are upgrading from one version of a feature to another.

    Feature Upgrade Actions

    Upgrade actions are defined in the Feature.xml file. The SPFeatureReceiver class contains a FeatureUpgrading method, which you can use to define actions to perform during an upgrade. This method is called during feature upgrade when the feature's Feature.xml file contains one or more CustomUpgradeAction tags, as in the following example:

    <UpgradeActions>

    <CustomUpgradeAction Name="text">

    ...

    </CustomUpgradeAction>

    </UpgradeActions>

    Each custom upgrade action has a name, which can be used to differentiate the code that needs to be executed in the feature receiver. As in following example, you can parameterize custom action instances.

    image

    This example contains two CustomUpgradeAction elements, one named "example" and the other named "SecondAction." Both elements have different parameters, which are dependent on the code that you have written for the FeatureUpgrading event receiver. The following example demonstrates how you can use these upgrade actions and their parameters in your code.

    image

    You can have as many upgrade actions as you want, and you can apply them to version ranges. The following example illustrates how you can apply upgrade actions to version ranges of a feature.

    image

    The AddContentTypeField upgrade action can be used to define additional fields for an existing content type. It also provides the option of pushing these changes down to child instances, which is often the desired behavior. When you initially deploy a content type to a site collection, a definition for it is created at the site collection level. If that content type is used in any sub-site or list, a child instance of the content type will be created. To ensure that every instance of the specific content type is updated, you will need to set the PushDown attribute to true, as in the following example.

    image

    See Introduction to Content Types for more information about working with content types programmatically.

    The ApplyFeatureManifests upgrade action can be used to apply new artifacts to a SharePoint 2010 site without reactivating features. Just as you can add new elements to any new SharePoint elements.xml file, you can instruct SharePoint to apply content from a specific elements file to sites where a given feature is activated.

    You can use this upgrade action if you are upgrading an existing feature whose FeatureActivating event receiver performs actions that you do not want to execute again on sites where the feature is deployed. The following example demonstrates how to include this upgrade action in a feature.xml file.

    image

    An example of a use case for this upgrade action involves adding new .webpart files to a feature in a site collection. You can use the ApplyElementManifest upgrade action to add those files without reactivating the feature. Another example would involve page layouts, which contain initial web part instances that are defined in the file element structure of the feature element file. If you reactivate this feature, you will get duplicates of these web parts on each of the page layouts. In this case, you can use the ElementManifest element of the ApplyFeatureManifests upgrade action to add new page layouts to a site collection that uses the feature without reactivating the feature.

    The MapFile element enables you to map a URL request to an alternative URL. The following example demonstrates how to include this upgrade action in a feature.xml file.

    image

    This would be useful to you in a case where you need to deploy a new version of a page that has been customized by using SharePoint Designer 2010. The resulting customized page would be served from the content database. When you deploy the new version of the page, the new version will not appear because content for that page is coming from the database and not from the file system. You could work around this problem by using the MapFile element to redirect requests for the old version of the page to the newer version.

    It is important to note that the FeatureUpgrading method will be called for each feature instance that is to be updated. If you have 10 sites in your site collection and you update a web-scoped feature, the feature receiver will be called 10 times for each site context. See Feature.xml Changes for more information about how to use these new declarative feature elements.

    Upgrading Features: A High Level Walkthrough

    This section describes at a high level how you can put these feature versioning and upgrading capabilities to work. When you create a new version of a feature that has already been deployed on a large SharePoint farm, you need to consider two different scenarios: what happens when the feature is activated on a new site and what happens on sites where the feature already exists. When you add new content to the feature, you will first need to update all of the existing definitions and include instructions for upgrading the feature where it is already deployed.

    For example, say that you have developed a content type to which you need to add an additional custom site column. You need to add a new column called City to the previously deployed content type. First, you add a new element file to the feature. This element file defines the new site column and modifies the feature.xml to include the element file. The second step is to update the existing definition of the content type in the existing feature element file. This update will apply to all sites where the feature is newly deployed and activated. The third step is to define the required upgrade actions for the existing sites. In this case you will need to ensure that the newly added element file for the additional site column is deployed and that the new site column is associated with the existing content types. To achieve these two objectives you will add the ApplyFeatureManifests and the AddContentTypeField upgrade actions to your feature.xml file.

    When you deploy the new version of the feature to existing sites and upgrade it, the upgrade actions will be applied to sites one by one. If you have defined custom upgrade actions, the FeatureUpgrading method will be called as many times as there are instances of the feature activated in your site collection or farm.

    Figure 12 illustrates how the different components of this scenario fit together when you perform the upgrade.

    image

    Different sites might have different versions of a feature deployed on them. In this case you can create version ranges, which define specific actions to be performed when you are upgrading from one version to another. If a version range has not been defined, all upgrade actions will be applied during each upgrade.

    Figure 13 illustrates how different upgrade actions can be applied to version ranges.

    image

    In this example, if a given site is upgrading directly from version 1.0 to version 3.0, all configurations will be applied, since you have defined specific actions for upgrading from version 1.0 to version 2.0 and from 2.0 to version 3.0. You have also defined actions that will be applied regardless of feature version.

    Code Design Guidelines

    To provide more flexibility for your code, you should not place your upgrade code directly inside the FeatureUpgrading event receiver. Instead put the code in some centralized location and refer to it inside the event receiver, as illustrated in figure 14.

    image

    By placing your upgrade code inside a centralized utility class you increase both the reusability and the testability of your code, since you can perform the same actions in multiple locations. You should also try to design your custom upgrade actions as generically as possible, using parameters to make them applicable to specific upgrade scenarios.

    Upgrading Solutions

    If you are upgrading a farm (full-trust) solution, you will first have to deploy the new version of your solution package to a farm.

    Execute either of the following scripts from the command line to deploy updates to a SharePoint farm. The first example uses the stsadm command-line tool.

    stsadm -o upgradesolution -name solution.wsp -filename solution.wsp

    The second example uses the Update-SPSolution Windows Powershell cmdlet.

    Update-SPSolution -Identity contoso_solution.wsp -LiteralPath c:\contoso_solution_v2.wsp -GACDeployment

    After the new version is deployed, you can perform the actual upgrade which executes the upgrade actions that you have defined in your feature.xml files.

    A farm solution upgrade can be performed either farm-wide or at a more granular level by using the object model. A farm-wide upgrade is performed by using the psconfig command line tool, as in the following example.

    psconfig -cmd upgrade -inplace b2b

    Note that this tool causes a service break on the existing sites. During the upgrade, all feature instances throughout the farm for which newer versions are available will be upgraded. You can also perform upgrades for individual features at the site level by using the Upgrade method of the SPFeature class. This method will cause no service break on your farm, but you are responsible for managing the version upgrade from your code. See SPFeature.Upgrade for a code example that demonstrates how to use this method.

    Upgrading a sandboxed solution at the site collection level is much more straightforward. Simply upload the .wsp file that contains the upgraded features. If you have a previous version of a sandboxed solution in you solution gallery and you upload a newer version, an Upgrade option will become available in the user interface, as illustrated in figure 15.

    image

    After you select the Upgrade option and the upgrade is started, all features inside the sandbox solution will be upgraded.

    Conclusion

    This article has discussed some considerations and examples of ALM design, and it has also enumerated and described the most important capabilities and tools that you can integrate into the ALM processes that you choose to establish in your own enterprise. The SharePoint 2010 feature framework and solution packaging model provide a great deal of flexibility and power that you can put to work in your own ALM processes.

    Additional Resources

    For more information, see the following resources:

    · MSDN: Team-Based Development in Microsoft Office SharePoint Server 2007

    · MSDN: Understanding and Creating Customized and Uncustomized Files in Windows SharePoint Services 3.0

    · MSDN: Administrator and Developer Guide to Code Access Security in SharePoint Server 2007

    · MSDN: ASP.NET vs. SharePoint: How Development Differs

    · MSDN: Business Connectivity Services in SharePoint Foundation 2010

    · MSDN: Sandboxed Solutions

    · MSDN: Setting Up the Development Environment for SharePoint 2010 on Windows Vista, Windows 7 and Windows Server 2008

    · MSDN: Using Visual Studio for SharePoint Development

    · MSDN: Using SharePoint Designer for SharePoint Development

    · Microsoft Patters & Practices: SharePoint Guidance

    · SharePoint Team Blog: Managing Upgrades on Sandbox Solutions

  • Microsoft SharePoint Developer Documentation Team Blog

    How to Create a Web Part with a Contextual Tab

    • 13 Comments

    This post will cover how to create a Web Part that opens a contextual tab on the Server ribbon in Microsoft SharePoint Foundation 2010. You will be working with Server ribbon XML, EcmaScript (JavaScript, JScript), and C# code. This solution will be a farm solution and will be built using Visual Studio 2010 Beta 2. If you have any questions, please feel free to leave a comment.

     The following will appear in a future version of the SDK. It is preliminary documentation and subject to change.

    First, you will create a new project. Click on File, New, and then Project.

    1. Under Visual C#, choose Empty SharePoint Project and enter ContextualTabWebPart for the Name. Click OK.

    2.       In the SharePoint Customization Wizard, choose Deploy as a farm solution. Click Finish.

    Now, you will implement the Web Part.

    3.  In the Solution Explorer, right click References and choose Add Reference.

    4.  On the Add Reference dialog, choose the .NET Tab. Select Microsoft.Web.CommandUI.dll. Click OK.

    5.  Right click on the ContextualTabWebPart project in the Solution Explorer and choose Add, New Item...

    6.   In the Add New Item dialog, choose Web Part. Enter ContextualTabWebPart as the name.

    7.  When the Web Part has been added and ContextualTabWebPart.cs file is shown, add the following using statements.

    using System.Xml;

    using Microsoft.Web.CommandUI;

     

    8.  Now, you need to implement the IWebPartPageComponentProvider interface as follows. You will work with this later.

    public class ContextualTabWebPart : WebPart, IWebPartPageComponentProvider

     

    9.  Next, you will create two global string variables for the ribbon XML. These two variables define the contextual tab and the group template. For a more in-depth discussion on defining a tab and group template, see How to Add a Tab to the Server Ribbon in SharePoint Foundation. In the contextualTab string, you will notice a ContextualGroup element. This element defines the following Tab element as a contextual tab. The Color attribute defines the color of the tab when it renders. The Id and ContextualGroupId are simply unique identifiers for the group. The Sequence attribute defines where the contextual tab will render. The following code implements the two global string variables.

            private string contextualTab = @"

       <ContextualGroup Color=""Magenta""

         Command=""CustomContextualTab.EnableContextualGroup""

         Id=""Ribbon.CustomContextualTabGroup""

         Title=""Custom Contextual Tab Group""

         Sequence=""502""

         ContextualGroupId=""CustomContextualTabGroup"">

              <Tab

                  Id=""Ribbon.CustomTabExample""

                  Title=""My Custom Tab""

                  Description=""This holds my custom commands!""

                  Command=""CustomContextualTab.EnableCustomTab""

                  Sequence=""501"">

                <Scaling

                  Id=""Ribbon.CustomTabExample.Scaling"">

                  <MaxSize

                    Id=""Ribbon.CustomTabExample.MaxSize""

                    GroupId=""Ribbon.CustomTabExample.CustomGroupExample""

                    Size=""OneLargeTwoMedium""/>

                  <Scale

                    Id=""Ribbon.CustomTabExample.Scaling.CustomTabScaling""

                    GroupId=""Ribbon.CustomTabExample.CustomGroupExample""

                    Size=""OneLargeTwoMedium"" />

                </Scaling>

                <Groups Id=""Ribbon.CustomTabExample.Groups"">

                  <Group

                    Id=""Ribbon.CustomTabExample.CustomGroupExample""

                    Description=""This is a custom group!""

                    Title=""Custom Group""

                    Command=""CustomContextualTab.EnableCustomGroup""

                    Sequence=""52""

                    Template=""Ribbon.Templates.CustomTemplateExample"">

                    <Controls

                      Id=""Ribbon.CustomTabExample.CustomGroupExample.Controls"">

                      <Button

                        Id=""Ribbon.CustomTabExample.CustomGroupExample.HelloWorld""

                        Command=""CustomContextualTab.HelloWorldCommand""

                        Sequence=""15""

                        Description=""Says hello to the World!""

                        LabelText=""Hello, World!""

                        TemplateAlias=""cust1""/>

                      <Button

                        Id=""Ribbon.CustomTabExample.CustomGroupExample.GoodbyeWorld""

                        Command=""CustomContextualTab.GoodbyeWorldCommand""

                        Sequence=""17""

                        Description=""Says good-bye to the World!""

                        LabelText=""Good-bye, World!""

                        TemplateAlias=""cust2""/>

                    </Controls>

                  </Group>

                </Groups>

              </Tab>

       </ContextualGroup>";

     

            private string contextualTabTemplate = @"

              <GroupTemplate Id=""Ribbon.Templates.CustomTemplateExample"">

                <Layout

                  Title=""OneLargeTwoMedium"" LayoutTitle=""OneLargeTwoMedium"">

                  <Section Alignment=""Top"" Type=""OneRow"">

                    <Row>

                      <ControlRef DisplayMode=""Large"" TemplateAlias=""cust1"" />

                    </Row>

                  </Section>

                  <Section Alignment=""Top"" Type=""TwoRow"">

                    <Row>

                      <ControlRef DisplayMode=""Medium"" TemplateAlias=""cust2"" />

                    </Row>

                    <Row>

                      <ControlRef DisplayMode=""Medium"" TemplateAlias=""cust3"" />

                    </Row>

                  </Section>

                </Layout>

              </GroupTemplate>";

     

    10.  Create a new string property called DelayScript. DelayScript contains EcmaScript (JavaScript, JScript) that adds and registers your custom page component. We will create the custom page component later in this topic. The _addCustomPageComponent method creates your custom page component and adds it to the page manager. Every Web Part has a page component, and you will use the Web Part's page component id when you create a custom page component object. This is necessary to associate the Web Part with the page component to enable contextually switching to your custom ribbon tab. The _registerCustomPageComponent method registers your EcmaScript file when the page loads. The following code implements DelayScript .

            public string DelayScript

            {

                get

                {

                    string webPartPageComponentId = SPRibbon.GetWebPartPageComponentId(this);

                    return @"

    <script type=""text/javascript"">

    //<![CDATA[

     

                function _addCustomPageComponent()

                {

                    var _customPageComponent = new ContextualTabWebPart.CustomPageComponent('" + webPartPageComponentId + @"');

                    SP.Ribbon.PageManager.get_instance().addPageComponent(_customPageComponent);

                }

     

                function _registerCustomPageComponent()

                {

                    SP.SOD.registerSod(""CustomContextualTabPageComponent.js"", ""\/_layouts\/CustomContextualTabPageComponent.js"");

                    SP.SOD.executeFunc(""CustomContextualTabPageComponent.js"", ""ContextualWebPart.CustomPageComponent"", _addCustomPageComponent);

                }

                SP.SOD.executeOrDelayUntilScriptLoaded(_registerCustomPageComponent, ""sp.ribbon.js"");

    //]]>

    </script>";

                }

            }

    11.  Create a new function called AddContextualTab. Inside the AddContextualTab method, you will insert code to register the contextual tab and custom templates with the ribbon. The Microsoft.Web.CommandUI.Ribbon.RegisterDataExtension method will be used to register the ribbon extensions. RegisterDataExtension tells the ribbon where to load the XML passed into it. We will use the ids of the ContextualTabs and Templates elements in CMDUI.xml. The following code implements the AddContextualTab method.

            private void AddContextualTab()

            {

     

                //Gets the current instance of the ribbon on the page.

                Microsoft.Web.CommandUI.Ribbon ribbon = SPRibbon.GetCurrent(this.Page);

     

                //Prepares an XmlDocument object used to load the ribbon extensions.

                XmlDocument ribbonExtensions = new XmlDocument();

     

                //Load the contextual tab XML and register the ribbon extension.

                ribbonExtensions.LoadXml(this.contextualTab);

                ribbon.RegisterDataExtension(ribbonExtensions.FirstChild, "Ribbon.ContextualTabs._children");

     

                //Load the custom templates and register the ribbon extension.

                ribbonExtensions.LoadXml(this.contextualTabTemplate);

                ribbon.RegisterDataExtension(ribbonExtensions.FirstChild, "Ribbon.Templates._children");

            }

     

    12.  Now, you need to implement the WebPartContextualInfo property of the IWebPartPageComponentProvider interface. You can implement the interface by right clicking on IWebPartPageComponentProvider and choosing Implement Interface, Implement Interface Explicitly.

     

    This interface lets the ribbon know when a Web Part has been selected and which contextual group and tab to show. When you add the contextual group, you send it the id of the contextual group, the VisibilityContext, and the Command. The id maps to the Id property of the ContextualGroup element in the ribbon XML. The VisibilityContext is used to group controls in order to show or hide them. The Command parameter maps to the Command of the ContextualGroup element in the ribbon XML. You will also add the tab that was defined in the ribbon XML. You only need to pass in the Id and the VisibilityContext parameters for the tab.

    Insert the following code for the WebPartContextualInfo.

            public WebPartContextualInfo WebPartContextualInfo

            {

                get

                {

                    WebPartContextualInfo info = new WebPartContextualInfo();

                    WebPartRibbonContextualGroup contextualGroup = new WebPartRibbonContextualGroup();

                    WebPartRibbonTab ribbonTab = new WebPartRibbonTab();

     

                    //Create the contextual group object and initialize its values.

                    contextualGroup.Id = "Ribbon.CustomContextualTabGroup";

                    contextualGroup.Command = "CustomContextualTab.EnableContextualGroup";

                    contextualGroup.VisibilityContext = "CustomContextualTab.CustomVisibilityContext";

     

                    //Create the tab object and initialize its values.

                    ribbonTab.Id = "Ribbon.CustomTabExample";

                    ribbonTab.VisibilityContext = "CustomContextualTab.CustomVisibilityContext";

     

                    //Add the contextual group and tab to the WebPartContextualInfo.

                    info.ContextualGroups.Add(contextualGroup);

                    info.Tabs.Add(ribbonTab);

                    info.PageComponentId = SPRibbon.GetWebPartPageComponentId(this);

     

                    return info;

                }

            }

     

     

    13.  Next, you will implement the OnPreRender method. This allows us to add elements to the ribbon before it is rendered on the page. Inside OnPreRender you will call the AddContextualTab method and register the DelayScript with the ClientScriptManager. The following code implements OnPreRender.

            protected override void OnPreRender(EventArgs e)

            {

                base.OnPreRender(e);

     

                this.AddContextualTab();

     

                ClientScriptManager clientScript = this.Page.ClientScript;

                clientScript.RegisterClientScriptBlock(this.GetType(), "ContextualTabWebPart", this.DelayScript);

     

            }

     

    The Web Part is complete. Next, you will create the page component. A page component is an EcmaScript (JavaScript, JScript) object used to interact with the Server ribbon. It enables commands on the ribbon and responds to the commands you define in the ribbon XML. The page component has required functions in order for it to operate properly. The following table lists the required functions and their purpose.

    Function

    Purpose

    init

    Initializes the page component.

    getFocusedCommands

    Returns a list of the focused commands. Your page component is called for the commands only if it has the focus

    getGlobalCommands

    Returns a list of the global commands. Your page component is called for commands regardless of focus.

    isFocusable

    Specifies if the page component can receive focus.

    canHandleCommand

    Defines if the page component can handle a command sent to it.

    handleCommand

    Handles the commands sent to the page component.

    getId

    Returns the id of the page component. This is used to associate a control with a page component.

     

    There are also two optional functions. These functions will not be defined in this example.

    Function

    Purpose

    yieldFocus

    Specifies the code that is run when the page component loses focus.

    receiveFocus

    Specifies the code that is run when the page component receives focus.

     

    In order for the page component to operate properly, you will have to deploy the file using a Module.

    14.  In the Solution Explorer, right click on the ContextualTabWebPart project and select Add, New Item.

    15.  In the Add New Item dialog, choose the Module template and type CustomContextualTabPageComponent as the Name. Click Add.

    16.  You will not need the files that are added by default. Select Elements.xml and Sample.txt in the Solution Explorer and delete them.

    17.  Now, you need to add the EcmaScript (JavaScript, JScript) file. Right click on CustomContextualTabPageComponent and select Add, New Item.

    18.  Under Visual C#, choose Web in the Installed Templates list. Select the Jscript File type and enter CustomContextualTabPageComponent as the name.

    19.  You will need to set the deployment location to make sure the file goes into the _layouts directory. To do that, select CustomContextualTabPageComponent.js in the Solution Explorer. In the Properties window, set the Deployment Type to Root File. Open the Deployment Location property and set the Path to Template\Layouts.

    The following code will go into the CustomContextualTabPageComponent.js file to implement your custom page component.

    Type.registerNamespace('ContextualTabWebPart');

     

    var _webPartPageComponentId;

    ContextualTabWebPart.CustomPageComponent = function ContextualTabWebPart_CustomPageComponent(webPartPcId) {

        this._webPartPageComponentId = webPartPcId;

        ContextualTabWebPart.CustomPageComponent.initializeBase(this);

    }

    ContextualTabWebPart.CustomPageComponent.prototype = {

     

        init: function ContextualTabWebPart_CustomPageComponent$init() {  },

     

        getFocusedCommands: function ContextualTabWebPart_CustomPageComponent$getFocusedCommands() {

            return ['CustomContextualTab.EnableCustomTab', 'CustomContextualTab.EnableCustomGroup', 'CustomContextualTab.HelloWorldCommand', 'CustomContextualTab.GoodbyeWorldCommand'];

        },

     

        getGlobalCommands: function ContextualTabWebPart_CustomPageComponent$getGlobalCommands() {

            return [];

        },

     

        isFocusable: function ContextualTabWebPart_CustomPageComponent$isFocusable() {

            return true;

        },

       

        canHandleCommand: function ContextualTabWebPart_CustomPageComponent$canHandleCommand(commandId) {

            //Contextual Tab commands

            if ((commandId === 'CustomContextualTab.EnableCustomTab') || (commandId === 'CustomContextualTab.EnableCustomGroup') || (commandId === 'CustomContextualTab.HelloWorldCommand') || (commandId === 'CustomContextualTab.GoodbyeWorldCommand')) {

                return true;

            }

        },

     

        handleCommand: function ContextualTabWebPart_CustomPageComponent$handleCommand(commandId, properties, sequence) {

     

            if (commandId === 'CustomContextualTab.HelloWorldCommand') {

                alert('Hello, world!');

            }

            if (commandId === 'CustomContextualTab.GoodbyeWorldCommand') {

                alert('Good-bye, world!');

            }

        },

     

        getId: function ContextualTabWebPart_CustomPageComponent$getId() {

            return this._webPartPageComponentId;

        }

    }

     

     

    ContextualTabWebPart.CustomPageComponent.registerClass('ContextualTabWebPart.CustomPageComponent', CUI.Page.PageComponent);

    SP.SOD.notifyScriptLoadedAndExecuteWaitingJobs("CustomContextualTabPageComponent.js");

     

    Notice that getFocusedCommands returns the Command properties that you defined in the ribbon XML above. In canHandleCommand you return true to signify that your page component can respond to the specified commands. When creating this object, you use the webPartPcId parameter to set the custom page component id. This is set to the same value as the Web Part’s page component id to associate the Web Part and page component through the getId method.

    20.  To test the code, press F5 to deploy the solution.

    21.  Open your site and put the page into Edit mode.

    22.  In the Insert tab, click the Web Part button.

    23.  In the Web Part Adder, select the Custom category.

    24.  In the list of Web Parts, select ContextualTabWebPart. Click Add.

    25.  Once the Web Part is added to the page, click the ContextualTabWebPart.

    26.  Notice the Custom Contextual Tab Group tab that shows up on selection.

  • Microsoft SharePoint Developer Documentation Team Blog

    How to Add a Tab to the Ribbon in SharePoint Foundation

    • 13 Comments

    (Before he left for a week of laying on various tropical beaches with drinks in his hand, Dallas asked me to post this for him. Since I'm stuck in the rainy Northwest and had nothing better to do, I was happy to oblige him.) 

    The ribbon has unified the command surface inside of SharePoint. It is now the primary point of entry for working with items inside of SharePoint. As such the ribbon is extensible through the use of declarative XML in a Feature.

    This post will cover how to add a new tab to the ribbon in Microsoft SharePoint Foundation 2010. It will also, by necessity, cover how to create a group, controls, template, and scaling behavior. I will build this solution in Visual Studio 2010 Beta 2 and as a sandboxed solution for the ease of deployment.

    The following will appear in a future version of the SDK. It is preliminary documentation and subject to change.

    First, you will want to create a new project. Click on File, New, and then Project.

    Under Visual C#, choose Empty SharePoint Project and enter AddARibbonTab for the Name. Click OK.

    In the SharePoint Customization Wizard, choose Deploy as a sandboxed solution. Click Finish.

    In the Solution Explorer, right click on Features and choose Add Feature.

    Change the Title of the Feature to Custom Ribbon Tab. Also, rename Feature1 in the Solution Explorer to CustomRibbonTab.

    Right click on the AddARibbonTab project in the Solution Explorer and choose Add, New Item…

    In the Add New Item dialog, choose the Empty Element template. Enter CustomRibbonTab as the Name.

    In the Elements.xml file, insert the following CustomAction element. The Location attribute tells the CustomAction where to apply the customization. The following list explains the acceptable values.

    Value

    Description

    CommandUI.Ribbon

    Customization appears everywhere for the specified RegistrationId.

    CommandUI.Ribbon.ListView

    Customization appears when the list view Web Part is present.

    CommandUI.Ribbon.EditForm

    Customization appears on the edit form.

    CommandUI.Ribbon.NewForm

    Customization appears on the new form.

    CommandUI.Ribbon.DisplayForm

    Customization appears on the display form.

     

    <?xml version="1.0" encoding="utf-8"?>

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

      <CustomAction

        Id="MyCustomRibbonTab"

        Location="CommandUI.Ribbon.ListView"

        RegistrationId="101"

        RegistrationType="List">

     

      </CustomAction>

    </Elements>

     

    Add the following elements to define the ribbon extension and tab. The Location on the CommandUIDefinition element defines where the controls inside of it will render. In this example, you reference the Tabs collection of the ribbon. The _children convention tells the ribbon to insert the following XML, whether it is a tab, group, or control, into the collection of tabs. The Sequence attribute on the Tab element defines where the tab will render in regards to other tabs. The default tabs use multiples of 100, so the Sequence attribute should not be a multiple of 100 to prevent collisions.

    <CommandUIExtension>

          <CommandUIDefinitions>

            <CommandUIDefinition

              Location="Ribbon.Tabs._children">

              <Tab

                Id="Ribbon.CustomTabExample"

                Title="My Custom Tab"

                Description="This holds my custom commands!"

                Sequence="501">

     

    When creating a custom tab, you must define how the tab will scale when controls are added. This is handled through the use of the Scaling element along with a GroupTemplate. The MaxSize element defines the maximum size of the controls in the group. The Scale element defines how the group will scale in different situations. The GroupId attribute associates a group with the scale size. The Size attribute is defined by the Layout element, which is defined later in this topic.

                <Scaling

                  Id="Ribbon.CustomTabExample.Scaling">

                  <MaxSize

                    Id="Ribbon.CustomTabExample.MaxSize"

                    GroupId="Ribbon.CustomTabExample.CustomGroupExample"

                    Size="OneLargeTwoMedium"/>

                  <Scale

                    Id="Ribbon.CustomTabExample.Scaling.CustomTabScaling"

                    GroupId="Ribbon.CustomTabExample.CustomGroupExample"

                    Size="OneLargeTwoMedium" />

                </Scaling>

     

    Now, you will define the groups of controls that will appear on the tab. The Group element contains the usual attributes along with a Template attribute. The Template attribute references the GroupTemplate that is defined later in this topic. The Controls element contains the controls that will render in the group. These can be buttons, dropdowns, and other control types. You can find a list in the SDK at this address: http://msdn.microsoft.com/en-us/library/ee537017(office.14).aspx. The controls inside the group must define the TemplateAlias and Command attributes. Like tabs, each control has a Sequence attribute that defines where they will render in the group. The default controls are based on multiples of 10, so any custom controls should not use a multiple of 10 to avoid collisions. The Command attribute is used by the CommandUIHandler defined later in this topic but is required even if the CommandUIHandler is not specified. The TemplateAlias attribute defines where the control will render in relationship to the GroupTemplate.

                <Groups Id="Ribbon.CustomTabExample.Groups">

                  <Group

                    Id="Ribbon.CustomTabExample.CustomGroupExample"

                    Description="This is a custom group!"

                    Title="Custom Group"

                    Sequence="52"

                    Template="Ribbon.Templates.CustomTemplateExample">

                    <Controls Id="Ribbon.CustomTabExample.CustomGroupExample.Controls">

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.HelloWorld"

                        Command="CustomTabExample.HelloWorldCommand"

                        Sequence="15"

                        Description="Says Hello to the World!"

                        LabelText="Hello, World!"

                        TemplateAlias="cust1"/>

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.GoodbyeWorld"

                        Command="CustomTabExample.GoodbyeWorldCommand"

                        Sequence="17"

                        Description="Says Good-bye to the World!"

                        LabelText="Good-bye, World!"

                        TemplateAlias="cust2"/>

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.LoveWorld"

                        Command="CustomTabExample.LoveWorldCommand"

                        Sequence="19"

                        Description="Says I &lt;3 the World!"

                        LabelText="I &lt;3 you, World!"

                        TemplateAlias="cust3"/>

                    </Controls>

                  </Group>

                </Groups>

              </Tab>

            </CommandUIDefinition>

     

    With that code in place, you have finished the first CommandUIDefinition that includes the tab, groups, and controls. You need to define how the controls will render inside of the group. You do this using a GroupTemplate element in another CommandUIDefinition. The CommandUIDefinition will have a Location of Ribbon.Templates._children. This follows the pattern for Groups and Tabs.

    The GroupTemplate element contains a Layout element with Section and Row elements. The Layout element has a LayoutTitle that is used for the Size attribute on the MaxSize and Scale elements. The Section elements define the position of the controls as well as how many rows will render inside that section. The Row element contains one or more ControlRef elements. ControlRef elements define how your controls will display. The DisplayMode attribute can have the following values:

    Value

    Description

    Small

    Renders as a small icon without label text.

    Medium

    Renders as a 16x16 icon with label text.

    Large

    Renders as a 32x32 icon with label text.

    Text

    Renders as text only.

     

    The ControlRef elements also define the TemplateAlias values that you used for the TemplateAlias attribute on the buttons. Note that only one control per group can use this value. You cannot have two controls with the same TemplateAlias unless it is an OverflowArea. You can reuse the TemplateAlias across different groups though. There is also an OverflowArea element that defines how controls will render if there are too many controls in a group. The TemplateAlias attributes that refer to OverflowAreas in the GroupTemplate can be used on multiple controls.

    In this example, you will define two sections for rendering the controls. One section will be a row of large buttons while the other section will contain two rows of medium-sized buttons.

            <CommandUIDefinition Location="Ribbon.Templates._children">

              <GroupTemplate Id="Ribbon.Templates.CustomTemplateExample">

                <Layout

                  Title="OneLargeTwoMedium"

                  LayoutTitle="OneLargeTwoMedium">

                  <Section Alignment="Top" Type="OneRow">

                    <Row>

                      <ControlRef DisplayMode="Large" TemplateAlias="cust1" />

                    </Row>

                  </Section>

                  <Section Alignment="Top" Type="TwoRow">

                    <Row>

                      <ControlRef DisplayMode="Medium" TemplateAlias="cust2" />

                    </Row>

                    <Row>

                      <ControlRef DisplayMode="Medium" TemplateAlias="cust3" />

                    </Row>

                  </Section>

                </Layout>

              </GroupTemplate>

            </CommandUIDefinition>

          </CommandUIDefinitions>

     

    The final step is to write handlers for the buttons. These are inside CommandUIHandler elements. The Command attribute is a unique name for the command and used for the Command attribute on controls. The CommandAction attribute contains the action that is performed for the control. This can be JavaScript, an URL, or anything that was previously contained in an UrlAction element.

          <CommandUIHandlers>

            <CommandUIHandler

              Command="CustomTabExample.HelloWorldCommand"

              CommandAction="javascript:alert('Hello, world!');" />

            <CommandUIHandler

              Command="CustomTabExample.GoodbyeWorldCommand"

              CommandAction="javascript:alert('Good-bye, world!');" />

            <CommandUIHandler

              Command="CustomTabExample.LoveWorldCommand"

              CommandAction="javascript:alert('I love you, world!');" />

          </CommandUIHandlers>

        </CommandUIExtension>

     

    With the addition of the CommandUIHandlers, you have finished your Elements.xml file. Press F5 to deploy your solution. Then, navigate to the Shared Documents folder. You should see the Custom Tab. Click on Custom Tab to open it. Click any of the buttons to show the associated alert.

    Hopefully this walkthrough has been helpful! If you have any questions or concerns, please let me know in the comments.

     

    Full Code Listing:

    <?xml version="1.0" encoding="utf-8"?>

    <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

      <CustomAction

        Id="MyCustomRibbonTab"

        Location="CommandUI.Ribbon.ListView"

        RegistrationId="101"

        RegistrationType="List">

          <CommandUIExtension>

            <CommandUIDefinitions>

              <CommandUIDefinition

                Location="Ribbon.Tabs._children">

                <Tab

                  Id="Ribbon.CustomTabExample"

                  Title="My Custom Tab"

                  Description="This holds my custom commands!"

                  Sequence="501">

                <Scaling

                  Id="Ribbon.CustomTabExample.Scaling">

                  <MaxSize

                    Id="Ribbon.CustomTabExample.MaxSize"

                    GroupId="Ribbon.CustomTabExample.CustomGroupExample"

                    Size="OneLargeTwoMedium"/>

                  <Scale

                    Id="Ribbon.CustomTabExample.Scaling.CustomTabScaling"

                    GroupId="Ribbon.CustomTabExample.CustomGroupExample"

                    Size="OneLargeTwoMedium" />

                </Scaling>

                <Groups Id="Ribbon.CustomTabExample.Groups">

                  <Group

                    Id="Ribbon.CustomTabExample.CustomGroupExample"

                    Description="This is a custom group!"

                    Title="Custom Group"

                    Sequence="52"

                    Template="Ribbon.Templates.CustomTemplateExample">

                    <Controls Id="Ribbon.CustomTabExample.CustomGroupExample.Controls">

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.HelloWorld"

                        Command="CustomTabExample.HelloWorldCommand"

                        Sequence="15"

                        Description="Says hello to the World!"

                        LabelText="Hello, World!"

                        TemplateAlias="cust1"/>

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.GoodbyeWorld"

                        Command="CustomTabExample.GoodbyeWorldCommand"

                        Sequence="17"

                        Description="Says good-bye to the World!"

                        LabelText="Good-bye, World!"

                        TemplateAlias="cust2"/>

                      <Button

                        Id="Ribbon.CustomTabExample.CustomGroupExample.LoveWorld"

                        Command="CustomTabExample.LoveWorldCommand"

                        Sequence="19"

                        Description="Says I love the World!"

                        LabelText="I love you, World!"

                        TemplateAlias="cust3"/>

                    </Controls>

                  </Group>

                </Groups>

              </Tab>

            </CommandUIDefinition>

            <CommandUIDefinition Location="Ribbon.Templates._children">

              <GroupTemplate Id="Ribbon.Templates.CustomTemplateExample">

                <Layout

                  Title="OneLargeTwoMedium"

                  LayoutTitle="OneLargeTwoMedium">

                  <Section Alignment="Top" Type="OneRow">

                    <Row>

                      <ControlRef DisplayMode="Large" TemplateAlias="cust1" />

                    </Row>

                  </Section>

                  <Section Alignment="Top" Type="TwoRow">

                    <Row>

                      <ControlRef DisplayMode="Medium" TemplateAlias="cust2" />

                    </Row>

                    <Row>

                      <ControlRef DisplayMode="Medium" TemplateAlias="cust3" />

                    </Row>

                  </Section>

                </Layout>

              </GroupTemplate>

            </CommandUIDefinition>

          </CommandUIDefinitions>

          <CommandUIHandlers>

            <CommandUIHandler

              Command="CustomTabExample.HelloWorldCommand"

              CommandAction="javascript:alert('Hello, world!');" />

            <CommandUIHandler

              Command="CustomTabExample.GoodbyeWorldCommand"

              CommandAction="javascript:alert('Good-bye, world!');" />

            <CommandUIHandler

              Command="CustomTabExample.LoveWorldCommand"

              CommandAction="javascript:alert('I love you, world!');" />

          </CommandUIHandlers>

        </CommandUIExtension>

      </CustomAction>

    </Elements>

     

  • Microsoft SharePoint Developer Documentation Team Blog

    SharePoint Client Object Model Redistributable Released

    • 6 Comments

    Microsoft has released the SharePoint Foundation 2010 Client Object Model Redistributable. The assemblies for the .NET and Silverlight versions  of the SharePoint client object model are included. 

    Microsoft.SharePoint.Client.dll
    Microsoft.SharePoint.Client.Runtime.dll
    Microsoft.SharePoint.Client.Silverlight.dll
    Microsoft.SharePoint.Client.Silverlight.Runtime.dll

    The installer deploys these to the C:\Program Files\Common Files\Microsoft Shared\SharePoint Client folder of the development computer. (There are versions for 64-bit and x86 client computers.) In addition, resource assemblies are deployed to a subfolder named with the culture ID.

    The redistributable package must be installed on any client machine where your .NET client application is installed. You can either give users instructions on where to obtain it or you can include the redistributable in your installation package. This insures that the redistributable can participate in Windows Update and that each client computer has a legal copy of the assemblies. Some installation technologies enable you to call the redistributable's MSI file so the installation of the SharePoint .NET client assemblies and your application is seamless. SharePoint client assemblies obtained in other ways cannot be legally redistributed.

    You may distribute the assemblies for the Silverlight version along with a solution that targets them. They can be encased inside the Silverlight xap file. Alternatively, your solution can reference the Microsoft.SharePoint.Client.xap located on every SharePoint server in the SharePoint root: ...14\TEMPLATE\LAYOUTS\ClientBin folder.  It is also possible to cache the Silverlight assemblies. They are located in that same folder.

    Note that the third version of the SharePoint client object model, the JavaScript/JScript version, is defined in *.js files. These, of course, are downloaded to client computer when a SharePoint page that references them is opened. The default SharePoint master page references these files. Unless your solution includes a custom master page, you do not need to reference them in your own custom pages.

  • Microsoft SharePoint Developer Documentation Team Blog

    Extending Workflow Actions for SharePoint Designer

    • 10 Comments

    Extending Workflow Actions for SharePoint Designer

    Hi there.  My name is Rodney Farris and I’m one of the newest Programming Writers on the Windows SharePoint Services SDK team.  I’ve been assigned to cover SharePoint Workflows as well as the developer aspects of SharePoint Designer 2007.

    For the last 8 years I’ve been with Microsoft supporting customers, 4 of those being with the SharePoint Developer Support team.  I have a good deal of experience talking to customers and dealing with the problems that they encountered in developing SharePoint applications.  Hopefully this experience will help me to focus my writing on helping you to find answers to your questions about SharePoint workflows.

    In the coming months I will be posting about the content that’s on the publishing horizon.  The first of which is rounding out the documentation for declarative, code-free, rules-based workflows.  This is a powerful means of developing workflows without needing to know the architecture of workflow or how to code. 

    In my first few months in this new position, I’ve been doing a lot of research on the topic by talking to the product team, customers, and product support as well as reviewing existing documentation and reading blog posts.  I’ve seen a lot of good information written about extending the list of workflow activities provided by Windows SharePoint Services 3.0, but I’ve also seen just as many questions.

    A lot of those questions are around how to extend the list of Actions, or workflow activities, and Conditions for use in SharePoint Designer.  This being the case, my first duty was to research and work with the product team to describe the schema that governs their development. 

    The following is a somewhat abridged version of what you will see in the upcoming SDK update, in that I have removed all of the in-line syntax and examples.  Not to worry, I will be posting those shortly along with a developer’s version of the schema in an XSD format. 

     

    Workflow Actions Schema Overview

    You can build powerful and robust workflows to automate most of their common business processes by using a declarative, rules-based, code-free workflow editor such as Microsoft Office SharePoint Designer 2007. Windows SharePoint Services provides 23 built-in workflow actions and 9 workflow conditions that can be incorporated in these workflows.

    However, sometimes it is necessary to build workflows around very complex and unique business requirements that cannot be accommodated by the default lists provided by Windows SharePoint Services.

    In order to allow a code-free editor to work with more complex business logic, you must create customized workflow libraries and deploy them to the server that is running Windows SharePoint Services. After you have deployed your customized workflow objects, the new actions and conditions will be visible to the workflow editor.

    XML schema definition files (XSD) are commonly used to validate XML structure and syntax. However, in the case of Action and Condition elements, the information that is normally contained in an XSD file, and is easily readable, is contained within Windows SharePoint Services internal code.

    Schema Elements
    I placed these in alphabetical order for easier reference, not in order of hierarchy.  I will post the hierarchy the next time.

    Action
    Actions
    Condition
    Conditions
    Default
    FieldBind
    Option
    Parameter
    Parameters
    RuleDesigner
    WorkflowInfo

    Action Element

    Contains the information needed for the workflow engine to process a workflow activity, which is called an action in Windows SharePoint Services 3.0. A workflow Action element represents a workflow activity, such as sending e-mail notifications, updating Windows SharePoint Services 3.0 list items, creating and assigning tasks, as well as many other activities.

    By default, Windows SharePoint Services 3.0 provides 23 built-in workflow actions. These are defined in the WSS.ACTIONS file.

    Attributes

     

    Attribute

    Description

    Name

    Required text. Represents the description of the workflow action that is displayed to the workflow editor.

    ClassName

    Required text. Fully qualified name of the class that implements the workflow action. For example: Microsoft.SharePoint.

    WorkflowActions.EmailActivity.

    Assembly

    Required text. The .NET assembly name that contains instructions to implement the Action element. The text should include the PublicKeyToken, Version and Culture.

    Category

    Optional text. Provides a category for the workflow action. This text is used to filter the list of available actions.

    CreatesTask

    Optional Boolean. If set to true, a task list item is created in the workflow. If left blank, the assumption is false and no task list items are created.

    CreatesInList

    Optional text. If a value is set for this attribute, the workflow creates an item in a list. Values must map to a parameter name that contains the ID of the list or document library.

    AppliesTo

    Required text. Indicates whether this workflow action should be available for lists, document libraries, or both. Valid values include list, doclib, and all.

    ListModeration

    Optional Boolean. If set to true, this Action element applies to a list or document library that has content approval enabled. If left blank, the assumption is false.

    UsesCurrentItem

    Optional Boolean. If set to true, indicates that the current item should be used or modified. If set to false or left blank, this Action element uses only the SharePoint list or document library item that is specified.

     

    Actions Element

    Windows SharePoint Services 3.0 provides a number of default actions to a declarative, code-free workflow editor, such as Microsoft Office SharePoint Designer 2007, that can be used to build workflows that address common business needs. However, complex business rules can sometimes require customized actions. You can use the Actions element to add custom workflow activities and expand the workflow actions available to you beyond those that are included in the default list.

    Attributes

     

    Attribute

    Description

    Parallel

    Required text. If the user creating the workflow indicates that all workflow actions should be executed in parallel, the string defined in this attribute is used to join the Actions elements in the RuleDesigner sentence.

    The default value for this attribute is and (which is defined in the WSS.ACTIONS file) and applies only to the English language version of Windows SharePoint Services . This value cannot be overridden in a custom .ACTIONS file.

    Sequential

    Required text. If the user creating the workflow indicates that all workflow actions should be executed in sequence, the string defined in this attribute is used to join the Actions elements in the RuleDesigner sentence.

    The default value is then (which is defined in the WSS.ACTIONS file) and applies only to the English language version of Windows SharePoint Services .This value cannot be overridden in a custom .ACTIONS file.

     

    Condition Element

    Represents a Condition statement, which is part of a rule sentence that can be displayed in a declarative, rules-based, code-free workflow editor, such as Microsoft Office SharePoint Designer 2007.

    When a workflow is triggered by an event corresponding to a SharePoint list or document library item in Windows SharePoint Services 3.0, it is often necessary to evaluate what workflow action should be taken or if an action is required. A Condition element allows the workflow to perform this evaluation with the values and arguments provided to it by the workflow editor.

    Each Condition element also corresponds to a Boolean method inside a specified Windows SharePoint Services 3.0 workflow library. These methods are used to evaluate values passed by their parameters and return either true or false.

    A Condition element contains information about the .NET assembly where the Condition code is implemented, as well as the parameters that are required to make the function call. It also contains information about how the Condition statement should be displayed to the workflow editor.

    Attributes

     

    Attribute

    Description

    AppliesTo

    Required text. Specifies that the conditional statement being evaluated is applied to a SharePoint list or document library. By changing the value, you can show or hide a specific condition statement in the workflow editor, depending on the type of SharePoint list that the workflow is associated with.

    The following values are not case sensitive.

     

    Value

    Description

    all

    Specifies that a condition statement is available to all list and document library types.

    doclib

    Specifies that a condition statement is visible to the workflow editor only when the workflow is associated with a document library. If the workflow is associated with any other type of list, the condition statement is hidden from the workflow editor.

    list

    Specifies that a condition statement is visible to the workflow editor only when the workflow is associated with a SharePoint list. If the workflow is associated with any type other than a list type, the condition statement is hidden from the workflow editor.

    none

    Specifies that a condition statement is hidden from the workflow editor.

     

     

    Assembly

    Required text. Specifies the .NET assembly that contains the implementation code for the Condition element.

     

    Value Type

    Description

    String

    Specifies the .NET assembly that contains the workflow code. The format should be as follows:

    Assembly name, Version, Culture, PublicKeyToken

    Example:
    Assembly="Microsoft.SharePoint.
                                 WorkflowActions,
                            Version=12.0.0.0,
                            Culture=neutral,
                            PublicKeyToken=  
                                71e9bce111e9429c"

    ClassName

    Required text. Contains the fully qualified class name in which the Condition element code is implemented.

     

    Value Type

    Description

    String

    Fully qualified class name in which the custom Condition element code is implemented. Example:

    XML:
    ClassName=
    "Microsoft.
                               SharePoint.                           
                               WorkflowActions.
                               Helper
    "

    FunctionName

    Required text. Name of the Boolean method in the class that implements the Condition code.

     

    Value Type

    Description

    String

    Represents the method name in the class in which the Condition element code is implemented.

    Example method:

    Bool myCondition(WorkflowContext context, string ListGUIDorName, int ItemWorkflowAttachedTo)

    XML:

    FunctionName="myCondition"

    Type

    Optional text. Specifies whether the Condition element is Custom or Advanced.

    The following values are not case sensitive.

     

    Value

    Description

    Custom

    Used to compare a value found in the current SharePoint list or document library item to a value specified by the workflow designer.

    Advanced

    Used to indicate that a Condition can be used to compare two values of any type (for example, text, integers, and dates).

    UsesCurrentItem

    Optional Boolean. Specifies that the item currently selected is associated with the workflow.

     

    Value Type

    Description

    Boolean

    If set to true, the workflow binds to the SharePoint list item or document library item that started the workflow instance. When using a declarative, code-free workflow editor, this value always returns true and cannot be changed.

     

    Conditions Element

    Conditions are used by declarative, rules-based code-free workflow editors, such as Microsoft Office SharePoint Designer 2007, to build workflows. Conditions are simply functions, in code, that return a Boolean value when called by Windows SharePoint Services 3.0.

    When using a code-free workflow editor to develop workflows, conditions are presented to the workflow designer in the form of a list of phrases. Each of the conditions in this list has a corresponding function in code that is used to evaluate values provided either by the user or by Windows SharePoint Services 3.0.

    The Conditions element is the parent element for all Condition elements.

    Note   The attributes listed below are only read from the default WSS.ACTIONS file and cannot be overridden in any custom .ACTIONS files.

    Attributes

     

    Attribute

    Description

    And

    Required text. The text defined in this attribute is displayed in the rule designer sentence when two or more conditions are used in the same conditional branch, and when all conditions must be satisfied before workflow actions can execute. The value is not case sensitive.

    The default value is and (applies only to the English language version of Windows SharePoint Services 3.0.

    Example:

    <Conditions And="and">

    Else

    Required text. The text defined in this attribute is displayed in the rule designer sentence when a conditional branch activity is added to the workflow. The value is not case sensitive.

    The default value is Else if (applies only to the English language version of Windows SharePoint Services 3.0).

    Example:

    <Conditions Else="Else if">

    Not

    Required text. The text defined in this attribute is displayed in the rule designer sentence when the condition must not contain a specified value or range of values. This value is not case sensitive.

    The default value is Not.

    Example:

    <Conditions Not="not">

    Or

    Required text. The text defined in this attribute is displayed in the rule designer sentence when there are two or more conditions in the same conditional branch and any value will satisfy the conditions, allowing the workflow actions to execute. The value is not case sensitive.

    The default value is or (applies only to the English language version of Windows SharePoint Services 3.0).

    Example:

    <Conditions Or="or">

    When

    Required text. The text defined in this attribute is displayed in the rule designer sentence when a conditional branch is added that requires the values or conditions that follow it to return true in order for the workflow actions to execute. The value is not case sensitive.

    The default value is If (applies only to the English language version of Windows SharePoint Services 3.0).

    Example:

    <Conditions When="If">

     

     

    Remarks

    Each Conditions element can occur only once in an .ACTIONS file.

    Default Element

    The Default element is a container for other elements and has no definable attributes.

    Note   The Default element is only read from the default WSS.ACTIONS file and cannot be overridden with a custom .ACTIONS file.

    Attributes

     

    None

     

    Remarks

    When you create workflows using a declarative, code-free workflow editor, such as Microsoft Office SharePoint Designer 2007, the .ACTIONS file that is installed on the server is combined into a single list of items and displayed to the workflow editor. Windows SharePoint Services 3.0 then searches for existing workflow conditions. If Windows SharePoint Services 3.0 finds a condition that is not represented by an entry in an .ACTIONS file, the Default element sentence is displayed for that condition.

    FieldBind Element

    The FieldBind element is a child of the RuleDesigner element. These elements are used together to create a readable sentence that describes a condition that needs to be evaluated or an activity that must be executed. When constructed properly, these elements can also be used to insert variables (such as hyperlinks) within the sentence, so that the code-free workflow editor can substitute dynamic values into the workflow while it is running. The FieldBind element maps the inputs from the workflow creator to parameters that are then passed to Windows SharePoint Services 3.0.

    Attributes

     

    Attribute

    Description

    DesignerType

    Required text. Specifies the type of control or user input that is presented to the workflow creator when building sentences in the workflow editor.

    Note   If you do not specify a DesignerType, the default DesignerType attribute is used. The default DesignerType is a text box followed by an ellipses button and a lookup button.

    Note   A code-free workflow editor should treat the values returned to it from the server as case-insensitive.

    Field

    Required text. Represents a Parameter element used to build workflows. The Field attribute maps directly to one or more Parameter elements when a parameter type and direction are defined.

    Note   If you use more than one parameter for a Field attribute, the parameter names should be separated by commas (for example, Field="Variable,ValueType").

    Function

    Optional Boolean. When set to true, this attribute inserts the name of the Action method into the sentence.

    Id

    Required Integer (non-negative). Id is used as the relational key between a FieldBind element and the Sentence property of the parent RuleDesigner element, much like a primary key is used in a database.

    OperatorTypeFrom

    Required text. Used only when DesignerType attribute is set to Operator. This attribute determines the types of operators that are available to the user, based on the .NET data type listed in the corresponding Parameter element. The parameter specified for the OperatorTypeFrom attribute can be different from the parameter listed in the Field attribute.

    Text

    Required text. Text displayed to the user as a hyperlink in the condition sentence.

    TypeFrom

    Optional text. Specifies the .NET data types that are valid for use with an instance of the FieldBind element. The TypeFrom attribute is associated with a Parameter element that contains the type definition.

    Value

    Reserved for future use.

     

    DesignerType Attribute

     

    Value

    Data Bound

    Default Builder

    Show Drop-down

    Adv-
    anced Builder

    Control Description

    Boolean

    Yes

    No

    Yes

    No

    Drop-down list box with the choices true and false populated.

    ChooseDoclibItem

    No

    No

    No

    Yes

    Document library item selector.

    ChooseListItem

    No

    No

    No

    Yes

    Default.

    CreateListItem

    No

    No

    No

    Yes

    Default.

    Date

    Yes

    Yes

    No

    No

    Date/Time selector.

    Dropdown

    No

    No

    Yes

    No

    Drop-down list box control. Static items can be populated by adding Option elements.

    Email

    No

    No

    No

    Yes

    E-mail advanced control. The form displays standard e-mail fields including To, From, CC, Subject and Body.

    FieldNames

    No

    No

    Yes

    No

    Drop-down list box control populated with all field names in the current list or document library.

    Float

    Yes

    No

    No

    No

    Text box. Allows entry of floating point values.

    Hyperlink

    Yes

    Yes

    No

    No

    URL browser. Select local or remote resources using a standard link builder.

    Integer

    Yes

    No

    No

    No

    Text box. Accepts non-negative integer values.

    ListNames

    No

    No

    Yes

    No

    Drop-down list box control populated with all lists in the current Web site.

    Operator

    No

    No

    Yes

    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

    No

    Yes

    No

    Drop-down list box populated with all local variables that have been entered for use by the workflow.

    Person

    Yes

    Yes

    No

    No

    Person or Group selector. You can choose only one person or group from either built-in, local users or groups or users and groups from a domain.

    SinglePerson

    Yes

    Yes

    No

    No

    Person or Group selector. You choose only one person or group from either built-in, local users or groups or users and groups from a domain.

    Stringbuilder

    No

    No

    No

    Yes

    Inline text box editor. Use to create simple strings.

    Survey

    No

    No

    No

    Yes

    Default.

    Text

    Yes

    No

    No

    No

    Default.

    TextArea

    Yes

    Yes

    No

    No

    Default.

    UpdateListItem

    No

    No

    No

    Yes

    Default.

    writablefieldNames

    No

    No

    Yes

    No

    Drop-down list box populated either with a list of fields in the current list or a list of document libraries that are editable. All other fields are hidden.

     

    Properties of DesignerTypes

    Property

    Description

    Data Bound

    Control that can be data bound to a SharePoint list or document library item.

    Default Builder

    Displays a button with ellipses. Depending on the DesignerType, this property opens either a Date/Time or Text Editor dialog box.

    Show Dropdown

    Displays a control for a drop-down list box. Depending on the DesignerType, the values may be populated. You can add Options elements to any Show DropDown controls that are not already populated.

    Advanced Builder

    Displays advanced builders based on the DesignerType. Advanced DesignerTypes can have multiple properties. For example, the e-mail advanced builder allows entry of To, From, CC, Subject and Body fields.

     

    Option Element

    Used to populate DesignerType drop-down list box controls that are not data bound. Option elements contain text and value pairs that can be used to build a workflow sentence. They also contain information about their .NET data types.

    Attributes

     

    Attribute

    Description

    Name

    String. The value displayed in the drop-down list box control.

    TypeFilter

    String. Used only if the parent FieldBind DesignerType is Operator. The TypeFilter attribute allows options to be hidden or displayed in the workflow editor, based on the data type of the parent element.

    You can define multiple types for the TypeFilter attribute but they must be separated by commas.

    UnaryHides

    String. Used only if the parent FieldBind RuleDesigner type is Operator. The value specified in this attribute should be synchronized with the Field attribute of a FieldBind element. If this option is selected, then the FieldBind specified here will be hidden from the workflow editor.

    Value

    String. Represents the value of the selected drop-down list item.

     

    Value Attribute

    The following table contains attribute values that are used with a TypeFilter attribute of Operator that performs conditional comparisons. Custom values can be substituted.

     

    Value

    Description

    Equal

    Returns true if queried values are equal. Case sensitivity must match.

    EqualNoCase

    Returns true if queried values are equal. Case sensitivity does not need to match.

    NotEqual

    Returns true if queried values are not equal. Case sensitivity must match.

    NotEqualNoCase

    Returns true if queried values are not equal. Case sensitivity does not need to match.

    StartsWith

    Returns true if queried values start with a specific pattern.

    NotStartsWith

    Returns true if queried values do not start with a specific pattern.

    EndsWith

    Returns true if queried values end with a specific pattern.

    NotEndsWith

    Returns true if queried values do not end with a specific pattern.

    Contains

    Returns true if queried values contain the specified pattern.

    NotContains

    Returns true if queried values do not contain the specified pattern.

    ContainsNoCase

    Returns true if queried values contain the specified pattern.

    Matches

    Returns true if queried values match a specified regular expression.

    IsEmpty

    Specifies empty string.

    Parameter Element

    Used to describe the input and output parameters for a custom Actions or Conditions method call.

    Attributes

     

    Attribute

    Description

    Type

    Required String. Partially qualified .NET data type. Values are not case sensitive.

    Example:

    System.Object, mscorlib

    Direction

    Optional text. Specifies an input or output parameter. Valid values are In and Out. Values are not case sensitive.

    Name

    Required text. Used to associate the FieldBind element with the parameter. Values are not case sensitive.

    InitialValue

    Optional text. Used to specify the default initial value that is passed to the parameter. Values are not case sensitive.

     

    Parameters Element

    Container for all Parameter elements and contains no definable attributes. Includes the descriptions of the parameters in a condition or action method signature.

    The Parameters element is a complex element type and can be used with both Actions and Conditions elements to define their parameters.

    Attributes

     

    None

     

     

    RuleDesigner Element

    Complex type element. The RuleDesigner element contains information needed to render a workflow sentence in a declarative, code-free workflow editor such as Microsoft Office SharePoint Designer 2007.

    Attributes

     

    Attribute

    Description

    Sentence

    Required text. Text displayed in the workflow editor that represents the workflow rule. The rule sentence can contain static text as well as text dynamically generated at run time.

    Variables can be embedded into the sentence using the notation %1, %2, and so on. Each variable maps to a FieldBind element Id. Then, during workflow design, the text displayed for these variables is the Text attribute of the FieldBind element.

     

    WorkflowInfo Element

    WorkflowInfo is the root element of the Actions schema. This element must be included in any .ACTIONS file that is installed on the server.

    Attributes

     

    Attribute

    Description

    Language

    Refers to the language of the server, not the client. This is notated as a language/culture pair. For example "en-us" is used to specify "English-United States" (See Locale Identifier Constants and Strings).

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    Synchronizing with Windows SharePoint Services, Part 1

    • 8 Comments

    Introduction

    There may be occasions where you will need to synchronize third party programs with Windows SharePoint Services. GetListItemChangesSinceToken, introduced in Windows SharePoint Services version 3.0, makes this synchronization much more efficient.

    This post explores using GetListItemChangesSinceToken to synchronize with Windows SharePoint Services version 3.0. The article details the queryOptions used by GetListItemChangesSinceToken.

    The follow on post will discuss conflict detection issues; and document best practices for clients who want to synchronize with calendar items, documents, and tasks in Windows SharePoint Services version 3.0.

    Please forgive the length of this entry, the various tables and descriptions I've included will be in future updates of the SDK.

    Synchronization Using GetListItemChangesSinceToken

    You can use GetList to download a list; however, the most efficient way to synchronize information is to download only those items that have changed since the last synchronization occurred. In Windows SharePoint Services version 3.0 this can be done by calling the GetListItemChangesSinceToken Web method.

    Sending a GetListItemChangesSinceToken request without including a token returns the list schema, the full list contents and a token. The token represents the moment when those changes were requested. By including this token the next time you call GetListItemChangesSinceToken, the server returns only those changes that have occurred since the token was generated.

    If the list schema itself has changed, GetListItemChangesSinceToken returns the entire list schema, the full list contents, and a token.

    #GetListItemChangesSinceToken Request and Response

    Here is a listing of the GetListItemChangesSinceToken Request and Response and an explanation of the very useful queryOptions parameter.

    Request

    public SoapXml.SoapXmlElement GetListItemChangesSinceToken(

                string listName,

                string viewName,

                SoapXml.SoapXmlElement query,

                SoapXml.SoapXmlElement viewFields,

                string rowLimit,

                SoapXml.SoapXmlElement queryOptions,

                string changeToken,

                SoapXml.SoapXmlElement contains)

     

    Name

    Description

    listName

    This can be the list title, but using the list id (GUID) results in better performance.

    viewName

    Not supported.

    query

    A CAML query similar to the CAML query used in GetListItems and SPQuery. Refer to GetListItems and SPQuery in the SDK for more information.

    Note   Not intended to be used with the contains parameter.

    viewFields

    Set of field references for each field required in the response. <ViewFields /> returns all fields in the list. A Properties='true' attribute will separate the MetaInfo field into its separate decoded properties.

    rowLimit

    The maximum number of values to return.  Used for paging.

    queryOptions

    Set of options related to the query (see details below).

    changeToken

    An opaque token used to determine the changes since the last call.  This token should never be parsed or constructed, as its format may change in the future.

    contains

    A CAML filter applied to the query results.  This is the Where clause in a SPQuery.

    Note   Not intended to be used with the query parameter.

     

    Query Options Parameter

    The queryOptions element can contain a variety of tags which modify the query.  For Boolean options the default is FALSE, only a value of TRUE (must be uppercase) enables them.

     

    Available Query Option Tags

    Query Option Tag

    Description

    <Paging ListItemCollection

    PositionNext="X" />

    X is an opaque token used to determine the page of items to return.  Like the changeToken value, this should never be parsed or constructed.

    <IncludeMandatory

    Columns>

    Ensures that fields defined as required are included, even if not specified in the viewFields. This option may be misleading because Windows SharePoint Services actually has a separate set of mandatory fields that are always returned independently of this option.

    <RecurrenceOrderBy>

    This is a requirement for some calendar programs. For each recurring series, the master item is returned first and then all exceptions. This is a special internal ordering that is applied ahead of any other ordering.

    Note   This should not be used unless your program explicitly requires it.

    If the view has a field of type Recurrence, the list will be ordered by fields of reference type UID, EventType and StartDate in the definition of the recurrence field.

    <ExpandUserField>

    Special rendering for the user field values that makes them include the login name, email, SipAddress, and the title when present. This causes a user field to behave as a multi lookup field.

    The lookup fields used in the expansion are "Name", "EMail", "SipAddress" and "Title". The values are separated by ,#. Any commas in the lookup field name are encoded as ,,.

    These values occur in the normal field data for each item. 

     

    Examples of ExpandUserField

    <ExpandUserField>FALSE</ExpandUserField> looks like:

    ows_Author="1;#Admin AdminName"

     

    <ExpandUserField>TRUE</ExpandUserField> looks like:

     ows_Author="1;#Admin AdminName,#login\name,#email@address,#sip@address,#Admin AdminName "

     

    More Query Option Tags

    Description

    < DateInUtc>

    Date fields are returned in UTC format and zone.

    UTC is in GMT time zone an ISO6801 format: 2006-10-04T10:00:00Z

    Normal is in local (server) time zone and the same as above with the T and the Z replaced by spaces.

    <ViewAttributes

    foo=bar />

    All attributes of this option will be used as view attributes of the view schema. The most commonly used is Scope="RecursiveAll" that defines the view as flat instead of scoped to a particular folder.

    <Folder>

     

    Set the root folder scope of the view. This is a server relative URL.

    <Folder>Shared Documents/foldername</Folder>

    <MeetingInstanceId>

     

    Defines which meeting instance to sync with if this list is part of a meeting workspace. -1 should be used for all instances unless the client wants to filter for a particular instance.

    <IncludePermissions>

     

    One way a client can request individual item permissions.

    <IncludeAttachmentUrls>

     

    Changes the value returned for the Attachments field from a Boolean to a list of full urls separated by ;#

    <IncludeAttachment

    Version>

    Used in conjunction with IncludeAttachmentUrls, IncludeAttachmentVersion also returns the GUID and version number used for conflict detection on update.

    <RecurrencePattern

    XMLVersion>

    v3

    </RecurrencePattern

    XMLVersion>

     

    Used to maintain backwards compatibility, RecurrencePatternXMLVersion changes the value of a RecurrenceData field to NOT return <V3RecurrencePattern /> when it contains elements only present on a version 3 pattern.

    Without this tag, recurrence patterns that were not present in Windows SharePoint Services version 2 are sent as <V3RecurrencePattern />. Including this tag means that recurrence patterns new to Windows SharePoint Services are sent correctly.

    <ExtraIds>

    1,4,23

    </ExtraIds>

    Request extra items to be included on the returned set regardless of whether they changed or not. The common use of ExtraIds is to specify the IDs of the folders you're syncing if you were in a doclib and chose "connect to..." on a folder rather than on the entire doclib.  This way you get the folder name and can tell when it is renamed.

    Note   This should only be used with a change token.

    This allows a client to sync to one or more folders and detect if any folder above the hierarchy was deleted or renamed.

    Folder names are not returned unless some changes are done to the list and the query to fetch changed items also uses IDs.

    <OptimizeFor>

    The two values supported are:

    • ItemIds
    • FolderUrls

    ItemIds is the default as long as a query or recurrence order is not requested and optimizes our SQL query with an ID order.

    FolderUrls optimizes a sync filtered to the flat contents of one or more folders by optimizing the SQL query with a DirName, LeafName order.

    <OptimizeFor>ItemIds</OptimizeFor>

     

    Default Query Options

    If the queryOptions parameter is absent, the following default options are used:

     

    <RecurrenceOrderBy>TRUE</RecurrenceOrderBy>

    <ViewAttributes Scope="Recursive" />

    <DateInUtc>TRUE</DateInUtc>

    <IncludePermissions>TRUE</IncludePermissions>

    <IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>

    <IncludeAttachmentVersion>TRUE</IncludeAttachmentVersion>

    <RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion>

    <ExpandUserField>TRUE</ExpandUserField>

    <MeetingInstanceID>-1</MeetingInstanceID>

     

    Note   Clients should always specify a query option; failing to do so will negatively impact scale performance.

    Response

    A GetListItemChangesSinceToken response is delivered in the following format:

     

    <listitems [list and global properties] [namespace declarations]>

      <Changes [MoreChanges="TRUE"] [LastChangeToken="X"]>

        [Changes]

      </Changes>

          <rs:data ItemCount="N" [ListItemCollectionPositionNext="X"]>

      [Data]

      </rs:data>

    </listitems>

    Note   X is an opaque token used to determine the page of items to return.  Like the changeToken value, this should never be parsed or constructed.

     

    Namespace declarations

    Any XML namespaces used below are declared here.

    List and global properties

    These include configuration properties, alternate URL information, and list permissions.

    List and global properties table

    Property

    Definition

    MinTimeBetweenSyncs

    A server parameter that represents the minimum amount of time between user-initiated or automatic synchronization. The value represents a time in minutes.

    Note   Clients should respect this value even if the user initiates synchronization manually.  That is, if this is set to 5 minutes, clients should only send one request per 5 minutes even if the user repeatedly clicks "send/receive".

    RecommendedTime

    BetweenSyncs

    The recommended minimum amount of time between synchronizations. This should specifically be respected for automatic syncs. Clients should never automatically synchronize more often than this.  User-initiated synchronizations can override this interval.

    MaxBulkDocumentSyncSize

    The total size of content to be synchronized to the client. The default is 500 MB. You get the URL and metadata for each document when you call GetListItemChangesSinceToken, but you then need to do an HTTP GET to retrieve the actual document contents. Setting this value to high may degrade performance.

    AlternateUrls

    Alternate URLs are listed in the following zone order, delimited by commas: Intranet,Default,Extranet,Internet,Custom

    EffectiveBasePermissions

    The permissions on the list as returned by SPList.EffectiveBasePermissions.ToString().

    Changes

    Changes consist of a list of change events that need to be specially handled by the client.

    These are taken from our internal change log when a change token is supplied. For a full synchronization (no change token) we still return the Changes tag with the current change token.

    The limit on the number of updates returned from a change token is 100. The MoreChanges attribute indicates that the last change token is not current. More changes were done on the list and the client should call this method again with the new change token.

    Change

    Description

    <List></List>

    If the list schema has changed, or if no change token was provided, we return the list here. The format is the same as returned by GetList.

    <Id ChangeType=

    "InvalidToken" />

    The token is either invalid or old.  You must do a full sync.

    <Id ChangeType="Restore" />

    The list has been restored from the recycle bin or from a backup.  You should do a full sync.

     

    In both of the cases above, the client should ignore other changes and do a full reconciliation of the list.

     

    Change Type

    Description

    <Id ChangeType=

    "Delete">ID</Id>

    This item is no longer present.  Note that Delete changes are sent even if the item was filtered out by the query.

    <Id ChangeType="MoveAway"

     AfterListId="ID"

    AfterItemId="ID">ID</Id>

    Treat in the same manner as a delete.

    <Id ChangeType="Restore">

    ID

    </Id>

    This item and any items beneath it were restored.

    <Id ChangeType=

    "SystemUpdate">ID</Id>

    Some clients may use hidden version, version history or modified time to determine whether to update an item. A SystemUpdate means Windows SharePoint Services has made changes and that you need to update all properties on that particular item.

    <Id ChangeType="Rename">ID</Id>

    Just like SystemUpdate, renamed items may retain hidden version information.

    Data

    The ItemCount attribute contains the number of items returned. Each Item is returned as a <z:row> tag.

    A ListItemCollectionPositionNext attribute is returned only for a full sync (no change token) when a row limit parameter was used to limit the number of items returned in one call. This type of paging is blocked on an incremental sync by restricting the number of updates processed from the change log to the row limit if smaller than our internal maximum.

    The contents of the items are returned as attributes with an "ows_" prefix and the internal name of the field. The values are encoded to be valid XML attribute values. A set of fields is always returned.

    Some fields are marked as required and returned if the IncludeMandatoryColumns option is set. If <ViewFields /> is sent, all fields are returned.

    When Properties="TRUE" is set in the ViewFields tag, the property bag (MetaInfo field) is separated into an attribute per property. These have a prefix of "ows_MetaInfo_".

    Most of the column values are simply converted from their internal representation, while others are constructed specially for a client. Several attributes are not represented by a field in the list schema.

     

    Table: List of attributes not represented by a field in the list schema.

    Attribute

    Description

    MetaInfo

    This is the property bag container, SPListItem.Properties. For more information, refer to the property bag in the SPListItem object model.

    Fields of type "Attachments"

    This is a bit column in the database, but query options modify it to return attachment data.

    Recurrence

    Data

    This is the XML definition of a recurrence.

     

    See http://blogs.msdn.com/sharepoint/archive/2007/05/14/understanding-the-sharepoint-calendar-and-how-to-export-it-to-ical-format.aspx for more details on this XML

    Acknowledgements

    I would like to acknowledge the following persons for their gracious help in technical reviews for this article: Matt Swann (Microsoft Corporation), Bill Snead (Microsoft Corporation).

    See Also

    I will be continuing this discussion in part 2.

  • Microsoft SharePoint Developer Documentation Team Blog

    SharePoint 2010 Beta Release Known Issues

    • 0 Comments

    This post lists and addresses known issues that developers have been frequently encountering while working with the Beta release of Microsoft SharePoint 2010. These issues relate only to the Beta versions of Microsoft SharePoint Foundation 2010 and Microsoft SharePoint Server 2010, and are limited to areas that concern developers specifically. See Microsoft Office Servers Beta 2 Known Issues/ReadMe for a broader list of known issues with the Beta release of Office 14 server applications.

    Installation Issues:

    The issues listed here supplement the guidance and instructions provided in Setting up the Development Environment for SharePoint Server.

    • When you install on Microsoft Windows 7 or Windows Vista, make sure that WCF HTTP Activation and WCF non-HTTP Activation are set. If these Windows Features are not set, the configuration wizard will fail at task 8. Step 2, item 8 in Setting up the Development Environment for SharePoint Server contains a command that you can use to enable all of the required Windows Features, including WCF HTTP Activation and WCF non-HTTP Activation. The command in that topic contains line breaks, however, so you will have to remove the line breaks manually before running it.
    • Install the WCF hotfix. A hotfix that provides a method to support token authentication without transport security or message encryption in WCF is available for.NET Framework 3.5 SP1. Use this link for Windows Server 2008 and this link for Windows Server 2008 R2. The Windows Server 2008 fix also applies to Vista, while the Windows Server 2008 R2 fix also applies to Windows 7.
      If you don't have this fix installed, you will get an "Unrecognized attribute 'allowInsecureTransport'" error in ULS log. And most of the service applications will not run properly. If you are installing on Windows 7 and have previously installed Visual Studio 2010, you may need to replace an installer file, as described in this blog post.
    • If after installing SharePoint 2010 you are not getting ULS logs, either disable Windows Firewall or create an exception in Windows Firewall for WSSTracing.exe.
    • We do not currently support installation on K or KN editions of Windows 7.
    • Web Application Companions (WAC), SharePoint Search, and SharePoint User Profile Sync cannot be installed on Windows 7.

    Development Issues:

    • When you create custom solutions with Visual Studio 2010, set the target framework to .NET Framework 3.5.
    • When you add resources to a Mapped Folder in Visual Studio 2010, the default build action is set to Embedded Resource. If you do not set the build action to Content or None, the files in the Mapped Folder will not be included in the WSP.
    • Deployment of BDC models with the Business Data Connectivity Model template in Microsoft Visual Studio 2010 does not yet work in SharePoint Foundation 2010. SharePoint Foundation is missing the feature event receiver that enables the import of BDC models. This does work in SharePoint Server, and before RTM Microsoft will release code for a feature event receiver that you can add to your BDC projects to deploy to SharePoint Foundation.
    • References to assemblies in "*\14\Templates\Layouts\ClientBin" (including Microsoft.SharePoint.Client.Silverlight.dll and Microsoft.SharePoint.Client.Silverlight.Runtime.dll) result in paths that are too long for Visual Studio 2010. Andrew Connell describes this problem and proposes a work-around in this blog post.
    • Sites created from SharePoint Designer 2010 do not have the AssociatedOwnerGroup property of SPWeb set by default. As a result, site owners cannot complete workflow tasks that are not assigned to them. When they try to do this, they receive error messages indicating that that workflow tasks were rolled back because the users do not have the correct permissions. Workflows use the AssociatedOwnerGroup property to determine who can override the rollbacks. To fix this, set the AssociatedOwnerGroup property with code, or create a new site from the browser.
    • Some assemblies, such as Microsoft.SharePoint.Publishing, appear in some cases to have a dependency on an incorrect version of the System.Web.DataVisualization assembly. The incorrect reference causes build failures. If you see this problem, add a reference to the correct version of System.Web.DataVisualization on your system. If your installation is on the C drive, that assembly will be located here:

    C:\Program Files (x86)\Microsoft  Chart Controls\Assemblies\System.Web.DataVisualization.dll

    • If you install or upgrade a custom solution built on Microsoft Office SharePoint Server 2007 that embeds the SearchBoxEx Web Control into your custom master page, you will get an error indicating that "the type or namespace name 'SearchBoxEx' does not exist in the namespace 'Microsoft.SharePoint.Portal.WebControls'." This will not happen if you simply add the Search Box Web Part to a Web Part page. This will be fixed in the RTM version. You can work around this issue by updating your customized master page to include this tag:

    <%@ Register Tagprefix="MSSWC" Namespace="Microsoft.SharePoint.Portal.WebControls" Assembly="Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

     Once you have added this tag,  you can then embed the SearchBoxEx Web Control with this tag:

    <MSSWC:SearchBoxEx id="SearchBox"…>

    The <SPSWC:SearchBoxEx id="SearchBox"…> tag should also work as long as the Web form has been registered to use the Microsoft.SharePoint.Portal.WebControls namespace in the Search assembly.

    • If you are testing your installation with Internet Explorer on your server machine, turn off IE Enhanced Security Configuration in your Server Manager. This will make certain site operations, such as "New|Edit" dialogs, work more smoothly.
  • Microsoft SharePoint Developer Documentation Team Blog

    Synchronizing with Windows SharePoint Services, Part 2

    • 7 Comments

    Introduction

    In my last blog post I introduced GetListItemChangesSinceToken and discussed how using GetListItemChangesSinceToken can make synchronization more efficient. In this post I'll talk some more about synchronization; take a quick look at GetList and UpdateListItems, and property bags. I'll finish up by discussing conflict detection, and performance best practices.

    Other Web Services

    In addition to GetListItemChangesSinceToken, Lists.asmx defines several other web services which allow clients to query for changes and make updates. There are several good examples in the Lists web service topic in the Windows SharePoint Services SDK.

    GetList

    GetList returns field schemas and other list properties.  Clients typically call this before syncing a new list, and then parse the response to match WSS fields to their client-side representation. 

    If the field exists as an out-of-box site column, it can be matched by its field ID.  In other cases, the field's internal name can be referenced.

    UpdateListItems

    UpdateListItems adds, modifies, or deletes list items.  Clients typically call this to keep server items in sync with changes made on the client.

    Request

    public SoapXml.SoapXmlElement UpdateListItems(string listName, SoapXml.SoapXmlElement updates)

    This is the format of the updates parameter:

     

    <Batch [update options]>

       <Method ID="X" Cmd="CMD">

          <Field Name="InternalName">VALUE</Field>

       </Method>

    </Batch>

     

    A batch is a collection of methods, each of which specifies the following value for the Cmd attribute:

     

    List of batch methods

    Method

    Description

    New

    Create a new item with the specified field values.

    Update

    Update the specified field values for an item.

    Moderate

    Change the moderation status for an item (used in the same manner as Update). The ModerationStatus field can only be changed by a Cmd=Moderate call. 

    Delete

    Delete the item with the following field values

    Note   Setting ModerationStatus must be done using a Cmd=Moderate call. Attempting to set ModerationStatus using Cmd=Update or Cmd=New has no effect. For more information about ListItem, refer to the SDK.

     

    The ID attribute of the Method tag is only used to correlate the method in the batch with the right item in the result.

     

    Update Options

    Option

    Description

    OnError="Continue"

    Continue processing the batch if errors are encountered

    LockSchema="TRUE"

    ListVersion="N"

    Only process the update if the list version matches

    ViewName="VIEW'

    Return columns present in this view with the item's data

    RootFolder="FOLDERURL"

    Perform the update in the context of this folder

    Properties="TRUE"

    Return the properties in the item property bag as separate fields

    DateInUtc="TRUE"

    The dates updated and returned are in UTC

     

    Fields

    In updates and deletes, the ID field needs to be supplied in order to identify the item.  If the update is being made on a document library, the FileRef field is also required to identify the document being updated.

    When updating an item, only the changed fields need to be supplied.

    When adding or changing certain types of items, certain fields may be required. 

     

    Clients may update the property bag in two ways:

    Update

    Description

    <Field Name="MetaInfo">

    XXX

    </Field>

    Add or update the specified name/value pairs in the property bag

    <Field Name=

    "MetaInfo" Property=

    "Name">

    VALUE</Field>

    Add or update this specific name/value pair in the property bag

     

    Note   There is no way for a client to delete individual name/value pairs in the property bag. See Property Bag below for more information.

     

    Response

    The return value is:

    <Results>.

       <Result ID="X,CMD">

          <ErrorCode>HR</ErrorCode>

          <ID>ID</ID>

          <z:row ... />

       </Result>

    </Results>

     

    Tag

    Description

    Error Code

    0x00000000 if no error. A hex HR if there was an error.

    ID

    Not sure if, when and why this shows. Maybe only for deletes?

    Z:row

    For all commands except Delete, the updated item with all its fields is returned.

    Property Bag

    Property bags are mechanisms for developers to add their custom data to corresponding objects inside of SharePoint.  Property bags let developers transform simple lists into rich data stores, and webs into full applications. The property bag is a virtual container that can store almost any typed of value. The SPListItem Properties property returns a property bag for the specified object.

    Note   If you use anything besides a String, int, or DateTime for the value, you will get a SPUnsupportedPropertyDataTypeException, with the message of "Only String, int, and DateTime datatypes can be used as the value in Properties."

    A call to the Update method on the object persists the values set in the property bag. All values can be stored and retried by using Web service methods.

    You must send the entire property bag, you cannot update just part of it.

    For more information about property bags in Windows SharePoint Services, refer to http://msdn2.microsoft.com/en-us/library/ms480101.aspx.

    Fields and Properties

    SharePoint has very extensible list schemas.  A client that has fixed content types (calendars, tasks, etc) needs to be able to relate its own item properties to specific fields on the list.  Typically this is done by calling GetList to get the field schema before a client syncs to a SharePoint list for the first time.

    Item properties in a client are best matched to fields on the server by the field GUID in the list schema.  The internal name of SharePoint fields can also be used to associate client-side properties with their server-side counterparts.  If a client cannot find an appropriate field on the server, it should store the data in the property bag for other clients to consume.  The client should cache these associations so that it doesn't have to fetch the list schema on every call.

    GetListItemChangesSinceToken is a very fast call when no changes were done on the list. GetList is not quite as fast.

    When a client calls GetListItemChangesSinceToken, it will receive a new list schema if the schema has changed. Unfortunately, if the schema change indicates a change in the internal name of one of the fields which are requested by name, the results of the call must be discarded. This is because the field you requested by name may not be included in the result set.

    There are a few snags with respect to client use of the property bag.  If, when making an update, a client doesn't know which particular property has changed, it must update every property (even the ones not set) so that it is sure to clear the ones recently emptied.

    Note   A field with an empty value is equivalent to an absent field; while an empty-value property is not.

    If a new field is added to the list, values stored by the client in an equivalent property are not automatically promoted into the field value. The client must decide whether to respect the value in the property and the value in the field, possibly losing user data in the process.

    Document Sync

    Clients should use HTTP/DAV to sync document content. Although some SharePoint web methods support document content fetch and update (for attachments), this is not the preferred way of transferring binary document content. Because SOAP is based on XML, binary documents need to be encoded into an XML-compliant form. This is generally accomplished using hex encoding, which roughly doubles the bandwidth used.

    A core field in document libraries (and also in generic lists in wssversion3short) is FileRef, which is basically a combination of two other fields associated with columns in the SQL table: DirName (server path to the containing folder) and LeafName (name of the document).

    Document libraries also have two other fields computed from FileRef - ServerUrl and EncodedAbsUrl.

    One of these can be used to reference a document.

    On a generic list, another field (Attachments) is used to determine if the item has attachments.

    Although there is a separate method to determine what these attachments are, by default there is no way to quickly determine if any attachments of an item have changed. This is what the IncludeAttachmentUrls and IncludeAttachmentVersion query options are for.

    When these options are used, the value of this field should contain; #[AttachmentUrl];#[AttachmentGuid],[AttachmentVersion] for each attachment. The client can compare these values with what they stored to determine which attachments need to be re-fetched.

    Because document contents can be quite big, a client can support a header-only mode that lets the user decide which document contents should be off-lined. MaxBulkDocumentSyncSize is a property that can be set on the server to guide the client when to automatically sync all contents.

    Note    Some generic lists have content that can be quite large. Discussion Boards are an example. The content of a discussion item is stored in a couple of rich text fields. The header-only concept could also be used here by separate the call for the generic fields from a separate GetListItems or call for the contents. We have no examples of the best way doing this and we have not analyzed it for performance.

    Conflict Detection

    Besides performance considerations, discussed below, this is arguably the most important sync topic: How to detect and deal with an object that was modified on both sides.

    Fetch-Send-Refresh

    It is better to have conflicts detected and resolved by the client. The client can better detect that the changes didn't actually conflict, it can raise an alert for the user to manually correct the conflict, and it can store a copy of the changes applied by the local user in the user's storage.

    Thus it is best if a sync operation consists first of fetching the changed data from the server, then detecting any conflicts with changes in the client copy, and finally uploading those changes if there is no conflict.

    SharePoint objects may have some business logic applied at the point of the update. Because of that, the UpdateListItems method returns the updated values of all the fields and properties of the updated items.

    owshiddenversion Field

    wssversion3short uses this field to detect conflicts. If the field value is not supplied on update, the server will overwrite any changes. A client should always supply it on update to prevent data loss. This number should be whatever the server last sent.

    This is used so that the server can tell if you're updating a stale copy of the item.  For example, a client syncs an item and gets a value of '2' for this attribute.  Someone changes the title of the item on the server, so the value increments to become 3.  When the client sends a change with value '2', the server complains because the item has been modified since the client last requested it.

    When there is a conflict, the server will return a TP_E_VERSIONCONFLICT (0x81020015) error and the current contents of the item.

    vti_versionhistory Property

    The hidden version field is sufficient for simple conflict detection when all clients are synchronizing with a central server however; peer to peer synchronization presents further challenges. You want to avoid raising unnecessary conflicts when the change was synchronized by a peer client.

    This situation may also happen in a non-peer-to-peer scenario. If a client successfully uploads a change to the server but does not receive an acknowledgment (response from UpdateListItems), the client needs a way to know that its changes were uploaded on next sync.

    ETag DAV Header

    Document and Attachment fetches and updates are done through HTTP/DAV. For that protocol, we have a separate mechanism for conflict detection. In every http get of a file (be it a document in a list, an attachment or a page outside a list) we return an ETag, which is supposed to be another blob that contains a guid and a version number. When uploading a document with http put, a client should request that the ETag matches the one supplied.

    Note   Version history is not supported for this protocol.

    Attachments

    Although updating attachments can be done through HTTP/DAV, adding attachments requires using the AddAttachment method from the lists.asmx web service which takes a binary array and returns the URL of the attachment.

    For more information about AddAttachment , refer to lists.asmx web service.

    Performance

    There are some performance issues to keep in mind when you are dealing with syncing with a server.

    Latency

    The amount of time it takes for an action to complete is what is important to a user. Also, there are usually limits on the amount of time allowed to process a request on a database, on a front end and by the entire request, so extremely long requests can turn into denied requests. Even despite this, you want to be able to give the users feedback on the action.  This is why paging is required.

    Using the row limit property on GetListItemChangesSinceToken to limit the amount of data requested each time is crucial for the above reasons, but it should be clear that it will also increase the total amount of time to complete a sync process.

    Throughput

    Obviously, reducing the total amount of cycles required to process a request helps performance by reducing latency. However, with multiple clients, it is more important to reduce the adverse effects one client has on the others. Most of the time, it is easier, cleaner, safer and more effective to make the server do some processing than to implement the same processing on a multiple number of clients. However, to increase throughput, it is almost always better to do that work on the client. Although the server will likely be a lot more powerful, the client will likely have more available CPU time. A sync client should make the data request to the server be as little and simple as possible.

    Bandwidth

    We target high-bandwidth scenarios, but even then, it is important to try to minimize the amount of data sent across the wire.

    It a client is not going to require a piece of information, it should avoid requesting it.

    Paging

    When performing a full sync (no change token), the client should request a maximum number of items returned per page using the rowLimit parameter. If the filtered number of items in the list is greater than that number, the server will return a ListItemCollectionPositionNext attribute to be used to request the next page.

    We will only return the current change token of the list on the first page to prevent the loss of any changes being made to the first page. The client should store the change token from the first page for a subsequent incremental sync.

    Secondary pages will also not include list and global properties like permissions, alternate urls and TTL.

     

    rowLimit is also supported on incremental syncs (change token supplied), but on an incremental sync this will limit the processing of our internal change log, and we have an internal limit of 100. Although the client can be sure the number of items returned will never be greater than that limit, in certain circumstances not all changes may have been synchronized even if the number of items returned is smaller than the limit. This is because we will stop processing the change log as soon as we reach a number of updates equal to the limit. When that is the case, we return the MoreChanges attribute to indicate there are more changes in the change log. Instead of waiting for the next sync period, the client should request more changes immediately using the returned change token.

     

    The limit works this way on incremental sync for a few reasons:

    • We have an internal limit of 100 because we don't have a modified time index we can use to filter the items returned and SQL has a limit of 160 on the number of ors in a query and starts performing badly close to that number. 100 gives us a potential extra 60 as part of the filter requested by the client.
    • We could have made several separate SQL queries, but that would imply supporting all ordering and filtering on the middle tier.

    Because of this, we needed to return a change token that is not current, so that extra changes could be processed on a separate call. We could have still looked at the entire change log to better determine the latest point at which the number of items returned would be smaller than the limit, but even this wouldn't be accurate without filtering on the middle tier.

    Filtering and Ordering

    Filtering is a way to allow the user to only get a certain set of items in a list. The two most common usages of this are for folder sync, where the user only gets the items inside a folder, and for certain Group Board scenarios where the user only gets the items associated with him/her.

    Filtering can be done using the contains parameter or the query parameter. Contains is more restrictive since it is basically the Where clause of a SharePoint CAML query, while query is the full query. Contains is safer to use because we can optimize certain scenarios. Query is more powerful and flexible, but the caller must understand its performance effects.

    A client should avoid filtering by a non-indexed column. Otherwise, fetching a page will require a scan of the entire list until it finds the number of items requested.

    A client should also avoid requesting an order unless the column of the order is indexed. Otherwise, fetching a page will at a minimum require a sort on the entire filtered dataset.

    Finally, if the filter is not on the same indexed column of the order, then SQL may still scan the entire list to avoid sorting the filtered dataset.

    An incremental sync has an implicit filter. We will request items with a certain ID. In this case, the client should never order by something other than ID. Filtering by something else is OK, for the dataset is restricted to a maximum of 100.

    Filtering by folder can be done using the Folder query option, but the list should be ordered by the FileLeafRef. For a recursive query, it should first be ordered by FileDirRef as well.

    There is also a way to filter by multiple folders using something like

    "<Or><BeginsWith><FieldRef Name="FileRef"/><Value Type="Note">Shared Documents/folder1/</Value></BeginsWith><BeginsWith><FieldRef Name="FileRef"/><Value Type="Note">Shared Documents/folder2/</Value></BeginsWith></Or>".

    This will synchronize the full contents of folder1 and folder2.

    The client should use this in the contains parameter and add the following query option:

    "<OptimizeFor>FolderUrls</OptimizeFor> "

    This will make sure the SQL query is optimized appropriately by ordering it by FileDirRef, FileLeafRef and constraining the right columns.

     

    Conclusion

    The most efficient way to synchronize with Windows SharePoint Services is to download only those items that have changed since the last synchronization occurred. In wssversion3short this can be done by calling the GetListItemChangesSinceToken Web method.

    GetListItemChangesSinceToken allows clients to track changes on a list.  Changes, including deleted items, are returned along with a token that represents the moment in time when those changes were requested. By including this token the next time you call GetListItemChangesSinceToken, the server looks for only those changes that have occurred since the token was generated.

    We discussed considerations that the developer must keep in mind to obtain the best possible performance.

    Acknowledgements

    I would like to acknowledge the following persons for their gracious help in technical reviews for this article: Matt Swann (Microsoft Corporation), Bill Snead (Microsoft Corporation).

    See Also

    http://blogs.msdn.com/sharepointdeveloperdocs/archive/2008/01/21/synchronizing-with-windows-sharepoint-services-part-1.aspx

    See Also

  • Microsoft SharePoint Developer Documentation Team Blog

    Content Migration in SharePoint

    • 6 Comments

    Around the time work started on a long whitepaper about migrating content files from SharePoint server "A" to SharePoint server "B" using the migration and deployment APIs in the Microsoft.SharePoint.Deployment namespace, I came across a series of blog posts by Stefan Goβner that covered the subject matter in detail. Many of you have probably seen Stefan's work:  Deep Dive into the SharePoint Content Deployment and Migration API, Parts 1-5.

    I contacted Stefan and he agreed to collaborate. He's allowed me to use some of his code examples, and to expand on some of his points. Additionally, I've collaborated with the feature PM and lead developer on the migration/deployment APIs here at Microsoft, Patrick Simek, so the whitepaper treats the subject quite a bit more broadly than does Stefan's blog posts.

    I'll chunk this article up into segments for posting to this blog.  Comments are DEFINITELY welcome.  I'll be converting much of the content of this article (and these posts) into Help content in the SharePoint SDK documentation, so anything that helps to improve the quality of the content is highly desired.  Here's the first section:

    The ABCs of Content Migration (Post 1)

    Many scenarios require moving content from one SharePoint site to another. When the scenario calls for a full migration (that is, moving the entire contents of a SharePoint site or site collection), the task is relatively simple. Typically, you use either of two main approaches:

    •  Use the export and import operations in the Stsadm.exe utility to migrate data from one site to another.
    • Alternatively, use SOAP calls to the  Sites.ExportWeb and  Sites.ImportWeb methods that are implemented on the Sites Web service to migrate data.

    However, both of these methods have limitations. Both limit you to migrating only a full SharePoint site, or site collection. In addition, neither allows you to retain object identity during the migration operation. Retaining object identity is an essential feature of selective migration. Using Stsadm.exe and Sites Web service have other limitations as well.

    Consequently, content migration scenarios that require you to export only selected content, or that require you to automate or customize migration operations, there is only one approach: you must write a custom solution that uses the APIs in the Microsoft.SharePoint.Deployment namespace.

    Note   Selective migration operates when there is an established source and a recognized destination for a known quantity of content. That is, selective migration requires that a full migration was initially performed so that the destination is a mirror image of the source.

    Selective migration applies, typically, to content that needs to be migrated from server to server based on factors such as content version (current vs. future), time stamp, and content state (approved vs. in review, for example). Selection criteria provides a high degree of granularity from the scope of the site collection down; that is, you have selection control at the scope of the Web, the list, folder, and list item.

    You can have any number of .cmp files in a migration operation, and you can also have multiple destinations. However, the objects contained in a given content migration package (.cmp) file must originate from a single site collection.

    Typical Migration Scenarios

    The APIs in the Microsoft.SharePoint.Deployment namespace provide a rich migration toolbox that gives you an enormous degree of flexibility to support wide ranging migration scenarios. Following is a list of migration and deployment features that are supported in Windows SharePoint Services 3.0. This list is only a high-level, generalized summary of supported migration scenarios. The Deployment APIs are sufficiently rich to support any number of special circumstances that you might face.

    • Export an entire site collection (that is, do a full migration).
    • Export a specific site inside a site collection, including or excluding content in subsites as needed. The deployment APIs allow you to include or exclude dependencies.
    • Export a SharePoint list or document library, or even of a specific folder inside a document library.
    • Export a single list item or document from a document library. This provides the extreme migration granularity that enables so much flexibility.
    • Export object dependencies like images or attached files.
    • Generate your export file as a compressed export (.cmp) package, or as uncompressed files.
    • Throttle exports by specifying a maximum size for the compressed export package file (multiple export files will be created if required).
    • Support incremental exports of items that are selected for export based on change tokens. This allows you to automate exporting all items that have been created, changed, or deleted after the timestamp specified in the change token.
    • Import the exported content with or without preserving object identity—that is, you can configure objects in the export package to retain their object GUID. This is a requirement for selective migrations.
    • Import the migration content under the same or a different parent in the destination content database. Moving items to a different position in the site hierarchy is an operation is known as reparenting.
    • Do link fixup during import.

    In my next post we'll continue with this high-altitude look at the subject of content migration. There, we'll talk extensively about key concepts in the migration/deployment feature area.

  • Microsoft SharePoint Developer Documentation Team Blog

    How to install Sandboxed Solution with Powershell (SharePoint Management Shell)

    • 0 Comments

    Farm solutions can be installed with SharePoint Management Shell (PowerShell), but did you know that sandboxed solutions can be too?

    The cmdlets have almost the same name as the corresponding cmdlets for farm solutions, the difference being that "User" is inserted after the "SP".

    To upload a sandboxed solution to a site collection's Solution Gallery with PowerShell, use the cmdlet Add-SPUserSolution. At a minimum, you need to identify the path to the solution package (wsp file) and the target site collection by using the LiteralPath and Site parameters. Example:

    Add-SPUserSolution -LiteralPath c:\CandidateSandboxedSolutions\MySandboxedSolution.wsp -Site http://MyServer/sites/Contoso

    Now, of course, you need to deploy the solution, except that when we are talking about sandboxed solutions, this step is called "activation" instead of "deployment".  But, between you and me, it is the same thing. (And activating a sandboxed solution is not conceptually the same thing as activating a SharePoint Feature.) To deploy the solution, use the Install-SPUserSoluton cmdlet. At a minimum, you need to identify the solution that you want to deploy and the site collection by using the Identity and Site parameters. Example:

    Install-SPUserSolution -Identity MySandboxedSolution.wsp -Site http://MyServer/sites/Contoso

    You can reverse the latter step with the Uninstall-SPUserSolution cmdlet with the same two mandatory parameters. You can reverse the first step with the Remove-SPUserSolution cmdlet. It also requires the Identity and Site parameters.

    There is also an Update-SPUserSolution cmdlet which is used, of course, to update a solution that has already been "activated" (that is, deployed). The syntax is the same as the Install-SPUserSolution except that you use the Identity parameter to identify the old solution and you use ToSolution parameter to identify the new replacement solution. You must first use the Add-SPUserSolution to upload the new version of the solution to the Solution Gallery. Example:

     Add-SPUserSolution -LiteralPath c:\CandidateSandboxedSolutions\MyImprovedSandboxedSolution.wsp -Site http://MyServer/sites/Contoso

    Update-SPUserSolution -Identity MySandboxedSolution.wsp -Site http://MyServer/sites/Contoso -ToSolution MyImprovedSandboxedSolution.wsp

    There are additional, optional, parameters for all of these cmdlets. For help on any of them, use the Get-Help cmdlet followed by the name of the cmdlet and the "full" parameter. Example:

    Get-Help Add-SPUserSolution -full

  • Microsoft SharePoint Developer Documentation Team Blog

    How to: Programmatically Back Up and Restore a Single Site Collection

    • 2 Comments

    Introduction

    This post describes how to back up and restore individual site collections programmatically.

    Note: Unless explicitly stated otherwise, all classes referred to in this post are in the Microsoft.SharePoint.Administration or Microsoft.SharePoint namespaces (not Microsoft.SharePoint.Administration.Backup).

    Procedures                         

     

    To Back Up or Restore a Site Collection

    1.    Add to your Visual Studio project a reference to Windows SharePoint Services.

    2.    Add using statements for Microsoft.SharePoint and Microsoft.SharePoint.Administration.   

    3.    Add the following lines to obtain a reference to the farm and its collection of services.

    [C#]

    SPFarm myFarm = SPFarm.Local;

    SPServiceCollection myServices = myFarm.Services;

    4.    Obtain a reference to the Web service that publishes the Web application that hosts your site collection by using the service's System.Guid which is the value of its SPWebService.Id property.

    [C#]

    Guid serviceID = new Guid("21d91b29-5c5b-4893-9264-4e9c758618b4");

    SPWebService webPubService = (SPWebService)myServices[serviceID];

    If you do not know the SPWebService.Id of the application publishing Web service, you can iterate through all the services and report their SPWebService.Name, SPWebService.TypeName, and SPWebService.Id. The following is an example:

    [C#]

    foreach (SPService service in myServices)

    {

        if (service is SPWebService)

        {

        Console.WriteLine("Web service name:" + webService.Name);

        Console.WriteLine("Web service type:" + webService.TypeName);

        Console.WriteLine("Web service ID:" + webService.Id);

        Console.WriteLine();

        Console.Readline();

        }

    }

    5.    Obtain a reference to the Web application that hosts your site collection. If you know the URL of the Web application you can obtain a reference with the static SPWebApplication.Lookup method. Alternatively, you can use the application's System.Guid which is the value of its SPWebApplication.Id property. The following code shows the second method.

    [C#]

    SPWebApplicationCollection myApps = webPubService.WebApplications;

    Guid appID = new Guid("10ea4e6f-ae37-4909-b04f-f516c066bc37");

    SPWebApplication myApp = myApps[appID];

    If you do not know the SPWebApplication.Id of the Web application that hosts your site collection, you can iterate through all the Web applications and report their SPWebApplication.Name, SPWebApplication.TypeName, and SPWebApplication.Id. The following is an example:

    [C#]

    foreach (SPWebApplication app in webApps)

    {

        Console.WriteLine("Web application name:" + app.Name);

        Console.WriteLine("Web application type:" + app.TypeName);

        Console.WriteLine("Web application ID:" + app.Id);

        Console.WriteLine();

        Console.Readline();

    }

    6.    Get a reference to the Web application's collection of site collections.

    [C#]

    SPSiteCollection mySiteCols = myApp.Sites;

    7.    To back up a site collection, call the SPSiteCollection.Backup method. As parameters pass the following:

    ·         The full URL of the site collection; that is, the full URL of its Top Level Web site.

    ·         The full path and file name of the file that will hold the compressed content of the site collection.

    ·         True, if the operation should overwrite an existing backup file of the same name; false, if it should not.

    [C#]

    mySiteCols.Backup(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

    8.    To restore a site collection, call the SPSiteCollection.Restore method. It takes the same parameters as the SPSiteCollection.Backup method. The Boolean parameter indicates whether the site collection should be overwritten if it already exists at the specified URL.

    [C#]

    mySiteCols.Restore(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

     

    Example

    The following example shows a simple way to programmatically back up or restore a site collection. You will need to replace all the System.Guid values with actual values from your deployment and replace the placeholder values in the Backup and Restore methods with actual URLs and paths from your deployment.

     

    // Get a reference to the Web application publishing

    // Web service.

    SPFarm myFarm = SPFarm.Local;

    SPServiceCollection myServices = myFarm.Services;

    Guid serviceID = new Guid("21d91b29-5c5b-4893-9264-4e9c758618b4");

    SPWebService webPubService = (SPWebService)myServices[serviceID];

     

    // Get a reference to the Web application that hosts the

    // site collection.

    SPWebApplicationCollection myApps = webPubService.WebApplications;

    Guid appID = new Guid("10ea4e6f-ae37-4909-b04f-f516c066bc37");

    SPWebApplication myApp = myApps[appID];

     

    // As alternative to the preceding three lines, you can use

    // the following when you know the URL of the Web application:

    //     SPWebApplication myApp = SPWebApplication.Lookup(url_of_Web_app)

     

    // Get a reference to the Web application's collection of

    // site collections.

    SPSiteCollection mySiteCols = myApp.Sites;

     

    // Back up a specified site collection.

    mySiteCols.Backup(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

     

    // Restoring the site collection is identical to the preceding

    // code except that the "Restore" is used in place of "Backup".

    //

    // mySiteCols.Restore(@"htt//Server/sites/MySiteCollection", @"\\OtherServer\WSSBackups\SiteCollections\BackupOfMySiteCollection", true);

    Comments

    The Microsoft.SharePoint.SPSite class does not implement Backup.IBackupRestore and the SPSiteCollection.Backup and SPSiteCollection.Restore methods do not use the facilities of the Microsoft.SharePoint.Administration.Backup namespace. This means that records of backups and restorations of site collections are not kept in a history file (spbrtoc.xml) in the backup directory. Similarly, backup and restoration data is not stored in spbackup.xml or sprestore.xml files, neither are these site collection operations logged in spbackup.log or sprestore.log files.

    If you want to do any kind of logging of backups and restorations of site collection operations, you will have to program your own system. Writing to the system-created spbrtoc.xml, spbackup.xml, sprestore.xml, spbackup.log, and sprestore.log files is not supported in Windows SharePoint Services 3.0. Neither is moving them, deleting them, or renaming them. However, you can create files that merge data from the system-created files with data from your site collection backups and restorations.

    See Also

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    How to: Programmatically Back Up Content

    How to: Programmatically Restore Content

    How to: Create a Content Class That Can Be Backed Up and Restored

     

     

  • Microsoft SharePoint Developer Documentation Team Blog

    Content Migration in SharePoint (Post 2):

    • 0 Comments

    Key Concepts in Selective Migration 

    Picking up where the first post left off, today's foray explores the basic concepts of SharePoint content migration. Most of these concepts come into play in nearly every migration scenario where you use the SharePoint.Deployment namespace APIs. This post covers the following concents:

    1. Content selection (also known as "cherry picking")
    2. The content migration package (.cmp) file
    3. Object identity (that is, retaining object identity on import)
    4. Reparenting objects
    5. Handling content types when migrating a site collection
    6. Handling workflows when migrating

     

         Content selection for export

    Once the initial full migration has occurred and the source and destination sites are established, selective migration relies on logic in your custom code for selection criteria that determines which items are selected for migration, and when. Also known as "cherry picking," this is the process through which specific items on the source site collection are migrated to the destination site collection based on selection criteria that is specified in the custom code.

    In the basic scenario, logic in a code module associated with a timer job runs on a recurring schedule (for example, every 24 hours at 3:00 a.m.); the module examines date stamps or change logs (or both), then selects and exports only those files that have changed since the last migration.

    The operation relies on the identity of objects in the source and destination site collections. At import time, the destination recognizes objects by GUID identifiers and then updates their corresponding files accordingly.

         Content migration package (.cmp) file

    The content migration package is a compressed cabinet (.cab) file that uses the .cmp file extension. The migration package (.cmp) file aggregates data for export from the source site, along with site structure and dependency data, and stores it as compressed, serialized XML files.

    While the export operation compresses site data by default, you can override this behavior and export uncompressed files by changing the SPDeploymentSettings.FileCompression property to false. This property is on the SPDeploymentSettings object.

    When using file compression, you must must specify the name of the compressed content migration (.cmp) file using the BaseFileName property on the SPExportSettings object. The FileLocation property specifies where the compressed file is located on the source server.

    By default, the .cmp files are limited to 24 MB in size, although you can change this using the FileMaxSize property. When site data exceeds the 24 MB limit, your site data is separated in to two or more migration files. However, where a single file exceeds the maximum file size, the operation resizes the .cmp file to accommodate the file. You can have any number of .cmp files.

         Object identity

    SharePoint objects are identified by GUID on the source server. Upon import, by default, the objects are assigned new GUIDs on import to the destination. To support selective migration scenarios, however, you must change the default and retain the identity of the object that you are exporting. This is very important, because the only way that files can successfully update their corresponding versions on the destination site is for the destination to recognize the object by its identifying GUID.

    You can retain object identity by setting the RetainObjectIdentity property on the SPImportSettings object to true.

    Note   To use the RetainObjectIdentity property to support selective migrations, you must also set the ExportMethod property to the value ExportChanges.

    Retaining object identity should be used carefully, and in limited scenarios. It most commonly supports a publishing scenario in which source and one or more destination servers are mirror images — for example, where a development or test server is migrating updates to one or more production servers.

    If you are creating a new site that you know in advance will receive file updates on a regular basis (for example, from a development or test server), you can enable a smooth link between the two by first doing a full migration from the source to a completely blank site, but with RetainObjectIdentity property set to true. It is very important, then, that you never modifythe destination. The initial migration established the mirrored hierarchy and mappings; any modifications to the destination can break the linkage. If this relationship gets broken, your only recourse is to delete the destination and then reestablish the linkage as originally done.

    Note   In the scenario described above, you can use Stsadm.exe to complete the export portion of the migration, since it does not support the retention of object identity. However, you must use the migration APIs to complete the import portion of the migration in order to retain object identity.

    SharePoint content databases do not permit duplicate GUIDs or file names, so you must be careful when implementing this property. You should not retain object identity when you are simply updating files on the destination server, because the import operation cannot determine whether a file is new or an update, and will therefore place a duplicate copy of the file on the destination.

    This happens because the migration process uses GUID identifiers, but only down to the level of the item collection. Beneath that level, that is, for individual files, the system uses the file name. Consequently, the import simply copies over the updated version of the existing file and leaves the original intact, potentially creating duplicates. When the destination server then encounters duplicate file names, it cannot resolve the ambiguity and becomes unstable.

    Important   When deleting files, it is very important to delete the files on both the source and destination servers. Not doing so can cause duplicate files names and an unstable site.

    To support field deletion (a feature that deletes previous versions of items on the source server when the migration updates and deletes the same file on the destination), the RetainObjectIdentity property must be set to true.

     

         Reparenting

    Now let's consider a much different scenario. Instead of a publishing scenario, in which objects on the source server have to map to their equivalent files on the destination server, consider instead a scenario in which a specific subweb or list item is migrated and you want to place it at a different place in the destination hierarchy. This is a very common requirement and you handle this by reparenting the object (or objects) on import.

    It's important to note that, as discussed in the section on retaining object identity, any time that you do not retain object identity, a migrated object will need a new parent specified on import. It doesn't matter if the destination site collection is the same site collection as the source or even if it is in the same database as the source site collection. It also doesn't matter if the destination site collection is in the same or a different farm as the source site collection.

    If you export an item from a database without exporting its parent, then the item that you've exported will become orphaned in the content migration package, but that's not necessarily a problem. A package can contain multiple orphaned objects.

    Having orphaned objects in the migration package is not a problem because the import method allows us to define a new parent for each of these orphaned objects. This is what is meant by "reparenting." However, objects that are exported with their parent objects keep their relationships during migration. So, for example, if you export Web A and Web B is a sub web of web A, then you can only change the parent of web A. The parent of Web B will remain as Web A, because Web B.

    There are two ways to reparent orphaned objects when importing. In the first, you import all of your orphaned objects into the same subweb, while in the other method you assign parent objects individually to each orphaned object.

          Reparent by importing all orphans to the same subweb

    You can reparent your orphan objects by simply importing all of them into the same subweb. However, this only works if all of the orphan objects are destined for the same subweb. For example, this is the preferred method if you have exported two or more list or document library objects and you want to import them all into the same subweb. This works even if the export objects are from different source sites. Here is some sample code for doing this. Of particular note are the WebUrl and RetainObjectIdentity properties.

     

    SPImportSettings settings = new SPImportSettings();

    settings.SiteUrl = "http://localhost:2001";

    settings.WebUrl = "http://localhost:2001/MyDestinationWeb";

    settings.FileLocation = @"c:\export";

    settings.FileCompression = false;

    settings.RetainObjectIdentity = false;

     

    SPImport import = new SPImport(settings);

    import.Run();

     

    In the above example, the WebUrl property defines the site (the SPWeb) that becomes the new parent for all orphaned objects in the export package.

    Note   You cannot use this method to reparent orphaned objects if the migration package contains orphaned documents; SharePoint site cannot become the parent of a document document object (only list or folder objects can parent documents).

    Note, too, that the RetainObjectIdentity property is set to false. This is important because keeping this property as false (which is the default) cases the operation to assign a new GUID to the orphaned objects, which is essential for reparenting those objects.

          Reparent by assigning new parent objects individually

    Assigning new parents to orphaned objects individually is much more flexible than the previous method, but also requires more coding. In this approch, you must intercept the import operation to assign a new parent to each orphaned object after the operation has accumulated a list of all orphaned objects in the migration package. You can do this by implementing a custom event handler, as in the following example:

     

    static void OnImportStarted(object sender, SPDeploymentEventArgs args)

    {

       SPSite site = new SPSite("http://localhost:2001");

       SPWeb web = site.RootWeb;

     

       SPImportObjectCollection rootObjects = args.RootObjects;

       foreach (SPImportObject io in rootObjects)

       {

          io.TargetParentUrl = web.Url;

       }

     

       web.dispose();

       site.dispose();

    } 

     

    This approach uses the RootObject collection of the event arguments to aggregate all and then reparent all of the orphan objects. Actually, we do much the same thing that we did when we imported all of the objects to the same subweb, that is, we defined a specific site (SPWeb) as the new parent of all included orphaned objects. However, notice how you can extend the logic in the event handler to, for example, assign different parents to different orphans based on object type, as shown here:

     

    static void OnImportStarted(object sender, SPDeploymentEventArgs args)

    {

       SPSite site = new SPSite("http://localhost:2001");

       SPWeb web = site.RootWeb;

       SPList list = web.Lists["MyDocLib"];

     

       SPImportObjectCollection rootObjects = args.RootObjects;

       foreach (SPImportObject io in rootObjects)

       {

          if (io.Type == SPDeploymentObjectType.ListItem)

          {

             io.TargetParentUrl = list.RootFolder.ServerRelativeUrl;

          }

          if (io.Type == SPDeploymentObjectType.List)

          {

             io.TargetParentUrl = web.Url;

          }

          ...

       }

     

       web.dispose();

       site.dispose();

    } 

     

    There is a great deal of flexibility here. In addition to reparenting based on the object type, you could instead look at the original TargetParentUrl, for example, to obtain the location of the source and then include that as part of your reparenting logic.

    The code example below shows us how to hook up the event handler to the import operation. You can do this as follows:

     

     

    static void ImportDocLibItem()

    {

       SPImportSettings settings = new SPImportSettings();

       settings.SiteUrl = "http://localhost:2001";

       settings.FileLocation = @"c:\deployment5";

       settings.FileCompression = false;

       settings.RetainObjectIdentity = false;

     

       SPImport import = new SPImport(settings);

     

       EventHandler<SPDeploymentEventArgs> eventHandler = new EventHandler<SPDeploymentEventArgs>(OnImportStarted);

       import.Started += eventHandler;

     

       import.Run();

    }

     

    Notice that you need to register the event handler with the import class before you start the import operation.

     

    There are several more event handlers that you can register and use during import; these are explained in more details at help topics for SPImportEvents and for SPExportEvents. Similar events can also be registered for export, if required:

     

     

         Content types (handling)

    Migration operations that use the export and import commands include your content type definition schema files in the export package. However, in cases where content type definitions hold references to custom SharePoint features, you must manually install and configure on the destination compute the feature for which the content type holds a reference. Features that are native to the SharePoint server environment will have their type definition references restored automatically.

    On starting the import operation, you will receive a warning message that alerts you with the identity of custom features for which references must be recreated. You must resolve these references after completing the import.

    For more information about content types, see Content Types. For more information about SharePoint features, see Working with Features.

     

         Workflows

    Workflows are not included in export packages so when you initially set up a migration target, you must copy any custom workflows that you have onto the destination server and reconfigure the workflow association table. This includes creating (or restoring on the destination) the workflow definitions files.

    Of course, manually restoring your custom workflows on the migration destination is only necessary when you initially set up your destination server. Subsequently, when doing selective migrations in a publishing scenario, it is advantageous that workflows are excluded from the migration package.

    For more information about managing workflows, see the following:

    ·         Introduction to Workflows in Windows SharePoint Services

    ·         Workflows in Windows SharePoint Services

     

  • Microsoft SharePoint Developer Documentation Team Blog

    SharePoint 2010 SDK Code Samples Posted to Code Gallery

    • 1 Comments

    For the SharePoint 2010 release, we’re trying something a little different with our sample code solutions. During the Beta timeframe, we’re going to be posting them to Code Gallery, rather than waiting to release them in the SharePoint 2010 SDK for the first time at RTM. This will let developers benefit from having the code samples available as early as possible. And we’re hoping it’ll benefit the code samples by having the SharePoint developer community giving us feedback on the samples and how we can make them better. We’ll include the code samples in their final form in the SharePoint 2010 SDK download at RTM.

    We’ll be keeping the list below up-to-date each time we release a new code sample, so you might want to bookmark this post. (We’ve already got three samples posted, and the SharePoint 2010 Beta isn’t scheduled for public availability until next month.)

    Unless otherwise noted, each code sample is written in C#.

    SharePoint Foundation 2010 Code Samples

    Implementation of IBackupRestore 

    This sample is a custom content class that implements Microsoft.SharePoint.Administration.Backup.IBackupRestore. Objects that instantiate this interface appear in the backup/restore UI of the SharePoint Central Administration application as items that can be selected for backup or restoration.

    SharePoint Server 2010 Code Samples

    Activity Feeds Console Application

    A console application that demonstrates the basic functions of a custom activity feed gatherer application.

    This sample creates a custom activity feed gatherer and demonstrates how to use the new Activity Feed object model in Microsoft SharePoint Server 2010. The sample creates custom ActivityTemplate, ActivityType, and ActivityEvent objects and shows how to publish and multicast events from a custom gatherer. Console output verifies that each step in the application is finished.

    Social Data Statistics Web Part 

    A Web part that displays social data statistics.

    This sample consists of a Microsoft Visual Studio 2010 SharePoint Visual Web part project. After you build and deploy this project on your Microsoft SharePoint Server 2010 site, you can add this Web part to any page where you want to display statistics for the social tagging activities of your users. The Web part displays the following information in three tables:

    ·         Each URL that has been tagged, and the terms with which each URL has been tagged.

    ·         Each term that has been used in a social tag, and the number of times that term has been used.

    ·         Each user who has added a social tag, and the number of times that user has tagged URLs.

    The sample demonstrates how to use the new Social Data object model in SharePoint Server 2010. It also takes advantage of the SharePoint Visual Web Part template, one of the new SharePoint templates that you can use in Visual Studio 2010.

  • Microsoft SharePoint Developer Documentation Team Blog

    First Look: SharePoint 2010 Developer Documentation Now Live on MSDN!

    • 0 Comments

    By now you’ve probably been hearing some of the big news coming out of the SharePoint Developer Conference being held this week in Las Vegas. Doubtlessly, there’ll be tons more great information coming out of the Conference over the next four days concerning what’s new and notable in SharePoint Foundation 2010 and SharePoint Server 2010. But if you weren’t lucky enough to make it to Vegas this year, or are there but can’t wait for the session on your favorite area of SharePoint development, then have we got something you’ll want to take a close look at:

    Introducing the SharePoint 2010 (Beta) Developer Center

    That’s right, this morning we launched the SharePoint 2010 (Beta) Developer Center on MSDN. We’re using this new, combined Developer Center to give you your first detailed, public technical information and instruction around both SharePoint Foundation and SharePoint Server 2010. This new sub-site of the revamped SharePoint Developer Center highlights some early videos, documentation, and hands-on lab walkthroughs to introduce you to the exciting developer features on both SharePoint Foundation 2010 and SharePoint Server 2010.

    But that‘s not all: we’ve also published a Beta release of the combined SharePoint 2010 SDK!

    You’ll definitely want to spend some time on the site, getting ramped up for when the SharePoint 2010 Betas are released in November.

    Learn SharePoint from the Ground Up

    Of particular interest to developers new to SharePoint will be the Get Started Developing on SharePoint 2010. We’ve put together a series of 10 modules to help you get your feet wet on some of the main areas of SharePoint development, including:

    ·         Building Web Parts

    ·         What Developers Need to Know About SharePoint 2010

    ·         Building Blocks for Web Part Development

    ·         Accessing Data and Objects with Server-Side APIs

    ·         Accessing Data and Objects with Client-Side APIs

    ·         Accessing External Data with Business Connectivity Services

    ·         Developing Business Processes with Workflows 

    ·         Creating Silverlight User Interfaces

    ·         Sandboxed Solutions for Web Parts

    ·         Creating Dialog Boxes and Ribbon Controls

    Each module includes multiple video lessons, as well as code samples and hands-on lab walkthroughs, to give you a firm grounding in the topics covered.

    Even experienced SharePoint developers will want to take a look at the modules that cover brand new development areas, like the client-side APIs, Silverlight user interfaces, sandboxed solutions, and the new ribbon user interface.

    Get Your First Look at What’s New for Developers in SharePoint 2010

    For an even deeper look at what’s new and notable in SharePoint Foundation and Server 2010, we’ve posted a Beta version of the combined SharePoint 2010 SDK. It’s packed with conceptual, procedural and reference material covering the major developmental areas of both Foundation and Server. All in all, it’s almost half a million words detailing how to develop SharePoint solutions.

    For example, take a look here for what’s new in SharePoint Foundation 2010, including:

    ·         Alerts Enhancements

    ·         Business Connectivity Services

    ·         Client Object Model

    ·         Events Improvements

    ·         Microsoft Synch Framework

    ·         Mobile Device Development Enhancements

    ·         Query Enhancements

    ·         Ribbon

    ·         Sandboxed Solutions

    ·         Service Application Framework 

    ·         Silverlight Integration and the Fluid Application Model

    ·         UI Improvements

    ·         Windows PowerShell for SharePoint

    ·         Workflow Improvements

    And take a look here for what’s new in SharePoint Server 2010, including:

    ·         User Profiles and Social Data

    ·         Business Connectivity Services (BCS)

    ·         Enterprise Content Management (ECM)

    ·         SharePoint Enterprise Search

    ·         PerformancePoint Services

    ·         Excel Services

    Some other places you might want to start:

    ·         If you’re newer to SharePoint development, you might want to spend some time in the Getting Started and Building Blocks sections of the SDK, getting a firm grounding in the basics.

    ·         If you’re coming to SharePoint from an ASP.NET development background, but sure and check out the Glide Path for ASP.NET Developers section, which is specifically aimed at developers transitioning from ASP.NET development to development on the SharePoint Foundation platform.

    Let Us Know What You Want

    Now, this SDK is a Beta release, so you’ll likely see some rough edges. But we’ve combined this SDK to cover both SharePoint Foundation and Server, and restructured it to present the continuum of SharePoint development in as logical and intuitive a way as we could. We then packed it with new and updated conceptual, procedural, and reference material.

    We’d love to hear what you think of what we’ve done. As always, as you read through the SDK, if you spot issues, don’t see the information you need, or have suggestions, please drop us a line and let us know how we can improve our developer documentation. It’s easy; just do one of the following:

    ·         Enter a comment in the MSDN ratings box

    ·         Email us directly at docthis (at) Microsoft.com

    ·         Email us through this blog

    Be sure and check back here often (or even better, subscribe to our RSS feed), as we plan on using the blog to preview draft versions of additional SDK content as it gets written.

  • Microsoft SharePoint Developer Documentation Team Blog

    Overview of Backing Up and Restoring Data in Windows SharePoint Services

    • 5 Comments

     

    Introduction

    This post provides some basic facts about backing up and restoring data in Windows SharePoint Services 3.0. It will serve as background information for several developer-oriented posts that I will create in the next couple of weeks.

    Note: Unless explicitly stated otherwise, all classes and members referenced in this post are in the Microsoft.SharePoint.Administration.Backup namespace.

    What Can Be Backed Up and What Can Be Restored

    There are six types of content components built-in to Windows SharePoint Services 3.0 that can be backed up and restored through either the Central Administration application's UI, the Stsadm.exe Command-line Tool or a custom application that uses the Windows SharePoint Services 3.0 backup and restore object model.

    ·         Site collections, each of which might contain multiple Web sites.

    ·         Content databases, each of which might contain multiple site collections.

    ·         Web applications, each of which might contain multiple content databases.

    ·         Content publishing "Web services," each of which might contain multiple Web applications.

    Note: This refers to content publishing "Web services" (which are really partitions of content) that are represented in the object model by Microsoft.SharePoint.Administration.SPWebService objects. It does not refer to the functional Web services in the more common sense of "Web service," such as the Alerts (websvcAlerts) service or the Meetings (websvcMeetings) service. For more information about content publishing "Web services," see Server and Site Architecture: Object Model Overview and The High Level Object Model of Windows SharePoint Sevices 3.0 (to be published on MSDN).

    ·         Search Windows service including its databases and indexes.

    Note: This does not refer to the Search Web service websvcSPSearch.

    ·         A whole Windows SharePoint Services farm.

    If an enhanced functionality product such as Office SharePoint Server 2007 has been installed in addition to Windows SharePoint Services 3.0 and that product includes Shared Service Providers, then they can also be backed up and restored with Windows SharePoint Services 3.0.

    In addition, you can create new types of content objects that can be backed up and restored by implementing the IBackupRestore interface.

    Limitations

    There are some limitations on what can be backed up and restored through either the Central Administration application's UI, the stsadm command line utility or a custom application that uses the Windows SharePoint Services 3.0 backup and restore object model.

    ·         You cannot backup (or restore) an individual Web site, list, or list item except by backing up (or restoring) the entire site collection to which it belongs.

    ·         You cannot back up a Windows SharePoint Services farm's configuration database or the content database of the Central Administration application except by backing up the whole farm.

    ·         You cannot restore a farm's configuration database or the content database of the Central Administration application. The backups of these components that are included in a backup of a farm provide a snapshot of these components at the time of the backup. Such snapshots might be useful for troubleshooting because they can be used to compare with the present state of the components using SQL Server tools. (There is an exception to this point: you can restore the configuration database and the content database of the Central Administration application if you are using the Volume Shadow Copy Service – VSS - of Windows Server 2003/2008).

    ·         You cannot back up the Internet Information Server (IIS) metabase.

    The following kinds of content cannot be backed up with either the Central Administration application's UI or the stsadm command line utility, but you can create custom backup solutions with the Windows SharePoint Services SDK that include these types of content.

    ·         Registry keys.

    ·         Files that live on the front-end servers; that is, outside any content database, such as certain master pages, .ascx files, web.config files, and other configuration files.

    Types of Backups and Restorations

    Backups of a given component can be either full or incremental. In the latter case, only parts of the component that have changed since the last full backup are backed up.

    Note: A Windows SharePoint Services Search index cannot be incrementally backed up. If a search index is included in an incremental backup job, the index will get a full backup.

    Restorations can either overwrite the original backup source or they can be to a new location. This means that the backup and restore functionality in Windows SharePoint Services 3.0 can also be used as a method of migrating content components.

    Two Kinds of Custom Backup Applications

    There are two ways to use the Windows SharePoint Services object model to create custom backup applications.

    The Main Backup and Restore Object Model

    You can create a backup and restore application by using the main backup and restore object model, sometimes called "catastrophic" backup/restore. This is located mainly in the Microsoft.SharePoint.Administration.Backup namespace; but backups and restores of individual site collections are performed with the Microsoft.SharePoint.Administration.SPSiteCollection.Backup() and Microsoft.SharePoint.Administration.SPSiteCollection.Restore() methods.

    Interface to the Volume Shadow Copy Service

    Windows SharePoint Services 3.0 deployments can also take advantage of the Volume Shadow Copy Service (VSS) in Windows Server 2003/2008. Windows SharePoint Services 3.0 includes a Windows SharePoint Services VSS Writer service that will create shadow copies of native and custom content in the deployment. The service contains a VSS writer that will write shadow copies of all native Windows SharePoint Services 3.0 databases and all custom databases. Non-database custom components can also be registered with the service by using the SPVssComponentDefinition and SPVssDiscoveryHelper classes. It is also necessary that you create a VSS writer for any such non-database custom components.

    Note: With the VSS service, you can target only the whole farm or individual content databases for database shadow copy. Individual Web applications and individual content publishing "Web services" cannot be set for shadow copying independently of making a shadow copy of the whole farm. (For information about the meaning of "content publishing Web service" see the first note of this post.)

     

  • Microsoft SharePoint Developer Documentation Team Blog

    We’ve Moved to the SharePoint Development Team Blog

    • 6 Comments

    Over the past few years, a number of MSDN blogs have been created that deal, at least in part, with SharePoint development, to the point where it’s sometimes challenging keeping up with them all. So, to make it easy for developers to make sure they’re getting all the latest technical information around developing SharePoint solutions, we’ve decided to combine those blogs into the one: the SharePoint Development Team Blog. Think of it as your one-stop shop for developer-centric SharePoint information, straight from the product teams and user assistance folk responsible for SharePoint Foundation, Server, SharePoint Online, and the SharePoint development tools in Visual Studio.

    Going forward, we’ll be posting the content that in the past you’d find on this blog to the SharePoint Development Team Blog. We’ve left this blog up, in maintenance mode, so that developers can still access the content we’ve published here. But be sure you subscribe to the new, consolidated blog for great content, including:

    ·       Detailed technical information on SharePoint development, such as walkthroughs and code samples, from the people who designed those product features and tools

    ·       Early, first-look versions of content being prepared for publication to MSDN

    ·       Cross-posts and pointers to SharePoint-centric developer content on other specialized blogs, such as Erika Ehrli’s, Eric White’s, or SharePoint in Pictures

    ·       Announcements of interest to SharePoint developers, such as content updates, service releases, or developer events.

    And pass the following easy-to-remember URL on to your SharePoint developer friends and colleagues:

    http://blogs.msdn.com/sharepointdev/

    Thanks for reading, and we hope to hear from you over at the SharePoint Development Team Blog!

  • Microsoft SharePoint Developer Documentation Team Blog

    Quick Tip: Find the Four-Part Name for an Assembly

    • 8 Comments

    When developing for SharePoint, you sometimes need to find the four-part name for an assembly. You can do this inside of Visual Studio 2010 using PowerShell. It’s pretty straight-forward.

    1. In the Tools menu of Visual Studio, click External Tools.
      Tools Menu
    2. In the dialog, click Add to get a new tool.
      External Tools Menu
    3. Now, configure the tool with the following options:
      Title: Get Four-Part Name
      Command: powershell.exe
      Arguments: –command "[System.Reflection.AssemblyName]::GetAssemblyName(\"$(TargetPath)\").FullName
      Use Output window: Checked
      image
    4. Click OK to dismiss the window.

    Now, you can go into the Tools menu to see your tool. If you click it, it will print out the four-part name including the public key token in your Output window.

    image

  • Microsoft SharePoint Developer Documentation Team Blog

    Where are Assemblies in Sandboxed Solutions Deployed?

    • 6 Comments

    Because sandboxed solutions cannot deploy files to a server's file system, there is some puzzlement over where the assemblies in sandboxed solutions are deployed and persisted.  The situation is not helped by the fact that the package manifest of a sandboxed solution implies that such assemblies are deployed to the GAC as the following screenshot shows. This is not the case.

    The assemblies in a sandboxed solution are included in the solution's package (wsp file) and the package is deployed to the site collection's Solutions Gallery. When a sandboxed solution is accessed for the first time, such as when a user navigates to a page containing a Web Part from a sandboxed solution, any assemblies in the solution are unpacked from the wsp and copied to the file system of the server that is handling the sandbox request. The location is C:\ProgramData\Microsoft\SharePoint\UCCache. The server that handles the sandbox request is not necessarily the front-end web server that is handling the initial HTTP request: the User Code Host Service can be run on back end application servers in the farm instead. Since the sandboxed user process (SPUCWorkerProcess.exe) cannot copy anything to the file system, the copying is done by the User Code Host Service.

    The assemblies do not stay in the file cache perpetually. When the user session that accessed the assemblies ends, the assemblies stay in the cache for only a short time and they may be reloaded from there if another user session assesses them. Eventually, if they are not accessed, they are removed in accordance with a proprietary algorithm that takes into account how busy the server is and how much time has gone by since the assemblies were last accessed. If the sandboxed solution is used after that time, the assemblies unpacked again and copied to the UCCache.

    Administrators, developers, and third-party code should not add, remove, or load anything from the UCCache. It should only be accessed by the SharePoint infrastructure.

    Rick - MSFT

  • Microsoft SharePoint Developer Documentation Team Blog

    Activity Event Sample on Code Gallery: How to Publish Events with a Timer Job

    • 0 Comments

    The SharePoint Server 2010 social data object model enables you to create your own activity types and publish activity events in custom applications. One important limitation, however, is that only users who have User Profile Service Application administrative privileges can publish activity events. You cannot, therefore, create a custom application that publishes activity events directly after a given user takes an action, unless you know for sure that the user will always be a User Profile Service Application administrator. This limitation helps keep unwanted items from overwhelming users’ activity feeds, but it also requires developers to plan ahead, work with administrators, and design custom applications that work around this limitation.

    One way to work around the limitation is to store information about activity events in a hidden list. You can then create a timer job that runs at times and frequencies that you and your administrators establish beforehand in order to balance performance considerations with user experience concerns, such as the timeliness of the information in the activity feeds. This timer job would use information in the hidden list to create activity events and then publish these events by using the multicasting methods in the social data object model. If the publication succeeds, the timer job would then clear the list. Because this hidden list might become large, you would need to follow the best practices guidance in the Handling Large Folders and Lists topic.

    The Microsoft SharePoint Server 2010: Activity Events for Document Libraries sample on Code Gallery provides a prototype for how this sort of design can work. It publishes an activity event to the activity feeds of a user’s colleagues whenever that user adds a document to a document library. The solution creates the new activity type to which the published activity events belong, along with the hidden list on feature activation.

    Take a look at the sample and provide feedback on it by commenting on this post or on the Code Gallery resource itself. In addition to performance considerations, one potential drawback of this approach is that there will be a short interval between the publication of activity events and the clearing of the hidden list, which means that someone could potentially add a document within that interval, the list would be cleared, and the event would not get published. Let us know if you notice other drawbacks, or if you can think of ways to improve upon this design.

  • Microsoft SharePoint Developer Documentation Team Blog

    New Visual Upgrade Article

    • 1 Comments

    Those of you who are interested in learning more about how to use Visual Upgrade in SharePoint 2010 should take a look at our recently published technical article, “Understanding Visual Upgrade,” by Ted Pattison. This and other upgrade resources are available at the SharePoint 2010 Upgrade Resource Center.

  • Microsoft SharePoint Developer Documentation Team Blog

    SharePoint SDKs (and Other Documentation Resources) Now Updated for SP1

    • 15 Comments

    By now you’ve no doubt heard that SP1 for Windows SharePoint Services 3.0, Office SharePoint Server 2007, and Office SharePoint Designer are now available. (And if you haven’t heard, go here to get all the important details before you download and install the Service Packs.)

    For a complete listing of the documentation available for SharePoint SP1, check out the What’s New in SharePoint Server 2007 Service Pack 1 page on MSDN, which includes information resources for both WSS and MOSS SP1.

    I’m happy to announce that as part of the SP1 push, we’ve again updated the WSS and MOSS SDKs on MSDN:

    ·         Windows SharePoint Services 3.0 SDK (December 2007 Refresh)

    ·         Office SharePoint Server 2007 SDK (December 2007 Refresh)

    Here’s a quick run-down of additions and updates we’ve made to the WSS SDK:

    New and Updated Material in the Windows SharePoint Services 3.0 SP1 SDK

    New conceptual sections and topics that detail new features in Windows SharePoint Services 3.0 SP1 include:

    ·      ASP.NET AJAX in Windows SharePoint Services

    This section provides overview information, installation instructions, and programming examples that introduce you to how Microsoft ASP.NET AJAX interacts with Web Parts. Topics include:

    ·         Overview: ASP.NET AJAX and Web Parts in Windows SharePoint Services 3.0

    ·         Installing ASP.NET 2.0 AJAX Extensions 1.0 in Windows SharePoint Services Version 3.0

    ·         Walkthrough: Creating a Basic ASP.NET AJAX-enabled Web Part

    Other new conceptual sections and topics include:

    ·      Workflow Actions Schema Overview

    The section discusses how to use the Workflow Actions schema to create and deploy custom workflow actions. The section includes reference topics for each of the 14 elements in the schema, as well as an example .ACTIONS file:

    ·         .ACTIONS File Example (WorkflowActions)

    ·      Alerts in Windows SharePoint Services

    This section provides 8 new topics of overview information and programming tasks to help you work with Windows SharePoint Services 3.0 Alerts.

    Significantly revised sections and topics include:

    ·      Custom Field Types

    This section has been expanded with nine new topics, including the following new walkthrough:

    ·         Walkthrough: Creating a Custom Field Type

    In addition, reference material for all base field-rendering control types, and most derived types, in Microsoft.SharePoint.WebControls has been expanded.

    ·      Mobile Development

    This section has been expanded with 6 new conceptual topics, including the following new procedural and walkthrough topics:

    ·         How to: Customize Mobile Home Pages

    ·         How to: Customize Mobile List View and Form Pages

    ·         How to: Customize Field Rendering on Mobile Pages

    ·         Walkthrough: Customizing Item Titles on a Mobile Display Form

    ·         Walkthrough: Creating a Custom Field Rendering Control for Mobile Pages

    In addition, reference material for all types in the Microsoft.SharePoint.MobileControls namespace has been added or expanded. The types in this namespace are now fully documented.

    ·      Working with Site Templates and Definitions

    Several topics have been expanded.

    ·      All types in the Microsoft.SharePoint namespace that connected to auditing are now fully documented.

    ·      More than 80 code samples rewritten to adhere to the best coding practices as described in the following articles:

    ·         Best Practices: Common Coding Issues When Using the SharePoint Object Model

    ·         Best Practices: Using Disposable Windows SharePoint Services Objects

    ·      Greatly expanded reference material for 39 types in the Microsoft.SharePoint.Utilities namespace.

    This update also includes numerous other updates and revisions to existing SDK content.

    And as for the SharePoint Server 2007 SDK, we’ve added and revised quite a bit of material there as well:

    New and Updated Material in the SharePoint Server 2007 SP1 SDK

    New and Improved Features in Office SharePoint Server 2007 SP1

    ·         Support for Custom HTTP and SOAP Headers

    New Conceptual Topics and How Tos

    ·         SharePoint Products and Technologies Customization Best Practices

    ·         Modeling Web Service Systems

    ·         Modeling Database Systems

    ·         Document Converter Framework Sample

    ·         Working with Menus and Navigation Objects

    ·         Modifying Navigation Settings Through the UI

    ·         Customizing Navigation Controls and Providers

    New Web Services and Class Library Reference Topics

    ·         Microsoft.SharePoint.UserProfiles (56 classes) 

    ·         User Profile Web Service (14 classes) 

    ·         User Profile Change Web Service (2 classes) 

    ·         Exception classes (multiple classes in various namespaces)

    ·         Internal only classes (multiple classes in various namespaces)

    New Tools/Samples

    ·         WCM Document Converters Code sample

    ·         Workflow Collect Feedback ASPX sample

    Check it out, and as always, let us know what you think—either through rating our content, entering a comment on the topic online, or pinging us with an email through our blog.

  • Microsoft SharePoint Developer Documentation Team Blog

    Programming with the Windows SharePoint Services Backup/Restore Object Model

    • 1 Comments

    Introduction

    This post describes the architecture of the backup and restore object model in Windows SharePoint Services 3.0 and provides some advice about how to program against it. Your backup application can be an independent application or an extension of the stsadm.exe command-line tool. For more information about how to extend stsadm, see How to: Extend the STSADM Utility.

    Note: All classes in this post are in the Microsoft.SharePoint.Administration.Backup namespace unless specified otherwise.

    The Backup and Restore Object Model

    At the top of the object model is the SPBackupRestoreConsole class. (See , in Figure 1.) It provides an umbrella operations manager responsible for queuing backup and restore jobs, starting jobs, and persisting a history of jobs in the form of xml files. An object of this class is "just underneath the surface" of the UI of a backup application. Its members are mainly static methods and properties that provide hooks for the UI of the backup application. Both the Central Administration application and the stsadm.exe command-line tool use these hooks.

    There is always just one object of this class and it is created the first time one of its members is called. It remains in memory until the next time Internet Information Server (IIS) is reset; however, its memory footprint is small.

    Figure 1: The primary objects in the backup/restore hierarchy.

    Primary Objects in WSS Backup Restore OM 

     

    Each particular backup or restore operation is represented by an object of the class SPBackupRestoreConsoleObject that is created by the SPBackupRestoreConsole.CreateBackupRestore method of the console object. (See , in Figure 1, the queued backup and restore operations.) The properties of one of these lightweight objects hold information about the operation such as whether it is a backup or a restore, the location of the backup files, the backup or restore method, the current stage of the operation, and the tree of content components that his being backed up or restored. These objects also have an SPBackupRestoreConsoleObject.Id property of type System.Guid that serves as a handle for the object that can be passed to the methods of SPBackupRestoreConsole. For example, SPBackupRestoreConsole.Run is passed the ID of the operation (that is; the SPBackupRestoreConsoleObject object) that the console is to run next. Finally, each SPBackupRestoreConsoleObject has a SPBackupRestoreConsoleObject.Settings property that holds a persisting object that contains a reusable pattern of backup (or restore) settings. This object also identifies the content component that the operation is to back up or restore. The settings objects are discussed in more detail near the end of this section.

    While the SPBackupRestoreConsoleObject objects represent operations, the content components themselves are represented by SPBackupRestoreObject objects. (See , in Figure 1.) These objects can be nested with the SPBackupRestoreObject.Children property. Therefore, each one represents a tree of one or more content components. For example, a Web application would be represented by a by SPBackupRestoreObject object that would have each of the Web application's content databases as child SPBackupRestoreObject objects. The tree of components that are the subject a particular backup or restore operation is internally linked to the SPBackupRestoreConsoleObject object that represents the operation. You can get a reference to the topmost SPBackupRestoreObject object in the tree by passing the ID of the SPBackupRestoreConsoleObject object to the SPBackupRestoreConsole.GetRoot method.

    A SPBackupRestoreObject object is a container for two critical types of objects:

    ·         In its SPBackupRestoreObject.Information property the SPBackupRestoreObject object holds either a SPBackupInformation or a SPRestoreInformation object. These kinds of objects hold information about how to back up or restore a particular component and methods that can be called internally by SPBackupRestoreConsoleObject and SPBackupRestoreObject as part of an operation. More specifically, these classes hold methods and properties whose implementation should never change regardless of what kind of content component is being represented. Hence, they are sealed and deriving a new class from their parent, SPBackupRestoreInformation, is not supported.

    ·         In its SPBackupRestoreObject.IBackupRestore property the SPBackupRestoreObject object holds an object that implements the IBackupRestore interface (and might also inherit from Microsoft.SharePoint.Administration.SPPersistedObject). (See , in Figure 1.) Implementation of the latter interface turns an object into something that can potentially be backed up and restored. Like an SPBackupRestoreInformation object, an IBackupRestore object contains members that provide information and methods needed for backups and restorations. But the members of IBackupRestore must be given different implementations depending on the kind of content component that is being represented. Most importantly, the implementation includes event handlers for an operation's events, such as IBackupRestore.OnBackup and IBackupRestore.OnRestore.

    Besides acting as a container, SPBackupRestoreObject is a helper class that provides easier interaction between the operation objects (SPBackupRestoreConsoleObject), on the one hand, and the component information objects (SPBackupRestoreInformation and IBackupRestore), on the other.

    The final major classes are SPBackupSettings and SPRestoreSettings. An object of one of these two types is passed to the SPBackupRestoreConsole.CreateBackupRestore method when an operation is created. (See , in Figure 1.) Each of these objects holds settings for use in operations; most importantly, they identify, in their SPBackupRestoreSettings.IndividualItem property, the content component that is the subject of the backup or restore operation. (See , in Figure 1.)

    Programming Advice

    Ways of Customization

    Most of the critical classes in the backup restore object model are sealed (NotInheritable in Visual Basic). Moreover, although the following classes are not sealed, deriving from them is not supported. In each case, you must use the existing derived classes:

    ·         SPBackupRestoreInformation. (Existing derived classes: SPBackupInformation and SPRestoreInformation.)

    ·         SPBackupRestoreSettings. (Existing derived classes: SPBackupSettings and SPRestoreSettings.)

    Accordingly, there are just two primary points of customization:

    ·         You can create your own high level application, and UI, that will use the static methods of the operations console — an SPBackupRestoreConsole object — to manage and run backup and restore jobs. For more information about how to do this see How to: Programmatically Back Up Content and How to: Programmatically Restore Content.

    ·         You can create a class that implements the IBackupRestore interface and might or might not also derive the Microsoft.SharePoint.Administration.SPPersistedObject class. For more information about how to create a custom content class, see How to: Create a Content Class That Can Be Backed Up and Restored.

    Permissions

    Code that backs up content must run in the user context of a farm administrator. Code that restores must run in the context of a user who is both a farm administrator and an administrator on all the front-end servers. The user should also have read and write permissions for the backup location.

    Failure Logging

    If a backup or restore operation fails, details about the failure will be logged in spbackup.log or sprestore.log in the backup location.

    Backups and Restores of Site Collections

    Aside from custom content types that you create by implementing IBackupRestore, the smallest content object that you can back up and restore with the classes in the Microsoft.SharePoint.Administration.Backup namespace is a content database. To programmatically backup or restore individual site collections, use Microsoft.SharePoint.Administration.SPSiteCollection.Backup(System.String,System.String,System.Boolean) and Microsoft.SharePoint.Administration.SPSiteCollection.Restore(System.String,System.String,System.Boolean). For more information on backing up and restoring site collections, see How to: Programmatically Backup and Restore a Single Site Collection.

     

  • Microsoft SharePoint Developer Documentation Team Blog

    How Should C# Property Syntax Signatures Appear in Office SDKs?

    • 7 Comments

    This post is to solicit your opinion about whether and how Microsoft should change the presentation of C# property declarations in SDK topics to take into account certain changes in the 3.0 version of C#.

    Every property of a managed class has a reference topic in the product’s offline SDK and a corresponding MSDN page. Near the top of the page is the declaration signature of the class, in a monospaced font, as it would look in each of several languages. For example, the SPList.AllowRssFeeds topic has the following for Visual Basic and C#:

    VB: Public ReadOnly Property AllowRssFeeds As Boolean

    C#: public bool AllowRssFeeds { get; }

    And for SPList.AlertTemplate, the topic has this:

    VB: Public Property AlertTemplate As SPAlertTemplate 

    C#: public SPAlertTemplate AlertTemplate { get; set; }

    In reality, nearly all managed code at Microsoft is written in C#. The syntax examples for other languages only show, approximately, what the declaration would have looked like if the class had been written in that language. Notice that whether or not the property is read-only can be conveyed in the VB with that language's ReadOnly keyword. But C#'s little-known readonly keyword can be applied to fields, not properties. So to indicate whether or not a property is read-only, the declaration adds "{ get; set; }", for read/write properties, or just "{ get; }", for read-only properties.

    This system has worked well even though the C# declarations were not literally correct syntax. Indeed, they worked well partly because they were not correct syntax. Since they were not valid declarations, there has been no danger that readers would think that the pseudo-declaration indicated anything about how the get and set accessors were implemented under the hood. Thus, the programming design principle of “information hiding” is preserved.

    But with C# 3.0, a declaration such as this one:

    A:

    public type SomeProperty { get; set; }

    is valid code and it would compile “as is.”  It is equivalent to the following code. In fact, it is transformed into the following code on an early pass of the compiler.

    B:

    private type someField;

    public type SomeProperty

    {

        get { return someField; }

        set { someField = value; }

    }

    The C# 3.0 syntax for a read-only wrapper property simply adds a “private” access modifier to the set accessor:

    C:

    public type SomeOtherProperty { get; private set; }

    which compiles to:

    D:

    private type someOtherField;

    public type SomeOtherProperty

    {

        get { return someField; }

    }

    ( Note by the way, that since both A and B compile to identical IL code, no code analysis tool, such as .Net Reflector or Visual Studio’s Object Browser, can determine whether the property’s source code originated as A or B. A parallel point applies to C and D.)

    The problem this creates for the property topics in our SDKs is that our presentation of read/write properties now can be mistaken for the actual implementation, especially by new developers who are coming to Microsoft managed code development after the release of C# 3.0 and are not familiar with the history of the syntax conventions on these pages.

    Such a misunderstanding can, in turn, lead developers to make mistaken assumptions about the property’s get and set accessors. Our current way of presenting a read/write property declaration in our SDKs implies, since the release of C# 3.0, that the property is a simple wrapper property. This, in turn, implies several things that may be false. Among them are:

    • The set accessor does no validation on the input.
    • The set and get accessors do not directly throw (or catch) any exceptions.
    • The get accessor is simply returning a field value as distinct from calculating a value from multiple fields.

    Two proposals have been made for how C# property declarations should look going forward.

    Explicit Labeling Proposal:

    Under this proposal, the read/write or read-only character of a property would be explicitly stated in a different font from the monospaced font of the declaration:

    public type SomeProperty [read/write]

    public type SomeOtherProperty [read-only]

    Put the ‘Pseudo’ Back in 'Pseudo-Code' Proposal:

    Under this proposal, the tradition of using pseudo-code to indicate the writeable status would be preserved, but the braces and semi-colons would be removed so that the presentation is once again not legal code.

    public type SomeProperty get set

    public type SomeOtherProperty get

    The Office developer documentation team would like you to vote on these proposals. One way is to add a comment to this post. If you are an MVP member of the Office Content Publishing Collaboration site, you also have the option of voting on this survey page.

    You may also, of course, vote to leave the property declarations just as they are, or make an alternate proposal.

    One final point: Although this survey is sponsored by Office Developer Documentation, the issue is relevant to all managed code SDKs (and to the way that Visual Studio’s Object Browser presents properties). Although it will take time for all branches of the company to align on a single policy, you should vote as though you were helping to set policy for all divisions of Microsoft. It is likely that, eventually, all the affected Microsoft teams will settle on a consistent manner of presenting C# properties. In other words, do not vote against a proposal merely because it is inconsistent with the current policy of some other SDK or tool.  

Page 1 of 2 (47 items) 12