LinkGenerator.GetPathByAction(...) doesn't resolves url for HttpWorkflowController.Invoke action
Describe the bug
LinkGenerator.GetPathByAction(...) and IUrlHelper.Action(...) doesn't resolves url for HttpWorkflowController.Invoke action when it get called from a script method ([js: workflowHttpEventUrlResolve(...)) while importing a recipe.
OrchardCore package version: 1.3.0
To Reproduce
Recipe:
{
...,
"steps": [
...,
{
"name": "WorkflowType",
"data": [
{
"WorkflowTypeId": "4adav53rhwvjkrvh48aesz3zxt",
"Name": "Competitor registration",
"IsEnabled": true,
"IsSingleton": false,
"LockTimeout": 0,
"LockExpiration": 0,
"DeleteFinishedWorkflows": false,
"Activities": [
{
"ActivityId": "45g5pkc6tpy86v71mdxq4685d8",
"Name": "HttpRequestEvent",
"X": 10,
"Y": 30,
"IsStart": true,
"Properties": {
"ActivityMetadata": {
"Title": "Registration request"
},
"HttpMethod": "POST",
"Url": ...,
"ValidateAntiforgeryToken": true,
"TokenLifeSpan": 0
}
},
...
],
...
}
]
},
{
"name": "content",
"data": [
...,
{
...,
"FlowPart": {
"Widgets": [
{
"ContentItemId": "46cjbawtdp6xd217ej85kb0emt",
"ContentItemVersionId": null,
"ContentType": "Form",
"DisplayText": null,
"Latest": false,
"Published": false,
"ModifiedUtc": "2022-05-12T19:00:59.783023Z",
"PublishedUtc": null,
"CreatedUtc": null,
"Owner": "",
"Author": "admin",
"TitlePart": {
"Title": null
},
"FormElementPart": {
"Id": null
},
"FormPart": {
"Action": "[js: workflowHttpEventUrlResolve('4adav53rhwvjkrvh48aesz3zxt', '45g5pkc6tpy86v71mdxq4685d8', 0)]",
"Method": "POST",
"WorkflowTypeId": null,
"EncType": "application/x-www-form-urlencoded",
"EnableAntiForgeryToken": true
},
"FlowPart": {
...
},
"FlowMetadata": {
"Alignment": 3,
"Size": 100
}
}
]
}
}
]
},
...
]
}
Method provider:
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using OrchardCore.Mvc.Core.Utilities;
using OrchardCore.Scripting;
using OrchardCore.Workflows.Http.Controllers;
using OrchardCore.Workflows.Http.Models;
using OrchardCore.Workflows.Services;
using System;
using System.Collections.Generic;
namespace Lombiq.Privacy.Samples.Scripting;
public class WorkflowHelperMethodProvider : IGlobalMethodProvider
{
private readonly GlobalMethod _workflowHttpEventUrlResolve;
public WorkflowHelperMethodProvider() =>
_workflowHttpEventUrlResolve = new GlobalMethod
{
Name = "workflowHttpEventUrlResolve",
Method = serviceProvider => (Func<string, string, int, object>)((workflowTypeId, activityId, tokenLifeSpan) =>
{
var securityTokenService = serviceProvider.GetRequiredService<ISecurityTokenService>();
var workflowTypeStore = serviceProvider.GetRequiredService<IWorkflowTypeStore>();
var linkGenerator = serviceProvider.GetRequiredService<LinkGenerator>();
var workflowType = workflowTypeStore.GetAsync(workflowTypeId).GetAwaiter().GetResult();
var token = securityTokenService.CreateToken(
new WorkflowPayload(workflowType.WorkflowTypeId, activityId),
TimeSpan.FromDays(
tokenLifeSpan == 0 ? HttpWorkflowController.NoExpiryTokenLifespan : tokenLifeSpan));
// LinkGenerator.GetPathByAction(...) and UrlHelper.Action(...) not resolves url for
// HttpWorkflowController.Invoke action.
// return $"/workflows/Invoke?token={Uri.EscapeDataString(token)}";
return linkGenerator.GetPathByAction(
nameof(HttpWorkflowController.Invoke),
typeof(HttpWorkflowController).ControllerName(),
new
{
Area = "OrchardCore.Workflows",
Token = token,
});
}),
};
public IEnumerable<GlobalMethod> GetMethods()
{
yield return _workflowHttpEventUrlResolve;
}
}
Expected behavior
LinkGenerator.GetPathByAction(...) or IUrlHelper.Action(...) resolves url for HttpWorkflowController.Invoke action.
@dministro I'm not sure how to repro this. I've tried with your code and it works for me on 1.3, 1.4 and on 1.5.0-preview-16970

created content item with url in a title:

here it is my recipe:
{
"name": "",
"displayName": "",
"description": "",
"author": "",
"website": "",
"version": "",
"issetuprecipe": false,
"categories": [],
"tags": [],
"steps": [
{
"name": "WorkflowType",
"data": [
{
"WorkflowTypeId": "4pap1mwj63xn51e3y82fqa1fx0",
"Name": "aaaExampleWorkflow",
"IsEnabled": true,
"IsSingleton": false,
"LockTimeout": 0,
"LockExpiration": 0,
"DeleteFinishedWorkflows": true,
"Activities": [
{
"ActivityId": "46vh4c3e5jz1r04hjerrz90z4k",
"Name": "HttpRequestEvent",
"X": 0,
"Y": 0,
"IsStart": true,
"Properties": {
"ActivityMetadata": {
"Title": null
},
"HttpMethod": "GET",
"Url": "/workflows/Invoke?token=CfDJ8Eccv2rzJ8pOsQGIv-oI-6fUFuJouSlcTPMs58mBli1zlfploesICiK-X4GWNyXfcGXOe-MbYU4AJBPA02r_p0Bzo8RkWw2ZZRpimE6ixIsynom221dxC_vkrp7Zddf1_d1AUlVLPoMoXZ2Fgd7D5bLJinWE0BcOStcSad89ngXV-p6mSig4D3gKeNSwDPZwn4NixKqkLQQRCp4hBcBJ8bO73VoC4nlinodPAPVZd0Tv",
"ValidateAntiforgeryToken": false,
"TokenLifeSpan": 0
}
},
{
"ActivityId": "4zfrfnr48k20b0jafqtyx6955p",
"Name": "HttpResponseTask",
"X": 780,
"Y": 10,
"IsStart": false,
"Properties": {
"ActivityMetadata": {
"Title": null
},
"HttpStatusCode": 200,
"Content": {
"Expression": "{\r\n\"test\" : \"test\"\r\n}"
},
"ContentType": {
"Expression": "application/json"
},
"Headers": {
"Expression": null
}
}
}
],
"Transitions": [
{
"Id": 0,
"SourceActivityId": "46vh4c3e5jz1r04hjerrz90z4k",
"SourceOutcomeName": "Done",
"DestinationActivityId": "4zfrfnr48k20b0jafqtyx6955p"
}
]
}
]
},
{
"name": "content",
"data": [
{
"ContentItemId": "4txsyef64x9cxx8vms9mf72xxx",
"ContentItemVersionId": "4y6mj2redzw2m0sgrvrn3vnyyy",
"ContentType": "Test",
"DisplayText": "[js: workflowHttpEventUrlResolve('4pap1mwj63xn51e3y82fqa1fx0', '46vh4c3e5jz1r04hjerrz90z4k', 0)]",
"Latest": true,
"Published": true,
"ModifiedUtc": "[js: new Date().toISOString()]",
"PublishedUtc": "[js: new Date().toISOString()]",
"CreatedUtc": "[js: new Date().toISOString()]",
"Owner": "4hyjxygx5h8ekzjh2pbw6mgjnk",
"Author": "dawid",
"Test": {}
}
]
}
]
}
@lampersky I'll check this again.
One more important piece of info, I called workflowHttpEventUrlResolve from a setup recipe.
@lampersky I'll check this again.
One more important piece of info, I called
workflowHttpEventUrlResolvefrom a setup recipe.
really important, I've checked all possible ways of running recipe, but not from setup, will check
@dministro how did you registered your WorkflowHelperMethodProvider to use it within RecipeExecutor?
as far as I know, RecipeExecutor (from SetupService.cs) has very limited access to some basic providers like:
- ParametersMethodProvider,
- ConfigurationMethodProvider,
- VariablesMethodProvider.
So, I doubt "workflowHttpEventUrlResolve" was called from startup recipe.
You are right, this issue was 5 months before, I remembered wrong.
Sorry for this.
I'll check this again and let you know.
Any news @dministro?
I can reproduce this with the code(see: https://github.com/OrchardCMS/OrchardCore/issues/11764#issuecomment-1246882597) provided by @lampersky in my environment. I need more time to check and give information about the context to reproduce.
It seems that this issue didn't really move for quite a while. Is this something you'd like to revisit any time soon or should we close? Please reply.
Closing this issue because it has been stale for very long. If you think this is still relevant, feel free to reopen it.