You are viewing limited content. For full access, please sign in.

Question

Question

Updating multi-value token breaks sdk script

asked on May 19, 2016

Good Afternoon,

I have a workflow that is showing some odd behavior when I am using the 'Assign Token Value' activity to modify a token value.  I've simplified my workflow in the illustration below.  

The problem I'm having is that when the path to modify token is taken, the SDK Script runs with error.  However when I run the process with the 'Retrieve field values' with 0 as the value, the SDK script runs correctly.  

My gut tells me that it has something to do with the modification of a multi-value token.  Essentially, what I want to do is nullify the token value(s) and pass 0/NULL to my SDK script.  If there is a better way to achieve this, please let me know.  

Thanks,

Nate

0 0

Replies

replied on May 19, 2016

What error are you getting? Why cant you pass another token with value zero when taken path is selected? In my opinion its better to use another token than to nullify it.

1 0
replied on May 20, 2016

Nate,

Is the token set up to be an integer? By default, when you create tokens they are strings:

1 0
replied on May 20, 2016

Glen,

I am not creating the token, I am modifying it.  Therefore, I am not seeing these options when modifying the token.  

Nate

0 0
replied on May 19, 2016

Junaid,

I am actually updating my token to be 0, when that path is taken.  When this path is taken, my script returns an error of 'Script threw exception' which is an error I have setup in my script.  The problem I have with this, is if I pass a 0 in the metadata (without updating the token) the script runs fine.  

The reason I cannot use another token, is because my script is looking at the 'Weight_All' token, so that is why I am trying to update it.  

0 0
replied on May 19, 2016

Can you post the script or a code sample showing the problem?

0 0
replied on May 20, 2016
namespace WorkflowActivity.Scripting.SDKScripttocallOptimiz
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Text;
    using ProTrans.Utilities;
    using Laserfiche.RepositoryAccess;
    using Newtonsoft.Json;
    using System.Net;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
    using System.IO;
    using Laserfiche;
    using System.Linq;

    [DataContract]
    public class DocumentReferenceTypeValueView
    {
        [DataMember]
        public string ReferenceType { get; set; }
        [DataMember]
        public string ReferenceValue { get; set; }
    }

    [DataContract]
    public class DocumentMetaDataView
    {
        [DataMember]
        public string PrimaryEntityType { get; set; }
        [DataMember]
        public string EntityKey { get; set; }
        [DataMember]
        public int ExternalDocumentId { get; set; }
        [DataMember]
        public string PrimaryDocumentType { get; set; }
        [DataMember]
        public string PrimaryDocumentTypeReference { get; set; }
        [DataMember]
        public ICollection<DocumentReferenceTypeValueView> SecondaryReferenceTypeValues { get; set; }
        [DataMember]
        public string LtlCarrierPro { get; set; }
        [DataMember]
        public ICollection<string> NmfcClassList { get; set; }
        [DataMember]
        public ICollection<Int32> PiecesList { get; set; }
        [DataMember]
        public ICollection<Int32> WeightList { get; set; }
    }

    public class ReturnWrapper
    {
        public ReturnPayload Message { get;set;}
    }

    public class ReturnPayload
    {
        public string message {get;set;}
        public string success { get;set;}
        public string trackingNumber { get;set;}
    }

    /// <summary>
    /// Provides one or more methods that can be run when the workflow scripting activity is performed.
    /// </summary>
    public class Script1 : RAScriptClass91
    {
        /// <summary>
        /// This method is run when the activity is performed.
        /// </summary>
        protected override void Execute()
        {
            try
            {
                // initialize things.. in the real flow the tokens would have been initialized

                #region Handling Units
                //This is work around code to handle the way LF populates the lists of objects in a free form.  NMFC seems to work normally as in the LF UI these values are prepopulated in a drop down list.

                //NMFC
                object[] nmfcListValues = GetTokenValue("RetrieveIntialFieldValuesfromQuickFields_NMFC Class_All") as object[];
                List<string> newNmfcList = new List<string>();
                for (int n=0; n<nmfcListValues.Length; n++)
                {
                    string nmfc = nmfcListValues[n].ToString();
                    newNmfcList.Add(nmfc);
                }

                //Pieces
                object[] piecesListValues = GetTokenValue("RetrieveIntialFieldValuesfromQuickFields_Pieces_All") as object[];
                List<int> newPiecesList = new List<int>();
                for (int p=0; p<piecesListValues.Length; p++)
                {
                    int pieces;
                    int.TryParse(piecesListValues[p].ToString(), out pieces);
                    newPiecesList.Add(pieces);
                }

                //Weight
                object[] weightListValues = GetTokenValue("RetrieveIntialFieldValuesfromQuickFields_Weight_All") as object[];
                List<int> newWeightList = new List<int>();
                for (int w=0; w<weightListValues.Length; w++)
                {
                    int weight;
                    int.TryParse(weightListValues[w].ToString(), out weight);
                    newWeightList.Add(weight);
                }
                #endregion

                SetTokenValue("scriptSuccess", "undetermined");
                SetTokenValue("ShipmentId", GetTokenValue("TransactionID").ToString()); //"0535761");
                SetTokenValue("DocumentEntryId", GetTokenValue("DocumentID").ToString());// "2272");
                SetTokenValue("DocumentType", GetTokenValue("Document Type").ToString());//BOL Code
                SetTokenValue("DocumentTypeReference", GetTokenValue("MasterPrimaryRefID_Primary Reference ID").ToString()); //"2933939");
                SetTokenValue("LtlCarrierPro", GetTokenValue("RetrieveIntialFieldValuesfromQuickFields_LTL Carrier Pro").ToString()); //"123456");

                // Write your code here. The BoundEntryInfo property will access the entry, RASession will get the Repository Access session
                var baseUrl = GetTokenValue("ServerUrl").ToString();  //"http://10.1.3.156:83";
                var hashedPassword = GetTokenValue("ServerUserPassword").ToString().ToMD5();  // "f00".ToMD5();
                var authenticatedCookie = ProTrans.Logix.Utilities.Http.HttpUtilities.Authenticate(baseUrl + GetTokenValue("LogOnRelativeUrl"), String.Format("username={0}&password={1}",GetTokenValue("ServerUserId").ToString(),hashedPassword));

                var requestString = JsonConvert.SerializeObject(
                new DocumentMetaDataView {PrimaryEntityType = "shipment",
                                EntityKey = GetTokenValue("ShipmentId").ToString(), //  "0535761",
                                ExternalDocumentId = Convert.ToInt32(GetTokenValue("DocumentEntryId").ToString()),  // 2272,
                                PrimaryDocumentType = GetTokenValue("DocumentType").ToString(), // "BOL Code",
                                PrimaryDocumentTypeReference = GetTokenValue("DocumentTypeReference").ToString(), // "2933939",
                                SecondaryReferenceTypeValues = new DocumentReferenceTypeValueView[]{},
                                NmfcClassList = newNmfcList, //"70"
                                PiecesList = newPiecesList, //20
                                WeightList = newWeightList, //1000
                                LtlCarrierPro = GetTokenValue("LtlCarrierPro").ToString()}); //"123456"); //500


                HttpWebResponse response = ProTrans.Logix.Utilities.Http.HttpUtilities.HttpPost(baseUrl+"/externaldocuments/document",
                    requestString,
                    authenticatedCookie,
                    "application/json; charset=utf-8");

                byte[] returnPayload = new byte[response.ContentLength+1];
                System.IO.Stream iss = response.GetResponseStream();
                StreamReader sr = new StreamReader(iss);
                var returnString = sr.ReadToEnd();

                var returnObject = JsonConvert.DeserializeObject<ReturnWrapper>(returnString);

                if (returnObject != null)
                {
                    SetTokenValue("scriptSuccess", returnObject.Message.success);
                    if (returnObject.Message.success.ToLower() == "true")
                    {
                        SetTokenValue("ShipmentDate", returnObject.Message.message);
                        SetTokenValue("ShipmentTrackingNumber", returnObject.Message.trackingNumber);
                        SetTokenValue("ErrorMessage", String.Empty);
                    }
                    else
                    {
                        SetTokenValue("ShipmentDate", null);
                        SetTokenValue("ShipmentTrackingNumber", returnObject.Message.trackingNumber);
                        SetTokenValue("ErrorMessage", returnObject.Message.message);
                    }
                }
            }
            catch (Exception e)
            {
                throw new LaserficheException("Script threw exception", e);
            }
      }
    }
}

I tried creating a new token and updating my script to look at this token and it did not work.  My guess is that it has something to do with:

object[] weightListValues = GetTokenValue("RetrieveIntialFieldValuesfromQuickFields_Weight_All") as object[];

and when I'm modifying the token value it is not passing as expected.  See below for a screenshot of how I am modifying my token.  

 

0 0
replied on May 21, 2016 Show version history

Ok, so I broke down you code just to this to see what would happen:

 //Weight
                object[] weightListValues = GetTokenValue("test") as object[];
                List<int> newWeightList = new List<int>();
                for (int w=0; w<weightListValues.Length; w++)
                {
                    int weight;
                    int.TryParse(weightListValues[w].ToString(), out weight);
                    newWeightList.Add(weight);
                }

                SetMultiValueToken("outWeight", weightListValues, true);

I can't get this to run by feeding it  a multivalue token from assign token values without getting a "object reference not set to an instance of an object". The "test" value is simply a multi token set to int with three numbers in it. I've also tried having it set to string. 

 

I then modified it to this:

List<object> weightListValues = GetTokenValue("test") as List<object>;
                List<int> newWeightList = new List<int>();
                for (int w=0; w<weightListValues.Count; w++)
                {
                    int weight;
                    int.TryParse(weightListValues[w].ToString(), out weight);
                    newWeightList.Add(weight);
                }

        SetMultiValueToken("outWeight", weightListValues, true);

 

and my output worked when I had more than one object, but not when I had one. (i.e. 0 didn't work, 0;0 did work.)

So then I did a quick test using: 

                string weightType = GetTokenValue("test").GetType().ToString();

                SetTokenValue("weightType", weightType);

This gave me a response of:

        System.Collections.Generic.List`1[System.Object]    when I used 0;0

and gave me 

        System.String

when I used just one 0. 

 

So if it's just one object, it's not an object anymore. 

 

So to correct this, I tried to use ".IsArray" but that won't work because it's a chicken and egg scenario - using object or object[] needs to be correct otherwise it fails. However this worked:

 List<int> newWeightList = new List<int>();

                string weightType = GetTokenValue("test").GetType().ToString();

                if (weightType != "System.String") {

                    List<object> weightListValues = GetTokenValue("test") as List<object>;

                    for (int w=0; w<weightListValues.Count; w++)
                    {
                        int weight;
                        int.TryParse(weightListValues[w].ToString(), out weight);
                        newWeightList.Add(weight);
                        
                    }
                 }
                 else {

                    object weightListValues = GetTokenValue("test") as object;


                        int weight;
                        int.TryParse(weightListValues.ToString(), out weight);
                        newWeightList.Add(weight);
                    
                 }

                SetMultiValueToken("outWeight", newWeightList, true);

 

You should be able to modify all three of your sections. Eventually you will run into a packing list that really only has one thing and those would fail too. 

3 0
replied on May 19, 2016

My recommendation would be to not modify the retrieve field values. Create a new token set to the results of that, then modify it from your tree. Also put in a couple track token activities so you can figure out what exactly everything is and when.

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.