Error creating the same task multiple times in state machine workflow

October 20, 2011

I created my first state machine workflow the other day and just when I thought everything was working as expected I encountered a really strange error. I went for a state machine workflow as I had to deal with the same item being changed numerous times and send emails and create tasks depending on one of the values on the list item. From the reading I had done on state machine workflows this seemed like the perfect fit for the requirements.

I found some articles on how to create the workflow and was surprised at how easy it was, ok my workflow was very simple but I can see the advantages of this approach. This was until I started getting errors when testing the various different use cases. Before I go into the actual error its important to first give some background into the actual workflow.

When an item is added to a list the workflow is initiated and the Initial State is executed. The next state has an event driven activity and within this I have a ‘OnWorkflowItemChanged’ activity in it so I can detect when the item has been modified. I then have an if else branch with 4 possible options with different tasks in each of the branches. In the ‘OnWorkflowItemChanged’ activity I perform some calculations which are used in the branching logic.

What I was finding was everything was working as expected first time around, however if I had already created a task within a and then encountered the same situation rather than creating a new task the workflow was failing. The details in the workflow history on the list item is not helpful in the slightest and it can be difficult to locate details in the ULS log but eventually I found the error below.

Workflow Error

System.InvalidOperationException: Correlation value on declaration "longTermSickToken" is already initialized.

Which I noticed this I looked around on Google and soon found it was because I had set the OwnerActivityName to the name of the workflow. This made sense as I guess these have to be unique so I changed the OwnerActivityName to be the name of the state but I found the same issues so next I changed it to be the name of the Event Driven Activity within my state and this corrected the problem.

I am sure people who are familiar with state machine workflows will think this obvious but it was an interesting learning curve and one I am determined not to repeat hence this article

Advertisements

Passing source querystring value which contains multiple querystring Values to an Display, Edit or New list item forms

October 13, 2011

While working on my most recent project I came across an interesting issue with passing around QueryString values to New, Display and Edit list forms. In my scenario I have a web part which displays certain information to the user. They can then choose to drill down which takes them to another page. From here they can they link to the edit or display forms for a custom list. In order to ensure the users is always able to go backwards at any point I was keeping various parameters in the QueryString, including one for the URL for the pervious page, see below example URL’s at each stage.

First Page

http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1

Second Page

http://sharepoint/site/SitePages/PageTwo.aspx?TestParamTwo=1&SourceURL=http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1

Third Page(List Form)

http://sharepoint/site/listname/EditForm.aspx?ID=1&Source=http://sharepoint/site/SitePages/PageTwo.aspx?TestParamTwo=1&SourceURL=http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1

What I was finding was when I clicked save or cancel on the edit form I was getting returned to the correct page but I was losing the SourceURL parameter hence couldn’t return the user to the first page. After some Googling around I found an article suggesting I should encode the ‘&’, ends up as %26, in the SourceURL parameter being passed to the Edit form. After changing and testing I found this worked like a treat so wanted to share for others and for my self in future. I have included the updated version of the URL’s above.

First Page

http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1

Second Page

http://sharepoint/site/SitePages/PageTwo.aspx?TestParamTwo=1&SourceURL=http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1

Third Page(List Form)

http://sharepoint/site/listname/EditForm.aspx?ID=1&Source=http://sharepoint/site/SitePages/PageTwo.aspx?TestParamTwo=1%26SourceURL=http://sharepoint/site/SitePages/PageOne.aspx?TestParamOne=1


Document Metadata not appearing when set via an event receiver

October 7, 2011

I have been working with a client to create a unique document numbering system on their MOSS 2007 intranet and have came across a really frustrating issue. The idea was simple enough an event receiver associated with all document libraries which sets a field to have a unique number. In practice this provided extremely frustrating.

I created the event receiver and was using the ItemAdded method to get the number from a list at the root of the site collection then setting this number to a column on the list. What I found was certain times this was working and others it wasn’t. I started outputting information to a log file to track what was happening and I could see everything was working as expected and even after updating the item in SharePoint the reference number was set, however when I looked at the UI there were times when it was empty.

Eventually when reviewing the ULS log I noticed a pattern when the reference number was not getting set. On all items regardless if they worked on not there was always details displayed in the log about getting document Metadata, see below. I noticed on the items where the reference number was set to what I expected this call happened before I set the reference number whereas on items where it failed the call was after.

Details in ULS Log

RPC method = getDocsMetaInfo
in getDocsMetaInfo after getlinks

I had a quick look on Google and found out this is SharePoint getting the Metadata properties on the document. All of a sudden I realised this made sense as when the call was after I set the reference number it must have been overwriting my details with those from the document.

I tried to figure out a way to get around this but in the end there was no way I could see that would always ensure this function was called after so I put in a 3 second delay before assigning the reference number and it started to work on a regular basis.

Obviously this isn’t ideal as there is still a chance the getDocsMetaInfo function could be called after so if anyone else has a better idea let me know.


Hide column in list depending on another columns value

October 5, 2011

While working on a SharePoint 2010 project a client wanted to have some columns in a list to only display depending on the value entered in another field. The obvious choice for this was InfoPath but dues to project decisions this was not an option.

With InfoPath not being an option I decided the next best option would be to use JQuery. After some looking around I found a similar article, however this didn’t seem to work for SharePoint 2010 so I have altered it original and included it below. 

Not only have i changed it to work in 2010 I have also modified it so you can pass in an additional parameter to the function which determines if the column should be displayed on the page load and if the column should be hidden or displayed on the click event.

I have not touched on how you include this JavaScript function and call it as there are several different ways of achieving this depending on your circumstances.

Function
  1. function HideColumn(targetColumn, hideColumn, hideInitially) {
  2.     var columnToHide = $("h3:contains('" + hideColumn +"')");
  3.     var columnToAttachClick = $("h3:contains('"+ targetColumn +"')");
  4.     var inputToAttachClick = columnToAttachClick.closest('td').next('td').find('input');
  5.  
  6.     if (hideInitially == 'true') {
  7.         columnToHide.closest("tr").hide();
  8.     }
  9.  
  10.     if (inputToAttachClick.is(':checked')) {
  11.         if (hideInitially == 'true') {
  12.             columnToHide.closest("tr").show();
  13.         }
  14.         else {
  15.             columnToHide.closest("tr").hide();
  16.         }
  17.     }
  18.     else {
  19.         if (hideInitially == 'true') {
  20.             columnToHide.closest("tr").hide();
  21.         }
  22.         else {
  23.             columnToHide.closest("tr").show();
  24.         }
  25.     }
  26.  
  27.     inputToAttachClick.bind('click', function () {
  28.         if ($(this).is(':checked')) {
  29.             if (hideInitially == 'true') {
  30.                 columnToHide.closest("tr").show();
  31.             }
  32.             else {
  33.                 columnToHide.closest("tr").hide();
  34.             }
  35.         }
  36.         else {
  37.             if (hideInitially == 'true') {
  38.                 columnToHide.closest("tr").hide();
  39.             }
  40.             else {
  41.                 columnToHide.closest("tr").show();
  42.             }
  43.         }
  44.     });     
  45.    }

Displayed on load then hidden
  1. HideColumn('Target column name','Column to hide', 'false');

 

Hidden on load then displayed
  1. HideColumn('Target column name','Column to hide', 'true');


%d bloggers like this: