Tuesday, September 16, 2008

How to start workflow programmatically

Hi All,

Sometimes i wonder about the Workflow triggering technique from the List and Document Library. I wonder because of one observation.

Let me share it with you, when you attach the workflow to a list or document library we have an option to configure it that when to trigger, is it on adding of the new item or is it on Updating the item. Adding a new item is a one time job, so for this scenario, it looks perfect for me.

But, when i consider trigger when updating item, it is something that i do not think this is done properly.

Because Once you open the ListItem for edit, do not edit anything and press OK. What happens, Still Workflow Triggers.

Now the question is, is it really cool to trigger the workflow even if you have not made any changes???????? I do not think so...


So bottom line is to check the proper condition in code and then dynamically from code, trigger the workflow.

Here is a way to trigger the workflow from code.

First you need to take the SPWorkflowManager Object.

SPWorkflowManager objWorkflowManager = null;


Then use SPWorkflowAssociationCollection object. every List and Document library has association with the workflow, to get this we have to use this object to collect all workflows which are associated with the List or DocumentLibrary.

SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;

I consider that i am using Event Handler, if you are using this code anywhere else, change the Web and Site objects accordingly.


We have WorkflowManager object at Site Level, so first we will take it.

objWorkflowManager = item.Web.Site.WorkflowManager;


Then we will take all association of the workflow for specific list.

objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;


Now consider a scenario, where you have multiple workflows associated with the same list or document library. So First we need to find the correct Workflow Association to trigger only that workflow.

So for that first Loop through all Associations,

foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)

{
if (String.Compare(objWorkflowAssociation.BaseId.ToString("B"), {"Workflow_GUID"}, true) == 0)

{

//We found our workflow association that we want to trigger.

//Replace the workflow_GUID with the GUID of the workflow feature that you
//have deployed.

objWorkflowManager.StartWorkflow(item, objWorkflowAssociation, objWorkflowAssociation.AssociationData, true);
//The above line will start the workflow...
break;
}
}


That's it. your job is done.

30 comments:

Gutha said...

Hi Malay,

I'm using your code as a reference to start a workflow manually.

Below is my code..

web.AllowUnsafeUpdates = true;
SPList list = web.Lists["EmailTest"];
SPListItem item = list.Items.Add();
item["Title"] = TextBox1.Text;
item.Update();

Guid wfBaseId = new Guid("{C7EF10FF-6090-46BE-A396-953761AAD3CA}");
SPWorkflowAssociation associationTemplate= list.WorkflowAssociations.GetAssociationByBaseID(wfBaseId);
site.WorkflowManager.StartWorkflow(item, associationTemplate, associationTemplate.AssociationData, true);

It's throwing an error during runtime at StartWorkfow.. The error is..

An exception of type 'Microsoft.SharePoint.SPException' occurred in Microsoft.SharePoint.dll but was not handled in user code

Additional information: Exception from HRESULT: 0x8102009B

Srikanth said...

Hi Malay,

I'm using your code as a reference to start a workflow manually.

Below is my code..

web.AllowUnsafeUpdates = true;
SPList list = web.Lists["EmailTest"];
SPListItem item = list.Items.Add();
item["Title"] = TextBox1.Text;
item.Update();

Guid wfBaseId = new Guid("{C7EF10FF-6090-46BE-A396-953761AAD3CA}");
SPWorkflowAssociation associationTemplate= list.WorkflowAssociations.GetAssociationByBaseID(wfBaseId);
site.WorkflowManager.StartWorkflow(item, associationTemplate, associationTemplate.AssociationData, true);

It's throwing an error during runtime at StartWorkfow.. The error is..

An exception of type 'Microsoft.SharePoint.SPException' occurred in Microsoft.SharePoint.dll but was not handled in user code

Additional information: Exception from HRESULT: 0x8102009B

Malay Vasavada said...

Hi Gutha,

Can you please try to catch SPException and check the Ex message what it gives you and then let me know, so that i can elaborate that Error in more specific way.

Does user has proper rights on that list in which workflow is attached?

Malay Vasavada said...

Hi Srikanth,

you can refer the same answer that i gave to Gutha as you have asked the same question.

Priyanka said...

Hi,

Nice post. I had a question though. can you please tell me where to place this code of starting the workflow. I mean my requirement is such that I got to start workflow on a particular date. I did try giving that date as "Start Workflow Date" which is an associated field with the item in the list, but it does not work. Any ideas?

Malay Vasavada said...

Hi Prinyanka,

That is good that post worked for you. Before answering your question, i would like to know that is the workflow start date is a column in the list or is that as a association page field for the workflow.

Because these are two different things which leads to two different answers.

Let me know so that i can get back to you as soon as possible.

Thank you

Malay Vasavada said...

Hi Priyanka,

I am sorry for misspelling your name in my previous reply.

Priyanka said...

Hi Malay,

Thanks for the reply. I have given reply before as well, but it doesn't seem to appear today. Anyways writing it up again. Workflow Start Date is the field in the library with which workflow is associated. I could not find anywhere a single idea by which you can start workflows based on some initial condition. However, I am now trying to make a custom timer job, and make it start my workflow. Lets see how successful I get in that. You have any other ideas by which I can start my workflow, irrespective of whether the item in the library is added or edited. My requirement is to start workflow on 2nd monday of every quarter. If I do put Workflow start date as the 2nd monday date for the item in the library, it doesn't help.

BTW, I have also passed out from the same college as yours!!

Malay Vasavada said...

Hi Priyanka,

You are on very correct track. you have to implement the custom timer job which you are creating.

This will solve your problem as well.

Let me know if you face any difficulty in this.

Regards,
Malay (SharepointKings)

Jayesh Prajapati said...

Hi priyanka,
for custom timer which will fire on every sencond monday for achive this task you dont need to add that on each list item, just you need to download

http://quartznet.sourceforge.net/

Quartz.net and understand it and configure it will work for you.though its too tought.

by using cronTrigger you can do this
see this...

http://quartznet.sourceforge.net/tutorial/lesson_6.html


Regards,
Jay (SharePointKings)

Priyanka said...

Hi,

Thanks Malay and Jayesh.

I was able to solve my problem. But I did it rather in a simple way. I created a library that would use the SP object model. I have a Workflow Start date associated with each item in a list. It checks if today matches with start date, if yes, it starts the workflow using WorkflowManager. Then I simply created a scheduled task for my library to run on every monday. Believe me its much simpler than creating a custom timer job.

cmpsfc said...

Hello there!
First, Nice post!

But i have one question. is there anyway to just VALIDATE workflow i created by Sharepoint Designer? Because, when i create other sites by my main sitetemplate this workflow NOT WORK! And i dont know why! So, to make it work i need to edit using SharePoint Designer again and just click on finish button.

I wanna know if i can do this job using custom webpart because my project have more than 3thousand web sites created. =S

(ps. sorry by my english. I'm learning yet)

Thanks anyway!
Cya!

Malay Vasavada said...

Hi,

Please clarify me with the requirement. I have certain questions. Are you not able to attach the workflow in your site? are you not able to complete the workflow? and how can a webpart act here in site?

do you want to attach the workflow in site? how did you deploy it?

Please let me know the details so that i can work on it.

cmpsfc said...

I'm sorry if my english is bad! =(

Well...
In my project there are 5 custom lists and workflows created. And all of it works just fine!
So i created sitetemplate! When i create another site using this site template one of that workflows just doesnt work. In order to make it work i need to edit this one in shrepoint designer and JUST CLICK on FINISH button (even if i do not change anything). I thing this validade, publish or somethingelse this workflow.

But this project is huge! There are more than 3.000 sites created on it!

In my first site (that i used to create a site template) all workflows are attached and works just fine, All workflows has been sucesfully completed too.

My idea is: i have more than 3.000 sites created and i need to "validade", "publish" or somenthingelse to make that workflows works. The same thing if i press finish button, but all programmatly instead open site on SPDesigner, open workflow, press finish button one-by-one...

I did almost the samething to disable search options on these custom lists like:

"foreach on ALL web sites{
foreeach on ALL custom lists{
list.NoCrawl = true;
}
}

Better now? =D

Thanks for your attention! =D

Filipe de Campos Cavalcante said...

HA! Another information about this issue! the status of job is "Failed to Start (retrying)"
And this is what found in log

12/11/2008 12:00:03.54 OWSTIMER.EXE (0x0A30) 0x0A68 Windows SharePoint Services Workflow Infrastructure 72fs Unexpected RunWorkflow: System.ArgumentException: Value does not fall within the expected range. at Microsoft.SharePoint.SPList.GetItemById(Int32 id, String strRootFolder, Boolean cacheRowsetAndId) at Microsoft.SharePoint.SPList.GetItemById(Int32 id) at Microsoft.SharePoint.Workflow.SPWorkflow.get_ParentItem() at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties.get_Item() at Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties..ctor(SPWorkflow workflow, Int32 runAsUserId, String associationData, String initiationData) at Microsoft.SharePoint.Workflow.SPWinOEWSSService.MakeActivation(SPWorkflow workflow, SPWorkflowEvent e) at Microsoft.SharePoint.Workflow.SPWinOeEngine.RunWorkflow(Guid trackingId, SPWorkflowHostService host, SPWorkflow workflow, Collecti...


Thx again!

Malay Vasavada said...

Hi,

Failed to Start (retrying) comes because of two reasons. Very first and important reason is there is something wrong with the code if you have written the code.

workflow does not gives you the exact clear picture to get the idea about the Exception and it gives you this message. Even if there is small mistake like workflowproperties are not assigned propoerly or taskpropoerties are not assigned propoerly.

this can happen also because of token not assigned to activity propoerly.

check all these possibility.

Let me know once you are done with this.

cmpsfc said...

And how can i see if this token is assigned to activity properly?
The workflow works just fine, cause since i dont have time enough to keep looking for any resolution i'm fixing this one by one (opening on SPDesigner, passing all steps and finish the wizard.) =S

Well, would u tell me how to manage that token programmatly i'll tank you!

Soon, i'll post on my blog something about this issue too and will say you and your blog as reference for the help and attention! =D

Thx again!

Ginni said...

Hi
I want to trigger a workflow on a particular date of every month. I am not getting how to do this. Can anyone help me?

Ginni said...

Hi
I want to trigger a workflow on a particular date of every month. I am not getting how to do this. Can anyone help me?

Ginni said...

Hi

I am using a SharePoint Library in which all the leaves of the employess are stored. I just want that at every 1 of every month, the number of leaves of every employee should get increased by 2. How can i achieve this by writing a workflow? I am not getting how to trigger a workflow on a particular date.

Jayesh Prajapati said...

hi Ginni,
if you are very good at c# so i would prefer you should go for Quartz framework which will accommodate your requirement and fire your code at specified time interval.. you can download it from
http://quartznet.sourceforge.net/
have look at it hope it will fulfill your requirement..

Regards,
SharePointKings

Lathama said...

hi malay and Gutha,


have you got solution for your quesiton actully i am also using the same code which you have use, but i have got the same exception which you got like

An exception of type 'Microsoft.SharePoint.SPException' occurred in Microsoft.SharePoint.dll but was not handled in user code

Additional information: Exception from HRESULT: 0x8102009B



My code is here

public void StartWorkFlow(int listItemID)
{
string approvalWorkFlowGUID = GetConfigSetting("ApprovalWorkFlowGUID");

try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite mySiteCollection = new SPSite(siteUrl))
{
using (SPWeb mySite = mySiteCollection.OpenWeb())
{
try
{
mySite.AllowUnsafeUpdates = true;
SPList oSPList = mySite.Lists[strProcessListName];

SPListItem oSpListItem = oSPList.GetItemById(listItemID);

Guid wfBaseId = new Guid(approvalWorkFlowGUID);

SPWorkflowAssociation associationTemplate = oSPList.WorkflowAssociations.GetAssociationByBaseID(wfBaseId);
mySiteCollection.WorkflowManager.StartWorkflow(oSpListItem, associationTemplate, associationTemplate.AssociationData);

oSpListItem.Update();
}
catch (Exception ex)
{
EventLog.LogError("iProcessUpdation - StartWorkFlow", ex.Message);
}


}
}
});
}

catch (Exception ex)
{
EventLog.LogError("iProcessUpdation - StartWorkFlow", ex.Message);
}


}


please some what urgent if you have any solution please share with me

Malay Vasavada said...

Hi Lathama,

Can you tell me at what line this Error is coming so that i can have more clear idea about this and i can look in to this

Vinay Bhatia said...

We were getting the error SPException reported by others above.

An exception of type 'Microsoft.SharePoint.SPException' occurred in Microsoft.SharePoint.dll but was not handled in user code

Additional information: Exception from HRESULT: 0x8102009B

It turned out to be permissions issue. The application which was starting the workflow programmatically was running under domain\user1. This account did not have permissions to the list item (we were programmatically removing permissions by breaking inheritance in another piece of code). Giving permissions to the account resolved it for us.

Priyanka said...

Hi Malay,

I am facing an error while at this line in my code: objWorkflowManager.StartWorkflow(photoItem, objWorkflowAssociation, objWorkflowAssociation.AssociationData);

Error is: Attempted to perform an unauthorized operation

I have enclosed the entire code in SPSecurity.RunWithElevatedPrivileges() and also all the SPWeb and other objects are declared within. Also I have made AllowUnsafeUpdates to true for the Web object. Additionally I do not face any problem when trying to start the workflow when logged in as system account or contributors to the website. The problem comes when I try starting logged in as a limited access account which is a visitor to the site. That is why am using RunWithElevatedPrivileges. My requirement is such that I cannot assign more permissions to this readonly account, but they should be able to start the workflow which is part of a request they make of the site. Am I missing anything. And other permissions or security I need to configure, any ideas please???

Malay Vasavada said...

Hi Priyanka,

Can you send me the more detailed code,so that i can more look in to that.

thanks.

pragna said...

Hi Malay,
I have taken refernce of this code, but i get "Value does not fall within the expected range" error.
This error comes at StartWorkflow and i get AssociationData parameter as NULL. Can this be the problem for the error.
How can i set the value for
AssociationData ???

thanks in advance.

Regards,
Pragna

Anonymous said...

Refer this post,to get more idea how you can run the wf programtically with full permissions.
http://sharepoint2010learnersworld.blogspot.com/2011/10/how-to-start-ninetex-workflow.html

agorlach said...

btw, here a freeware product to start workflow by schedule: http://www.harepoint.com/Products/HarePointWorkflowScheduler/Default.aspx

WBR, Alexnder

SharePoint Kings said...

@WBR, Alexnder,

thanks, its good but programmatic way more user full when so much customization where some field is something then start else not start kind of things

referred product also looks quite cool :)




Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com