Returning The SharePoint Start Workflow Link

Building the “Start Workflow” link is pretty straight forward. I am pretty sure there are better ways to do it, but here is an approach when you have to build the link using a string return. How it works is pretty straightforward. Consuming a SPListItem and SPWorkflowAssociation parameter, the SPListItem exposes the ParentList and ID properties and the SPWorkflowAssociation provides the InstantiationUrl and Id properties. The only field level stuff is I was passing a finish url in the query string (_finalurl in the below). When the link is built, it is cleaned up using the inherent SPHttpUtility.UrlKeyValueEncode method.

[csharp]
private string _finalurl;

public static string QueryStringAppend(string url, string args)
{
if (string.IsNullOrEmpty(url))
{
return url;
}
var num = url.LastIndexOf(“?”);
switch (num)
{
case -1:
return (string.Format(“{0}?{1}”, url, args));
}
return num == (url.Length – 1) ? url + args : string.Format(“{0}&{1}”, url, args);
}

protected string BuildWorkflowStartLink(SPListItem listItem, SPWorkflowAssociation workflowAssociation)
{
var builder = new StringBuilder();
builder.Append(SPHttpUtility.UrlPathEncode(string.Format(“{0}/{1}”, Web.Url, workflowAssociation.InstantiationUrl), true));
builder.Append(“?List=”);
builder.Append(listItem.ParentList.ID.ToString());
builder.Append(“&ID=”);
builder.Append(listItem.ID.ToString());
builder.Append(“&TemplateID=”);
builder.Append(workflowAssociation.Id.ToString(“B”));
string url = _finalurl ?? Request.QueryString[“Source”];
url = QueryStringAppend(url, string.Format(“{0}={1}”, FinishIdName ?? “ID”, listItem.ID));
if (!string.IsNullOrEmpty(url))
{
builder.Append(“&Source=”);
builder.Append(SPHttpUtility.UrlKeyValueEncode(url));
}
return builder.ToString();
}
[/csharp]

:)

Share

Fault Handling In SharePoint Workflows

Handling faults in WorkFlows is an important concept to consider because sometimes a routine that your workflow is inherently calling will just fart out. It just happens, sucks, but happens. It happens with generic .NET development, it happens when building custom workflows. An error will occur with your workflow, bubble up, and it must be handled appropriately. Typically, within a workflow, as an exception occurs, you want to do generally do one of two things, either exit the workflow and clean-up the persistence, or attempt to keep the persistence of the workflow.

Since a majority of the default activities that you are offered with the workflow foundation are pretty worthless (I am being negative since I had a bad day with them), you are going to end up writing a bunch of your own custom WorkFlow activities, in which case this becomes very important. The activity execution might fail, in which case an exception will bubble which has to be handled.

So how does one go about handling these dreaded faults as they occur within your WorkFlow code, and more importantly, when creating custom activities that are going to be tapped within a custom workflow?

I do this through the use of the ISharePointService interface and by overriding the HandleFault method. This is a good way to handle faults as they occur within your workflow activities The ISharePointService interface is one of the 4 local communication interfaces that you are afforded tapping into. There are also the three other communication interfaces that you can exploit, namely, IListService, ITaskService, and IWorkflowModificationService.

You will also see the use of ActivityExecutionStatus.Closed. This is because the clean-up work that is required before the activity within this code is assumed, and therefore I can close the execution status of the activity. It is possible to as well use ActivityExecutionStatus.Faulting is

When the HandleFault execution handler is dispatched by the runtime, it is expected that the activity will perform any cleanup work that is required prior to its transition to the Closed state. If your clean up work is short, you can do that and return ActivityExecutionStatus.Closed. If it is long, then return ActivityExecutionStatus.Faulting and wait for the required callbacks before ultimately creturning Closed.

[csharp]

protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
{
((ISharePointService) executionContext.GetService(typeof(ISharePointService))).LogToHistoryList(base.WorkflowInstanceId, SPWorkflowHistoryEventType.WorkflowComment, 0, TimeSpan.MinValue, string.Empty, string.Format(“Your WorkFlow Farted!: {0}”, exception.Message), string.Empty);
return ActivityExecutionStatus.Closed;
}

[/csharp]

This is pretty simplistic, and not exceptionally impressive, however it is getting the job done for me and may save you some time while you are developing your custom WorkFlows :-).

Share