This article explains how to create an activity with a ‘placeholder’ destination user for scenarios where the destination user for an activity is not known at design-time - or when users need to ‘pull’ items from a shared Worklist.

It may happen that the destination user for an activity is not known at design-time. By design, K2.net™ will not allow a process to be exported if there are client events within an activity, but no destination rules to couple with these client events.

One solution for this scenario would be to create a ‘ghost’ user and set the ‘ghost’ user as the destination user for the activity. You would then use custom code within your application to connect as the ‘ghost’ user and then redirect the Worklist item to the current user.

This may be compared to users ‘pulling’ work from a shared Worklist, instead of the normal K2.net™ behaviour of ‘pushing’ worklist items onto users/groups.

Note: This solution only caters for instances where the activity slots for the activity are limited to one slot.

The following procedure may be followed to achieve this functionality:

1.  Create a user account in Active Directory that represents a ‘ghost’ user.
2.  In K2.net Studio, set the Destination Rule for the activity to point to the ‘ghost’ user created in step 1.
3.  Create a page/function/sub within your application which retrieves Worklist items for the ‘ghost’ user. Typically, this page/function/sub would perform the following actions:
  a.  Open a connection to the K2.net™ Server using the ‘ghost’ user’s credentials.
  b.  Obtain the first item in the ‘ghost’ user’s Worklist, taking into consideration factors such as process name, folio name or start date to return the correct item.
  c.  Redirect the Worklist item to the current user.
  d.  Do a Response.Redirect() or similar function in your code to open the Worklist item as the current user.

The following is sample code for a web-based ASP.NET form which demonstrates the steps a - d:

C#

if (!Page.IsPostBack)
{
  string FoundItem = string.Empty;

  // Open the connection as the ‘ghost’ user (the destination user you specified for the activity in K2 Studio)
  // Note: replace the values , , and
  // with the correct values for your environment
  SourceCode.K2ROM.Connection MyConn = new SourceCode.K2ROM.Connection();
  MyConn.Open("MyServerName", "domain,GhostUser,password");

  try
  {
    // Ensure that only the items for the desired process are returned
    // Note: you may do some further processing to filter the worklist items returned
    // In this example, only the activities from the project MyProject and its process MyProcess
    // will be returned
    // Note: replace the values with the correct values for your environment
    WorklistCriteria MyCriteria = new WorklistCriteria();
    MyCriteria.AddFilterField(WCField.ProcessFullName, WCCompare.Equal, @"MyProject\MyProcess");

    // Make sure the oldest item is picked up first
    MyCriteria.AddSortField(WCField.EventStartDate, WCSortOrder.Ascending);

    // Open the ‘ghost’ user’s worklist
    Worklist CurrentWorklist = MyConn.OpenWorklist(MyCriteria);

    // If an item is found, choose the first one.
    if (CurrentWorklist.Count > 0)
    {
      CurrentWorklist[0].Redirect(this.Page.User.Identity.Name);
      FoundItem = CurrentWorklist[0].Data;
    }
  }
  finally
  {
    // Close the connection, regardless of whether there was an error.
    MyConn.Close();
  }

  if (!FoundItem.Equals(String.Empty))
  {
    // Redirect to the item,
    Response.Redirect(FoundItem);
  }
}

Visual Basic

If Not Page.IsPostBack Then
  Dim FoundItem As String = String.Empty

  ' Open the connection as the ghost user (the destination user you specified for the activity in K2 Studio)
  ' Note: replace the values , , and
  ' with the correct values for your environment
  Dim MyConn As New SourceCode.K2ROM.Connection
  MyConn.Open("MyServerName", "domain,GhostUser,password")

  Try
    ' Ensure that only the items for the desired process are returned
    ' Note: you may do some further processing to filter the worklist items returned
    ' In this example, only the activities from the project MyProject and its process MyProcess
    ' will be returned
    ' Note: replace the values with the correct values for your environment
    Dim MyCriteria As New WorklistCriteria
    MyCriteria.AddFilterField(WCField.ProcessFullName, WCCompare.Equal, "MyProject\MyProcess")

    ' Make sure the oldest item is picked up first
    MyCriteria.AddSortField(WCField.EventStartDate, WCSortOrder.Ascending)

    ' Open the ghost users worklist
    Dim CurrentWorklist As Worklist = MyConn.OpenWorklist(MyCriteria)

    ' If an item is found, choose the first one.
    If CurrentWorklist.Count > 0 Then
      CurrentWorklist(0).Redirect(Me.Page.User.Identity.Name)
      FoundItem = CurrentWorklist(0).Data
    End If
  Finally
    ' Close the connection, regardless of whether there was an error.
    MyConn.Close()
  End Try

  If Not FoundItem.Equals(String.Empty) Then
    ' Redirect to the item,
    Response.Redirect(FoundItem)
  End If
End If