private async Task <IList <jsTreeNode> > GetFolderContents(string href)
        {
            IList <jsTreeNode> nodes = new List <jsTreeNode>();

            // the API SDK
            FoldersApi folderApi = new FoldersApi();

            folderApi.Configuration.AccessToken = Credentials.TokenInternal;

            // extract the projectId & folderId from the href
            string[] idParams  = href.Split('/');
            string   folderId  = idParams[idParams.Length - 1];
            string   projectId = idParams[idParams.Length - 3];

            // check if folder specifies visible types
            JArray  visibleTypes = null;
            dynamic folder       = (await folderApi.GetFolderAsync(projectId, folderId)).ToJson();

            if (folder.data.attributes != null && folder.data.attributes.extension != null && folder.data.attributes.extension.data != null && !(folder.data.attributes.extension.data is JArray) && folder.data.attributes.extension.data.visibleTypes != null)
            {
                visibleTypes = folder.data.attributes.extension.data.visibleTypes;
            }

            var folderContents = await folderApi.GetFolderContentsAsync(projectId, folderId);

            // the GET Folder Contents has 2 main properties: data & included (not always available)
            var folderData     = new DynamicDictionaryItems(folderContents.data);
            var folderIncluded = (folderContents.Dictionary.ContainsKey("included") ? new DynamicDictionaryItems(folderContents.included) : null);

            // let's start iterating the FOLDER DATA
            foreach (KeyValuePair <string, dynamic> folderContentItem in folderData)
            {
                // do we need to skip some items? based on the visibleTypes of this folder
                string extension = folderContentItem.Value.attributes.extension.type;
                if (extension.IndexOf("Folder") /*any folder*/ == -1 && visibleTypes != null && !visibleTypes.ToString().Contains(extension))
                {
                    continue;
                }

                // if the type is items:autodesk.bim360:Document we need some manipulation...
                if (extension.Equals("items:autodesk.bim360:Document"))
                {
                    // as this is a DOCUMENT, lets interate the FOLDER INCLUDED to get the name (known issue)
                    foreach (KeyValuePair <string, dynamic> includedItem in folderIncluded)
                    {
                        // check if the id match...
                        if (includedItem.Value.relationships.item.data.id.IndexOf(folderContentItem.Value.id) != -1)
                        {
                            // found it! now we need to go back on the FOLDER DATA to get the respective FILE for this DOCUMENT
                            foreach (KeyValuePair <string, dynamic> folderContentItem1 in folderData)
                            {
                                if (folderContentItem1.Value.attributes.extension.type.IndexOf("File") == -1)
                                {
                                    continue;                                                                           // skip if type is NOT File
                                }
                                // check if the sourceFileName match...
                                if (folderContentItem1.Value.attributes.extension.data.sourceFileName == includedItem.Value.attributes.extension.data.sourceFileName)
                                {
                                    // ready!

                                    // let's return for the jsTree with a special id:
                                    // itemUrn|versionUrn|viewableId
                                    // itemUrn: used as target_urn to get document issues
                                    // versionUrn: used to launch the Viewer
                                    // viewableId: which viewable should be loaded on the Viewer
                                    // this information will be extracted when the user click on the tree node, see ForgeTree.js:136 (activate_node.jstree event handler)
                                    string treeId = string.Format("{0}|{1}|{2}",
                                                                  folderContentItem.Value.id,                                       // item urn
                                                                  Base64Encode(folderContentItem1.Value.relationships.tip.data.id), // version urn
                                                                  includedItem.Value.attributes.extension.data.viewableId           // viewableID
                                                                  );
                                    nodes.Add(new jsTreeNode(treeId, WebUtility.UrlDecode(includedItem.Value.attributes.name), "bim360documents", false));
                                }
                            }
                        }
                    }
                }
                else
                {
                    // non-Plans folder items
                    nodes.Add(new jsTreeNode(folderContentItem.Value.links.self.href, folderContentItem.Value.attributes.displayName, (string)folderContentItem.Value.type, true));
                }
            }

            return(nodes);
        }
        private async Task <IList <jsTreeNode> > GetFolderContents(string href, string qtype, string qtext)
        {
            IList <jsTreeNode> nodes = new List <jsTreeNode>();

            // the API SDK
            FoldersApi folderApi = new FoldersApi();

            folderApi.Configuration.AccessToken = Credentials.TokenInternal;

            // extract the projectId & folderId from the href
            string[] idParams  = href.Split('/');
            string   folderId  = idParams[idParams.Length - 1];
            string   projectId = idParams[idParams.Length - 3];

            // check if folder specifies visible types
            JArray  visibleTypes = null;
            dynamic folder       = (await folderApi.GetFolderAsync(projectId, folderId)).ToJson();

            if (folder.data.attributes != null && folder.data.attributes.extension != null && folder.data.attributes.extension.data != null && !(folder.data.attributes.extension.data is JArray) && folder.data.attributes.extension.data.visibleTypes != null)
            {
                visibleTypes = folder.data.attributes.extension.data.visibleTypes;
            }

            var folderContents = await folderApi.GetFolderContentsAsync(projectId, folderId);

            // the GET Folder Contents has 2 main properties: data & included (not always available)
            var folderData     = new DynamicDictionaryItems(folderContents.data);
            var folderIncluded = (folderContents.Dictionary.ContainsKey("included") ? new DynamicDictionaryItems(folderContents.included) : null);

            // let's start iterating the FOLDER DATA
            foreach (KeyValuePair <string, dynamic> folderContentItem in folderData)
            {
                // do we need to skip some items? based on the visibleTypes of this folder
                string extension = folderContentItem.Value.attributes.extension.type;
                if (extension.IndexOf("Folder") /*any folder*/ == -1 && visibleTypes != null && !visibleTypes.ToString().Contains(extension))
                {
                    continue;
                }

                // if the type is items:autodesk.bim360:Document we need some manipulation...
                if (extension.Equals("items:autodesk.bim360:Document"))
                {
                    //mb
                    continue;
                    // as this is a DOCUMENT, lets interate the FOLDER INCLUDED to get the name (known issue)
                    foreach (KeyValuePair <string, dynamic> includedItem in folderIncluded)
                    {
                        // check if the id match...
                        if (includedItem.Value.relationships.item.data.id.IndexOf(folderContentItem.Value.id) != -1)
                        {
                            // found it! now we need to go back on the FOLDER DATA to get the respective FILE for this DOCUMENT
                            foreach (KeyValuePair <string, dynamic> folderContentItem1 in folderData)
                            {
                                if (folderContentItem1.Value.attributes.extension.type.IndexOf("File") == -1)
                                {
                                    continue;                                                                           // skip if type is NOT File
                                }
                                // check if the sourceFileName match...
                                if (folderContentItem1.Value.attributes.extension.data.sourceFileName == includedItem.Value.attributes.extension.data.sourceFileName)
                                {
                                    // ready!

                                    // let's return for the jsTree with a special id:
                                    // itemUrn|versionUrn|viewableId
                                    // itemUrn: used as target_urn to get document issues
                                    // versionUrn: used to launch the Viewer
                                    // viewableId: which viewable should be loaded on the Viewer
                                    // this information will be extracted when the user click on the tree node, see ForgeTree.js:136 (activate_node.jstree event handler)
                                    string treeId = string.Format("{0}|{1}|{2}",
                                                                  folderContentItem.Value.id,                                       // item urn
                                                                  Base64Encode(folderContentItem1.Value.relationships.tip.data.id), // version urn
                                                                  includedItem.Value.attributes.extension.data.viewableId           // viewableID
                                                                  );
                                    nodes.Add(new jsTreeNode(treeId, WebUtility.UrlDecode(includedItem.Value.attributes.name), "bim360documents", false));
                                }
                            }
                        }
                    }
                }
                else if (extension.Equals("folders:autodesk.bim360:Folder"))
                {
                    //mb: , string qtype, string qtext
                    string   legend      = "";
                    string   permissions = "";
                    string   userId      = "";
                    string[] useremails  = null;
                    string[] companies   = null;
                    string[] roles       = null;

                    if (qtype.Equals("userId"))
                    {
                        //get user company and roles
                        userId = qtext.Trim();
                        string utoken  = Credentials.TokenInternal;
                        var    uclient = new RestClient("https://developer.api.autodesk.com/bim360/admin/v1/projects/" + projectId.Substring(2) + "/users/" + userId);
                        uclient.Timeout = -1;
                        var urequest = new RestRequest(Method.GET);
                        urequest.AddHeader("Content-Type", "application/json");
                        urequest.AddHeader("Accept", "application/json");
                        urequest.AddHeader("Authorization", "Bearer " + utoken);
                        IRestResponse uresponse = uclient.Execute(urequest);
                        JObject       ures      = JObject.Parse(uresponse.Content);
                        useremails = new string[] { ures["email"].ToString() };
                        companies  = new string[] { ures["companyId"].ToString() };
                        List <string> lroles = new List <string>();
                        foreach (var item in ures["roleIds"].Children())
                        {
                            lroles.Add(item.ToString());
                        }
                        roles = lroles.ToArray();
                    }
                    else if (qtype.Equals("by_emails_only"))
                    {
                        useremails = qtext.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    }
                    else if (qtype.Equals("companies"))
                    {
                        companies = qtext.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    }
                    else if (qtype.Equals("roles"))
                    {
                        roles = qtext.Split(new Char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    }

                    string token     = Credentials.TokenInternal;
                    string folderUrn = folderContentItem.Value.links.self.href.ToString();
                    folderUrn = folderUrn.Split("/folders/")[1].Split("/contents?")[0].Replace(":", "%3A");
                    var client = new RestClient("https://developer.api.autodesk.com/bim360/docs/v1/projects/" + projectId.Substring(2) + "/folders/" + folderUrn + "/permissions");
                    client.Timeout = -1;
                    var request = new RestRequest(Method.GET);
                    request.AddHeader("Content-Type", "application/vnd.api+json");
                    request.AddHeader("Accept", "application/vnd.api+json");
                    request.AddHeader("Authorization", "Bearer " + token);

                    try
                    {
                        bool   validresponse = false;
                        int    countvr       = 0;
                        int    maxvr         = 3;
                        JArray res           = null;
                        while (!validresponse)
                        {
                            ++countvr;
                            IRestResponse response = client.Execute(request);
                            //Console.WriteLine(response.Content);
                            try
                            {
                                res           = JArray.Parse(response.Content);
                                validresponse = true;
                            }
                            catch
                            {
                                if (countvr >= maxvr)
                                {
                                    break;
                                }
                                System.Threading.Thread.Sleep(25000);
                            }
                        }



                        foreach (var item in res.Children())
                        {
                            dynamic data = JObject.Parse(item.ToString());
                            if (data["subjectType"].ToString().Equals("USER") && useremails != null)
                            {
                                int count = 0;
                                foreach (string useremail in useremails)
                                {
                                    ++count;
                                    if (data["email"].ToString().Equals(useremail.Trim()))
                                    {
                                        permissions += " " + GetPermissionString(data, count, useremail);
                                    }
                                }
                            }
                            else if (data["subjectType"].ToString().Equals("COMPANY") && companies != null)
                            {
                                int count = 3;
                                foreach (string company in companies)
                                {
                                    ++count;
                                    if (data["name"].ToString().Equals(company.Trim()) || data["subjectId"].ToString().Equals(company.Trim()))
                                    {
                                        permissions += " " + GetPermissionString(data, count, "C:" + data["name"].ToString());
                                    }
                                }
                            }
                            else if (data["subjectType"].ToString().Equals("ROLE") && roles != null)
                            {
                                int count = 6;
                                foreach (string role in roles)
                                {
                                    ++count;
                                    if (data["name"].ToString().Equals(role.Trim()) || data["subjectId"].ToString().Equals(role.Trim()))
                                    {
                                        permissions += " " + GetPermissionString(data, count, "R:" + data["name"].ToString());
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception e) { permissions = e.Message + "###" + e.StackTrace; }


                    // non-Plans folder items
                    //if (folderContentItem.Value.attributes.hidden == true) continue;
                    nodes.Add(new jsTreeNode(folderContentItem.Value.links.self.href, folderContentItem.Value.attributes.displayName + permissions, (string)folderContentItem.Value.type, true));
                }
            }
            //nodes.Add(new jsTreeNode("", "long long text", "folders", false));
            return(nodes);
        }