Back to Cleverworkarounds mainpage
 

Trials or tribulation? Inside SharePoint 2013 workflows–Part 4

Hi and welcome to part 4 of my series of articles that take a peek under the hood of SharePoint 2013 workflows from . In part 1, I introduced you to Megacorp Inc and their need for a controlled documents approval workflow. In part 2, we created a basic SharePoint 2013 workflow and in part 3, we made our first attempt to publish the workflow. Unfortunately, we encountered an error and had to work our way around some particularly unhelpful error messages. Now we are at part 4, and we will have another go at publishing our workflow from part 2.

Now like the last post, I’ll tell you up front that our second attempt to run this workflow is not going to work. Remember that my intent here is to show you a “warts and all” view of this functionality – both the great bits and the not so great bits. I hope that this gives you development and troubleshooting ideas in your own workflow adventures.

If you have been following along so far, you should have a simple workflow like the one below. It is attempting to assign a task to a nominated process owner for controlled documents. We just fixed a configuration issue in part 3 that prevented the workflow from working. We did this by disabling the default behaviour of the workflow where it updates the workflow status with the current stage name.

image

So let’s run the workflow on the same document as part 3 – the Burger Additives Standards for Megacorp GM Foods. Do we have liftoff yet? Nope – the workflow was cancelled as shown below, with another cryptic message.

RequestorId: 8ad4a017-7e6f-0d0f-35d2-81c56a05b37c. Details: System.InvalidCastException: The value ‘d/results(0)/Organisation’ cannot be read as type ‘String’. at Microsoft.Activities.GetDynamicValueProperty`1.CheckedRead(String propertyName, DynamicItem value) at Microsoft.Activities.GetDynamicValueProperty`1.Execute(CodeActivityContext context) at System.Activities.CodeActivity`1.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

image

So what do we make of this message and in particular, “The value ‘d/results(0)/Organisation’ cannot be read as type ‘String’”?. Firstly, you might be wondering what this  “d/Results(0)/Organisation” stuff is  all about. Secondly, even if you do know what that is about, why the hell can’t it be read as type string?

A REST and JSON interlude

For the non developers (and self-described citizen developers) reading this series, I am going to attempt to explain what’s going on here because it is important foundational knowledge. If you are a developer who understands REST/OData and JSON,  feel free to skip this bit because you probably won’t like how I explain it.

First up, remember my dodgy diagram in part 3 that explained how Workflow Manager talks to SharePoint? I made the point that workflow manager uses REST web services to do all of its interactions with SharePoint content. REST is actually a really cool technology, and if you are serious about learning to use SharePoint Designer 2013 workflows you should learn more it.

Snapshot

Let’s put aside our workflow for a second, and instead access a REST webservice ourselves, just like workflow manager does behind the scenes. To do this is easy. Open up internet explorer and turn “feed reading view” off. Then try this URL, adjusting it to your site name:

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbytitle(‘Documents’)/Items

If you have done it right, you will get a heap of ugly XML data back in your browser. If this worked then congratulations – you are now a REST guru. You have successfully asked SharePoint to send you information about all documents in the Documents library, including the data stored in the columns. Each <entry> tag in the XML represents a document – and you can collapse these entries as shown below..

<?xml version="1.0" encoding="utf-8" ?> 
- <feed xml:base="http://megacorp/iso9001/_api/" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
  <id>76c69d23-d5f3-4cee-a954-9910ad81bd16</id> 
  <title /> 
  <updated>2013-11-27T23:49:25Z</updated> 
+ <entry m:etag=""6"">
+ <entry m:etag=""7"">
+ <entry m:etag=""7"">
+ <entry m:etag=""8"">

If you expand one of those entries, you will see the full detail of that document. Scroll down into the detail and look for the <Content Type> entry in the XML as shown below. This is the same data that your workflow is working with.

- <content type="application/xml">
-   <m:properties>
      <d:FileSystemObjectType m:type="Edm.Int32">0</d:FileSystemObjectType> 
      <d:Id m:type="Edm.Int32">10</d:Id> 
      <d:ContentTypeId>0x010100683F42634030C946A9F8165B365FD886</d:ContentTypeId> 
      <d:Title m:null="true" /> 
      <d:OData__dlc_DocId>DPRYTK5567JW-5-10</d:OData__dlc_DocId> 
-     <d:OData__dlc_DocIdUrl m:type="SP.FieldUrlValue">
        <d:Description>DPRYTK5567JW-5-10</d:Description> 
        <d:Url>http://megacorp/iso9001/_layouts/15/DocIdRedir.aspx?ID=DPRYTK5567JW-5-10</d:Url> 
      </d:OData__dlc_DocIdUrl>
      <d:URL m:null="true" /> 
      <d:DocumentSetDescription m:null="true" /> 
-     <d:Organisation m:type="SP.Taxonomy.TaxonomyFieldValue">
         <d:Label>9</d:Label> 
         <d:TermGuid>f2109460-a473-493f-9d08-fb01ecbf793b</d:TermGuid> 
         <d:WssId m:type="Edm.Int32">9</d:WssId> 
      </d:Organisation>
      <d:Modified m:type="Edm.DateTime">2013-11-10T00:21:45Z</d:Modified> 
      <d:Process_x0020_Owner_x0020_Approval m:null="true" /> 
      <d:ID m:type="Edm.Int32">10</d:ID> 
      <d:Created m:type="Edm.DateTime">2013-11-08T14:33:12Z</d:Created> 
      <d:AuthorId m:type="Edm.Int32">1</d:AuthorId> 
      <d:EditorId m:type="Edm.Int32">1</d:EditorId> 
      <d:OData__CopySource m:null="true" /> 
      <d:CheckoutUserId m:null="true" /> 
      <d:OData__UIVersionString>2.0</d:OData__UIVersionString> 
      <d:GUID m:type="Edm.Guid">c75a0728-7a5f-4236-8d45-7b72fa41781e</d:GUID> 
    </m:properties>
  </content>

Now when you add a workflow action, and Workflow Manager then talks to SharePoint to perform the action, it is doing a very similar thing to the URL we just accessed. The only difference is that when workflow manger does it, it asks for the data to be returned in a different format than XML called JSON – a more lightweight but less human readable data format. Below is a tiny snippet of that the JSON version of the above data looks like – ugh! no wonder XML is the default return format eh?

{“d”:{“results”:[{“__metadata”:{“id”:”71deada5-6100-48a5-b2e3-42b97b9052a2″,”uri”:”http://megacorp/iso9001/_api/Web/Lists(guid’a64bb9ec-8b00-407c-a7d9-7e8e6ef3e647′)/Items(1)”,”etag”:”\”6\””,”type”:”SP.Data.DocumentsItem”},”FirstUniqueAncestorSecurableObject”:{“__deferred”:{“uri”:”http://megacorp/iso9001/_api/Web/Lists(guid’a64bb9ec-8b00-407c-a7d9-7e8e6ef3e647′)/Items(1)/FirstUniqueAncestorSecurableObject”}},”RoleAssignments”

Fortunately, there are plenty of tools out there that parse JSON data and Fiddler is one of them. We will be using Fiddler later in this series, so I will save a detailed introduction to the tool for later. But below is a screenshot of the above JSON data displayed in Fiddler. Now that’s a bit more palatable!

image

Now that we can read the JSON data in a meaningful way, let’s go back to the error message in the workflow. It stated that “The value ‘d/results(0)/Organisation’ cannot be read as type ‘String’”. Now look in the JSON screenshot above. If you look at the hierarchy and look at the message, we can see now what the message meant. It has a problem with the Organisation entry. Follow the path below the JSON label at the top… We have d –> Results –> {} –> Organisation. This essentially matches the ‘d/results(0)/Organisation’ in the message.

So takeaway number 1 – workflow uses JSON format when it makes REST calls to SharePoint, so learn to recognise a JSON reference when you see it. As a future workflow developer – and later in this series – you will have to learn how to parse JSON data in more fine detail.

Now let’s take a closer look at Organsiation entry in the JSON data above. What you might notice is that some of the other data entries have data values specified, such as EditorID = 1, AuthorID =  1 and Modified = 2013-11-10. But not so with Organisation. Rather than have a data value, it has sub entries. Expanding the Organisation section and you can see that we have more data elements within it. Note that we do not see the organisation name at all. We have numbers and a GUID – so what gives?

image

So what was the error again? ‘Organisation’ could not be read as type ‘String’. Kind of makes sense now doesn’t it? The managed metadata column called Organisation doesn’t store the organisation name, but a pointer to the organisation name, as it is specified in the managed metadata term store. The workflow assumes that the data returned from the REST call is going to be string, and cannot handle the format of the data above.

Troubleshooting Attempt #1 – Use Organisation_0

So at this point, you might be thinking “What the hell?” how can I get the name of the Organsiation if it not actually in the data returned by the REST web service call?

Well, if you were paying attention back in part 2, I noted the existence of another column called Organisation_0. This column was listed as one of the columns available from the current item (“Current item” being the document that the workflow was triggered from). It is now time to understand what this column does. To do so, let’s use another workflow action. This time, we will use the Log to History List action. When you add this action, click the fx button and choose Current Item from the Data source dropdown. Then choose Organisation_0 from the Field from source dropdown as shown below.

image  image

Now if you rerun your workflow and then check the workflow status, you will see what has been logged to the workflow history. Note the description column. Aha! We see our organisation name buried in there.

image

Now if you look closely, you will notice that we also have the GUID of the managed metadata term. The term and its GUID are separated by a pipe character. Even better, it is in string format (note Return field as dropdown above).

It turns out that when you create a managed metadata column, behind the scenes two columns get created. The second column is a hidden column that is a multi-line of text format. This is the the one with an _0 appended to the end. In other words, the Organisation column only stores the pointers (lookup values) to the term, but this hidden column actually stores the names and Id’s of each term the user has added. So let’s use this column instead because it’s a string format. To do this, return to the task assignment action in our workflow. We still need to get the Assigned To field from the Process Owners list, so we leave that alone. But below that, in the Find the List Item section, we need to make a change.

Unfortunately (and perhaps ominously), the Organisation_0 field seems to only be selectable for the Current Item, because clicking the Field dropdown (which displays all columns for process owners), only lists the Organisation column. Why is this? Well, it appears that hidden columns are displayed on Current item, but not displayed when you specify a different list. Thus, we are forced to leave Organisation from Process Owners as is. So click the fx button next to the Value textbox and choose Current Item from the Data source dropdown and Organisation_0 from the Return field as dropdown as shown below.

image  image

Now republish the workflow and let’s give it a go. Checking the workflow status screen and we find the workflow is started. Are we onto a winner here?

Gong! there still another of those exciting error messages. This time we have a complaint of a HTTP BadRequest. Given my explanation of how managed Metadata columns work behind the scenes, can you guess what the issue is?

Retrying last request. Next attempt scheduled in less than one minute. Details of last request: HTTP BadRequest to http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items?%24filter=Organisation+eq+’Metacorp+Burgers%7Ce2f8e2e0-9521-4c7c-95a2-f195ccad160f’&%24select=ID%2CGUID Correlation Id: f16749d5-1bfe-4a8d-9e06-a5b196907e9c Instance Id: 60c538e8-f7a9-4945-919b-ca973c00eb31

image

Now this error message might look evil, but it is actually the most useful one so far as it shows us the REST call made by the workflow manager as part of the task assignment action. If I remove the encoded spaces to make things more readable, the workflow attempted this call.

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items?”filter=Organisation+eq+’Metacorp+Burgers|e2f8e2e0-9521-4c7c-95a2-f195ccad160f’&”select=ID,GUID

This webservice essentially says to SharePoint “Using the Process Owners list (which is GUID 0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a), please bring me back the ID and GUID of any list entries where the Organisation column is equal to the value “Metacorp+Burgers|e2f8e2e0-9521-4c7c-95a2-f195ccad160f”.

Now even if it cannot find a matching item, this should return a HTTP 200 with 0 items matched. But the error that has been returned (400) suggests that there is a problem with the above request itself. Hmmm – eventually the workflow will give up and cancel the workflow. It then logs a more verbose message…

RequestorId: 8ad4a017-7e6f-0d0f-35d2-81c56a05b37c. Details: System.ApplicationException: HTTP 400 {“error”:{“code”:”-1, Microsoft.SharePoint.SPException”,”message”:{“lang”:”en-US”,”value”:”The field ‘Organisation’ of type ‘TaxonomyFieldType’ cannot be used in the query filter expression.”}}} {“Transfer-Encoding”:[“chunked”],”X-SharePointHealthScore”:[“0″],”SPClientServiceRequestDuration”:[“221″],”SPRequestGuid”:[“a202df2e-69df-4a31-b63f-dac25f84676d”],”request-id”:[“a202df2e-69df-4a31-b63f-dac25f84676d”],”X-FRAME-OPTIONS”:[“SAMEORIGIN”],”MicrosoftSharePointTeamServices”:[“15.0.0.4420″],”X-Content-Type-Options”:[“nosniff”],”X-MS-InvokeApp”:[“1; RequireReadOnly”],”Cache-Control”:[“max-age=0, private”],”Date”:[“Thu, 28 Nov 2013 03:31:09 GMT”],”Server”:[“Microsoft-IIS\/8.0″],”X-AspNet-Version”:[“4.0.30319″],”X-Powered-By”:[“ASP.NET”]} at Microsoft.Activities.Hosting.Runtime.Subroutine.SubroutineChild.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

image

Despite the ugliness of the above message, this time we get the root cause logged. Note the section that states:  “The field ‘Organisation’ of type ‘TaxonomyFieldType’ cannot be used in the query filter expression”. So what does this mean?

Another REST interlude…

If you re-examine the REST web service call that was logged by the workflow, you will see some stuff we have not covered so far. The first half of the URL was pretty much what I showed you in the first REST interlude. We are getting all of the items from a SharePoint list, except this time we are using the GUID of the list rather than its name as shown below.

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items

But what is this extra stuff tacked on the rest of the URL – $filter and $select as seen below?

$filter=Organisation+eq+’Metacorp+Burgers|e2f8e2e0-9521-4c7c-95a2-f195ccad160f’&$select=ID,GUID

The answer is that Microsoft’s use of REST (called oData) allows you to do SQL like queries to filter the data that comes back. This is really handy indeed and to help you understand it, here is an example: The URL below says “Give me all documents with an a title of ‘Burger Additives Standards’”

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items?$filter=Title eq ‘Burger Additives Standards’

This example says “Give me just the Titles of all documents created after November 1 2013”

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items?$filter=Created gt datetime’2013-11-01T00:00:00’&$select=Title

Now that you have seen those examples, take another look at what the workflow was trying to do without any luck…

http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’0ffc4b79-1dd0-4c36-83bc-c31e88cb1c3a’)/Items?”filter=Organisation+eq+’Metacorp+Burgers|e2f8e2e0-9521-4c7c-95a2-f195ccad160f’&”select=ID,GUID

Why did the REST call made by the workflow return a HTTP 400 error given my two working examples that look very similar? The answer is that the $filter option does not work with Managed Metadata columns. As I described in this article previously, managed metadata columns are not compatible with the $filter operator – hence the error message “The field ‘Organisation’ of type ‘TaxonomyFieldType’ cannot be used in the query filter expression.”

Damn!

Conclusion…

So it seems that for every step forward, we have taken a step back again. Fear not though, as the next post will start to show a way forward. But be warned – we are about to get deeper into the bowels of REST/oData, so make sure that you fully understand this article before moving on. To that end, if anything is unclear, please let me know and I will adjust these articles accordingly.

Thanks for reading

Paul Culmsee

HGBP_Cover-236x300.jpg

www.hereticsguidebooks.com

 



Trials or tribulation? Inside SharePoint 2013 workflows–Part 3

Hi and welcome to part 3 of my series of articles that take a peek under the hood of SharePoint 2013 workflows, while trying to answer the question of whether SharePoint 2013 workflows can enable citizen developers to go forth and solve business problems and catapault organisations to success. In part 1, I introduced you to Megacorp Inc and their need for a controlled documents approval workflow. In part 2, we created a basic SharePoint 2013 workflow that implements the logic outlined in the picture below. The workflow is not yet finished, but we did enough to be able to run it and learn from it, which brings us to this post.

Now I will tell straight up that our first test of this workflow is not going to work. The entire point of this series of articles is to show you *why* things do not always work what you need to do about it. As we progress, I hope that you will learn quite a bit about the operation of workflows in SharePoint 2013, as well as developing and troubleshooting them. After all, we all know that the best citizens are informed citizens!

Snapshot_thumb3

So let’s get on with testing this particular workflow. We published it to the Documents library in part 2, so now we trigger it by selecting one of the files in the library. In this example, I will select one of the documents tagged as from Megacorp GM Foods. So using the filtering feature provided by metadata navigation, we just show the four documents owned by the Megacorp GM Foods division.

image4_thumb[1]

In this example, we will update the document called Burger Additives Standard. The workflow has not yet been set to automatically start, so we will need to manually trigger the workflow ourselves. To do so, click the ellipses next to the Burger Additives Standard document, and then click the ellipsis in the bottom right of the properties/preview window. This will show a second drop down menu. Choose Workflows from this menu as shown below.

image9_thumb

Underneath the Start a New Workflow text, you will see the workflow we published in part 2 called Process Owner Approval. Clicking it will start the workflow on this document.

image12_thumb

First sign of trouble…

After starting the workflow, the browser will redirect you back to the Documents library.  At this point, we see our first sign of trouble. When a workflow is published on a list or library, a column is added that is used to track workflow progress. In this case, we started our workflow, but there is nothing displayed in the workflow status column and the workflow does not appear to run. Hmm… what gives?

image15_thumb

When a workflow does not behave as you intended, the easiest way to troubleshoot is to use the workflow status page. As it happens, you have already seen this page, because it is the same page where we started the workflow. So once again, we click on the ellipsis next to the burger additives standard document, click the ellipsis in the properties window and choose Workflows from the drop down menu.

Well look at that… it says the workflow is indeed started…

image18_thumb

Clicking on the running workflow, we can see more detail which I have shown below. This screen also says that the workflow is started and nothing appears amiss. But then there is the little blue information symbol next to the Internal Status label. Hovering over this icon displays yet more information. This time, we see an error that would stump many – the sort of error that an information worker would have to call up helpdesk for.

Retrying last request. Next attempt scheduled in less than one minute. Details of last request: HTTP InternalServerError to http://megacorp/iso9001/_vti_bin/client.svc/web/lists/getbyid(guid’a64bb9ec-8b00-407c-a7d9-7e8e6ef3e647′)/Items(7) Correlation Id: de95e312-e24b-42c3-9369-5bae68040219 Instance Id: 9ed3a11d-f665-4512-9b17-78850356c846

image21_thumb  image241_thumb

Okaaaay, so that error message is about as useful as Windows Vista. It shows an internal server error and a correlation ID. Furthermore, if you wait another minute or so, and then refresh the workflow status screen, it’s internal status is no longer started, but now has the status of Cancelled. You can see it for yourself below…

image27_thumb

One again, clicking the little blue info button gives us more detail. Unfortunately, the detail consists of an even scarier appearing message than the previous one. This one looks nasty enough to freak out some SharePoint admins too. Check it out – it is pretty much useless in terms of conveying any information of value.

RequestorId: 8ad4a017-7e6f-0d0f-35d2-81c56a05b37c. Details: System.ApplicationException: HTTP 500 {“Transfer-Encoding”:[“chunked”],”X-SharePointHealthScore”:[“0″],”SPClientServiceRequestDuration”:[“211″],”SPRequestGuid”:[“3d7950b2-3d9d-47d9-a5fb-588bf02b9551″],”request-id”:[“3d7950b2-3d9d-47d9-a5fb-588bf02b9551″],”X-FRAME-OPTIONS”:[“SAMEORIGIN”],”MicrosoftSharePointTeamServices”:[“15.0.0.4420″],”X-Content-Type-Options”:[“nosniff”],”X-MS-InvokeApp”:[“1; RequireReadOnly”],”Cache-Control”:[“max-age=0, private”],”Date”:[“Sun, 17 Nov 2013 22:56:19 GMT”],”Server”:[“Microsoft-IIS\/8.0″],”X-AspNet-Version”:[“4.0.30319″],”X-Powered-By”:[“ASP.NET”]} at Microsoft.Activities.Hosting.Runtime.Subroutine.SubroutineChild.Execute(CodeActivityContext context) at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager) at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

image30_thumb

So what the hell is going on here?

Unfortunately, both of the error messages above are virtually useless for most people and the only way to dig deeper is to delve into the SharePoint ULS logs. Of course, if you use Office 365 you don’t have that luxury because accessing the ULS logs are not available to you – so your best option to figuring out errors like this is trial and error. you need to learn CSOM code to access the logs. For the rest of us living in on-premises or IaaS land, a quick search of the ULS logs for the file name “Burger additives standards” reveals the issue and the root cause. Check out the errors reported below – it should be quite clear…

SharePoint Foundation             General                           8kh7    High        The file “http://megacorp/iso9001/Documents/Burger additives standards.pdf” is not checked out.  You must first check out this document before making changes.

SharePoint Foundation             General                           aix9j    High        SPRequest.AddOrUpdateItem: UserPrincipalName=i:0).w|s-1-5-21-1480876320-1123302732-2276846122-500, AppPrincipalName=I:0I.T|MS.SP.EXT|2CC54B18-3F9D-43A3-BE55-B3A81C045562@B9A66C21-F39D-42DB-B6CD-DE520B6C1C91 ,bstrUrl=http://megacorp/iso9001 ,bstrListName={A64BB9EC-8B00-407C-A7D9-7E8E6EF3E647} , bAdd=False , bSystemUpdate=False , bPreserveItemVersion=False , bPreserveItemUIVersion=False , bUpdateNoVersion=False ,pbstrNewDocId=00000000-0000-0000-0000-000000000000 , bHasNewDocId=False , bstrVersion=8 , bCheckOut=False ,bCheckin=False , bUnRestrictedUpdateInProgress=False , bMigration=False , bPublish=False , bstrFileName=<null>

SharePoint Foundation             CSOM                              ahjq1    High        Exception occured in scope Microsoft.SharePoint.SPListItem.UpdateWithFieldValues. Exception=Microsoft.SharePoint.SPException: The file “http://megacorp/iso9001/Documents/Burger additives standards.pdf” is not checked out.  You must first check out this document before making changes. —> System.Runtime.InteropServices.COMException: The file “http://megacorp/iso9001/Documents/Burger additives standards.pdf” is not checked out.  You must first check out this document before making changes.     at Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bPreserveItemUIVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDo…    3b84d615-e006-4457-811a-0af089963216

So in case it is not clear from the above messages, we have an error stating that the file Burger additives standards is not checked out and that to make changes to the document, we need to check it out first. This raises several questions:

  • 1. Why is the document library configured to require check-out?
  • 2. Why is the workflow trying to change the document anyway? The workflow we created in part 2 does no action on the Documents library.
  • 3. Why were the error messages so useless (which really hurts in Office365 scenarios)
  • 4. How can we fix this problem?

Let’s examine each of these in turn…

1. Why is the document library configured to require check-out?

The first question is really easy to answer. When you create a site using the Document Center site template, the document library versioning settings enable the Require Check Out option as shown below. Therefore no changes can be made to this document unless the user making the change checks it out.

image

2. Why is the workflow trying to change the document anyway?

The second question is also easy to answer, but the answer is somewhat more complicated. When a workflow is associated to a list or content type, it adds a column to track the status of the workflow. In SharePoint 2013, the default behaviour is to update this column with whatever stage in the workflow currently being executed. Therefore, as soon as the workflow runs, and before it has run any of the actions, it attempts to update its stage to the document that it was triggered from. So looking at the images below, if things were working we should see the string “Stage 1” in the Process Owner Approval column for the document Burger additives standards. But since the document requires check-out to make a change, SharePoint prevents this from happening by design.

image

image

Some readers who are experienced with SharePoint Designer workflow might be thinking “easy… just use the check out item workflow action before you do anything else.”Unfortunately this won’t work for you because this issue gets triggered when the stage info is written to the workflow status column which happens before any actions run.

3. Why were the error messages so useless (which really hurts in Office365 scenarios)

The next question is why on earth wasn’t the true error able to be reported back to the workflow? After all, in the end, this was a clearly identified error in SharePoint, yet all we got was error messages that did not state the problem at all.  This would have saved the effort of delving deep into the ULS logs and that is not even possible in Office 365.

The answer to this question is a little more complex and relates to how Workflow Manager and SharePoint interact with each other. Without getting into detail, the gist of the issue is that Workflow Manager uses REST webservice calls to do all of its operations on SharePoint content. Each and every workflow action (like the Log to History List) uses REST to talk to SharePoint to get the work done. While a detailed discussion of REST would take us too far afield, I have drawn you possibly the dodgiest ever diagram of this process ever to help you understand it. The main point with REST worth mentioning is that the intention of REST is to embrace the key protocols of the web, so a successful or failed request is conveyed via a HTTP status code.  If you have ever experienced your browser giving you a 404 page not found, then you know what I mean when I speak of HTTP status codes.

Snapshot

Now look again at the gory detail of the error that was logged by the workflow. We see the following string amongst all the other stuff. “Details: System.ApplicationException: HTTP 500”. So what happened is when the workflow tried to update the document with its stage, the check-out requirement resulted in SharePoint sending back a HTTP Error 500 (server error) back to the workflow manager.  Unfortunately for us, it did not send back the underlying cause of the error. Instead, the details of the response logged by workflow has all sorts of information about the HTTP request, but no hint to the underlying error. Sucks eh?

4. How can we fix this problem?

The final question was what we could do about this issue. There are two relatively easy ways, but before I do that, let me show you what happens if you check out the document and then attempt to run the workflow. While you might think this problem might go away, instead we get a friendly dialog box telling us to check the document back in before we attempt to start a workflow. Given that I couldn’t run this workflow because the item needed to be checked out, I had to laugh.

image

Anyways, the two options you have are to disable require check out on the Documents library or change the default behaviour of the workflow so that it does not write the stage back to the item that triggered the workflow. The first one is pretty easy – in the Versioning Settings of the Documents library, we change the Require documents to be checked out before they can be edited? option from Yes to No

image

The problem with the first option is that requiring check-out for controlled documents is likely to be a key requirement, so it is not an option in all circumstances. So the other option is to change the behaviour of the workflow itself so that it does not write its stage information back to the Documents library. Luckily for us, this is actually really easy to do. In SharePoint Designer 2013, there is an option to disable the updating of stage information. In the workflow settings screen, look for the option called Automatically update the workflow status to the current stage name and untick it.

image

Now unticking this box will get us past this error, but the problem now is that we have no easy way to track workflows, as this status update can be used in views on the Documents library to see which workflows are at a particular stage. For a complex workflow, or one that will be running on many items, not being able to see the status of the workflow would make life difficult. One workaround is to add a Check Out Item workflow action to the start of the workflow, and then use the Set Workflow Status action to update the status column on the current item as the workflow progresses. This will give us back the ability to track the workflow behaviour in the Documents library, but it will mean that a new version will be added to that Document each time the status updates. So another workaround is to log workflow status to some other list altogether (using the Create List Item action) and use that list for tracking and reporting instead.

Conclusion

I think that the separation of SharePoint and Workflow Manager into separate products is ultimately a good thing. It’s just a pity that one of the legacies of this change is an issue like what we covered in this post, where a relatively simple problem was exacerbated by poor reporting of errors between Workflow Manager and SharePoint. I guess this is part of the bigger price we pay – that of increased technical complexity via more moving parts. Hopefully an issue like this one can be addressed in a future service pack or update, because it is this sort of stuff that can cause people to lose some confidence and jump to the 3rd party solution perhaps prematurely. So if this issue was enough for you to think “pah – let’s go third party”, I have news for you. As you progress through this series we are going to deal with more complex issues than this one too.

Anyway, the point is that we have identified the cause of this particular issue and gotten past it, so we should be able to continue testing the workflow and marvel at our awesomeness. So in the next article, we will continue with testing our workflow and see what else SharePoint throws at us.

Thanks for reading

Paul Culmsee

HGBP_Cover-236x300.jpg

www.hereticsguidebooks.com

 



Trials or tribulation? Inside SharePoint 2013 workflows–Part 2

Hi and welcome to part 2 of a series that aims to showcase the good and the bad of SharePoint 2013 workflows, using a simple use-case. In part 1 I introduced you to the mythical multinational called Megacorp and its document control requirements. Also in part 1, we created a site with the necessary lists and libraries from which we can build the workflow. To recap, we used the Document Center site template, and then modified the built-in document library (Documents) to store the organisation that each document belongs to. We created a custom list called Process Owners that stored who is accountable for controlled documents in each organisation. Below is an XMind map to show you the Information Architecture of the Megacorp document control site.

image_thumb1

Our workflow is going to:

  • Look at a document and determine the organisation that a document belongs to
  • Look in the process owners list for that organisation and then determine the process owner for the organisation by grabbing the information in the “Assigned To” field
  • Create an approval task for the process owner to approve the release of a controlled document.

Now this all sounds straightforward enough in theory, but this is SharePoint we are talking about. Let’s see how reality stacks up against theory. I will give lots of screenshots for readers who have never tried using SharePoint Designer Workflow before…

Creating the workflow

Step 1:

Right, so the workflow will fire when a document is modified, so we will start by adding a list workflow and link it to the Documents library. So using SharePoint Designer 2013, we open the Megacorp site and in the ribbon, we click the List Workflow button. This will cause a dropdown menu to appear below the icon, showing the lists and libraries on the Megacorp site. From this list, we choose the Documents library.

image    image_thumb23

Step 2:

We are presented with the workflow creation screen. Call the workflow “Process Owner Approval” and click OK.

image_thumb9

Note: If, at this point, you get an error, it means that Workflow manager has not been provisioned properly. Remember that in SharePoint 2013, workflow is a separate product and needs to be installed. This is a change from previous versions of SharePoint where workflow was always there, as it was part of SharePoint.

Assuming SharePoint is configured right, SharePoint Designer will have a think for a while and eventually display the following workflow creation screen, ready for us to do cool things!

image_thumb12

The next step is to add a workflow action. The most logical workflow action for us to try is one of the task actions. We will attempt to assign a task to the process owner for a document.

Step 3:

From the workflow ribbon, click the Action icon and choose “Assign a task”. The action will be added to the workflow, ready for you to fill in. For those of you reading this who have never done this before, the process is reminiscent of configuring email rules in outlook in that the action is added and you then fill in the blanks..

image_thumb15   image_thumb18

Now let’s configure the finer details of the Assign action above. A task needs to be assigned to a user, and we need to set up the logic for the workflow to work out who that user is. If you recall, the Documents library has a column called Organisation that specifies which Megacorp entity owns each document. A separate list called Process Owners then stores whoever is assigned as the process owner for each organisation (using the Assigned To column). So when the workflow runs on a particular document, we have to take Organisation specified for that document and use it to search the Process Owners list for the matching Organisation. Once we find it, we grab the value of the Assigned to user and create a task for them.

Here is a dodgy diagram that explains the logic I just described.

Snapshot

So let’s give it a go…

Step 4:

Go back to your newly minted “assign task” that you just added. Click the “this user” hyperlink on the newly created task. The task properties screen will appear as shown below. In the Participant textbox, click the ellipses button to bring up the Select User dialog box.

image_thumb19  image_thumb24

In the Select User dialog box, choose Workflow Lookup for a User and click the Add >> button. This will bring up the ambiguously named Lookup for string dialog box that allows us to choose where to look for our process owner. In the Data source drop down, we choose Process Owners from the list.

Next we have to tell the workflow which column holds the details of the person to perform the task. In the Field from source drop down, choose the Assigned to column as we talked about above.

image_thumb27image

At this point, the workflow knows which list and column holds the information it needs as per the image below:

Snapshot,

But currently we do not know the specific user we need. Is it John Smith, Jane Doe or Jack Jones? Fear not though – this is what the Find the list item section of the Lookup for string dialog box is for. This is where we will tell the workflow to find only the person who matches the value of the Organisation column assigned to the document.

Step 5:

First up, we tell the workflow which field in Process Owners will be used to compare. This is the Organisation column, so in the Field: drop down, choose Organisation. Next we have to match that organisation column with the one in the Documents library. Click the Fx button next to column textbox called Value. A new dialogue box will appear called Lookup for Extended Field. Leave the Data source dropdown as Current item and in the Field from source dropdown, choose the Organisation column.

image   image

Note 1: in a workflow, “Current item” refers to the item that the workflow has been invoked from. If you recall at the start of this post, we created a list workflow and associated with the Documents library. Current item refers therefore to any document in the Documents library that has had a workflow invoked. All of the metadata associated with the current document is available to the workflow to use.

Note 2: Keen eyed readers may be wondering what the deal is with the column labelled Organsiation_0. Don’t worry – I’ll get to that later.

Now that you have selected the organisation column from the Documents library, we have filled in all of the logic we need to grab the right Assigned to user. Clicking ok, the workflow designer will warn you that if you have been silly enough to add multiple process owners for a given organisation, that it will use the first one it finds.

image  image

Finally, we are back at the task designer screen. A lot of screenshots just to wire up the logic for finding the right process owner eh? We haven’t even configured the behaviour of the task itself yet!

image

In fact, for now we are not going to wire up the rest of the task. I would like to know if the logic we have just wired up will work. If I can confirm that, I will come back and finish off creating the task with the behaviours I want.  So instead, let’s click Ok to go back to the workflow designer. Now we can see our Assign a task action, ready to go.

image_thumb39

Now before we can test and publish the workflow, we need to tell it to end. Now this is a little counter intuitive to someone who is used to SharePoint 2010 workflows, but it makes sense once you understand the concept of a workflow stage.

SharePoint Workflow 2013 Stages – an interlude…

If you have ever sat around and tried to map out a business process, you have probably experienced the fun (not) of discovering that even a relatively simple business process has a lot of variations to it – some quite ad-hoc or dynamic. Trying to account for all of these variations in workflow design can make for some very complex and scary diagrams with even scarier implementations. As an example, take a look at the diagram below – this is a real process and apparently it is only page 12 of a 136!

image

Now in SharePoint 2010, implementing these sorts of workflows was pretty brutal, but in 2013 it has been rethought. A stage is a construct that allows you to group a number of workflow actions together, as well as defining conditions that govern how those actions happen. Each stage in a workflow can transition to any other workflow stage based on conditions. This means that a workflow can effectively loop around different stages and greatly simplify implementing business logic compared to SharePoint 2010.

The means by which this is done is via the the new Transition to Stage workflow action. The way this works is at the end of each workflow stage, there is a transition to stage section as shown below:

image

Step 6:

When you click into the Transition to stage section of the workflow, there is only one workflow action available: the Go To A Stage action. Adding this to the workflow will present a dropdown that will allow you to transfer the workflow to any the you have defined, or to end the workflow. Right now we will end the workflow, but we will be revisiting this stage idea later in the series.

image_thumb40  image_thumb41  image_thumb43

All right! We are done. The final step is to save and publish the workflow.

Step 7:

In the ribbon, look for the Publish icon and click it. Assuming everything goes according to plan, you will be back at the workflow overview screen in SharePoint Designer.

image  image

Congratulations – you have published your workflow. “Well that was easy,” I hear you say… But we haven’t tested it yet! In the next post we will test our masterpiece and see what happens. You might already have an inkling that the result may not be what you expect… but let’s save that for the next post.

Thanks for reading

Paul Culmsee

HGBP_Cover-236x300.jpg

www.hereticsguidebooks.com

 



Trials or tribulation? Inside SharePoint 2013 workflows–Part 1

Hi all

Workflows are big business in SharePoint land, despite the capability of SharePoint Designer Workflows being a fairly weak link in the overall SharePoint value proposition. If this wasn’t the case, then products like Nintex or K2 would not be so popular and workflow vendors wouldn’t have the biggest booths at the average SharePoint conference.

One of the serious strategic advantages of going with the SharePoint stack is the amazing 3rd party ecosystem that flourishes around the base product. No other platform in the space has the level of 3rd party support that SharePoint enjoys. But while its nice to be able to have great options for serious SharePoint workflow development, with each successive version of SharePoint that comes out, there is always that hope that one can use the base functionality without having to jump straight away to the 3rd party tools.  After all, it is quite common for organisations, having just gone to the time and expense of adopting SharePoint, to be dismayed that they have to part with yet more cash for 3rd party tools to address large functional gaps that were not apparent in the contrived product demos.

Another important trend being hidden by cloud hubris is the rise of the citizen developer. The CIO’s fountain of knowledge known as Gartner, stated that by 2014 25% of new business applications will be delivered by Citizen Developers.  They defined citizen developers as “a user operating outside of the scope of enterprise IT and its governance who creates new business applications for consumption by others either from scratch or by composition.” Elaborating, Gartner stated that

“Future citizen-developed applications will leverage IT investments below the surface, allowing IT to focus on deeper architectural concerns, while end users focus on wiring together services into business processes and workflows. Furthermore, citizen development introduces the opportunity for end users to address projects that IT has never had time to get to — a vast expanse of departmental and situational projects that have lain beneath the surface.”

So with SharePoint 2013, Microsoft has indeed changed things up a notch in the workflow world. Is it enough to enable and empower citizen developers?

That is what this series aims to find out… First up, lets take a quick look at the forces we are going to be meddling with…

What’s new with SharePoint 2013 and workflow…

Workflow in SharePoint 2013 is significantly different from SharePoint 2010. It fact, it is essentially a completely separate product called Workflow Manager. Technically, Workflow Manager is not part of SharePoint at all – there is no “workflow” service application or “service on a server” to be found. Instead, it is a separate process that works by communicating with SharePoint over the HTTP protocol in various ways.

This means that we have the option of deploying Workflow Manager onto its own server, or set of servers (although for you smaller sites, it happily installs onto your SharePoint servers and coexists with the rest of SharePoint too). This loosely coupled model has scalability benefits as workflow load can now be separated from the rest of SharePoint. It also means badly behaved workflows are less likely to affect SharePoint sites because they run in a separate process or separate servers. 3rd party applications (think about solutions built using the SharePoint 2013 apps model here) can also interact and communicate with workflow manager separately to SharePoint. It also helps Microsoft to realise their strategy of “encouraging” everyone to their vision of a cloud-based happy place.

Now new does not always equate to good – and Microsoft have a bit of a dubious history with V1 products and technology. So in this series, I’d like to show you an example of what the SharePoint 2013 new workflow regime can do. The example that I am going to use for this set of articles is useful for this purpose for several reasons:

  • 1. It is a common use-case that many organisations would find familiar – particularly those with compliance regimes
  • 2. It demonstrates a fairly typical SharePoint consulting “oh crap” moment, where you realise your masterpiece of a solution is completely undone by an untested assumption or a SharePoint caveat that you forgot about.
  • 3. It demonstrates a path to redemption that is an excellent utilisation of the new capabilities of SharePoint 2013 and Workflow Manager
  • 4. It gives you a great sense as to whether workflows are a real developer, information worker or citizen developer tool. In other words, after reading this, you should have a good idea what you are getting yourself into!

I have a lot to cover, so this series will be multi-part. This first post will outline the scenario that we are dealing with.

The scenario: Document Control at Megacorp

Many organisations operate in industries where they are required to manage documentation in a systematic way. Documents that are subject to any sort of quality or compliance regime are often referred to as “Controlled Documents”. Typically, a controlled document will have an assigned responsible party who is accountable for the management (i.e. approving the issuing of updates) of that document.

To illustrate, consider the document control requirements of Megacorp Inc – a mythical multinational conglomerate with a vide variety of businesses in many different industries and locations. Megacorp is your typical diversified multinational, making everything from Iron Man suits to hamburgers. A managed metadata term set illustrating the Megacorp conglomerate structure can be seen below. If you look closely, Megacorp Inc, actually consists of several companies and each is structured differently. For example: Megacorp Pharmaceutical divides itself based on country and state jurisdiction, whereas Megacorp GM foods divides itself up on the particular food it is generically modifying.

image

So let’s say that Megacorp is maintaining ISO9001 certification for assurance purposes and therefore has to control their documents as I have stated above. Let’s create a SharePoint site called ISO9001 to handle this requirement. We perform the following steps:

  1. Build a term set (called Megacorp Inc)that stores all of the Megacorp businesses (you can see that in the image above)
  2. Create a site based on the built-in Document Center template
  3. Create a managed metadata site column called Organisation and associate it to the Megacorp term set
  4. Add the organisation column to the document library (called Documents) in the Document Center site
  5. Enable Metadata Navigation on the Documents library and add the Organisation column as a hierarchy field

For those of you who are new to SharePoint, below are screenshots from those steps to help you with the above steps… I am not going through this stuff in detail, so hopefully this suffices…

image  image

imageimage

Now that the above plumbing is done, a few documents have been added to the Documents library and tagged to their organisation. With Metadata Navigation enabled, we now have the easy means to browse and filter documents to the specific organisation who owns them as shown below…

image

So let’s now think through a workflow scenario. Each organisation that makes up Megacorp has a process owner and when a document is ready for publishing, the process owner needs to approve it. Now we could do this by adding a “Person or Group” column to the document library and call it “process owner.” But Megacorp has some additional considerations that need to be pondered…

  • 1. They have thousands of documents in the library
  • 2. The process owner is a role, not an individual person. For audit purposes, Megacorp wants to have a record of when a person was in a particular process owner role.

The reason this complicates things is twofold. If we use a person’s user account in Active directory for tagging the process owner, we can easily track when a process owner changes because it will show up in the version history of the documents. But the downside is that we would have to update each document individually when that process owner changes to someone else. Not to mention that we may not want this change to be a version change in the document itself.

Now I know what your thinking – “Just use an Active Directory Group instead of an account”. Yes, it is a good and logical suggestion, since a SharePoint or Active Directory group allows us to easily manage changes in personnel between roles by changing group members. But the downside is that we have no easy way to see the history of who was in the process owner role at a given time because SharePoint would see and store the group, not the members of that group.

So let’s try an alternative approach. We will make a custom list called “Process Owners” and add two columns to it. We will add the Organisation site column that we created and used earlier, and we will add the “Assigned To” column that is built-into SharePoint and used in task lists. This will give us a list of process owners for a given Megacorp company or division. Even better – if we turn on version history on the Process Owners list, we now have a record of who was in the process owner role at any given time because it will show up in the changes in the “Assigned to” field over time.

The image below illustrates the Process Owners list.

image

So to summarise, we have a document library where all documents are tagged to the organisation that they belong to. We have a list of the process owners for each organisation. To better visualise this, I have drawn an xmind map to show you the Information Architecture of the Megacorp document control site

image

Now we turn our attention to the document approval workflow. It should be able to:

  • Look at a document and determine the Organisation that a document belongs to
  • Look in the process owners list for that organisation and then determine the process owner for the organisation by grabbing the information in the “Assigned To” field
  • Create an Approval task for the Process owner to approve the release of a controlled document.

Now this all sounds straightforward enough in theory but as we will see as this series progresses, when it comes to SharePoint, theory and reality are two very different things. So in part 2, we will build out the workflow..

Thanks for reading

Paul Culmsee

h2bp2013_thumb.jpg

www.heretisguidebooks.com



« Previous Page

Today is: Wednesday 3 June 2026 -