Skip to content

Workflow Webhook attribute mappings stop resolving after any save on v19 #6992

Description

@azturner

Description

Saving a Workflow Webhook defined value through the v19 admin UI stores its WorkflowAttributes mapping URL-encoded. LaunchWorkflow.ashx never decodes it, so every mapping in that webhook silently stops resolving — the launched workflow receives the literal template text instead of the value.

The admin UI continues to display the mapping correctly, because the field type's read path decodes what its write path encoded. Only the webhook handler sees the encoded bytes. There is no error, no exception, and nothing written to ~/App_Data/Logs/LaunchWorkflow.txt.

KeyValueListFieldType has two save paths that write two different on-disk formats.

Rock/Field/Types/KeyValueListFieldType.cs — WebForms path (GetEditValue) passes the value through untouched:

public override string GetEditValue( Control control, Dictionary<string, ConfigurationValue> configurationValues )
{
    var picker = control as KeyValueList;
    if ( picker != null )
    {
        return picker.Value;
    }

    return null;
}

Same file — Obsidian path (GetPrivateEditValue) URL-encodes both halves of every pair:

return values.Select( v => $"{HttpUtility.UrlEncode( v.Key )}^{HttpUtility.UrlEncode( v.Value )}" )
    .JoinStrings( "|" );

So Body^{{ RawBody }} is stored verbatim by one editor and as Body^%7b%7b+RawBody+%7d%7d by the other.

The consumer never decodes. RockWeb/Webhooks/LaunchWorkflow.ashxPopulateWorkflowAttributes:

string workflowAttributes = hook.GetAttributeValue( "WorkflowAttributes" );
string[] attributes = workflowAttributes.Split( '|' );
foreach ( string attribute in attributes )
{
    if ( attribute.Contains( '^' ) )
    {
        string[] settings = attribute.Split( '^' );
        workflow.SetAttributeValue( settings[0], settings[1].ResolveMergeFields( mergeFields ) );
    }
}

ResolveMergeFields receives %7b%7b+RawBody+%7d%7d, finds no {{, and returns it unchanged.

Actual Behavior

The mapped workflow attribute holds the URL-encoded template text:

%7b%7b+RawBody+%7d%7d

That is {{ RawBody }} with {%7b, }%7d, and spaces → +, i.e. HttpUtility.UrlEncode.

The workflow launches normally and reports success. Opening the webhook's defined value in the admin UI shows {{ RawBody }}, correctly, giving no indication anything is wrong.

Expected Behavior

The mapped attribute holds the resolved value — the request body, in this example — as it does on v18 and as the admin UI implies.

More generally: PopulateWorkflowAttributes should read the same format the field type writes. Every other consumer of a KeyValueList value UrlDecodes each half; this one does not.

Steps to Reproduce

  • Go to Admin Tools > Settings > General > Defined Types > Workflow Webhook (defined type Guid 7B39BA6A-E7EF-48A6-9EC7-4A0F498D8FDB)
  • Add or edit a defined value. Set Process Request to True and pick any workflow type that has a text attribute keyed Body
  • Set Workflow Attributes to Body^{{ RawBody }} and save
  • POST any JSON payload to ~/Webhooks/LaunchWorkflow.ashx
  • Open the launched workflow and inspect its Body attribute — it holds %7b%7b+RawBody+%7d%7d rather than the payload
  • Reopen the defined value in the admin UI and note that it still displays {{ RawBody }}

To see the stored bytes directly:

SELECT dv.[Value] AS Hook, ft.[Class] AS FieldType, av.[Value] AS StoredValue
FROM AttributeValue av
  JOIN Attribute    a  ON a.Id  = av.AttributeId
  JOIN FieldType    ft ON ft.Id = a.FieldTypeId
  JOIN DefinedValue dv ON dv.Id = av.EntityId
  JOIN DefinedType  dt ON dt.Id = dv.DefinedTypeId
WHERE dt.[Guid] = '7B39BA6A-E7EF-48A6-9EC7-4A0F498D8FDB'
  AND a.[Key] = 'WorkflowAttributes';

Issue Confirmation

  • Perform a search on the Github Issues to see if your bug is already reported.
  • Reproduced the problem on a fresh install or on the demo site.

Rock Version

19.3

Client Culture Setting

en-US

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions