Below are simple extension methods for copying managed metadata field values from one field to another, using CSOM, assuming both fields are referencing the same term set.
This post will demonstrate how we can create an approval delegation process using Nintex Workflow for Office 365.
The idea behind it is to check if someone who will be assigned an approval task will not be available (on holidays, maternity leave, just doesn’t care at the moment…), and to assign the task to their delegate instead. It’ll then keep checking the delegate’s availability or if it needs to be re-delegated until it finds someone who can action the approval task.
This diagram outlines the workflow process we’ll be going through in detail below.
We had a requirement from a client who was planning to build a new Sitefinity portal that allows external users to log in and view documents, based on document types and other metadata. All the documents and metadata exists on their SharePoint 2013 intranet, so they were looking to synchronise the documents from SharePoint into Sitefinity and surface the documents in listings and search results based on metadata.
Sitefinity does provide an OOTB SharePoint Connector, which allows you to target a specific SharePoint list and download the documents and selected fields into Sitefinity. However, there were a few limitations and design choices that made it unsuitable for our purposes:
- Documents are downloaded into a Sitefinity document library, but field values are added as a new list item in a custom module. This separates out the document and its metadata, making it difficult to create searches that can index document content and filter based on document metadata at the same time.
- The connector does not support certain SharePoint field types, such as Managed Metadata fields. This in particular was critical for us as our document types were managed in SharePoint as a Managed Metadata field.
- Basic filtering options, which only supports text field comparison of equals or not equals.
- Documents deleted in SharePoint still exist in Sitefinity’s document library, and is only removed from the custom module list.
To overcome those limitations, we decided to prototype our own custom SharePoint connector to get documents and its metadata out of SharePoint and into Sitefinity’s document library. What we built was only a one way connector (from SharePoint to Sitefinity) but it was able to overcome the obstacles above.
In SharePoint 2013, when you want to grant permissions, this dialog opens, with the secret “Send an email invitation” checkbox hidden in the Options section.
Most of the time, I would uncheck that before sharing, to avoid email spams.
One of our clients wanted it unchecked by default, so that users don’t have to always remember to manually uncheck it to prevent spams, if they even knew it existed there in the first place.
You could easily default it to uncheck by updating the OOTB layouts page in the 15 hive at TEMPLATE\LAYOUTS\AclInv.aspx, and updating the chkSendEmailv15 asp:CheckBox control and setting Checked=”false”.
But we don’t want to do that! Updating OOTB components is not recommended and we like to stick to Microsoft best practices.
The code below will terminate all running workflow instances for a give SPListItem.
Getting Checked out Files
<Where> <IsNotNull> <FieldRef Name='CheckoutUser' /> </IsNotNull> </Where>
<Where> <Eq> <FieldRef Name='_Level' /> <Value Type='Integer'>255</Value> </Eq> </Where>
Getting Published Files
<Where> <Eq> <FieldRef Name='_Level' /> <Value Type='Integer'>1</Value> </Eq> </Where>
Getting Checked-in Files
<Where> <Eq> <FieldRef Name='_Level' /> <Value Type='Integer'>2</Value> </Eq> </Where>
Getting Files Only (i.e. excluding Folders)
<Where> <Eq> <FieldRef Name='FSObjType' /> <Value Type='Integer'>0</Value> </Eq> </Where>
Getting Folders Only (including Document Sets)
<Where> <Eq> <FieldRef Name='FSObjType' /> <Value Type='Integer'>1</Value> </Eq> </Where>
<Where> <Eq> <FieldRef Name='WorkflowLink' /> <Value Type='URL'>/subsite/listname/item-url.docx</Value> </Eq> </Where>
Note that you must use a server relative URL when querying against a URL field.
Querying Content Type ID
<Where> <Eq> <FieldRef Name='ContentTypeId' /> <Value Type='ContentTypeId'>0x0120D52000058D5968BC2445489FC509B9E038862900A88F92769A306640872EDF8D34E64427</Value> </Eq> </Where>
Querying Current User
<Where> <Eq> <FieldRef Name="UserField"></FieldRef> <Value Type="User"><UserID /></Value> </Eq> </Where>
<Where> <Eq> <FieldRef Name="UserField"></FieldRef> <Value Type="Integer"><UserID /></Value> </Eq> </Where>
Querying User Based on ID
<Where> <Eq> <FieldRef Name="UserField" LookupId="TRUE"></FieldRef> <Value Type="User">11</Value> </Eq> </Where>
<Where> <Eq> <FieldRef Name="UserField" LookupId="TRUE"></FieldRef> <Value Type="Integer">11</Value> </Eq> </Where>
In general, I try to avoid using .ToString() as much as possible. Instead I prefer to just rely on the automatic string conversion that is done in string concatenations, or in the string.Format() methods.
Consider the simple code example below.