Redirect to custom "Thank you" page based on answers.
Umbraco Forms 4.3.2
I'm trying to add a custom workflow that redirects to a custom page based on submitted answers but I have hit a wall.
When implementing a custom workflow from the WorkflowType base class the appropriate method to override is
public override WorkflowExecutionStatus Execute(Record record, RecordEventArgs e)
As you can see the return type is WorkflowExecutionStatus however if I want to use Response.Redirect(url) then I cannot possibly return a result since that method aborts the current thread throwing a ThreadAbortException.
Theoretically I could maybe use Response.RedirectToRoute() but I have no idea how I would find the route to the picked "Thank you" page.
I cannot find any documentation on how to do this and there doesn't seem to be an implementation in the source (Yes I know, bad James, but make the docs better.) despite there being a redirect workflow available in the back office.
Any ideas how I would implement this?
Additionally I will add, adding a macro or custom code to the "Thank you" page is definitely a no-no since that would be an enormous hack which you should be ashamed of for thinking up.
You should rather implement a doctype that varies. Point to it as the "thank you" page. In it, have ie. some nested content with a predicate and a new URL or some content.
In a RenderMvcController, template or child-controller, access TempData["RecordId"] to get the posted record id, and check your predicates against it.
Makes sense?
Here's a snippet I use in the response view for some fancy Forms logic. You could change it from returning stuff to doing the redirect. Or make it return the content you want to show.
public static List<ScoreResult> Fetch(ViewContext context)
{
if (context == null || context.TempData == null)
throw new Exception("Invalid controller context or session state");
Guid recordId = Guid.Empty;
if (context.TempData.ContainsKey("Forms_Current_Record_id"))
recordId = (Guid)context.TempData["Forms_Current_Record_id"];
var record = context.ViewData["Record"] as Record;
if (recordId == Guid.Empty && record != null)
{
recordId = record.UniqueId;
}
// TODO: Refactor everything and abstract cache
var resultCacheKey = "Result_" + recordId;
if (HttpContext.Current != null && HttpContext.Current.Items.Contains(resultCacheKey))
{
return (List<ScoreResult>) HttpContext.Current.Items[resultCacheKey];
}
if (record == null && recordId != Guid.Empty)
{
var recordStorage = new RecordStorage(ApplicationContext.Current.DatabaseContext);
record = recordStorage.GetRecordByUniqueId(recordId);
}
if (record == null)
return new List<ScoreResult>();
Dictionary<Guid, string> recordData;
if (record.RecordData != null)
recordData = JsonConvert.DeserializeObject<Dictionary<Guid, string>>(record.RecordData);
else
recordData = record.RecordFields.ToDictionary(f => f.Key, f => f.Value.ValuesAsString());
var form = record.GetForm();
var workflowStorage = new WorkflowStorage();
var activeWorkFlows = workflowStorage.GetActiveWorkFlows(form, FormState.Submitted);
var settings = activeWorkFlows
.Where(wf => wf.Type is IWeightedResultsWorkflow)
.Where(wf => wf.Settings.ContainsKey("ResultField"))
.Select(wf => wf.Settings["ResultField"]);
var results = new List<ScoreResult>();
foreach (var key in settings)
{
Guid fieldId;
if (!Guid.TryParse(key, out fieldId))
continue;
if (!recordData.ContainsKey(fieldId))
continue;
var resultValue = recordData[fieldId];
var result = JsonConvert.DeserializeObject<ScoreResult>(context.HttpContext.Server.UrlDecode(resultValue ?? ""), SerializationOptions.Options);
if (result != null)
{
results.Add(result);
}
}
if (HttpContext.Current != null)
{
HttpContext.Current.Items.Add(resultCacheKey, results);
}
return results;
}
If the editors / customers have access to forms and workflows, there's no way you can guarantee they add the "thank-you" workflow last. If they don't, it'll redirect before all workflows have executed. You also have the option of running workflows asynchronously, and then the Response.Redirect would probably throw.
If you don't mind the above, you could probably go like so in the workflow:
Redirect to custom "Thank you" page based on answers.
Umbraco Forms 4.3.2
I'm trying to add a custom workflow that redirects to a custom page based on submitted answers but I have hit a wall.
When implementing a custom workflow from the
WorkflowType
base class the appropriate method to override isAs you can see the return type is
WorkflowExecutionStatus
however if I want to useResponse.Redirect(url)
then I cannot possibly return a result since that method aborts the current thread throwing aThreadAbortException
.Theoretically I could maybe use
Response.RedirectToRoute()
but I have no idea how I would find the route to the picked "Thank you" page.I cannot find any documentation on how to do this and there doesn't seem to be an implementation in the source (Yes I know, bad James, but make the docs better.) despite there being a redirect workflow available in the back office.
Any ideas how I would implement this?
Additionally I will add, adding a macro or custom code to the "Thank you" page is definitely a no-no since that would be an enormous hack which you should be ashamed of for thinking up.
Cheers
James
You should rather implement a doctype that varies. Point to it as the "thank you" page. In it, have ie. some nested content with a predicate and a new URL or some content.
In a
RenderMvcController
, template or child-controller, access TempData["RecordId"] to get the posted record id, and check your predicates against it.Makes sense?
Here's a snippet I use in the response view for some fancy Forms logic. You could change it from returning stuff to doing the redirect. Or make it return the content you want to show.
Hi Lars,
Thanks for the code sample and workflow process. I'll probably end up doing something similar
I feel like this should be possible within Workflow though. It's the correct place for it and how does the original exists if it isn't?
If the editors / customers have access to forms and workflows, there's no way you can guarantee they add the "thank-you" workflow last. If they don't, it'll redirect before all workflows have executed. You also have the option of running workflows asynchronously, and then the Response.Redirect would probably throw.
If you don't mind the above, you could probably go like so in the workflow:
Just for anyone coming across this I don't think you can run Workflows asynchronously in Umbraco Forms 8
is working on a reply...