How to dynamically call an action in Outsystems, based on the eSpace name and Action name.

This post describes how to call an action in Outsystems, based on a given eSpace name and action name.

 

Lets says you want the user to select a action name from a dropdownlist and execute this action, then you can create a big switch statement to call the actions supplied in the dropdownlist, but if you don’t want to change this switch statement each time a new action is added to the list, then you have to create an Outsystems actions and write some C# code, to dynamically execute the action based on a given eSpace name and action name.

 

Extension

image

 

Visual Studio

image

 

C# code

namespace OutSystems.NssDynamicExtension {
using System;
using System.Collections;
using System.Data;
using OutSystems.HubEdition.RuntimePlatform;
using GotDotNet.ApplicationBlocks;
using System.Text;
using System.Linq;
using System.Reflection;
public class CssDynamicExtension: IssDynamicExtension {
/// <summary>
/// 
/// </summary>
/// <param name="ssresult"></param>
/// <param name="sseSpaceName"></param>
/// <param name="ssactionName"></param>
public void MssInvokeAction(out string ssresult, string sseSpaceName, string ssactionName) {
ssresult = string.Empty;
var messages = new StringBuilder(string.Empty);
try
{
// Get all assemblies in current AppDomain.
AppDomain currentDomain = AppDomain.CurrentDomain;
Assembly[] assemblies = currentDomain.GetAssemblies();
// Log all assemblynames.
assemblies.ToList()
.OrderBy(x => x.FullName).ToList()
.ForEach(x => { messages.AppendLine(x.GetName().Name); });
// Get eSpace assembly.
Assembly eSpaceAssemlby = assemblies.ToList()
.First(x => x.GetName().Name.Equals(sseSpaceName, StringComparison.InvariantCultureIgnoreCase));
// Get assembly that contians the "HeContext" type.
Assembly runtimePlatform = assemblies.ToList()
.First(x => x.GetName().Name.Equals("OutSystems.HubEdition.RuntimePlatform"));
// Get the type that contains all actions from an eSpace.
Type actionsType = eSpaceAssemlby.GetType(string.Format("ss{0}.Actions", sseSpaceName));
// Get "HeContext" type (curent HttpContext object).
Type contextType = runtimePlatform.GetType("OutSystems.HubEdition.RuntimePlatform.HeContext");
// Create an instance of the "HeContext" type.
object contextInstance = Activator.CreateInstance(contextType);
// Invoke the given action and supply as first parameter the "HeContext" (curent HttpContext) object.
actionsType.InvokeMember(string.Format("Action{0}", ssactionName), 
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, 
null, null, new object[] { contextInstance });
}
catch (Exception ex)
{
messages.AppendLine(ex.ToString());
}
ssresult = messages.ToString();
} // MssInvokeAction
} // CssDynamicExtension
} // OutSystems.NssDynamicExtension

 

Use the action in Outsystems

image

 

Result

image

 

The action that was dynamically invoked, inserted a record in the database and I could see this record was created, so everything worked just fine.

 

So instead of:

image

 

My code now looks like this:

 

image

 

 

Sometimes, reflection is your friend Smile.

2 Comments

  1. Rogier Kolstein

    I’m trying to dynamically call a screenaction… To call an action I don’t think you even need the HeContext. I pass in null for the heContext parameter and the method is called just fine. However, to call a screenaction (which does not start with “Action” but with “Method” and resides in the ModuleName + “Codebehind” assembly with namespace “ss” + ModuleName + “.Flows.FlowWizard.Scrn” + screenFlowName) you need the current HeContext I guess. I tried “var context = new HeContext(System.Web.HttpContext.Current);”, which would work fine in your example too, but unfortunately it doesn’t call the screenaction in the right HttpContext. It does call the ScreenAction… but just not in the right context. Do you have any ideas to call a screenaction from another screenaction? Many thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *