Install Workflow Manager with PowerShell

By default, SharePoint 2013 on-premises installation includes the legacy SharePoint 2010 workflow engine only. To take advantage of Workflow 2013 you must install Workflow Manager. You can achieve this by installing Workflow Manager with the Web Platform Installer and then configure with the Workflow Manager Configuration Wizard. I have recently cobbled together my own SharePoint 2013 configuration scripts to setup SharePoint 2013 on-prem – soup to nuts – with Powershell. In keeping with this same theme, this blog post details the script required to install and configure Workflow Manager.

First things first, Workflow Manager is a separate installation from SharePoint, available on the web. I used the latest version of the Web Platform Installer to pull down the files. I had to install WPI first.

With WPI installed, open an elevated console and run the following command:

webpicmd /offline /Products:WorkflowManagerRefresh /Path:c:\WorkflowManagerFiles

We now have the Workflow Manager installation files in c:WorkflowManagerFiles. Installing WFM is a simple case of running the following command:

WebpiCmd.exe /Install /Products:WorkflowManagerRefresh /XML:c:/WorkflowManagerFiles/feeds/latest/webproductlist.xml

Note: Make sure you install the ‘Refresh’ of WFM if installing on Windows Server 2012 R2. Installing the original 1.0 version causes issues when registering WFM with SharePoint 2013. I strongly recommend patching SharePoint 2013 to SP1.

After completing the installation, Workflow Manager launches the configuration wizard. You can use the wizard WFM if you like and need do no more, but if you want to see the juicy script that the wizard generates, then read on.

The following is my complete script to configure a WFM farm – it’s a simple configuration. For those interested, Spencer Harbar has a series of good posts on configuring load balanced WFM: http://www.harbar.net/articles/wfm2.aspx.

function WFM-Configure {
    # Create new SB Farm
    $SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $WFCertAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $managementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Management;Integrated Security=True;Encrypt=False';
    $gatewayCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Gateway;Integrated Security=True;Encrypt=False';
    $messageContCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_MessageContainer;Integrated Security=True;Encrypt=False';
    Write-Host -ForegroundColor White ' - Creating new Service Bus farm...' -NoNewline;
    try {
        $sbFarm = Get-SBFarm -SBFarmDBConnectionString $managementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-SBFarm -SBFarmDBConnectionString $managementCS -InternalPortRangeStart 9000 -TcpPort 9354 -MessageBrokerPort 9356 -RunAsAccount $spServiceAcctName `
            -AdminGroup 'BUILTIN\Administrators' -GatewayDBConnectionString $gatewayCS -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey `
            -MessageContainerDBConnectionString $messageContCS;
        Write-Host -ForegroundColor White 'Done';
    }
    # Create new WF Farm
    Write-Host -ForegroundColor white " - Creating new Workflow Farm..." -NoNewline;
    $wfManagementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_Management;Integrated Security=True;Encrypt=False';
    $wfInstanceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_InstanceManagement;Integrated Security=True;Encrypt=False';
    $wfResourceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_ResourceManagement;Integrated Security=True;Encrypt=False';
    try {
        $wfFarm = Get-WFFarm -WFFarmDBConnectionString $wfManagementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-WFFarm -WFFarmDBConnectionString $wfManagementCS -RunAsAccount $spServiceAcctName -AdminGroup 'BUILTIN\Administrators' -HttpsPort 12290 -HttpPort 12291 `
            -InstanceDBConnectionString $wfInstanceCS -ResourceDBConnectionString $wfResourceCS -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    }
    # Add SB Host
    Write-Host -ForegroundColor white ' - Adding Service Bus host...' -NoNewline;
    try {
        $SBRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Add-SBHost -SBFarmDBConnectionString $managementCS -RunAsPassword $SBRunAsPassword -EnableHttpPort `
            -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    } 
    catch {
        Write-Host -ForegroundColor white 'Already Exists';
    }
    Write-Host -ForegroundColor white ' - Creating Workflow Default Namespace...' -NoNewline;
    $sbNamespace = $dbPrefix + '-WorkflowNamespace';
    try {
        $defaultNS = Get-SBNamespace -Name $sbNamespace -ErrorAction SilentlyContinue;
        Write-Host -ForegroundColor white 'Already Exists';
    }
    catch {
        try {
            # Create new SB Namespace
            $currentUser = $env:userdomain + '\' + $env:username;
            New-SBNamespace -Name $sbNamespace -AddressingScheme 'Path' -ManageUsers $spServiceAcctName,$spAdminAcctName,$currentUser;
            Start-Sleep -s 90
            Write-Host -ForegroundColor white 'Done';
        }
        catch [system.InvalidOperationException] {
            throw;
        }
    }
    # Get SB Client Configuration
    $SBClientConfiguration = Get-SBClientConfiguration -Namespaces $sbNamespace;
    # Add WF Host
    try {
        $WFRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Write-Host -ForegroundColor White ' - Adding Workflow Host...' -NoNewline;
        Add-WFHost -WFFarmDBConnectionString $wfManagementCS `
        -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true `
        -SBClientConfiguration $SBClientConfiguration -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor White 'Done';
    }
    catch {
        Write-Host -ForegroundColor white "Already Exists";
    }
}

Let’s break the script down a little. I should mention that cutting and pasting my script into your Powershell window won’t work to start because the script assumes the existence of a few predefined variables, as follows:

  • $dbServer – SQL Alias for my SQL server (best to use an alias not the server name)
  • $dbPrefix – Prefix for all my database names
  • $spServiceAcctName – Name of my service account (used for workflow manager)
  • $spServiceAcctPWD – Password for my service account
  • $spAdminAcct – Admin account for SharePoint
  • $passphrase – Passphrase used by WFM when joining new hosts to the farm

WFM consists of two parts – the Service Bus and the Workflow Engine. To start with, my script creates a new Service Bus Farm…

$SBCertificateAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $WFCertAutoGenerationKey = ConvertTo-SecureString -AsPlainText  -Force  -String $passphrase;
    $managementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Management;Integrated Security=True;Encrypt=False';
    $gatewayCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_Gateway;Integrated Security=True;Encrypt=False';
    $messageContCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFMSB_MessageContainer;Integrated Security=True;Encrypt=False';
    Write-Host -ForegroundColor White ' - Creating new Service Bus farm...' -NoNewline;
    try {
        $sbFarm = Get-SBFarm -SBFarmDBConnectionString $managementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-SBFarm -SBFarmDBConnectionString $managementCS -InternalPortRangeStart 9000 -TcpPort 9354 -MessageBrokerPort 9356 -RunAsAccount $spServiceAcctName `
            -AdminGroup 'BUILTIN\Administrators' -GatewayDBConnectionString $gatewayCS -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey `
            -MessageContainerDBConnectionString $messageContCS;
        Write-Host -ForegroundColor White 'Done';
    }

Notice that my script does some checking and error control so that I can run this script multiple times without it causing error because of pre-configuration. OK, now to the Workflow Farm…

Write-Host -ForegroundColor white " - Creating new Workflow Farm..." -NoNewline;
    $wfManagementCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_Management;Integrated Security=True;Encrypt=False';
    $wfInstanceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_InstanceManagement;Integrated Security=True;Encrypt=False';
    $wfResourceCS = 'Data Source=' + $dbServer + ';Initial Catalog=' + $dbPrefix + '_WFM_ResourceManagement;Integrated Security=True;Encrypt=False';
    try {
        $wfFarm = Get-WFFarm -WFFarmDBConnectionString $wfManagementCS;
        Write-Host -ForegroundColor White 'Already Exists';
    }
    catch {
        New-WFFarm -WFFarmDBConnectionString $wfManagementCS -RunAsAccount $spServiceAcctName -AdminGroup 'BUILTIN\Administrators' -HttpsPort 12290 -HttpPort 12291 `
            -InstanceDBConnectionString $wfInstanceCS -ResourceDBConnectionString $wfResourceCS -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    }

With both Service Bus and Workflow farms created, it’s time to create a Service Bus host and a Workflow Management Host. WFM adopts a similar architecture to ADFS and SharePoint in that a farm consists of one or many hosts. The more hosts the better availability of service with network load balancing.

Here’s the part script to create a new Service Bus Host…

Write-Host -ForegroundColor white ' - Adding Service Bus host...' -NoNewline;
    try {
        $SBRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Add-SBHost -SBFarmDBConnectionString $managementCS -RunAsPassword $SBRunAsPassword `
            -EnableFirewallRules $true -CertificateAutoGenerationKey $SBCertificateAutoGenerationKey;
        Write-Host -ForegroundColor white 'Done';
    } 
    catch {
        Write-Host -ForegroundColor white 'Already Exists';
    }
    Write-Host -ForegroundColor white ' - Creating Workflow Default Namespace...' -NoNewline;
    $sbNamespace = $dbPrefix + '-WorkflowNamespace';
    try {
        $defaultNS = Get-SBNamespace -Name $sbNamespace -ErrorAction SilentlyContinue;
        Write-Host -ForegroundColor white 'Already Exists';
    }
    catch {
        try {
            # Create new SB Namespace
            $currentUser = $env:userdomain + '\' + $env:username;
            New-SBNamespace -Name $sbNamespace -AddressingScheme 'Path' -ManageUsers $spServiceAcctName,$spAdminAcctName,$currentUser;
            Start-Sleep -s 90
            Write-Host -ForegroundColor white 'Done';
        }
        catch [system.InvalidOperationException] {
            throw;
        }
    }

…and finally, we create the Workflow Manager host…

$SBClientConfiguration = Get-SBClientConfiguration -Namespaces $sbNamespace;
    # Add WF Host
    try {
        $WFRunAsPassword = ConvertTo-SecureString -AsPlainText  -Force  -String $spServiceAcctPwd;
        Write-Host -ForegroundColor White ' - Adding Workflow Host...' -NoNewline;
        Add-WFHost -WFFarmDBConnectionString $wfManagementCS `
        -RunAsPassword $WFRunAsPassword -EnableFirewallRules $true -EnableHttpPort `
        -SBClientConfiguration $SBClientConfiguration -CertificateAutoGenerationKey $WFCertAutoGenerationKey;
        Write-Host -ForegroundColor White 'Done';
    }
    catch {
        Write-Host -ForegroundColor white "Already Exists";
    }

At this point, we’ve completed configuration of Workflow Manager, but we’re not quite finished with configuration yet. We need to tell SharePoint about the existence of the WFM farm, which involves installing WFM client on each SharePoint server (you don’t need to install the client if you have installed the WFM on a SharePoint server). Ideally, your WFM farm is independent of SharePoint (servers and databases), but for test purposes you can install the whole lot on one server.

Let’s make sure WFM is working before we configure SharePoint. Open a browser to the following location…

http://WFM-server-name:12291

You should see some XML returned from the service (you may need to run IE as admin for this to work).

<ScopeInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/workflow/2012/xaml/activities">
  <DefaultWorkflowConfiguration /> 
  <Description>Root Scope</Description> 
  <LastModified>2014-05-12T23:17:49.47</LastModified> 
  <LastRevised>2014-05-12T23:17:49.47</LastRevised> 
  <Path>/</Path> 
 <SecurityConfigurations>
 <ScopedSecurityConfiguration i:type="WindowsSecurityConfiguration">
  <Name>Microsoft.Workflow.Management.Security.WindowsSecurityConfiguration</Name> 
  <WorkflowAdminGroupName>BUILTIN\Administrators</WorkflowAdminGroupName> 
  </ScopedSecurityConfiguration>
  </SecurityConfigurations>
  <Status>Active</Status> 
 </ScopeInfo>

Our last task is to tell SharePoint 2013 about our new Workflow farm, which we accomplish with the following cmdlet (run this on each SharePoint server):

Register-SPWorkflow -spsite 'http://web-application-url' -WorkflowHostUri 'http://WFM-server-FQDN:12291' -AllowOAuthHttp;

All being well, you should have a Workflow Manager Proxy listed under Manage Service Applications in Central Administration. Note: This proxy gets created whether the Register-SPWorkflow cmdlet succeeds or fails, so remember to remove this proxy after an error. Selecting the proxy and clicking the Manage icon in the ribbon should give you a page that indicates SharePoint is connected to the WFM. You’re good to go and create 2013 workflows.

Some things to note…

My configuration uses HTTP between SharePoint and WFM. In a production scenario, I recommend using HTTPS. In which case, you need to export the auto-generated certificate (from https://WFM-server-FQDN:12290) and import it into SharePoint Central Admin under Security -> Manage Trust. When using SSL, run the same Register-SPWorkflow cmdlet, but change the WFM location to https://WFM-server-FQDN:12290 and drop the -AllowOAuthHttp switch.

Some organizations rely heavily on workflow. Not unlike SharePoint, ADFS, and other farm based services, it’s a good idea to configure WFM with multiple hosts when high availability is important.

Filter Document Lib to Last Published Version

My customer brought up an interesting requirement to filter their document library to show just the last approved versions when content approval and major/minor versions applied.

Any unpublished document – that is a document where the major version is 0 will not show up in the filter. Any document that has a major version number greater than 0 and is in draft or pending status – e.g a document at version 1.1 – will only show a link to the last published version.

Turns out the solution was quite easy and involved just adding some query string parameters…

?IncludeVersions=TRUE&FilterField1=_ModerationStatus&FilterValue1=0&FilterField2=_IsCurrentVersion&FilterValue2=1

The IncludeVersions parameter instructs the list view to show all versions. Then it’s a simple case of filtering on the most current version of each item where not in moderation state.

SharePoint Site Pages, What Are They?

SharePoint Foundation introduced Site Pages. Site Pages are pages created, edited, and customized by end users.  Site Pages are different to Application Pages, which have been around since WSS 3, live in the SharePoint filesystem (hive), and are responsible for back-end functionality (such as site settings etc.).

Site Pages are either un-customized (ghosted) or customized (un-ghosted). The state of a Site Page will determine where the page content resides – on the file system, in the content database or both, and this can sometimes be the topic of confusion.

Un-customized Site Pages

An un-customized (or ghosted) Site Page is one that resides on the file system. Typically, these files live in the TEMPLATES\SiteTemplates folder or some location within the TEMPLATES folder within the SharePoint file system. An un-customized page is sometimes referred to as a Page Template.

An un-customized page also maintains a reference in the site collection content database. This reference points to the location of the page in the file system.

An un-customized Site Page may contain inline code because SharePoint assumes a developer, with console access to the SharePoint server, has vetted any inline code or script.

Customized Site Pages

A customized (un-ghosted) Site Page is one that consists of edits made by end users or designers, using SharePoint Designer, SharePoint API, or via download from the SharePoint UI. The edits reside in the content database for the SharePoint site collection.

Whereas an un-customized page maintains a reference to the template on the filesystem in the content database, a customized page retains both page content (the customized page content) as well as the reference to the original template.

Customized Site Pages may NOT include inline code because edits are not controlled by administrators with access to the server console. SharePoint controls this behavior by running all customized page content through a Page Parser, which strips out any inline code.

Sandbox Solution Site Pages

Sandbox solutions do not allow deployment of files to the SharePoint file system, therefore, any Site Page deployed as a module as part of a Sandbox solution deploy ONLY to the site collection content database. Users may customize these pages also, but there is no reference to a location on the file system in the content database.

Page Parsing

SharePoint parses ASPX (both application and site page) content in one of two modes, depending on the page – direct, or safe-mode. The first time a user requests an Application or Un-customized Site Page, SharePoint parses the page content in direct mode. In direct mode, the page content is parsed and compiled and placed into memory cache for faster subsequent requests for the same page.

Customized Site Pages reside in the content database and undergo a stricter parsing method, called safe-mode parsing. In safe-mode, the page content may not contain any inline server code, user and server controls must be registered as safe in the application web.config, and the page is not compiled. Safe-mode pages do not live in memory cache, so their use is a performance consideration.

Note: It is possible to override the behavior of the safe-mode parser by adding <PageParserPath> elements to the <SafeMode> element in the web.config, which enables you to select certain Site Pages that may contain inline server code. However, this is not recommended because it compromises the security of your site collection by allowing end users to include potentially dangerous code in page content.

Yammer Integrated with Office 365

Yammer has become the popular social network for the workplace. Yammer provides a discrete network for organizations looking to engage in social network activity without giving employee participants free reign to network with individuals outside their organization, such as with twitter and Facebook.
Many organizations have moved their SharePoint farms to Office 365 – SharePoint Online. The cloud provides an attractive alternative to self-hosting expensive SharePoint infrastructure on premises. The latest wave of SharePoint Online – wave 15 – includes the Newsfeed and social networking capabilities, consistent with on premises SharePoint 2013.
The baked-in social capabilities of SharePoint 2013/Wave 15 are pretty awesome, and with the proliferation of the SharePoint Newsfeed app for Windows Phone, Android, and iOS, SharePoint social networking is becoming as ubiquitous as Facebook and Twitter in the mobile-sphere. However, Microsoft has not ignored those organizations that went the Yammer route and use SharePoint Online, as Yammer now integrates with SharePoint Online.
If you log into your SharePoint Online administration portal within your Office 365 tenant and click the settings link, you should see the Yammer integration option at the top of the page. Toggling the Enterprise Social Collaboration from Newsfeed (default) to Yammer, takes about 30 minutes to take effect, after which time users of SharePoint Online see the Newsfeed link replaced with a link to Yammer in the top navigation.

Presently, the integration with Yammer is very loose. The Yammer link in the top navigation redirects users to the http://www.yammer.com home page, where users can sign-in. Your Organization’s Yammer feed is not yet integrated into your SharePoint Online My Site, and the default Newsfeed remains in place. However, this is just the first phase of roll-out, and Microsoft promises single-sign-on and Yammer feeds integrated into the SharePoint Online user interface in the coming months.

For those that cannot wait, there is a free app that will render Yammer feeds within the SharePoint Online UI, which administrators can download and install from the SharePoint App Store.

My organization – Planet Technologies – uses Yammer (we’re a social bunch), so I am quite excited for the next phase of Yammer integration, which will bring Yammer and SharePoint Online together seamlessly.

SharePoint Related Fields

I had an interest request from a client I was working with this week. They wanted
me to create a list for their store tracking business, which consisted of a large
number of columns. No big deal! That is until my client indicated that they wanted
to associate notes with each column for each list item entered into the list.


image

The image attached to this post shows the standard SharePoint New and Edit Form
for a list item. Ignore the fact that this is SharePoint 2007, because my solution
works just as well in SharePoint 2010 and 2013. Notice that each field has a notes
link, which when clicked will display a text box for adding additional notes, as
shown.

You may be thinking “just add additional columns of multiple lines of text to the
list”, and I considered this approach, but my client wanted the ability to add a
new column in their list without having to remember to add an additional column
for the notes. Further, they wanted a way to associate the notes with the column
automatically.

My next instinct was to use custom fields and custom field controls, which turned
out to be the core of my solution. Custom fields and field controls can be a pain
at times, and not always behave as predicted, but fortunately my client only used
single line of text, yes/no, lookup, choice, and date-time columns, so I was able
to derive custom versions of these controls to provide the behavior I was looking
to achieve.

The standard SPField type, from which all custom fields derive, contains a property
called “RelatedField”. This related field contains the title of a related field
to current column. The SPField class also includes some event handlers for the added
and deleting events, which I used to automatically create notes fields whenever
a new column is added to the list.

Let’s start with one of my custom SPField classes, which derives from the SPFieldText
to add custom logic to the stock single-line-of-text field type:

 
    public class CustomFieldText : SPFieldText
    {
        #region Fields

        private readonly SPFieldCollection _fields;

        #endregion Fields

        #region Construction

        public CustomFieldText(SPFieldCollection fields, string fieldName)
            : base(fields, fieldName)
        {
            _fields = fields;
        }

        public CustomFieldText(SPFieldCollection fields, string typeName, string displayName)
            : base(fields, typeName, displayName)
        {
            _fields = fields;
        }

        #endregion Construction

        #region Properties

        public override BaseFieldControl FieldRenderingControl
        {
            [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
            get
            {
                BaseFieldControl fieldControl = new CustomFieldTextControl();
                fieldControl.FieldName = InternalName;
                return fieldControl;
            }
        }

        #endregion Properties

        #region Methods

        public override void OnAdded(SPAddFieldOptions op)
        {
            CustomFieldHelper.CreateSlaveField(this);
        }

        public override void OnDeleting()
        {
            CustomFieldHelper.DeleteSlaveField(_fields, this);
        }

        #endregion Methods
    }

Looking at the previous class, there really isn’t much to my implementation. My
class implements the standard constructors for an SPField derived class, overrides
the FieldRenderingControl property because I wish to use my own, and overrides the
OnAdded and OnDeleting events, which enables me to detect when a column of my field
type is created or deleted. The interesting code logic exists in my helper class,
as follows:

 
    static class CustomFieldHelper
    {
        private const string RenderFieldSuffix = "_Shaddow";

        public static void CreateSlaveField(SPField master)
        {
            if (null == master) throw new ArgumentNullException("master");
            // Create a shadow field to store the value we want to display
            // in list views.
            var list = master.ParentList;
            if (null == list) return;
            // We only need a shadow copy when associated with a list.
            var relatedFieldName = master.InternalName + RenderFieldSuffix;
            var relatedDisplayName = String.Format("{0} Notes", master.Title);
            var sb = new StringBuilder();
            sb.Append("<Field Type=\"Note\" ReadOnly=\"TRUE\" ");
            sb.AppendFormat("Name=\"{0}\" ", relatedFieldName);
            sb.AppendFormat("DisplayName=\"{0}\" ", relatedFieldName);
            sb.Append("Sortable=\"TRUE\" Filterable=\"TRUE\" ");
            sb.Append("EnableLookup=\"FALSE\" SourceID=\"http://schemas.microsoft.com/sharepoint/v3\">");
            sb.AppendFormat("<FieldRefs><FieldRef Name=\"{0}\" /></FieldRefs>", master.InternalName);
            sb.Append("<DisplayPattern><HTML><Column HTMLEncode=\"FALSE\"/></HTML></DisplayPattern>");
            sb.Append("</Field>");
            list.Fields.AddFieldAsXml(sb.ToString());
            var field = list.Fields[relatedFieldName];
            field.Title = relatedDisplayName;
            field.RelatedField = master.Title;
            field.Update(true);
        }

        public static void DeleteSlaveField(SPFieldCollection fields, SPField master)
        {
            if (null == fields) throw new ArgumentNullException("fields");
            if (null == master) throw new ArgumentNullException("master");
            var relatedFieldInternalName = master.InternalName + RenderFieldSuffix;
            if (!fields.ContainsField(relatedFieldInternalName)) return;
            var field = fields.GetFieldByInternalName(relatedFieldInternalName);
            field.ReadOnlyField = false;
            field.Hidden = false;
            field.Update();
            fields.Delete(relatedFieldInternalName);
        }

        public static void SaveValueToSlave(SPListItem item, string value, SPField master, bool callUpdate)
        {
            if (null == item) throw new ArgumentNullException("item");
            if (null == master) throw new ArgumentNullException("master");
            if (null == value) return;
            var relatedFieldInternalName = master.InternalName + RenderFieldSuffix;
            var list = item.ParentList;
            var field = !list.Fields.ContainsField(relatedFieldInternalName) ? 
                list.Fields.Cast<SPField>().FirstOrDefault(f => f.RelatedField == master.Title) : 
                list.Fields.GetFieldByInternalName(relatedFieldInternalName);
            if (null == field) return;
            item[field.Id] = value;
            if (callUpdate) item.SystemUpdate();
        }

        public static string GetValueFromSlave(SPListItem item, SPField master)
        {
            if (null == item) throw new ArgumentNullException("item");
            if (null == master) throw new ArgumentNullException("master");
            var relatedFieldInternalName = master.InternalName + RenderFieldSuffix;
            var list = item.ParentList;
            var field = !list.Fields.ContainsField(relatedFieldInternalName) ?
                list.Fields.Cast<SPField>().FirstOrDefault(f => f.RelatedField == master.Title) :
                list.Fields.GetFieldByInternalName(relatedFieldInternalName);
            if (null == field) return "";
            var obj = item[field.Id];
            return null == obj ? "" : obj.ToString();
        }

        public static Control GetNotesMarkUp(out TextBox notesCtrl, SPField field)
        {
            if (null == field) throw new ArgumentNullException("field");
            var ph = new PlaceHolder();
            // Does shaddow field have data?
            var ident = (null != SPContext.Current.ListItem)
                            ? GetValueFromSlave(SPContext.Current.ListItem, field)
                            : null;
            var jsStr = String.Format("document.getElementById('{0}').style.display='block';", field.Id);
            ph.Controls.Add(!String.IsNullOrEmpty(ident)
                                ? new LiteralControl(String.Format(
                                    "<a href='#' onclick=\"{0}\"><b>Notes</b> &bull;</a>", jsStr))
                                : new LiteralControl(String.Format("<a href='#' onclick=\"{0}\">Notes</a>", jsStr)));
            ph.Controls.Add(new LiteralControl(String.Format("<div id='{0}' style='display:none;'>", field.Id)));
            var table = new HtmlTable { Width = "100%" };
            ph.Controls.Add(table);
            ph.Controls.Add(new LiteralControl("</div>"));
            var row = new HtmlTableRow();
            var header = new HtmlTableCell();
            var headerText = new LiteralControl("<span class='ms-formlabel'><H3 class='ms-standardheader'>Enter notes below</H3></span>");
            header.Controls.Add(headerText);
            row.Controls.Add(header);
            table.Controls.Add(row);
            row = new HtmlTableRow();
            var cell = new HtmlTableCell();
            notesCtrl = new TextBox { TextMode = TextBoxMode.MultiLine, Rows = 6, Width = new Unit(100, UnitType.Percentage) };
            cell.Controls.Add(notesCtrl);
            row.Controls.Add(cell);
            table.Controls.Add(row);
            return ph;
        }
    }

In case you’re wondering why I didn’t just include my helper code in my custom field
class it’s because I created several custom field classes for my client and wanted
to reuse the same code. Since I’m inheriting from SharePoint’s classes I cannot
provide my own base class either, so a static helper class seemed like an easy approach.

The CreateSlaveField method is the most interesting of the previously show class.
This method creates a new Note field and adds it to the list that the master field
associates, it then populates the RelatedField property so I can find the association
later.

The notes field is only created if the master field is associated with a list. In
the case when a site owner creates a site column in a web, my method exits without
creating the slave field, because it’s only pertinent in lists. Since list columns
added from the web site columns gallery are new instances of the same field type,
the OnAdded method is called again when the new column adds to a list and this time
my method creates the slave column.

The DeleteSlaveField method removes the notes slave field when the master field
is removed from a list instance – this is just good house keeping.

When creating the slave field I set it as read only, this is so intrigued users
of the site cannot use the notes field for any other purpose than adding notes via
my custom field control, which brings me to my next class:

    public class CustomFieldTextControl : TextField
    {
        #region Fields

        private TextBox _notesCtrl;

        #endregion Fields

        #region Methods

        protected override void OnInit(EventArgs e)
        {
            CanCacheRenderedFieldValue = false;
            base.OnInit(e);
        }

        protected override void CreateChildControls()
        {
            if (IsFieldValueCached)
            {
                base.CreateChildControls();
                return;
            }
            if (null == Field) return;
            base.CreateChildControls();
            // Add the notes if in edit mode.
            if (ControlMode == SPControlMode.Edit || ControlMode == SPControlMode.New)
                base.Controls.Add(CustomFieldHelper.GetNotesMarkUp(out _notesCtrl, Field));
            // Update the controls with the current value stored.
            if (null != _notesCtrl && null != Field)
                _notesCtrl.Text = CustomFieldHelper.GetValueFromSlave(SPContext.Current.ListItem, Field);
        }

        public override void UpdateFieldValueInItem()
        {
            Page.Validate();
            if (!Page.IsValid) return;
            base.UpdateFieldValueInItem();
            // do actions after save
            if (null == Field) return;
            CustomFieldHelper.SaveValueToSlave(SPContext.Current.ListItem, _notesCtrl.Text.Trim(), Field, false);
        }

        #endregion Methods
    }

The previous and last class is my custom field control, which does the work of rendering
data from my custom field class. Again, this is a lightweight class, leaving the
heavy lifting to the field helper class.

The CreateChildControls method is called for any ASP.NET UI class (which custom
field controls ultimately derive) to load an child control instances. In this method,
I check that we’re not using a cached version of the control and that we’re in a
new or edit form, since my client didn’t want notes to appear in display only views.
I then inject HTML for the display of the notes text box, which is populated from
the contents of the associated slave control.

The overridden method UpdateFieldValueInItem ensures that the slave field in the
list item receives any text changes applied to the notes field when saving the list
item in the new/edit form.

That’s about it, except for the fldtypes_custom.xml file, which I deploy to the
%HIVE%\Templates\XML folder to register my custom field type(s):

 
<FieldTypes>
  <FieldType>
    <Field Name="CAMLRendering">TRUE</Field>
    <Field Name="TypeName">CustomFieldText</Field>
    <Field Name="TypeDisplayName">CustomFieldText</Field>
    <Field Name="TypeShortDescription">Custom Single Line of Text (with Notes).</Field>
    <Field Name="ParentType">Text</Field>
    <Field Name="UserCreatable">TRUE</Field>
    <Field Name="AllowBaseTypeRendering">TRUE</Field>
    <Field Name="FieldTypeClass">CustomSharePoint.CustomFieldText, CustomSharePoint, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cd2be6bc9c119b34</Field>
  </FieldType>
</FieldTypes>

Posting Code into WordPress.com

if (posting-code-to-blog == true && blog.engine == WordPress) {
printf("Who knew?");
}

http://en.support.wordpress.com/code/posting-source-code/

SharePoint Authentication and Session Management

What is authentication?

1. A security measure designed to protect a communications system against acceptance of a fraudulent transmission or simulation by establishing the validity of a transmission, message, or originator.
2. A means of identifying individuals and verifying their eligibility to receive specific categories of information.

Authentication is essentially the process of validating a user is who they say they are, such that they can gain access to a system – in this context, the system is SharePoint. Authentication is not authorization, which is the process in determine if a known user is permitted access to certain data in the system, after successful authentication.

SharePoint, much like any content management system, relies on user authentication to provide user access to secured content. Pre-SharePoint 2010, SharePoint relied on NTLM, Kerberos, or basic (forms-based) authentication protocols (their discussion out of scope of this text). SharePoint 2010 introduced Claims-based-Authentication (CBA), also present in SharePoint 2013. CBA consists of authentication abstraction, using a Secure Token Service (STS), and identification of users with multiple attributes –claims – not just the traditional username and password pair.

A Secure Token Service implements open standards. A typical STS implementation communicates over HTTPS, and packages user identity information (claim data) via signed and encrypted XML – Secure Assertion Markup Language (SAML). Examples of STS implementations are the STS engine in SharePoint 2010/2013, ADFS, and third party applications build using the Windows Identity Framework.

SharePoint Session Management

A user session in SharePoint 2010/2013 is the time in which a user is logged into SharePoint without needing to re-authenticate. SharePoint, like most secure systems, implements limited lifespan sessions – i.e. users may authentication with a SharePoint system, but they’re not authenticated with the system indefinitely. The length of user sessions falls under the control of session management, configured for each SharePoint Web Application.

SharePoint handles session management differently, depending on the authentication method in play (Kerberos, NTLM, CBA, Forms, etc.). This article discusses how SharePoint works with Active Directory Federated Services (ADFS) – an STS – to maintain abstracted user authentication and user session lifetime. The following is a sequence diagram of the default authentication and session creation process in SharePoint 2010/2013 when using CBA with ADFS.

The following is a summary of the authentication process, shown in the sequence diagram.

  1. A user requests a page in SharePoint from their browser this might be the home page of the site.
  2. SharePoint captures the request and determines that no valid session exists, by the absence of the FEDAUTH cookie.
  3. SharePoint redirects the user to the internal STS – this is important because the internal STS handles all authentication requests for SharePoint and is the core of the CBA implementation in SharePoint 2010/2013.
  4. Since we have configured SharePoint to use ADFS as a trusted login provider, the internal STS redirects the user to the ADFS login page.
  5. ADFS acquires credentials and authenticates the user.
  6. ADFS creates a SAML token, containing the user’s claims, as encrypted and signed.
  7. ADFS posts the SAML token to the internal SharePoint STS.
  8. The Internal STS saves the SAML token in the SAML Token Cache.
  9. SharePoint creates the FEDAUTH cookie, which contains a reference to the SAML token in the cache.
  10. The Internal STS redirects the user back to SharePoint, and then back to the original requested page.

Session Lifetime

The lifetime of a SharePoint session, when using ADFS, is the topic of much confusion. Ultimately, SharePoint determines whether a user has a current session by the presence of the FEDAUTH cookie. The default behavior of SharePoint is to store this persistent cookie on the user’s disk, with fixed expiration date. Before sending a new FEDAUTH cookie back to the user’s browser, SharePoint calculates the expiration of the cookie with the following formula:

SAML Token Lifetime – Logon Token Cache Expiration Window

The above values are important since they govern the overall lifetime of the FEDAUTH cookie, and hence the session lifetime. The following table describes each value and its source:

Configuration Value Description
SAML Token Lifetime This value, in minutes, is provided by the token issuer – ADFS. In the case of ADFS, each Relying Party configuration (one for each instance of SharePoint farm) has this value as part of the configuration.By default, SharePoint sets the session lifetime the same as this SAML token lifetime.

You can change this value using PowerShell and the ADFS command: Set-ADFSRelyingPartyTrust.

E.g.

Add-PSSnapin Microsoft.ADFS.PowerShell

Set-AdfsRelyingPartyTrust –TargetName “Relying Party Name” –TokenLifeTime 10

Logon Token Cache Expiration Window This value, in minutes, is provided by SharePoint STS and governs how long the SAML token remains active in the cache, and therefore how long the associated user session remains alive.For example, of ADFS sets the SAML Token Lifetime to 10 minutes and this value is set in the STS as 2 minutes then the overall SharePoint session lifespan is 8 minutes.

E.g.

$ap = Get-SPSecurityTokenServiceConfig

$ap.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 2)

$ap.Update();

IIsreset

Sliding Session

A siding session is one where the session expiration time changes as a user interacts with the system. By default, SharePoint 2010/2013 does not offer sliding sessions. Each new session expires on a fixed time, based on the aforementioned formula, earlier in this text.

Use of a sliding session does not mean that we must compromise security. Should a user become inactive, a sliding session will timeout just as the fixed session, the main difference that a user can extend a sliding session with continued use of the SharePoint system.

An important point here is that Patriot should only extend sliding sessions with explicit user interaction – polling and passive processes should not extend sessions indefinitely.

Creation of sliding session requires configuration of the Relying Party in ADFS and the SharePoint Logon Token Cache Expiration. The following PowerShell configures the Relying Party to 60 minutes, which is the absolute maximum time that a session remains active should the user become inactive:

Add-PSSnapin Microsoft.ADFS.PowerShell
Set-AdfsRelyingPartyTrust –TargetName “Relying Party Name” –TokenLifeTime 60

The following PowerShell sets the Logon Token Cache Expiration in SharePoint STS, which forces the sliding session lifetime to 20 minutes.

$ap = Get-SPSecurityTokenServiceConfig
$ap.LogonTokenCacheExpirationWindow = (New-TimeSpan -minutes 40)
$ap.Update();
IIsreset

The above settings are only part of the solution. On their own we have a fixed session duration of 20 minutes, determined by the earlier mentioned formula subtracting the logon token cache expiration from the RP token lifetime. To make sure the session renews with continued activity, we must refresh the session (and FEDAUTH cookie), which we can achieve with an HTTP module. The following code is an excerpt to refresh the session with each HTTP request.

Persistent verses Session Cookies

By default, SharePoint stores the authentication/session (FEDAUTH) cookie as a persistent cookie on disk. This allows the user to close and reopen their browser and access SharePoint without having to re-authenticate. This behavior is not always desirable.

Fortunately, we can ask SharePoint to use in-memory cookies (session cookies) for the authentication (FEDAUTH) cookie, as follows:

$sts = Get-SPSecurityTokenServiceConfig
$sts.UseSessionCookies = $true
$sts.Update()
iisreset

SharePoint 2013 MCSD Beta MCSD Exams

I just signed up for the new SharePoint 2013 MCSD Beta exams 71-488 and 71-489. I managed to snag registration of these exams for free, with some promotions codes floating around the Internet.
Vlad has the codes posted on his blog – if you try them you migth be lucky to register for free, otherwise, the exams cost $150 a peice.

Unfortunately, there’s not a ton of material out there for study as yet (plug my book), as you’d expect with the exams in Beta.
Some of the topics in the beta exams require development skills and knowledge of Visual Studio. Vlad has included a summary of the study topics at the following locations:

Developing Microsoft SharePoint 2013 Core Solutions (71-488).
Developing Microsoft Sharepoint 2013 Advanced Solutions (71-489).

For those of you wondering the difference between 70-488 & 71-488; and 70-489 & 71-489…
Microsoft uses 71-xxx for Beta exams. Release of the official exam is scheduled for June and will use the 70-488 and 70-489 numbers.

If you pass the beta exams now, you won’t have to retake the official release versions after June.

Incase Vlad changes his blog, and for my study reference, the following is a list of the topics measured in each exam. Also check out these handy PDF (fillable) checklists I created…

70-488 Checklist
70-489 Checklist

71-488/70-488 – Skills Measured
 
Plan and Design SharePoint Sites (10-15 percent)
  • Manage the site life cycle.
    • This objective may include but is not limited to: create a delayed site collection, manage site collection disposition, identify inactive site collections, back up and archive site collection data
  • Create content types.
    • This objective may include but is not limited to: subscribe to published content types, choose appropriate content type creation, use Schema Development, create content types using Object Model, create site columns, use content type inheritance
  • Manage content type behaviors.
    • This objective may include but is not limited to: manage event receivers, manage workflow associations, manage policies, manage document templates
  • Implement site provisioning.
    • This objective may include but is not limited to: create site definitions, create web templates, implement feature stapling, implement custom provisioning code
Implement Authorization and Authentication (10-15 percent)
  • Implement user authentication.
    • This objective may include but is not limited to: create a custom claims provider, create a custom sign-in page, create a custom membership provider, package and deploy a custom claims provider, package and deploy a custom membership provider, authenticate a user from a client application
  • Implement application authentication and authorization.
    • This objective may include but is not limited to: use the SharePoint App TokenHelper class, specify the App permission request scope manifest and permission request manifest, specify permissions for Office Store Apps, specify permissions for Corporate Catalog Apps, specify permissions for remote apps to access SharePoint data
  • Plan and implement user authorization.
    • This objective may include but is not limited to: create custom role definitions, create custom permission levels, maintain permissions, implement impersonation, plan and implement anonymous access, create a custom role manager
Access and Manage Data (10-15 percent)
  • Design solutions to handle large amounts of data.
    • This objective may include but is not limited to: create efficient CAML queries and views, choose appropriate APIs, create and use indexed columns, use Object Model Overrides, use Content Iterator, implement cross-site queries
  • Access data contained in SharePoint.
    • This objective may include but is not limited to: access data using server-side object model, access data using client-side object model (CSOM), access data using REST API, access data using out-of-the-box Web Services, access data using a custom WCF (Windows Communication Foundation) service to facilitate integration with an existing application
  • Store configuration data.
    • This objective may include but is not limited to: implement a hierarchical data store, implement a property bag, implement web.config, implement SharePoint List, implement credential storage
Implement SharePoint Solutions (15-20 percent)
  • Manage SharePoint Object Life Cycle.
    • This objective may include but is not limited to: implement Object Life Cycle management for SPWeb, implement Object Life Cycle management for SPSite, implement Object Life Cycle management for other objects, implement Object Life Cycle management with Windows PowerShell, implement Object Life Cycle management for SPContext
  • Upgrade solutions and features.
    • This objective may include but is not limited to: implement versioning of features and solutions, upgrade features and solutions, implement assembly versioning, build components for in-process request routing
  • Determine a solution structure.
    • This objective may include but is not limited to: select feature scope and visibility, define feature dependencies, define solution dependencies, organize SharePoint project items, structure app packages
  • Create sandbox solutions.
    • This objective may include but is not limited to: scope features to constraints, identify SharePoint artifacts that can be used in sandbox, access data outside of Sandbox scope, configure and troubleshoot sandbox solution deployment, upgrade sandbox solutions, implement solutions validators
  • Create a no-code solution.
    • This objective may include but is not limited to: configure no-code customizations for the SharePoint 2013 platform, create XSLT for web parts, create and upload JavaScript files, create Display Templates
Implement the User Experience and Information Architecture (10-15 percent)
  • Implement branding.
    • This objective may include but is not limited to: incorporate designer outputs, use Design Manager functionality, apply custom themes, export the design, create Master Page, create a channel
  • Implement navigation.
    • This objective may include but is not limited to: create a custom navigation provider, create taxonomy-based navigation, create search-driven navigation, configure global\current navigation
  • Customize UI elements.
    • This objective may include but is not limited to: customize the ribbon, customize the edit control block (ECB), customize the status bar and notifications, customize the modal dialog window, customize the upgrade notification, select areas for Focus on Content
Create Business Processes (10-15 percent)
  • Create event receivers and timer jobs.
    • This objective may include but is not limited to: plan the use of event receivers or timer jobs, create remote event receivers, create a work item timer job
  • Create SharePoint Designer workflows.
    • This objective may include but is not limited to: plan the type of workflow and associated forms (site, reusable, list, InfoPath), use custom actions, create workflow definition, create reusable workflows for content types, import and export Microsoft Visio workflows, export a workflow to a SharePoint solution
  • Create and deploy Microsoft Visual Studio workflows.
    • This objective may include but is not limited to: create custom actions, create a workflow definition, create external connectors, deploy a workflow as part of a SharePoint solution or app, upgrade a SharePoint 2013 Visual Studio workflow, plan the type of workflow and associated forms
Create Office Apps (10-15 percent)
  • Plan and design applications.
    • This objective may include but is not limited to: choose a hosting location, specify a starting location, specify a licensing model, specify permission requirements, select a user experience for apps
  • Create applications.
    • This objective may include but is not limited to: create provider-hosted applications, create auto-hosted applications, create SharePoint-hosted applications, apply chrome control
  • Package and deploy Apps.
    • This objective may include but is not limited to: package an application, publish to Corporate Catalog, publish to SharePoint store, publish to Windows Azure, manage trust relationship with other providers
  • Manage the App life cycle.
    • This objective may include but is not limited to: upgrade an application, remove an application, manage licensing, manage usage tracking
71-489/70-489 – Skills Measured
 
Design and Implement Search (15-20 percent)
  • Query Search.
    • This objective may include but is not limited to: build search queries using FQL (FAST Query Language) and KQL (Keyword Query Language), execute search queries using client-side object model (CSOM), Web Services, and REST
  • Customize search results.
    • This objective may include but is not limited to: create custom result sources, create display templates, create result types, create custom refiner definitions, implement query rules
  • Customize content processing.
    • This objective may include but is not limited to: feed external content types, implement content processing extensions (entity extraction), configure out-of-the box content processing, create content mappings
Implement  BCS (Business Connectivity Services) (10-15 percent)
  • Create a model.
    • This objective may include but is not limited to: optimize queries for performance and throttling, use naming conventions, use batching, create filters, implement methods, create associations
  • Create external content types.
    • This objective may include but is not limited to: use SQL data sources, use WCF (Windows Communication Foundation) Web Services, use oData, use.NET connector
  • Implement authorization and authentication.
    • This objective may include but is not limited to: use pass-through, use BCS Identity and User Identity, use a custom model
  • Create custom connectors.
    • This objective may include but is not limited to: implement methods (including Search), implement security trimming, implement configuration properties, implement caching, implement external event receiver
  • Access BCS data.
    • This objective may include but is not limited to: use BCS Web Parts, use BCS data in workflows, use BCS CSOM, use the server-side object model, use BCS REST
  • Implement client-side BCS.
    • This objective may include but is not limited to: use caching, use Microsoft Office apps, use Microsoft Visual Studio Tools for Office, use SQL replication, implement authorization and authentication
Implement User Profiles and Customize Social Workload (15-20 percent)
  • Manage user profile properties.
    • This objective may include but is not limited to: create and update user profile properties, update privacy filters, map properties to external data, use managed metadata term sets, update profile picture
  • Manage feeds.
    • This objective may include but is not limited to: use CSOM to follow documents, people, sites, get feeds, create posts, and manage Like, reply, mention, tag, link, add pictures
  • Access user profile data.
    • This objective may include but is not limited to: use CSOM, use the object model, use REST, use Web Services
Implement ECM (Enterprise Content Management) and WCM (Web Content Management) (15-20 percent)
  • Implement a multi-lingual site.
    • This objective may include but is not limited to: submit a page or batch of pages for translation, publish pages, create source and target labels, create channels, implement multi-language site navigation
  • Implement E-discovery.
    • This objective may include but is not limited to: create a new hold, integrate with Microsoft Exchange Web Services, specify content sources and Search criteria, export discovery sets, manage permissions for hold
  • Implement SEO (Search Engine Optimization).
    • This objective may include but is not limited to: create a site map, customize a site map, maintain SEO configuration properties, maintain robots.txt file, maintain SEO properties on term
  • Implement content management.
    • This objective may include but is not limited to: create information management policies, create content organizer rules, create document sets, create document ID providers
  • Implement a publishing page.
    • This objective may include but is not limited to: add field controls to a page layout, add web parts to a page layout, create a publishing page layout, inherit content types
Design for Performance and Troubleshooting (15-20 percent)
  • Design solutions to handle a high-traffic site.
    • This objective may include but is not limited to: combine images, implement caching, minimize number of queries, optimize JavaScript loading, use CDNs (Content Delivery Networks), create a scalable aggregator
  • Design client applications for performance.
    • This objective may include but is not limited to: leverage health score rules, optimize number of batch server requests, use client-side cache, minimize amount of data requested
  • Monitor and mitigate performance and scalability issues.
    • This objective may include but is not limited to: diagnose application stability issues, debug the server side and app code on the client side, create application diagnostics, measure and test application performance
Implement Managed Metadata Service (MMS) (15-20 percent)
  • Manage term sets.
    • This objective may include but is not limited to: import and export term sets, create multi-lingual labels, re-use terms, manage term properties, perform translation, create groups and assign permissions
  • Create solutions by using MMS.
    • This objective may include but is not limited to: use Profile Pages, use the Product Catalog, use cross-site publishing, integrate with Search, implement metadata-driven navigation
  • Use an MMS API.
    • This objective may include but is not limited to: use CSOM in client applications, use REST in client applications, use managed fields, use server-side object model

Creating External Content Types in SPD Preview 2013

I am using SharePoint Designer 2013 Preview. I recently tried to create a new External Content Type and ran into an issue when adding a data source. SharePoint Designer hangs “Loading Data Sources”. Fortunately, there’s a work-around…

Copy the following commands to a batch file and run it as an elevated administrator on the SPD machine:

reg add HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,71e9bce111e9429c /f
reg add HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,71e9bce111e9429c /f
reg add HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,* /f
reg add HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,* /f

Recycle the Windows Installer service (or start it if stopped).

You should be good to go.

Thanks to a user called Dalibor, for this info Winking smile

Configuring SharePoint 2013 for Windows Azure Workflow

SharePoint 2013 now abstracts workflow processing to the cloud – using Windows Azure Workflow (WAW). SharePoint still maintains the legacy workflow engine, as part of the .NET Framework 3.5.1, to enable execution of SharePoint 2010 workflows. However, SharePoint 2013 does not install WAW by default. The following steps detail additional configuration.

1. Ensure you are not installing on a domain controller – WAW integration does not work with SharePoint 2013 running on a single server domain controller

2. Create an account in your domain for WAW

3. Add this account to the local administrators group on the SharePoint server and grant log on locally permissions

4. Ensure the SQL server accepts connections via TCP/IP – use the SQL Server Configuration Manager tool

5. Provide the WAW account access to SQL Server, include create database permissions (or you could grant administrative permissions if you are brave)

6. Log onto the SharePoint server as that account

7. Install Workflow Beta 1.0 (http://technet.microsoft.com/en-us/library/jj193478), using the Web Platform Installer

8. After installation, you should see the WAW Configuration Wizard

9. Click to create a new farm, using custom settings

10. Configure databases and click the Test Connection button for each

11. Make sure the WAW service account is correct – use the fully qualified domain name (FQDN), by default it prepopulates the textbox with a non-FQDN

12. Provide certificate generation keys

13. Leave the ports as default

14. Check the checkbox to allow management over HTTP (if you choose to use HTTPS you will need to establish trust between SharePoint and WAW using a trusted certificate)

15. Click the next button to move onto configuring the service bus

16. Complete similar steps for database, service account, and certificates settings as you did above

17. Again, leave the ports as default

18. Review the summary page, then click the tick button to complete the configuration

19. Wait for the configuration to complete – this might take a little time

20. After WAW configuration completes, run the following PowerShell command:

Register-SPWorkflowService –SPSite "http://{sitecollectionurl}" –WorkflowHostUri "http://{workflowserve}:12291" –AllowOAuthHttp

21. Assuming no errors, you have now configured WAW in SharePoint 2013 for your site collection

More information on installing and configuring WAW is available at the following URL: http://technet.microsoft.com/en-us/library/jj658588%28v=office.15%29

Follow

Get every new post delivered to your Inbox.

Join 294 other followers

%d bloggers like this: