January 27, 2014

New Authoring Process

With my commitment to revive this blog with new content I have also switched to a new authoring and publishing process.

Previously I wrote all my blog posts directly in Blogger’s HTMl editor. At the beginning of my blog it was the most sensible thing for me to do. Blogger provided me with an interface to directly write my articles into the publishing engine. And it was a good choice. But over time I began to regularly fiddle with the HTML which was generated while typing into Blogger’s editor. And I did not focus on the area which is most important: content.

Besides my blog I have been looking for an editor solution which provides me a simple and universal user experience from my Windows laptop which I have for work and on my private iMac. Early on I found Markdown a very interesting solution. You are basically typing plain text into an editor with formatting commands. And the available commands are quite comprehensive for a blog post. This is then rendered into formatted output, e.g. HTML. Fundamentally, you can use just a simple text editor like Notepad or Notepad++ on Windows, or TextEdit or TextWrangler on OS X.

But in my case I would still need a Markdown processor which renders the final HTML, because Blogger does not directly support Markdown. The text files can be synced for example with a cloud storage solution like Dropbox or Google Drive between my computers.

But until recently there were two major flaws:
  1. Although I am just saving and loading text files, the available Markdown editors for Windows 7/8/8.1 and OS X did not work very well together. There were encoding issues and problems with the different ways the system interprets special characters, e.g. line breaks.
  2. The publishing process for the blog would have suffered a serious break. After I have created an article with a Markdown editor, I would need to
    • export the Markdown as HTML
    • Open the HTML file.
    • Copy the correct HTML fragment
    • Paste the fragment into Blogger.
With both of those drawbacks I did not want to use Markdown in my writing process.

Then I discovered a very nice Chrome app with the name +StackEdit. The Chrome app appears to be a link which redirects you to stackedit.io. And since it is just web application I am able to use it from basically any browser.

StackEdit Chrome App
Although the data can be stored inside the browser, I decided to use the Google Drive integration, so my posts can be easily shared between multiple computers. And now comes the killer argument: I can directly publish from StackEdit to Blogger — no manual fiddling required. Exactly what I wanted in the first place.

Auhtoring Process
With the new setup I have now published two new blog posts and have some more in preparation. And the new setup has proven itself. How does your authoring process looks like?

January 20, 2014

Green Gamification

Device with a Twist

At my company’s new year kick-off everyone got a present which at first sight does not have much in common with our daily work: Creating rich intranets based on SharePoint. It might be even seen as a pure geek gadget: a DIN A4 sized solar panel and a rechargeable battery. The solar panel is used to charge the battery. And the battery then can be used to charge for example your mobile phone.
But now comes the twist. Changers, the company behind it, has created an online community which allows you to upload your CO2 savings by charging your devices with solar energy. And this community provides multiple incentives to regularly use your device. You can
  1. Track how much CO2 you have saved by charging your mobile devices with solar energy.
  2. Track how many watt-hours of energy you have created.
  3. Earn badges by achieving certain energy saving levels
  4. Start a green energy competition with your peers, e.g. colleagues or friends.
  5. Earn credits and redeem those at partner shops.
  6. Post about your achievements into your social networks.
  7. and more
All of the above incentives are typical for gamification. By making the path to the environmental objective use green energy more enjoyable the founders of Changers bait you into this direction.

Drive Engagement

A similar strategy is used by many online communities and social networks. They aim for an increase in user numbers as well as a high engagement rate of existing users. The Microsoft Developer Network for example has an extensive Recognition System which covers many areas of community interactions. From points , over bronze, silver and gold medals to achievements you there are many ways to reward you. The overall objective: User engagement.
Something comparable can be achieved with SharePoint 2013’s Reputation System. The Reputation System allows to reward users for their contribution to a community. And consequently the engagement and the quality of the SharePoint community sites should increase. But before you begin, you should definitely check the default settings which activities are rewarded. Because otherwise you might end-up with unwanted user behavior of due to wrong incentives.

Heavy Cloudy with a Chance of…

Looking out of my window I realize that the sun is still hiding somewhere behind clouds and the weather forecast for the next days is not much better. I am pretty much on the verge in building my green energy credit empire. So let’s hope for sunny days.

December 22, 2013

Looking back and ahead

At the end of a year I have the tendency to look back at the past year and set a vision of what lies in the twelve months to come.

When I look at the post history from this year I must admit that this blog was pretty silent in 2013. I published only three posts in January - which is eleven months ago. Then nothing has happened until this post. Wow, time flew by.

What has kept me from publishing new posts in this time? Frankly, I cannot attribute to a single cause. There were multiple reasons for this:
  • I have started a new job in February which provided new challenges.
  • In my prior job I was regularly involved in Nintex projects. In my new job my projects are most of the time around software architecture and quality assurance in SharePoint development projects. (SharePoint will never let you go ;-))
  • and many other reasons.
So with the new tasks in my daily job, I am going to shift the core topics of this blog more in the direction of software architecture and quality assurance. Nintex posts will still be published from time to time but the majority of posts will be around software architecture and quality assurance in the context of SharePoint.

Additionally, I have become a regular consumer of lifehack and personal effectiveness sites. So when an interesting topic from this area comes up, I am going to discuss this as well.

So stay tuned.

January 24, 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.

January 22, 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.


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  

January 14, 2013

Integrating Nintex Workflow with Twitter Pt. 1


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=,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
   2:  <%@ Register Tagprefix="SharePointWebControls" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3:  <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   4:  <%@ Register Tagprefix="PublishingWebControls" Namespace="Microsoft.SharePoint.Publishing.WebControls" Assembly="Microsoft.SharePoint.Publishing, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> 
   5:  <%@ Register Tagprefix="PublishingNavigation" Namespace="Microsoft.SharePoint.Publishing.Navigation" Assembly="Microsoft.SharePoint.Publishing, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   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>
  35:  <asp:Content ContentPlaceholderID="PlaceHolderPageTitle" runat="server">
  36:      <SharePointWebControls:FieldValue id="PageTitle" FieldName="Title" runat="server"/>
  37:  </asp:Content>
  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>
  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>
  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.


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

February 23, 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.