1

I had asked my last question regarding this. I have one rfa file and a bigger JSon file as input. When I debug, it looks perfectly passing all values until last line: WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemAsync(workItemSpec);

Looks like workItemSpec has some problem. Please have a look at these code fractions and please let me know what is wrong here.

code fraction from ForgeDesignAutomation.js as below:

    {
    var inputFileField = document.getElementById('inputFile');
    
    if (inputFileField.files.length === 0) { alert('Please select an input file'); return; }
    if ($('#activity').val() === null) { alert('Please select an activity'); return };
    var file = inputFileField.files[0];
    var inputFileField2 = document.getElementById('inputJsonFile');
    if (inputFileField2.files.length === 0) { alert('Please select an input file'); return; }
    var file2 = inputFileField2.files[0];
    let activityId = $('#activity').val();
    if (activityId == null)
    {
        alert('Please select an activity'); return
    };
    
    if (activityId.toLowerCase() === "_da4ractivity+dev")
       {
        startConnection(function () {
            var formData = new FormData();
            formData.append('inputFile', file);
            formData.append('inputJsonFile', file2);
            formData.append('data', JSON.stringify({
                activityName: $('#activity').val(),
                browerConnectionId: connectionId
            }));
        writeLog('Uploading input file...');
        $.ajax({
                url: 'api/forge/designautomation/workitems',
                data: formData,
                processData: false,
                contentType: false,
                type: 'POST',
                success: function (res)
                {
                    writeLog('Workitem started: ' + res.workItemId);
                }
            });
        });
    }
}```


code fraction from "CreateActivity" in DesignAutomationController.cs

```  Parameters = new Dictionary<string, Parameter>()
                    {
                        { "inputFile", new Parameter() { Description = "input file", LocalName = "$(inputFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
                        { "inputJsonFile", new Parameter() { Description = "input Json file", LocalName = "$(inputJsonFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
                        { "outputFile", new Parameter() { Description = "output file", LocalName = "outputFile." + engineAttributes.extension, Ondemand = false, Required = true, Verb = Verb.Put, Zip = false } }
                    }```

code fraction from "StartWorkitem" in DesignAutomationController.cs


``` [HttpPost]
        [Route("api/forge/designautomation/workitems")]
        public async Task<IActionResult> StartWorkitem([FromForm]StartWorkitemInput input)
        {
            // basic input validation
            JObject workItemData = JObject.Parse(input.data);
           
            string activityName = string.Format("{0}.{1}", NickName, workItemData["activityName"].Value<string>());
            string browerConnectionId = workItemData["browerConnectionId"].Value<string>();
            
            // save the file on the server
            var fileSavePath0 = Path.Combine(_env.ContentRootPath, Path.GetFileName(input.inputFile.FileName));
            using (var stream0 = new FileStream(fileSavePath0, FileMode.Create)) await input.inputFile.CopyToAsync(stream0);
            
            var fileSavePath1 = Path.Combine(_env.ContentRootPath, Path.GetFileName(input.inputJsonFile.FileName));
            using (var stream1 = new FileStream(fileSavePath1, FileMode.Create)) await input.inputJsonFile.CopyToAsync(stream1);


            //---------------------------------------------------------------------------------------------------------------------
            // OAuth token
            dynamic oauth = await OAuthController.GetInternalAsync();

            // upload file to OSS Bucket
            // 1. ensure bucket existis
            string bucketKey = NickName.ToLower() + "-designautomation";
            BucketsApi buckets = new BucketsApi();
            buckets.Configuration.AccessToken = oauth.access_token;
            try
            {
                PostBucketsPayload bucketPayload = new PostBucketsPayload(bucketKey, null, PostBucketsPayload.PolicyKeyEnum.Transient);
                await buckets.CreateBucketAsync(bucketPayload, "US");
            }
            catch { }; 
            
            // in case bucket already exists
            // 2. upload inputFile
            string inputFileNameOSS0 = string.Format("{0}_input_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputFile.FileName)); // avoid overriding
            string inputFileNameOSS1 = string.Format("{0}_inputJson_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputJsonFile.FileName)); // avoid overriding

            //string inputFileNameOSS = Path.GetFileName(input.inputFile.FileName); // avoid overriding


            ObjectsApi objects = new ObjectsApi();
            objects.Configuration.AccessToken = oauth.access_token;
            using (StreamReader streamReader = new StreamReader(fileSavePath0))
                await objects.UploadObjectAsync(bucketKey, inputFileNameOSS0, (int)streamReader.BaseStream.Length, streamReader.BaseStream, "application/octet-stream");
            System.IO.File.Delete(fileSavePath0);// delete server copy

            // prepare workitem arguments
            // 1. input file
            XrefTreeArgument inputFileArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS0),
                Headers = new Dictionary<string, string>()
                 {
                     { "Authorization", "Bearer " + oauth.access_token }
                 }
            };

            using (StreamReader streamReader1 = new StreamReader(fileSavePath1))
                await objects.UploadObjectAsync(bucketKey, inputFileNameOSS1, (int)streamReader1.BaseStream.Length, streamReader1.BaseStream, "application/octet-stream");
            System.IO.File.Delete(fileSavePath1);// delete server copy

            // 1. input Json file
            XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS1),
                Headers = new Dictionary<string, string>()
                 {
                     { "Authorization", "Bearer " + oauth.access_token }
                 }
            };

            
            // 3. output file
            string outputFileNameOSS = string.Format("{0}_output_{1}", DateTime.Now.ToString("yyyyMMddhhmmss"), Path.GetFileName(input.inputFile.FileName)); // avoid overriding
            XrefTreeArgument outputFileArgument = new XrefTreeArgument()
            {
                Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, outputFileNameOSS),
                Verb = Verb.Put,
                Headers = new Dictionary<string, string>()
                   {
                       {"Authorization", "Bearer " + oauth.access_token }
                   }
            };

           
            // prepare & submit workitem
            string callbackUrl = string.Format("{0}/api/forge/callback/designautomation?id={1}&outputFileName={2}", OAuthController.GetAppSetting("FORGE_WEBHOOK_URL"), browerConnectionId, outputFileNameOSS);
            WorkItem workItemSpec = new WorkItem()
            {
                ActivityId = activityName,
                Arguments = new Dictionary<string, IArgument>()
                {
                    { "inputFile", inputFileArgument },
                    { "inputJsonFile", inputJsonArgument },
                    { "outputFile", outputFileArgument },
                    { "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } }
                }
            };
            WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemAsync(workItemSpec);
            return Ok(new { WorkItemId = workItemStatus.Id });
        }```





```/// <summary>
        /// Input for StartWorkitem
        /// </summary>
        public class StartWorkitemInput[![enter image description here][1]][1]
        {
            public IFormFile inputFile { get; set; }
            public IFormFile inputJsonFile { get; set; }
            public string data { get; set; }
        } ``` 


  [![enter image description here][1]][1]


  [1]: https://i.stack.imgur.com/GktUC.png
Modus Tollens
  • 5,083
  • 3
  • 38
  • 46
nayra n
  • 29
  • 7
  • 1
    What is the response you get from `CreateWorkItemAsync()`? What is the value of `workItemStatus`? Also, could you include the entire activity definition, please? – Rahul Bhobe Jun 13 '20 at 08:46
  • I am glad your workItemStatus issue is resolved! Could you kindly mark Emma's answer as `accept as answer`. If you see this _Error: Application revitcoreconsole.exe exits with code 4 which indicates an error_. it does mean that `revitcoreconsole.exe` started and loaded your addin but there was some failure in the addin. To debug this you could have `System.Console.WriteLine()` calls in your addin to see some feedback in the `report.txt`. See [here](https://stackoverflow.com/a/61395427/11057988). – Rahul Bhobe Jun 15 '20 at 06:43
  • You might find these helpful - [AU Class](https://www.autodesk.com/autodesk-university/class/Getting-Started-Design-Automation-Revit-Forge-2019) and [Webinar](https://www.youtube.com/watch?v=PkdBM0cFrN4). Some of your questions this week (and other related topics) are addressed here. You may also reach out for help at `forge.help@autodesk.com`. And learn more about our accelerator program [here](https://forge.autodesk.com/accelerator-program). – Rahul Bhobe Jun 15 '20 at 06:56
  • 1
    Rahul, Thanks a lot for elaborate answer.OK. I will do System.Console.WriteLine(). My addin was working perfectly. I did local debugging and it worked perfect too. I think I am passing input files wrongly and I may need a chat with some one. I think I need accelerator. I have very interesting projects on hand :) But I am new to this cloud world. I want to keep this question open for another two days. I am looking into codes, because my feeling, I did not pass the file correctly. I will do some digging for 2 days and come back. I think just passing input file to the add-in has some problem. – nayra n Jun 15 '20 at 09:17
  • I rolled back the question to the state it was in when it was answered. Please don't change a question like this, it will invalidate the answer and provides no help for users having the same problem in the future. – Modus Tollens Feb 09 '21 at 00:02

1 Answers1

3

I noticed your activity defines the "localName" of "inputFile"/"inputJsonFile" to be "$(inputFile)"/"$(inputJsonFile)"

Parameters = new Dictionary<string, Parameter>()
 {
     { "inputFile", new Parameter() { Description = "input file", LocalName = "$(inputFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } },
     { "inputJsonFile", new Parameter() { Description = "input Json file", LocalName = "$(inputJsonFile)", Ondemand = false, Required = true, Verb = Verb.Get, Zip = false } }
 }

This could cause some issue when resolving the naming of inputs during the job process. I would suggest you provide a concrete filename as WorkItem argument's localname and try again. For example:

XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
{
      Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, inputFileNameOSS1),
      Headers = new Dictionary<string, string>()
      {
         { "Authorization", "Bearer " + oauth.access_token }
      },
      // Note: if your appbunldes(addin) uses this json, this is the name your addin should know 
      LocalName = "inputJson.json" 
};
Emma Zhu
  • 220
  • 2
  • 6
  • Thanks Emma, for the advise. Looking into the code and will get back soon. I did not work yesterday and today. – nayra n Jun 14 '20 at 10:21
  • Thanks Emma, with your advise, work item started. But it is failing, looks like engine mismatch issue. I am looking into it now. – nayra n Jun 14 '20 at 16:10
  • If you want, you can provide the workitem id which failed by failed instruction, we can help more. – Emma Zhu Jun 14 '20 at 20:12
  • Hi Emma, Many thanks for the reply. I am doing some struggle, this way, I will get a better understanding. Will be back soon. – nayra n Jun 15 '20 at 08:06