Friday, May 1, 2009

Error Update WF Task

The Error

I ran into a rather interesting error as a result of me finding this error. I was getting the following:

This task is currently locked by a running workflow and cannot be edited

What I was trying to do was update a task list item that was generated from a WF workflow. I had a situation where the Assigned To field had not been properly set, and I wanted to modify the existing item. I could get this error in numerous ways. For instance, you cannot access the Assigned To field by going to task itself but if you select Edit in Datasheet you have the ability to update it.

As well I had written a little a small code snippet to update the task as well.

private static void UpdateTaskAssignedTo(string siteURL, string web,
string taskListName, string loginName, string email, int itemID)
{
using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb(web))
{
SPListItemCollection listItems = web.Lists[taskListName].Items;
SPListItem listItem = listItems.GetItemById(itemID);

web.AllowUnsafeUpdates = true;

SPUser user = web.AllUsers.GetByEmail(email);
SPFieldUserValue fieldUser = new SPFieldUserValue(web, user.ID, user.LoginName);
listItem["Assigned To"] = fieldUser;
listItem.SystemUpdate(false);

web.AllowUnsafeUpdates = false;
}
}
}

What would happen if did either the task would get updated as expected, however if I tried to update it again I would get the above error.

WORSE – the workflow task item will not start up the workflow again – for all intensive purposes it will seem that the workflow is stuck.

The Issue

I found this blog, among a few others discussing the issue. Several claimed this as a "bug" for WF and MOSS. It is not once I sat down and started thinking about it. The issue has to do with the task correlating to the WF workflow instance.

If you have built a custom workflow in MOSS, you will know that if you put in a OnTaskChanged event in your workflow basically the WF workflow is waiting for task to be updated. When you go to update the task by clicking on the task directly you will be taken to Workflow Form (InfoPath in most cases) which will submit back to the WF server within MOSS to start back up the workflow. However, if you access the task list item by other means (examples above), you are changing the state of the task itself and the WF instance gets out of sync.

The Resolution

It is pretty simple; all you need to do is add an action to the state for an Update. So put a dropdown on your IP form with the actions that a user can do like Approve, Deny or Update. Approve or Deny will move the workflow to a completely different state however, the Update will call back to the current state. The task will be recreated (so it is good practice to delete the task in the StateFinializationActivity. This is why I like to use K2 blackpearl instead to avoid this……

SharePoint 2007 SP2 Released

SharePoint 2007 SP2 has been officially release. It "includes all the fixes prior to SP2, and also several enhancements to improve server farm performance, availability and stability. Plus, a new stsadm operation has been added to help customers prepare for the upgrade to the next version of SharePoint."

You should start planning on how to deploy this into your QA, Staging and Production environments…

The things I was happy to see for MOSS where (KB953334) improvements with Microsoft Office Forms Server (InfoPath) given I use it a lot with K2 blackpearl:

  • Improves performance of large browser forms on InfoPath Form Services, both for memory usage and for page load time.
  • Improves reliability of Forms Server and of Microsoft Office SharePoint Server by addressing the previous behavior in which an upgrade of an administrator-approved form template triggers an IIS reset.
  • Improves the Digital Signature functionality for InfoPath Forms Services.

K2 May User Group

Anthony Petro (Technical Product Manager for K2) will be presenting on the 90x releases for K2 blackpearl and blackpoint. Please tune in and ask questions.

--------------------------------

Tuesday, May 12, 11am-1pm central time

Phillip Knight from Merit Energy will be hosting the K2 user group meetings at Merit Energy, located at 13727 Noel Road, 2nd Floor Conference room, Tower 2, Dallas, Texas 75240. Parking information is included in the linked map below. Remote attendance information is included at the bottom of this message.

Link to map: http://www.meritenergy.com/content/MeritMap.pdf. Reminder: Merit Energy is on the 5th floor, but the meeting will be held in a 2nd floor conference room. Once off the elevator, go to the reception area and we will bring you back to the conference room.

Please RSVP to me via email
whether you are attending via live meeting or if you will be attending in person (so that we can plan for the number of people to order food for).

Check out the K2 Underground site and our user group at http://k2underground.com/k2/InterestGroupHome.aspx?IntGroupID=11. We are posting webexes/live meetings from our meetings at this site.

06/9/2009 11am – 1pm
07/14/2009 11am – 1pm
08/11/2009 11am – 1pm
09/8/2009 11am – 1pm
10/13/2009 11am – 1pm

Meeting Agenda:
11-11:15 Networking/Refreshments
11:15-11:30 Announcements/Intros of New people
11:30-11:45 Tips & Tricks
11:45-12:45 Technical Presentation
12:45-1:00 Meeting Wrapup

The Announcements section of the meeting will include any information regarding K2 upcoming events and user group events as well as brief introductions of our presenter and refreshment provider.

The Tips & Tricks Presentation is when we as members can pose questions to each other on projects that we are working on and having difficulty with. It is also a time when if we have learned something that we feel will be helpful to others, we can share it with the group. Bring yours to share/ask.

Meeting Presentation & Company & Sponsor:

We thank Anthony Petro from K2 for
presenting at our May K2 user group meeting. Anthony will be giving our K2 User group a sneak peak at the new features coming up in the 90x release of K2 BlackPearl. Don't miss this meeting, you will be the first of the K2 user community to know what's new.


We thank K2 for providing our presenter and Joe Bocardo from K2 for sponsoring our refreshments at our May meeting.


K2 blackpoint, a subset of K2 blackpearl features, provides unparalleled capabilities and affordability. It also offers an upgrade path so that organizations can grow their investment and add complexity over time, if needed.


For more information, go to http://www.blackpoint.k2.com.


The K2 platform is for delivering process-driven applications that improve business efficiency. Visual tools make it easy for anyone to assemble reusable objects into applications that use workflow and line-of-business information.


K2-based solutions are deployed by a growing number of the global Fortune 100. K2 is a division of SourceCode Technology Holdings, Inc. based in Redmond, Washington, and has offices all over the world.


For more information, contact Joe Bocardo at joeb@k2.com.



Meeting Presenter:


Anthony Petro resides in Silverthorne, Colorado and is the Technical Product Manager for K2. He started his professional career in the consulting world 14 years ago and has always remained focused on Microsoft technologies and solutions. He joined Microsoft in 2001 and spent the next 5 years heavily immersed in SharePoint Joint Development Programs bridging the gap between the product development teams in Redmond and the enterprise customers around the world. He was a strong contributor to the SharePoint community in its infancy focused on teaching the masses about the complexities of search and enterprise scale and using products such as K2 filling the enterprise workflow gaps of SharePoint. He joined K2 in 2006 to help bring K2 blackpearl to market through early adopter programs that spanned the alpha and beta cycles through to RTM. Anthony remains actively involved in early adopter programs for K2 blackpoint and K2 connect and planning the future releases of all product lines.


For Virtual Attendees:

Note: please keep your phone on mute until you are ready to speak.

Audio Information

Telephone conferencing
Choose one of the following:

Start Live Meeting client, and then in Voice & Video pane under Join Audio options, click Call Me. The conferencing service will call you at the number you specify. (Recommended)

Use the information below to connect:
Toll: +1 (719) 867-1571

Toll-free: +1 (877) 860-3058

Participant code: 914421

First Time Users:

To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

Copy this address and paste it into your web browser:

1. Copy this address and paste it into your web browser:
https://www.livemeeting.com/cc/scna1/join

2. Copy and paste the required information:

Meeting ID: RPFR8T
Entry Code: M~`5~pd!p
Location: https://www.livemeeting.com/cc/scna1


If you would like to provide refreshments at an upcoming meeting or present at an upcoming meeting, please contact me.


Our next meeting announcement will be sent out next Tuesday.


Let me know if you have any questions prior to the meeting.

WF Error When Missing Assigned To

The Error


I recently came across some strange errors which caused me to lose a lot of time on and could not find anything on. I had a Publishing with a WF Workflow and I was getting errors like this whenever I would access my page after initiating the workflow.


Application error when access /_layouts/Workflow.aspx, Error=Object reference not set to an instance of an object. at Microsoft.SharePoint.Publishing.Internal.WorkflowUtilities.GetIsTaskAssignedToUserOrGroup(CachedWorkflowTask task, Int32 userId) at Microsoft.SharePoint.Publishing.Internal.WorkflowUtilities.GetCurrentUserApprovalTask(CachedListItem listItem) at Microsoft.SharePoint.Publishing.Internal.WorkflowUtilities.IsApprovalWorkflowTaskActiveForUser(CachedListItem listItem) at Microsoft.SharePoint.Publishing.WebControls.ConsoleNode.CurrentState(Page currentPage, Boolean cacheResult) at Microsoft.SharePoint.Publishing.WebControls.ConsoleNode.CurrentState(Page currentPage) at Microsoft.SharePoint.Publishing.WebControls.ConsoleDataSource.PopulateDataSource() atMicrosoft.SharePoint.Publishing.WebControls.XmlConsoleDataSource.PopulateDataSource() at Microsoft.SharePoint.Publishing.WebControls.ConsoleDataSource.GetHierarchicalView(String viewPath) at Microsoft.SharePoint.Publishing.WebControls.PublishingSiteActionsMenuCustomizer.OnPreRender(EventArgs e) at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)


I was also seeing "unexpected" errors on SharePoint and in the logs I would find the following:


ERROR: request not found in the TrackedRequests. We might be creating and closing webs on different threads. ThreadId = 13, Free call stack = at Microsoft.SharePoint.SPRequestManager.Release(SPRequest request) at Microsoft.SharePoint.SPWeb.Invalidate() at Microsoft.SharePoint.SPWeb.Close() at Microsoft.SharePoint.SPSite.Close() at SourceCode.SharePoint.Common.SPObject.System.IDisposable.Dispose() at SourceCode.SharePoint.Workflow.Proxy.Common.GetK2IntegrationListItem(SPWorkflowActivationProperties properties) at SourceCode.SharePoint.Workflow.Proxy.MultipleTasksAndUsers.ActionK2WorkListItem(SPUser user, Boolean isFinished, String actionResult, String serialNr, String actionResponse, SPWorkflowTaskProperties afterProperties) at SourceCode.SharePoint.Workflow.Proxy.MultipleTasksAndUsers.OnTaskChanged_Event(Object sender, TaskEventArgs e) at System.Workflow.ComponentModel.Activity.RaiseGenericEvent[T](DependencyProperty dependencyEvent, Object sender, T e) at SourceCode.SharePoint.Workflow.ActivityLibrary.TaskActivity.onTaskChanged_Invoked(Object sender, ExternalDataEventArgs e) at System.Workflow.ComponentModel.Activity.RaiseGenericEvent[T](DependencyProperty dependencyEvent, Object sender, T e) at System.Workflow.Activities.HandleExternalEventActivity.RaiseEvent(Object[] args) at System.Workflow.Activities.HandleExternalEventActivity.Execute(ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.WorkflowComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) at System.Workflow.Runtime.Scheduler.Run() at System.Workflow.Runtime.WorkflowExecutor.RunScheduler() at System.Workflow.Runtime.WorkflowExecutor.RunSome(Object ignored) at System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService.WorkItem.Invoke(WorkflowSchedulerService service) at System.Workflow.Runtime.Hosting.DefaultWorkflowSchedulerService.QueueWorkerProcess(Object state) at System.Threading._ThreadPoolWaitCallback.WaitCallback_Context(Object state) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack) at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state) , Allocation call stack (if present) null


This was pretty frustrating because every time I would go to the publishing page I would get this error. However the minute that I cancel the workflow or finish by completing the tasks in the task list the error would go away and I could access the publishing page.


The Issue


I was able to narrow down the issue to the following scenario:

  • I had a Site with the Publishing Feature Turned on.
  • In the Pages Library I had it configured such that all content had to be approved.
  • I had configured a custom WF Workflow on Pages Library configured to "Start this workflow to approve publishing a major version of an item".

The issue was that even though the workflow could be started I would only get this error if I had it configured to "Start this workflow to approve publishing a major version of an item". I manually initiated the workflow I would not get the error.


What I found out is the Assigned To field in the task was missing! Now if you have an OOB Approval workflow or do something in SharePoint Designer it is impossible to create this error. However if you are writing a custom workflow in Visual Studio and do not set the Assigned To field in the task you will get this error.


This error will ONLY occur if you are using it for a Publishing Page too. I was able to run this same workflow with the exact configuration on a MS Word document and would not receive the error. I do not know exactly what to call this menu system (below) but you will see it when using publishing pages.



Basically when you have a workflow started when a major version is published, the WF workflow will be "daisy chained" into the approve/deny workflow that is turned on when you require content approval. This menu system is validating against the Assigned To field in the Task that is associated to the running workflow instance. If the Assigned To is blank, you will get the errors above when trying to access the page.


The Resolution


Make sure to set the Assigned To field of tasks being created for your workflows.

Deploy Publishing Page and IgnoreIfAlreadyExists

For a project I was working on, I wanted to do a deployment of a SharePoint publishing page through a WSP and a Feature. I found a few blogs that assisted with me getting this started. Creating the actual Feature was not too hard but I run into a few issues.

The following is the Feature that I created.

<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Id="64A687A4-B4DD-4742-8FE9-66191929D8BD"
Title="ML Demo KB Publishing Page Template"
Description="This feature will load the KB Publishing Page Template."
Version="1.0.0.0"
Scope="Site">
<ElementManifests>
<ElementManifest Location="Elements.xml"/>
<ElementFile Location="KBArticle.aspx"/>
</ElementManifests>
<ActivationDependencies>
<!--ML.Demo.KBMgt.WSS.CTypes-->
<ActivationDependency FeatureId="15A053C6-59DB-4a14-9CB6-3DB667634493" />
</ActivationDependencies>
</Feature>


<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="KBPageLayoutsModule" Url="_catalogs/masterpage" RootWebOnly="True" Path="">
<File Url="KBArticle.aspx" Name="KBArticle.aspx" IgnoreIfAlreadyExists="TRUE" Type="GhostableInLibrary">
<Property Name="Title" Value="KB Article"></Property>
<Property Name="ContentType" Value="KB Article"></Property>
<Property Name="PublishingAssociatedContentType" Value=";#KB Article;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F200
7948130EC3DB064584E219954237AF3900
242457EFB8B24247815D688C526CD44D00
DECC999E401842A08C5F380CB73E0191;#"
></Property>
</File>
</Module>
</Elements>

In this feature I am doing several things:

  • I am deploying to the Master Page Gallery because the Feature has Site scope, the Module Url is set to _catalogs/masterpage, File Type is set to GhostableInLibrary.
  • I have a Feature dependency on another Feature that is responsible for deploying a custom content type. I could have combined these all into one Feature however I like keeping them separate.
  • When creating the publishing page I simply created it through SharePoint Designer, I then viewed the code and copy and pasted it into an aspx within my solution in Visual Studio. I really do not want to rely on SharePoint Designer over the long term.
  • In the File element I specify Properties which are used to set values into the columns within the Master Page Gallery library. For instance I set the title and content type association for the publishing page.

Remember that if you cannot use Features to do a production deployment, you should really rethink your deployment and configuration management procedures for your SharePoint environment over the long run. Otherwise your environment will become a mess of one-off solutions with no way to redeploy solutions across development, quality assurance, staging and production. In this case I know I could have simply gone into the SharePoint user interface, manually create the content type and then associate a publishing page to the content type via SharePoint Designer – however that is not really that repeatable from a deployment perspective.

The first challenge I ran into was trying to understand how the IgnoreIfAlreadyExists attributed actually worked. According to the documentation on MSDN, if IgnoreIfAlreadyExists is set to TRUE, it will suppress any errors if the file has already been loaded into the Master Page Gallery and continue uploading. I found several blogs providing incorrect information claiming that the IgnoreIfAlreadyExists does not work as intended. My experience was it works. When I did the deployment the new Publishing page does get pushed up. I say this because I would look at pages that were referencing the publishing page and the changes would be reflected. HOWEVER the deceiving thing is if you look at the entry in the Master Page Gallery, neither the time date stamp nor version will be updated making you think that the change was not applied.

Another interesting thing was if you deactivate this Feature the publishing aspx page will remain in the Master Page Gallery even if the publishing page is not being referenced anywhere. I had initially assumed SharePoint was keeping the publishing page there because it is not possible to delete a publishing page it is referenced. The only way you remove the publishing page is to create a Feature event handler for ondeactivation to delete it manually from the Master Page Gallery. Remember if you do this you can get an exception saying "This item cannot be deleted because it is still referenced by other pages" if the publishing page is being used anywhere.

Another issue I ran into was trying to update the properties of the publishing page in the Master Page Gallery. No matter what I do, if I change the file properties in the Feature, the changes would not take be visible in the Master Page Gallery. This is some related to the first issue I had. Anyways, I determined the only way to update the entry the Master Page Gallery is to put an onactivation event handlers onto the Feature.

References: