Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have the following code running in a Visual Studio workflow. I am trying to specify the user who is adding list items in the code because I guess the system account (default for VS) will not allow declarative workflows to start. The declarative WF's are not started from this code but from "item updated" on the list. The WF errors out in SP with the following error:

Error in workflow! Object reference not set to an instance of an object.

        SPUser user = SPContext.Current.Web.AllUsers["wgl\\username"];
        SPUserToken token = user.UserToken;
        using (SPSite site = new SPSite(workflowProperties.SiteId, token))
        {
            using (SPWeb web = site.OpenWeb(workflowProperties.WebId))
            {
                SPList list = web.Lists["Approvals"];
                SPListItem item = list.Items.Add();
                item["Title"] = "ECO Approval";
                item["Approval Type"] = approvalType;
                item["Approver"] = workflowProperties.Item[approverColumn];
                item["ECO ID"] = workflowProperties.Item["ID"];
                item["ECO Number"] = web.Url + "/Lists/ECO/DispForm.aspx?ID=" + workflowProperties.ItemId + ", " + workflowProperties.ItemId;
                item.Update();
                SPWorkflowManager objWorkflowManager = null;
                SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;
                objWorkflowManager = item.Web.Site.WorkflowManager;
                objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;
                foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)
                {
                    SPWorkflow.CreateHistoryEvent(this.workflowProperties.List.ParentWeb, workflowId, 0, workflowProperties.OriginatorUser, TimeSpan.MinValue, "WorkFlow " + objWorkflowAssociation.Name, "WorkFlow " + objWorkflowAssociation.Name, "WorkFlow " + objWorkflowAssociation.Name);
                    if (objWorkflowAssociation.Name == "Approval Workflow")
                    {
                        site.WorkflowManager.StartWorkflow(item, objWorkflowAssociation, objWorkflowAssociation.AssociationData);
                    }
                }
            }
        }

The only thing that was changed was adding:

        SPUser user = SPContext.Current.Web.AllUsers["wgl\\switter"];
        SPUserToken token = user.UserToken;
        using (SPSite site = new SPSite(workflowProperties.SiteId, token))
share|improve this question
add comment

2 Answers 2

Workflows do not have an SPContext so SPContext.Current will always be null. In order to do what you appear to be trying to do, you may have to open the site once as the AppPool account to get the user token then release the site. Then open it again using the token like you are doing now. Something like this :

SPUserToken token = null;
using (SPSite site = new SPSite(workflowProperties.SiteId))
{
   token = site.RootWeb.GetUserToken("wgl\\username");
}

using (SPSite site = new SPSite(workflowProperties.SiteId, token))
{
   ... other code ...
}
share|improve this answer
    
thanks for the quick response! I am getting the error: 'Microsoft.SharePoint.SPWeb' does not contain a definition for 'GetUserToken' and no extension method 'GetUserToken' accepting a first argument of type 'Microsoft.SharePoint.SPWeb' could be found (are you missing a using directive or an assembly reference?) –  Steve W May 9 '12 at 22:30
    
The details are here : msdn.microsoft.com/en-us/library/… - Is this SharePoint 2007 or 2010? –  Dave Wise May 9 '12 at 22:35
    
sharepoint 2007 –  Steve W May 9 '12 at 22:37
    
That would explain it as that method is only in 2010. try this : msdn.microsoft.com/en-us/library/… –  Dave Wise May 9 '12 at 22:49
    
However, now that I look at the code, it appears that you are attempting to process an action as a specific user, which cannot be done without passing some form of authentication. Either you have to hard-code the user's ID and Password in the code or somehow force the process to run in a context that they have initiated and authenticated to –  Dave Wise May 9 '12 at 22:54
show 2 more comments

I nailed it thanks in large part to Dave! here is what I did:

    public void addApproval(string approvalType, string approverColumn)
    {
        SPSecurity.RunWithElevatedPrivileges(delegate()
        {
            //get the site owner token
            SPUser user = null;
            using (SPSite site1 = new SPSite(workflowProperties.SiteId))
            {
                user = site1.Owner;
            }
            SPUserToken token = user.UserToken;

            using (SPSite site = new SPSite(workflowProperties.SiteId, token))
            {
                using (SPWeb web = site.OpenWeb(workflowProperties.WebId))
                {
                    SPList list = web.Lists["Approvals"];
                    SPListItem item = list.Items.Add();
                    item["Title"] = "ECO Approval";
                    item["Approval Type"] = approvalType;
                    item["Approver"] = workflowProperties.Item[approverColumn];
                    item["ECO ID"] = workflowProperties.Item["ID"];
                    item["ECO Number"] = web.Url + "/Lists/ECO/DispForm.aspx?ID=" + workflowProperties.ItemId + ", " + workflowProperties.ItemId;
                    item.Update();
                    SPWorkflowManager objWorkflowManager = null;
                    SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;
                    objWorkflowManager = item.Web.Site.WorkflowManager;
                    objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;
                    foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)
                    {
                        SPWorkflow.CreateHistoryEvent(this.workflowProperties.List.ParentWeb, workflowId, 0, workflowProperties.OriginatorUser, TimeSpan.MinValue, "WorkFlow " + objWorkflowAssociation.Name, "WorkFlow " + objWorkflowAssociation.Name, "WorkFlow " + objWorkflowAssociation.Name);
                        if (objWorkflowAssociation.Name == "Approval Workflow")
                        {
                            site.WorkflowManager.StartWorkflow(item, objWorkflowAssociation, objWorkflowAssociation.AssociationData);
                        }
                    }
                }
            }
        });
    }

The list item now shows up as being created and modified by a user (owner) instead of the system account.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.