24 January, 2013

Readlist 02/2013: Search in SharePoint 2013

With this month I start a post series with Readlists. Each posts contains some links to articles devoted to one topic. besides introducing a new tag "Readlist" there is also a page where all reading lists can be accessed.

February 2013 is all about Search in SharePoint 2013.


22 January, 2013

Integrating Nintex Workflow with Twitter Pt. 2

This is the second part in the series Integrating Nintex Workflow with Twitter. Please go to part 1 to see the full story.

In the first part of this series we have created a content News Page, a page layout and deployed the feature to a SharePoint Publishing site. The page has an extra field which is used to enter the message sent to Twitter.

This part covers the workflow which is used to tweet the availability of a new News Page. In order to get the following to work you need Nintex Workflow 2010 with Nintex Live enabled. (If you want to know how enable Nintex Live take a look at the Installation Manual which can be found on Nintex's Support Pages.)

Step 1: Creating the Workflow

The workflow for this scenario should be executed everytime a new page with version 1.0 of our content type is approved. Consequently, for updates to the content no tweet is sent. Nintex offers the possibility to hook into the item changed event for list workflows. Therefore go to the library Pages of your publishing site and create a new Nintex Workflow.


Step 2: Add Actions from Nintex Live Catalog

Nintex provides the activities Google URL shortener and Twitter Tweet through the Live Catalog. (The Nintex Live functionality is a seperate feature which has to be activated on the current site collection.) Open the catalog from the ribbon.



Then use the search function to locate Twitter Tweet as well as Google URL shortener and add both activities.



After adding both activities your workflow activity catalog looks like this:


Step 3: Configuring the URL shortener

Add the activity Google URL shortener to your workflow and configure it as shown below. The workflow variable Item URL shortened, in which the shortened URL is saved, has the type Single line of text.


Step 4: Configuring Twitter Tweet

All you need now is the activity Twitter Tweet. Add it to the workflow and configure it as shown in the image.


Enter as Authorizing User someone who can approve Nintex Live's access request to your company's Twitter account. As Twitter text we set the content of the field TWITTERMESSAGE from the content type News Page as well as the shortened URL.

Step 4: Configuring the Startup Options

We want to run this workflow after a page based on the content type News Page was approved for the first time, i.e. Version 1.0. Subsequent updates to the content should not trigger further tweets. Therefore open the workflow settings and set the following start up options:

  1. Uncheck Start manually
  2. Set Start when items are modified to Conditional
Open the dialog Conditional Startup Options by clicking on the button Conditions. Configure the conditions in the following way:


Close the dialog by clicking on Save. Set the name of the workflow to Twitter about News Page.Your workflow settings should look like this:


Close the workflow settings by hitting on Save then publish the workflow.

Conclusion

In this post you have created a workflow which tweets the availability of a News Page. Next week's post is about the experience of the News editor and how the result looks like on Twitter.

Complete code from this week is available on codeplex: http://vsanner.codeplex.com, Project: 2013-01 SocialMedia-2  


14 January, 2013

Integrating Nintex Workflow with Twitter Pt. 1

Overview

One common scenario for corporate Internet sites is to sent notifications when a new article is published via social networks to their followers. With the availability of Nintex Live it became possible to twitter a tweet. In one of the later versions a similar activity for Yammer became available. In this post I will show how you can use the "Twitter a Tweet" activity to notify your Twitter followers about new articles.

This is going to be a two part series. In the first part I will create a News Page content type and page layout. In the second part I will show you the workflow which ensures that every time a News Page was approved the notification is sent to Twitter.

Step 1: Content Type News Page

In order to get started open Visual Studio 2010 and create an empty SharePoint project. Then add a new content type to this project based on Page.


Modify the added content type to look like the this:


   1:  <!-- Parent ContentType: Page (0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39) -->
   2:    <ContentType ID="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900d765018dfe204899adbdfeca8fd70d8f"
   3:                 Name="News Page"
   4:                 Group="Social Media"
   5:                 Description="News Page with Twitter Message"
   6:                 Inherits="TRUE"
   7:                 Version="0">


Step 2: Field Twitter Message

The field is used by editors to define the message which is sent to Twitter.  Just add before the content type declaration from step 1 following field:


   1:  <Field ID="{D46E8C75-4C20-4118-A367-A553429602F0}"
   2:         StaticName="TWITTERMESSAGE"
   3:         Name="TWITTERMESSAGE"
   4:         Title="Twitter Message"
   5:         DisplayName="Twitter Message"
   6:         Type="Text"
   7:         Group="Social Media"
   8:         TextOnly="TRUE"
   9:         ShowAlways="TRUE"
  10:         Hidden="FALSE"
  11:         MaxLength="119"
  12:           />

Please note: MaxLength (line 11) is set to 119. This allows us to append URL to the article during the workflow.

Then add the field to the News Page content type declaration:


   1:  <!-- Parent ContentType: Page (0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39) -->
   2:    <ContentType ID="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900d765018dfe204899adbdfeca8fd70d8f"
   3:                 Name="News Page"
   4:                 Group="Social Media"
   5:                 Description="News Page with Twitter Message"
   6:                 Inherits="TRUE"
   7:                 Version="0">
   8:      <FieldRefs>
   9:          <FieldRef ID="{D46E8C75-4C20-4118-A367-A553429602F0}" Name="TWITTERMESSAGE" Required="TRUE"/>
  10:      </FieldRefs>
  11:    </ContentType>

Step 3: Binding the News Page to the library Pages

And finally before the closing Elements tag insert the content type binding. This ensures that the content type is available in the library Pages.


   1:  <!-- Bind Content Type to Pages library-->
   2:      <ContentTypeBinding
   3:          ContentTypeId="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900d765018dfe204899adbdfeca8fd70d8f"
   4:          ListUrl="$Resources:cmscore,List_Pages_UrlName;"
   5:          />

Step 4: Adding the Page Layout

As of now we have defined the content type News Page and have added a field to hold the message sent to Twitter. What is still missing is a page layout which allow editors to create a news page and define the message content. Add a new module named PageLayouts to the project. Then rename the file Sample.txt to NewsPage.aspx.

Open NewsPage.aspx and paste the following code into the file:

   1:  <%@ Page language="C#"   Inherits="Microsoft.SharePoint.Publishing.PublishingLayoutPage,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
   2:  <%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3:  <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   4:  <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   5:  <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   6:   
   7:  <asp:Content ContentPlaceholderID="PlaceHolderAdditionalPageHead" runat="server">
   8:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent1" UIVersion="4" runat="server">
   9:          <ContentTemplate>
  10:              <SharePointWebControls:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/pageLayouts.css %>" runat="server"/>
  11:              <PublishingWebControls:editmodepanel runat="server" id="editmodestyles">
  12:                  <!-- Styles for edit mode only-->
  13:                  <SharePointWebControls:CssRegistration ID="CssRegistration1" name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/zz2_editMode.css %>" runat="server"/>
  14:                  <style>
  15:                      .ms-long{width:900px !important;}
  16:                  </style>
  17:              </PublishingWebControls:editmodepanel>
  18:          </ContentTemplate>
  19:      </SharePointWebControls:UIVersionedContent>
  20:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent2" UIVersion="4" runat="server">
  21:          <ContentTemplate>
  22:              <SharePointWebControls:CssRegistration name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/page-layouts-21.css %>" runat="server"/>
  23:              <PublishingWebControls:EditModePanel ID="EditModePanel1" runat="server">
  24:                  <!-- Styles for edit mode only-->
  25:                  <SharePointWebControls:CssRegistration ID="CssRegistration2" name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/edit-mode-21.css %>"
  26:                      After="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/page-layouts-21.css %>" runat="server"/>
  27:              </PublishingWebControls:EditModePanel>
  28:          </ContentTemplate>
  29:      </SharePointWebControls:UIVersionedContent>
  30:      <SharePointWebControls:CssRegistration ID="CssRegistration3" name="<% $SPUrl:~sitecollection/Style Library/~language/Core Styles/rca.css %>" runat="server"/>
  31:      <SharePointWebControls:FieldValue id="PageStylesField" FieldName="HeaderStyleDefinitions" runat="server"/>
  32:  </asp:Content>
  33:   
  34:   
  35:  <asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
  36:      <SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
  37:  </asp:Content>
  38:   
  39:   
  40:  <asp:Content ContentPlaceholderID="PlaceHolderPageTitleInTitleArea" runat="server">
  41:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent3" UIVersion="4" runat="server">
  42:          <ContentTemplate>
  43:              <SharePointWebControls:TextField runat="server" id="TitleField" FieldName="Title"/>
  44:          </ContentTemplate>
  45:      </SharePointWebControls:UIVersionedContent>
  46:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent4" UIVersion="4" runat="server">
  47:          <ContentTemplate>
  48:              <SharePointWebControls:FieldValue FieldName="Title" runat="server"/>
  49:          </ContentTemplate>
  50:      </SharePointWebControls:UIVersionedContent>
  51:  </asp:Content>
  52:   
  53:   
  54:  <asp:Content ContentPlaceHolderId="PlaceHolderTitleBreadcrumb" runat="server">
  55:      <SharePointWebControls:VersionedPlaceHolder ID="VersionedPlaceHolder1" UIVersion="4" runat="server">
  56:          <ContentTemplate>
  57:              <asp:SiteMapPath ID="siteMapPath" runat="server" SiteMapProvider="CurrentNavigation" RenderCurrentNodeAsLink="false" SkipLinkText="" CurrentNodeStyle-CssClass="current" NodeStyle-CssClass="ms-sitemapdirectional"/>
  58:          </ContentTemplate>
  59:      </SharePointWebControls:VersionedPlaceHolder>
  60:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent5" UIVersion="4" runat="server">
  61:          <ContentTemplate>
  62:              <SharePointWebControls:ListSiteMapPath runat="server" SiteMapProviders="CurrentNavigation" RenderCurrentNodeAsLink="false" PathSeparator="" CssClass="s4-breadcrumb" NodeStyle-CssClass="s4-breadcrumbNode" CurrentNodeStyle-CssClass="s4-breadcrumbCurrentNode" RootNodeStyle-CssClass="s4-breadcrumbRootNode" NodeImageOffsetX=0 NodeImageOffsetY=353 NodeImageWidth=16 NodeImageHeight=16 NodeImageUrl="/_layouts/images/fgimg.png" HideInteriorRootNodes="true" SkipLinkText="" />
  63:          </ContentTemplate>
  64:      </SharePointWebControls:UIVersionedContent>
  65:  </asp:Content>
  66:   
  67:   
  68:  <asp:Content ContentPlaceholderID="PlaceHolderMain" runat="server">
  69:      <SharePointWebControls:UIVersionedContent ID="UIVersionedContent6" UIVersion="4" runat="server">
  70:          <ContentTemplate>
  71:              <table id="MSO_ContentTable" cellpadding="0" cellspacing="0" border="0" width="100%">
  72:                  <tr>
  73:                      <td>
  74:                          <div class="pageContent">
  75:                              <PublishingWebControls:RichHtmlField id="content" FieldName="PublishingPageContent" runat="server" />
  76:                          </div>
  77:                      </td>
  78:                  </tr>
  79:              </table>
  80:              <PublishingWebControls:editmodepanel runat="server" id="editmodepanel2">
  81:                  <!-- Add field controls here to bind custom metadata viewable and editable in edit mode only.-->                
  82:                  <table cellpadding="10" cellspacing="0" align="left" class="editModePanel" width="100%">
  83:                      <tr valign="top">
  84:                          <td>
  85:                              <asp:label text="Please enter your twitter message." runat="server" />
  86:                          </td>
  87:                          <td width="950">
  88:                              <SharePointWebControls:TextField FieldName="TWITTERMESSAGE" runat="server" />
  89:                          </td>
  90:                      </tr>
  91:                  </table>            
  92:              </PublishingWebControls:editmodepanel>
  93:          </ContentTemplate>
  94:      </SharePointWebControls:UIVersionedContent>
  95:  </asp:Content>

In line 80 the edit mode panel begins. This section is only displayed when a user edits the page. This is where we allow the editor to enter the Twitter message. In line 88 we bind a TextField control to the field TWITTERMESSAGE of the content type.

Step 5: Binding the Page Layout to the Content Type

Although we have just defined the page layout. there is currently no binding between the page layout and the content type. In order to create this binding, update the elements.xml of the module with these lines:


   1:  <Module Name="PageLayouts" Url="_catalogs/masterpage" Path="PageLayouts" >
   2:        <File Path="NewsPage.aspx" Url="PageLayouts/NewsPage.aspx" Type="GhostableInLibrary">
   3:            <Property
   4:                  Name="PublishingAssociatedContentType"
   5:                  Value=";#News Page;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900d765018dfe204899adbdfeca8fd70d8f"/>
   6:            <Property
   7:                Name="Title"
   8:                Value="News Page (Twitter)"/>
   9:        </File>
  10:  </Module>

The first Property element binds the page layout to the content type.

Conclusion

During this post we have create a content type which has a page layout and stores a twitter message. The next post will be covering the workflow will be available by next week.

Complete code from this week is available on codeplex: http://vsanner.codeplex.com, Project: 2013-01 SocialMedia-1


23 February, 2012

How to use Workflow Constants as Environment Information

After showing how workflow constants can help you with environment information in my last post How to Handle Environment Variables with Nintex Workflow, I am going to explain how workflow constants can be used in your deployment scripts.

Starting of we create a workflow constant at website level. Therefore go to the Site Settings of the site where you want to use the workflow constant, then select Manage workflow constants under Nintex Workflow. Select New from the ribbon and create a workflow constant with the following settings:

click to enlarge


Then open the command prompt and switch to the Nintex Workflow 2010 install folder. (Typically: C:\Program Files\Nintex\Nintex Workflow 2010). In order to export the workflow constant you have just created enter the following command:

   1:  nwadmin -o ExportWorkflowConstants -siteUrl [url to your site] -outputFile wfconst_dev.xml -includeSite

The output file wfconst_dev.xml contains all workflow constants which do exists at the selected site. As you can guess by the file extension this is a XML which can be edited. Opening the XML you will see something like this:

   1:  <?xml version="1.0"?>
   2:  <ArrayOfWorkflowConstant>
   3:    <WorkflowConstant>
   4:      <SiteId>662cb00b-6401-4a66-af25-8e33982bacbd</SiteId>
   5:      <WebId>a37b2ecd-d760-41ef-a3dc-a20c633e2480</WebId>
   6:      <Id>3</Id>
   7:      <Title>CRM web service</Title>
   8:      <Description/>
   9:      <Value>http://crmdev/MSCRMServices/2007/CrmService.asmx</Value>
  10:      <Sensitive>false</Sensitive>
  11:      <Type>String</Type>
  12:      <AdminOnly>false</AdminOnly>
  13:    </WorkflowConstant>
  14:  </ArrayOfWorkflowConstant>

You can change the URL of the web service in line 9 to http://crmtest/MSCRMServices/2007/CrmService.asmx in order to have the correct setting for the test environment. When you save the changed file save it as wfconst_test.xml. Usually I have a file with workflow constants for every environment:

  •  wfconst_dev.xml
  •  wfconst_test.xml
  •  wfconst_prod.xml

With the following command you can import the file with the workflow constants into your target environment:

   1:  nwadmin -o ImportWorkflowConstants -siteUrl [url to your site] 
-inputFile wfconst_test.xml -handleExisting Overwrite -includeSite



This should take care of most aspects you have to consider for configuration management.


14 February, 2012

How to Handle Environment Variables with Nintex Workflow

A topic you sure will run across is how to handle environment variables when you deploy workflows designed with Nintex Workflow. The values are by definition just valid for one specific environment, and have to be changed in order to deploy the workflow into another environment. Example for environment variables are URLs of web services or service accounts, which are different between development, test and production system.

Basically, there are three ways how you can handle this information:

  1. store the information within the workflow activity
  2. create a workflow variable
  3. create a workflow constant
Most people start with alternative 1. The environment specific information is directly configured on the workflow activities. This has one advantage: You are pretty fast when you configure the activities the first time. But in the long run the disadvantages outweigh. After deploying the workflow from environment to the next stage, you have to update all affected activities. Beside the fact that this is time-killing, it is also error-prone. Furthermore, such a workflow requires some effort if you put it under source control. For every functional change you implement, you have to update all workflow variants (e.g. for development, test, production).

Alternative 1: Configuration values are set in the workflow activity. 


With alternative 2 you will set the workflow variables carrying the environment specific information to the beginning of the workflow. So you do not have to scan the complete workflow for activities that require an update. Consequently, the risk of a faulty configuration is also mitigated. But you still have the issue, that you have a workflow variant for each environment which has to be maintained in the source code management system. And this method cannot be applied to credentials for service accounts.

Alternative 2: Configuration value is set in the beginning of the workflow.


The issue that you have to maintain a variant for every environment is resolved with alternative 3. In this solution you create a workflow constant for every environment information your workflow requires. Therefore the workflow does not have to be altered when you deploy it into another environment.

Alternative 3: Configuration values are set with workflow constants.


How workflow constants can be created using a script will be featured in my next post.

27 January, 2012

How long does "Delay for..." really wait?

First looking at the action "Pause for..." I was thinking think that I could configure the delay period precisely to the minute.



However, when I used this activity I discovered that the activity did not behave as I as expected. This was especially true when I entered an interval shorter than five minutes. I always waited longer than configured.

Looking deeper, I found out that the cause for this is the SPTimerJob job-workflow which controls the triggers for "
Pause for...". This timer job runs with the standard configuration every five minutes. If you set "Pause for..." to a shorter interval, the trigger send by the timer job will be sent every five minutes anyway. The same applies when you set the action to pause the workflow for any period of time that lies between the configured schedule for job-workflow.

Of course, an option to solve this issue is to reconfigure the timer job to run in shorter intervals. But ask yourself if this is really necessary. In my experience this is mostly annoying during demos or the design phase. If your workflow design relies on a shorter interval you should consider a redesign. The workflow engine has not been designed for timing actions to the minute.

Nintex advises, that the full impact of shortening the interval below the standard configuration of minutes cannot be estimated. Therefore the following change should only be done for demo and development systems.

  • SharePoint 2007
    stsadm -o setproperty -propertyname "job-workflow" -propertyvalue "every 1 minutes between 0 and 59" -url http://<webapplication>
  • SharePoint 2010
    Set-SPTimerJob -Identity 'job-workflow' -Schedule 'every 1 minutes between 0 and 59' 
If you have more issues with the responsiveness of the timer job, Comeron McConnel has collected some tips what you can do in his post Increasing the responsiveness of the workflow timer job on Nintex Connect.

This behavior also applies to all actions where you can enter a specific time or a time interval. Examples:

  • Flexi Task (escalation)
  • Pause for / Delay For
  • Pause until / Delay until
  • Change State
  • Loop
  • ...

25 January, 2012

Run Now in Nintex Workflow 2010

With version 2.3 Nintex introduced Run Now into Nintex Workflow 2010. Nintex promises that with Run Now the integration with other system will be easier, because workflow designers can test actions with Run Now support already during the design stage. It is not necessary to start and step through the workflow until you reach the actions.

Can it keep up to the promise?
Run Now can be accesed on all supported actions during the workflow design stage. Start with a new blank workflow and then drag an integration action into the design area. I will be using Query LDAP for the rest of this post. The other actions work alike.


After you have configured the action select "Run Now" in the ribbon. A new window is displayed where you can test the configuration. If you are using workflow variables for the configuration you can replace them with actual values. And remember:

As soon as you press execute the target system will behave as if you execute the action from the workflow. Meaning you are able to create, read, update and delete data in the connected system.

Once you click "Execute" in the ribbon area the action is executed and the configuration is tested. The result is afterwards displayed in the lower part of the window.


Conclusion
Run Now definitely makes configuring workflow actions lot easier. Any change to the configuration can be directly tested. There is no need to step through the workflow every time you make a change to the configuration in order to check that everything still works just fine. Further on, it is possible to test how the action behaves for different configurations if you use workflow variables.

An additional benefit is that you can easily retrieve the result from actions which support this feature. This can be then used to configure subsequent actions correctly.

Overall I say that Run Now helps during the design and testing of your Nintex Workflows. And it will not only shorten the time required to bring workflows which integrate with other system, but it will also help to make the workflows more robust. Promise is kept.

List of actions supporting Run Now:
  • Build String 
  • Call Web Service 
  • Execute SQL 
  • Query BCS 
  • Query LDAP 
  • Query List 
  • Query XML 
  • Regular Expression 
  • Web Request