How to save workflow activity's setting into data base not in activityrecord's state filed ?

Topics: Customizing Orchard
Nov 20, 2014 at 3:02 AM

I want to write a activity like UserTask, But I want to save roles setting into database. But I can't find where to receive this trigger. I look in Orchard.Workflow.Control.AdminControl EditPost(). I can write code in the function. But it will produce upgrade problem.

How to do ?
Nov 20, 2014 at 5:09 AM
I'm afraid no events are exposed when it comes to persisting form values there.
One workaround I can think of is by implementing an ActionFilter, form which you "sniff" the request type (e.g. "POST"), the action name, controller name and area name.
If these value match "POST", "EditActivity", "Admin" and "Orchard.Roles", then you know the user updated an activity. You would then have to inspect the posted values further to see if it has anything to do with your activity.

One caveat though is this: the entire workflow definition (including the form state) is not persisted until the user clicks the "Save" button on the workflow editor screen. So if a user configures your activity, during which you save information to the database, but then the user decides to not save the workflow, you may end up with data in your database that is not associated with a workflow. That doesn't have to be a problem, but it is something you should be aware of.

Alternatively, you could apply the same "sniffing" technique, but against the "Edit" action, which executes when the user saves the workflow.
Nov 20, 2014 at 11:53 PM
Hi sfmskywalker

Thank you very much, it workable. But I have modified workflow module's AdminController. Original, will delete all activity and recreate new. It will make log unconsistent. And if there are waiting activity. The waiting workflow will be error. So I modify the function like below. It will check, if deleted activity there are
waiting activity. It will be notify error: So, I want to know the workflow is saved safely in actionfilter. How to do ?
    [HttpPost, ActionName("Edit")]
    public ActionResult EditPost(int id, string localId, string data) {
        if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to edit workflows")))
            return new HttpUnauthorizedResult();

        var workflowDefinitionRecord = _workflowDefinitionRecords.Get(id);

        if (workflowDefinitionRecord == null) {
            return HttpNotFound();

        workflowDefinitionRecord.Enabled = true;

        var state = FormParametersHelper.FromJsonString(data);
        var activitiesIndex = new Dictionary<string, ActivityRecord>();

        // Ezra Modified Start

        foreach (var activity in state.Activities) {
            ActivityRecord activityRecord;
            int activityId;

            if (!((string)activity.ClientId).Contains("jsPlumb") && 
                int.TryParse(((string)activity.ClientId).Split('_').Last(), out activityId))
                activityRecord = workflowDefinitionRecord.ActivityRecords.First(a => a.Id == activityId);

                activityRecord.X = activity.Left;
                activityRecord.Y = activity.Top;
                activityRecord.Start = activity.Start;
                activityRecord.State = FormParametersHelper.ToJsonString(activity.State);
                activityRecord = new ActivityRecord
                    Name = activity.Name,
                    X = activity.Left,
                    Y = activity.Top,
                    Start = activity.Start,
                    State = FormParametersHelper.ToJsonString(activity.State),
                    WorkflowDefinitionRecord = workflowDefinitionRecord
            activitiesIndex.Add((string)activity.ClientId, activityRecord);
        //Get deleted activities
        var delWaitingActivityRecords = from orgActivityRecord in workflowDefinitionRecord.ActivityRecords
                                         join newActivityRecord in activitiesIndex.Values.ToList() on
                                              orgActivityRecord.Id equals newActivityRecord.Id into joinActivityRecords
                                         from delActivityRecord in joinActivityRecords.DefaultIfEmpty()
                                         where delActivityRecord == null
                                         select orgActivityRecord;

        // Check deleted activities is awaiting activity
        delWaitingActivityRecords = from delActivityRecord in delWaitingActivityRecords
                                    join awaitingActivityRecord in _awaitingActivityRepository.Table.AsEnumerable()
                                    on delActivityRecord equals awaitingActivityRecord.ActivityRecord
                                    select delActivityRecord;
        if (delWaitingActivityRecords != null && delWaitingActivityRecords.Count() > 0)
            // Cancel current hibernet transaction
            Services.Notifier.Error(T("Can't delete {0} activity there are awaiting activity! ", delWaitingActivityRecords.ElementAt(0).Name));
            return RedirectToAction("Edit", new { id, localId });

        foreach(var activityRecord in activitiesIndex.Values)


        foreach (var connection in state.Connections) {
            workflowDefinitionRecord.TransitionRecords.Add(new TransitionRecord {
                SourceActivityRecord = activitiesIndex[(string)connection.SourceId],
                DestinationActivityRecord = activitiesIndex[(string)connection.TargetId],
                SourceEndpoint = connection.SourceEndpoint,
                WorkflowDefinitionRecord = workflowDefinitionRecord

        // Ezra Modified End 

        Services.Notifier.Information(T("Workflow saved successfully"));

        return RedirectToAction("Edit", new { id, localId });