Custom Actions: how to pass objects in Input and Output parameters

In custom actions it is possible to create input and/or output parameters of all the types displayed on the next picture.

custom_action_in_out_parameters

Despite the available parameters types cover most of all the needs we might face as developers, there may be some situations where it would be great if we could set a parameter as any other type. Well, in fact there is a work-around! The goal of this article is to outline how to achieve that.

Let us suppose that we have a custom action where there is the need to access a reporting server. The next class models an object where the data to access the reporting server may be set and get:

public class ReportServer
{
   public String Url { get; set; }
   public String UserDomain { get; set; }
   public String UserName { get; set; }
   public String UserPassord { get; set; }
}

In the action, instead of creating an input parameter for each ReportServer class property:

  • Create an input parameter named ReportServer string type which will be used to send into the action the ReportServer object serialized as a JSON string;
  • In a Code Activity, inside de action, then the ReportServer object is obtained, de-serializing the JSON string received in the input parameter.

To serialize the object into a JSON string and de-serialize the JSON string back to the object type, the next code may be used:

class JsonHelper
{
   internal static string JsonSerializer<T>(T t)
   {
      string jsonString = null;
      using (MemoryStream ms = new MemoryStream())
      {
         DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
         ser.WriteObject(ms, t);
         jsonString = Encoding.UTF8.GetString(ms.ToArray());
      }
      return jsonString;
   }

   internal static T JsonDeserialize<T>(string jsonString)
   {
      DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
      MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
      T obj = (T)ser.ReadObject(ms);
      return obj;
   }
}

When calling the action, set the input parameter with the ReportServer object as string:

// CALL ACTION
var reportServer = new ReportServer();
var request = new OrganizationRequest("new_Test");
request.Parameters.Add("ReportServer", JsonHelper.JsonSerializer<ReportServer>((reportServer)));
service.Execute(request);

Inside the action (Code Activity) the ReportServer object is rebuilt de-serializing the JSON string.

// Access the Input Parameter String Type Inside the ACTION CodeActivity
var reportServer = JsonHelper.JsonDeserialize<ReportServer>(ReportServer.Get<String>(context));

This approach is obviously valid for any class and for any type of its properties, since the class and its properties can be serialized. The example here described is for input parameters but for output parameters the process is the same.

In custom actions passing any type of object in input and/or output parameters can be achieved through a parameter string type which holds the object in a JSON string.

Leave a comment