Run SharePoint Designer 2007 Workflows as System User


There’s quite a bit of documentation and confusion
around SharePoint Designer workflows and the context under which they
run.  I’d naively assumed that Workflows would run in the context of the
user that initiated the workflow, but with system user permissions.

The following offers some insight and an approach for certain people to follow
in the case they have email-enabled libraries:
http://blogs.technet.com/victorbutuza/archive/2009/03/14/workflows-do-not-start.aspx

This didn’t help me, as I’d got some ‘working’ workflows that, once tested with
a non-privileged user simply didn’t complete, as they hit permissions issues.

The specific issue was that these users have the ability to add into a list,
but not edit, delete or approve, as the entry into the list is via a complex
InfoPath form.  Workflow actions occur on addition to the list to route
the request to an appropriate approver, and kick of an escalation process.

It appears that SharePoint 2010 has a new Impersonate feature in Workflow, but hey – I’m
still using 2007, and am ‘specifically’ using SharePoint Designer (for business
compatibility purposes).  I’ve used a lot of third-party SPD Workflow actions
from Nick Grattan, I Love SharePoint, and wasn’t about to be beaten,
as I can currently do everything I need from SPD Workflows. 

I finally found a solution that did exactly what I needed).

Though vigorous googling, I found in the comments of the Useful
SharePoint Workflow Activities
, that people were complaining
that the ‘Start a Workflow‘ action was running the new workflow as the
system user.  Not me!  – that’s exactly what I need.

I downloaded and installed the activities, but had to apply another update to get them to work properly in
SharePoint Designer.

I now have a new ‘wrapper’ workflow, which is automatically called on ‘new
item’ to the list, and this calls the 2 existing workflows (now manually
started), that were previously set to be automatic. 

This has had an added benefit, in that the ordering of these workflows is now
consistent as one is called after the other.  The only thing to bear in
mind of course is whether this behaviour is what you want, based on your
situation.

Fixing SharePoint error: No item exists at [url]?ID=n. It may have been deleted or renamed by another user

Yesterday I was creating a page in SharePoint Designer and on testing got a server error:

No item exists at http://sharepointsite/WebPages/My-Page?ID=56.  It may have been deleted or renamed by another user.

I’d got code in the page that examined the ‘ID’ QueryString parameter and tried to load that item from a particular list.  This same code was working on another page.

This MSDN article described the problem,

This problem happens because Sharepoint has its own variable named ID 
which it uses to identify documents/pages on the server. Our solution 
should not be using a variable named ID.

I changed my QueryString parameter to RequestID instead and all was good, apart from the thought of why the other page still worked fine. 

I then realised that if it didn’t know what list it was trying to target, then the ‘List’ querystring parameter needs to be there too – as per other ‘application page’ requests in the _layouts folder, like approve/reject.

It then became obvious that I was doing too much work anyway:

Passing in the List as well as the ID allows you to then just get straight to the list item with the following code…

        SPListItem item = (SPListItem)SPContext.Current.Item;

as the List and ID are already taken care of.  A little neater than what I ‘was’ doing….

        SPListItem currentItem = null;

        //Get ID and List Item information
        requestList = SPContext.Current.Web.Lists["My List"];        
        if (requestList != null && Request.QueryString["ID"] != null)
        {
            if (int.TryParse(Request.QueryString["ID"].ToString(), out requestID))
            {
                //Get Item
                currentItem = requestList.GetItemById(requestID);


            }
            
        }

This code’s still fine (apart from the querystring ‘ID’ name) if you need to load an item from a list that you don’t know the guid for at the time.

Embedding InfoPath forms in SharePoint WebPart pages using the XmlFormView control

I recently needed to take a simple InfoPath form and surface that through a ‘themed’ SharePoint page.  It’s possible to load the form in a browser without needing a specific page, but this effectively eliminates your master page from the equation.

Nick Grattan wrote an excellent paper on using the XmlFormView control to contain InfoPath forms on SharePoint webpart pages.

This is all great until you then need to send in input parameters to the form.  I looked around for quite a while before I found the (rather obvious) Initialize event allows you to set the Input parameters of the form.  All other methods of loading the form (InfoPath client, FormServer.aspx) use a querystring-style format.

The following code should do the trick in the case where you’re passing information from a current ‘list item’ to the form:
 

    private SPList requestList = null;
    private int requestID;
    private SPListItem currentItem = null;

    protected void Page_Load(object sender, EventArgs e)
    {

        XmlformView1.Initialize    += XmlformView1_Initialize;
        //Get ID and List Item information (passed into this page)
        requestList = SPContext.Current.Web.Lists["My List"];        
        if (requestList != null && Request.QueryString["ID"] != null)
        {
            if (int.TryParse(Request.QueryString["ID"].ToString(), out requestID))
            {
                //Get Item
                currentItem = requestList.GetItemById(requestID);

                if (currentItem == null)
                    throw new ArgumentException("The specified ID does not exist");

            }
            
        }
        
    }

    protected void XmlformView1_Initialize(object sender, InitializeEventArgs e)
    {
        //Set input parameters for embedded Form
        e.InputParameters["foo"] = currentItem["foo"].ToString();
        e.InputParameters["bar"] = currentItem["bar"].ToString();

    }

I discovered that in order to write code in a WebPart page (using SharePoint Designer)
you’ll need to add a PageParserPath to the web.config as follows – otherwise you’ll get an error saying something like ‘code not allowed in this page’.  I’ve got a folder called ‘WebPages’ that houses the page.  The standard web.config already has the PageParserPaths element:

    <SafeMode MaxControls="200" CallStack="true" DirectFileDependencies="10" 
TotalFileDependencies="50" AllowPageLevelTrace="false">
<PageParserPaths>
    <PageParserPath VirtualPath="/WebPages/*" CompilationMode="Always"
AllowServerSideScript="true" IncludeSubFolders="true" />
</PageParserPaths>
</SafeMode>


NOTE:
If you’re showing/hiding the form based on a flag/checkbox etc in the page (I’m doing this), then make sure you wrap the XmlFormView in a container Panel/div that you show/hide server-side, rather than showing/hiding the XmlFormView itself.  For some reason this doesn’t seem to work properly (at least in FireFox).

Setup Single Sign-on for SharePoint 2007. The missing link

I need to use the SharePoint 2007 Single Sign-on service for the purposes of InfoPath Form authentication on Web Services.  I went through the Microsoft installation steps and immediately got

You do not have the rights to perform this operation.

A bit of googling later, and I found that this isn’t uncommon. 

Looking at Dave Wollerman’s post on the subject made me check everything again.

In the end the missing link (that I failed to read) from the Microsoft doc was simply that the Single Sign-on Windows service needed to be running with a domain account (I chose the same as the administrator accounts), and it then worked fine.