So what happens when you’ve built out a SharePoint Designer workflow with a Pause Until Date activity, and then the date changes on you? Obviously, we want to the workflow to handle this situation and update the Delay logic accordingly.

Scenario

Let’s assume we have a Date Received column. After 2 weeks of initial item creation, we want to send a reminder notification to the user. So based on the value of Date Received column, add 14 days, and if Today matches that value, then send a notification. For this we need the Pause Until Date activity, so we do a quick evaluation, if there is a match, send the reminder, otherwise, pause until we reach that date.

  1. User enters Jan 13, 2012 in date received and creates new item.
  2. Workflow kicks off and determines that Jan 13, 2012 + 14 days is equal to Jan 27, 2012.
  3. Workflow checks if Today is equal to Jan 27, 2012. If it is, send the email reminder.
  4. If it isn’t, Pause Until Jan 27, 2012. You will see the pause activity log to the workflow history list the day it’s planning to pause until.

Perfect right, works great. Now what happens when a user edits the item and changes the date received to Jan 17, 2012. We want the delay to postpone until the 31st of Jan, not the 27th. I’ve read a great deal of posts that document how others have tackled this problem, ranging from an event handler to some sort of custom workflow logic. In our case, since the forms were custom ASP.NET forms submitting programmatically to the list, it was easy enough for me to track any changes to the date received column, and if I do find that it has changed, I simply stop and restart the workflow within the submit event. The logic looks like this:

// stop and restart the workflow if date received is different
if (dtcDateReceived.SelectedDate.ToShortDateString() != dateReceived.Value)
{
    // stop workflow
    SPWorkflowCollection itemWorkflowCollection= item.Workflows;
 
    SPWorkflowAssociation workflowAss = yearEnd.WorkflowAssociations[new Guid("369dcef7-b35c-48f1-bf2f-5b9f53d568ee")];
 
    foreach (SPWorkflow itemWorkflow in itemWorkflowCollection)
    {
        if (itemWorkflow.ParentAssociation.Id == workflowAss.Id && (itemWorkflow.InternalState & SPWorkflowState.Running) == SPWorkflowState.Running)
        {
            SPWorkflowManager.CancelWorkflow(itemWorkflow);
            site.WorkflowManager.StartWorkflow(item, workflowAss, workflowAss.AssociationData);
            break;
        }
    }
}

For completeness, this is how I set the hidden field on load that stores the original Date Received value.

// set date received to see if it changes
 dateReceived.Value = Convert.ToDateTime(yearEndItem["Date Received"]).ToShortDateString();

Thanks Tony for the original post that helped me build out the logic above:

http://www.tonytestasworld.com/post/Howto-Start-a-Sharepoint-Workflow-Programmatically.aspx

Tagged with:  

Ok I thought I’d post on this because it stumped me for close to 2 hours. So in my scenario, I have a WSS 3.0 installation with several SharePoint Designer workflows built. Many of these workflows use the Useful SharePoint Designer Custom Workflow Activities solution available on codeplex. After doing a migration from one server to another, I found that when I attempted to open up my workflows that contained those custom activities, I would get an error:

Failed to load workflow.

Really frustrating error because it gives you absolutely nothing to go on. I do want to mention that I also tried building a brand new workflow and selecting one of these custom workflow activities and the behavior was odd. If i tried to add one as an ACTION inside my workflow designer, nothing would happen. No error, but the activity wasn’t added to the step either. It was as if my click/selection had no effect.

So I made the decision to completely remove and reinstall the custom activities. The codeplex solution comes nicely packaged using the SharePoint Installer, so all I had to do was run a remove and then a reinstall. Normally, a final step to getting this working according to the InstallGuide.txt is to:

Go to Central Administration -> Application Management -> Manage Web Application Features and activate the feature for desired web applications (usually it’s Sharepoint – 80 or Sharepoint – 443).

The odd thing was that I found this step was already done for me and the solution was listed as already deployed. So back to SharePoint Designer I went, double clicked on the .xoml file, damn, same error! I found several blog posts indicating that I should clear the SharePoint Designer cache. So I closed down SD, deleted the folders starting with 12.x.x.x and loaded SD back up. I tried to open my xoml file, still no luck, same error.

At this point I was getting pretty confused. I manually did a check of the Assembly to make sure it contained the DP.SharePoint.Workflow dll, I double checked the Features folder to make sure it contained the DP.SharePoint.Workflow folder and I make sure the .ACTIONS file was contained within the Workflow folder and that the permissions on it were not wonky. I also verified the web.config contained the safe control entries for that dll. All looked good to me.

FINALLY, I decided to compare my web.config against the old server’s web.config to make sure that I wasn’t missing anything. I did a quick search on DP and found that the old web.config contained one more entry than my new web.config did:

1
<authorizedType Assembly="DP.Sharepoint.Workflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=0298457208daed83" Namespace="DP.Sharepoint.Workflow" TypeName="*" Authorized="True" />

So it would appear that I was missing this authorized type necessary for custom workflow activities. How or why this did not get added when I did my reinstall, I have no idea. But once that entry was added back, I was good to go again. My workflows open just fine without error.

I hope this helps someone else out there!

Tagged with:  

So this particular error seems to be quite common, based on posts I’ve read here and here. If you’ve built a SharePoint Designer workflow and utilized the Update List Item activity, you may have run into a workflow error that logs an Outcome of:

List Item Not Found

For this particular scenario, here was my setup:

  1. I have two lists: Survey and Customers
  2. Survey has a custom column called Customer that is of type Lookup. This column is configured to lookup on the Title column in Customers
  3. My custom SD workflow has a single activity, the Update List Item activity, configured to update the Customers list, on the Survey Status column, and the criteria for determining what item to update is based on the Customer lookup in the Survey list

Pretty straight forward stuff. I’ve done this a thousand times before and it’s worked without issue. However, I ran into a specific list where the workflow would error every single time, with the List Item Not Found message. Unfortunately, it’s very difficult to get any information other than what’s in the workflow history log. I attempted to read through the operations logs as well, but the information wasn’t really too helpful.

Doing some basic troubleshooting by adding an email activity and outputting the lookup variables in the body helped me determine that the Customer column in the Survey list was returning a blank value. That’s strange. Adding, editing and displaying items in the Customer list gives me no issue, I can select customers from my lookup and they read just fine. So why the heck does my workflow not properly record this value?

It gets a bit more puzzling when I grant myself Site Collection Administrator access to my site. Now all of a sudden, the workflow works and the lookup executes without issue. My entry in the Customers list is updated, all is happy for once. But granting users Site Collection Administration access is not a viable solution. It’s actually pretty crazy, so that’s not going to happen.

So after much frustration, I am sorry to report I don’t have much new information. What I did attempt to do however, was build my own version of the Update List Item activity in Visual Studio 2008. That turned out to be relatively straight forward. I used a bit of reflector to get the bits that I needed to successfully write this. That gave me the debugging capabilities that I desperately needed.

What I was now able to see with my custom activity was that the ListItem property was returning -1, and thus the GetItemById call on the Customers list was unable to find the item. Now why in the world was it returning -1? I’m still puzzled by this, and I’m not 100% sure if this is indeed a permissions related problem or if it’s something a entirely different.

I’m opening this up to anyone out there who might have some information regarding this particular issue. In the end, I wrote a custom Visual Studio sequential workflow, with literally 5 or so lines of code that essentially does the update for me and that runs without issue. I didn’t want to have to do that, but it was the only option I was left with for this particular list.

If anyone has any info, please drop me a line @ shereen at qumsieh dot ca. I would LOVE to get to the bottom of this.

Tagged with:  

I’ve been working over the past few days with a custom workflow I’m building in Visual Studio 2005 that’s responsible for notifying users when specific criteria was met. Inside the workflow, I have a few sendEmail functions responsible for building the content within the email message:

1
2
sendEmail1.Body += "<font face=\"Arial\">This is the body of my email.<br/><br/>";
sendEmail1.Body += "Adding some information for users that will describe some detail about this item.</font>";

The above worked well until I started to see some truncating in my emails. I did some comparisons and found that the truncating would occur when the character count exceeded 2048 characters. I figured this couldn’t be the limit for a string in .NET so I did a bit of digging around and finally discovered that the root of the issue was because I didn’t have any line breaks in my string: “\r\n”. Once I inserted those at specific intervals, the truncating disappeared.

Awesome! Hope this helps someone else out there.

Tagged with:  

Triggering SharePoint workflows programmatically from within a custom built Visual Studio workflow is not difficult once you know where to look. Tony Testa wrote a great post on this very same thing that describes these concepts in more detail than I will — so go check that out if you haven’t already. I had to tweak his concept a little bit because I was doing this within an already running workflow that belonged to a content type not a list.

So in my scenario, I had a single workflow tied to a Content Type, and because I knew there was only one workflow, I used index at 0 to get the current workflow association. If your workflow is tied to a list, then you may not need to call ContentType, you might be able to use:

1
SPWorkflowAssociation workflowAssociation = workflowProperties.List.WorkflowAssocations[0];

If you have multiple workflows tied to a Content Type or a List, you will need to grab the Guid associationId for that workflow instead of using the index.

Finally, once I have my workflow association configured, I can start my workflow by passing it the parameters it needs:

1
2
3
4
5
if (workflowProperties.Site.WorkflowManager.GetItemActiveWorkflows(setLeaderItem).Count == 0)
{
    SPWorkflowAssociation workflowAssociation = workflowProperties.Item.ContentType.WorkflowAssociations[0];
    workflowProperties.Site.WorkflowManager.StartWorkflow(setLeaderItem, workflowAssociation, workflowAssociation.AssociationData, true);
}

The IF block is there to check if any active workflow are running on that list item. If there aren’t, it attempts to start the workflow. There you have it! That should trigger the workflow on the list item you specified.

Tagged with:  

If you’re working with custom workflows, and you’ve run into a scenario where you have the login name of the user in the form of domain\juser but would like to see a more user friendly display name like Joe User then here’s how you do it:

What I usually do is create an SPUser object and then use the Name property to get at the display name of the user. Once I’ve got an SPUser object created, I have access to several different properties and methods. You can view the full list on msdn. The SiteUsers property will take in a string containing the login name of the user

SPUser user = workflowProperties.web.SiteUsers[string loginName];
string fullName = user.Name;
Tagged with: