#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public async Task <object> ActionAsync(CancellationToken cancelToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            return(FailableRun <object>(this, delegate {
                ++this.ActionExecuteCount;

                if (this.sequenceItem.run == null)
                {
                    throw new NullReferenceException($"{nameof(this.sequenceItem)}.{nameof(this.sequenceItem.run)} missing");
                }


                this.state.ProgressLog?.Progress($"Running {this.sequenceItem.run.exec}...");

                var scribanModel = new { run_id = this.state.RunId, command_args = this.state.CommandLineOptions, this.model, sequence_item = this.sequenceItem, unique_no = Program.unique_no++ };

                // Exec run external program
                var workingExec = ScribanUtil.ScribanParse(this.sequenceItem?.run?.exec ?? "", scribanModel);
                var workingArgs = ScribanUtil.ScribanParse(this.sequenceItem?.run?.args ?? "", scribanModel);

                this.state.ProgressLog?.Progress($" running exec '{workingExec}', with args '{workingArgs}'...");

                var itsStandardInput = (model != null)
                                        ? JsonConvert.SerializeObject(model)
                                        : "";

                var execReturn = ProcessExecute(this.sequenceItem.run, workingExec, workingArgs, itsStandardInput);
                var responseContentLength = execReturn?.Length ?? 0;
                var responseContent = execReturn;

                var responseModel = SequenceItemStatic.GetResponseItems(this.state, this.sequenceItem, execReturn);

                return responseModel;
            }));
        }
        private async Task <HttpResponseMessage> DoSendAction(HttpClient client, object scribanModel)
        {
            this.state.ProgressLog?.Progress($" using method '{this.sequenceItem.send.http_method}'...");

            if (this.sequenceItem.send.query != null)
            {
                WorkingUri = AppendSendActionQuery(this.WorkingUri, scribanModel);
            }

            if (this.sequenceItem.send?.body != null)
            {
                //ADD unique_no and other bits?



                this.WorkingBody = ScribanUtil.ScribanParse(this.sequenceItem.send.body, scribanModel);
                this.state.ProgressLog?.Progress($" using content body \n'{this.WorkingBody}'\n...");

                if (this.sequenceItem.send.save_body_filename != null)
                {
                    SaveSendActionBody(scribanModel, WorkingBody);
                }
            }

            this.state.ProgressLog?.Progress($" using url '{this.WorkingUri}'...");

            // Process the response content
            var contentType = client.DefaultRequestHeaders.Where(w => w.Key.Equals("accept", StringComparison.OrdinalIgnoreCase)).FirstOrDefault().Value.First().ToString();

            return(await SortOutHttpMethodAndReturnResult(this.sequenceItem.max_instant_retrys, client, this.sequenceItem.send.http_method, contentType, WorkingBody));
        }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        public async Task <object> ActionAsync(CancellationToken cancelToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            return(FailableRun <object>(this, delegate {
                ++this.ActionExecuteCount;

                if (this.sequenceItem.load == null)
                {
                    throw new NullReferenceException($"{nameof(this.sequenceItem)}.{nameof(this.sequenceItem.load)} missing");
                }


                this.state.ProgressLog?.Progress($"Loading {this.sequenceItem.load.csv}...");

                var scribanModel = new { run_id = this.state.RunId, command_args = this.state.CommandLineOptions, this.model, sequence_item = this.sequenceItem, unique_no = Program.unique_no++ };

                var loadfile = ScribanUtil.ScribanParse(this.sequenceItem?.load?.csv ?? "", scribanModel);

                var csvRows = LoadFile(this.sequenceItem.load, loadfile);

                var noOfRows = csvRows?.Count() ?? 0;

                var stringContent = JsonConvert.SerializeObject(csvRows);

                var responseModel = SequenceItemStatic.GetResponseItems(this.state, this.sequenceItem, stringContent);                // csvRows.ToList<dynamic>());

                return responseModel;
            }));
        }
        private string AppendSendActionQuery(string workingUri, object scribanModel)
        {
            foreach (var query in this.sequenceItem.send.query)
            {
                var templatedValue = ScribanUtil.ScribanParse(query.Value, scribanModel);
                workingUri = QueryHelpers.AddQueryString(workingUri, query.Key, templatedValue);
            }

            return(workingUri);
        }
        private static HttpClient MakeClientWithHeaders(Options o, YamlScript yaml, SequenceItem entry = null)
        {
            var client = new HttpClient();

            const int defaultClientTimeoutSeconds = 90;

            client.Timeout = TimeSpan.FromSeconds(yaml.client_timeout_seconds ?? defaultClientTimeoutSeconds);

            var scribanModel = new { yaml.run_id, command_args = o, model = new { } };

            client.DefaultRequestHeaders.Accept.Clear();
            if (entry?.send?.header != null)
            {
                /* UN TESTED  - for POST*/

                //Add customer headers
                foreach (var addHeader in entry.send.header)
                {
                    if (addHeader.Key.Equals("accept", StringComparison.InvariantCultureIgnoreCase))
                    {
                        var vals = ScribanUtil.ScribanParse(addHeader.Value, scribanModel);
                        foreach (var val in vals.Split(',').Select(s => s.Trim()))
                        {
                            var queryParts = val.Split(';');
                            if (queryParts.Length > 1)
                            {
                                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(queryParts[0]));
                                foreach (var queryPart in queryParts.Skip(1))
                                {
                                    var keyVal = queryPart.Split('=');
                                    client.DefaultRequestHeaders.Add(keyVal[0], keyVal[1]);
                                }
                            }
                            else
                            {
                                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(val));
                            }
                        }
                    }
                    else
                    {
                        client.DefaultRequestHeaders.Add(addHeader.Key, ScribanUtil.ScribanParse(addHeader.Value, scribanModel));
                    }
                }
            }

            var contenType = entry.send.content_type ?? "text/plain";

            if (client.DefaultRequestHeaders.Accept.Count == 0)
            {
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contenType));
            }

            return(client);
        }
        private void SavingContentsEtc(string itemUniqueThing, dynamic responseModel, HttpResponseMessage httpResponse, long responseContentLength, string responseContent)
        {
            if (this.sequenceItem?.send?.save == null)
            {
                return;
            }

            var saveModel      = new { run_id = this.state.RunId, command_args = this.state.CommandLineOptions, sequence_item = this.sequenceItem, model = this.model, response = responseModel, unique_string = itemUniqueThing, unique_no = Program.unique_no++ };
            var folderSaveName = this.sequenceItem.send.save?.folder ?? "";
            var saveTo         = ScribanUtil.ScribanParse(folderSaveName, saveModel);

            var contentSaveName = this.sequenceItem.send.save?.content_filename ?? "";

            if (contentSaveName.Trim().Length > 0)
            {
                var contentFn = Path.Combine(saveTo, ScribanUtil.ScribanParse(contentSaveName, saveModel));
                this.state.ProgressLog?.Progress($" saving content to '{contentFn }'...");

                Directory.CreateDirectory(Path.GetDirectoryName(contentFn));

                if (this.sequenceItem.send.save.content_is_binary)
                {
                    if (httpResponse != null)
                    {
                        using (Stream output = File.OpenWrite(contentFn)) { Task.WaitAll(httpResponse.Content.CopyToAsync(output)); }
                    }
                }
                else
                {
                    File.WriteAllText(contentFn, responseContent);
                }
            }

            var responseSaveName = this.sequenceItem.send.save?.response_filename ?? "";

            if (httpResponse != null && responseSaveName.Trim().Length > 0)
            {
                var nonContentFn = Path.Combine(saveTo, ScribanUtil.ScribanParse(responseSaveName, saveModel));
                this.state.ProgressLog?.Progress($" saving non content response to '{nonContentFn}'...");

                var nonContent = new
                {
                    httpResponse.StatusCode,
                    httpResponse.Headers,
                    httpResponse.ReasonPhrase,
                    httpResponse.IsSuccessStatusCode,
                    //httpResponse.TrailingHeaders,
                    httpResponse.RequestMessage,
                    ContentLength = responseContentLength
                };

                Directory.CreateDirectory(Path.GetDirectoryName(nonContentFn));
                File.WriteAllText(nonContentFn, JsonConvert.SerializeObject(nonContent));
            }
        }
        private void SaveSendActionBody(object scribanModel, string workingBody)
        {
            var saveBodyFilename = ScribanUtil.ScribanParse(this.sequenceItem.send.save_body_filename, scribanModel);
            var saveBodyPath     = Path.GetDirectoryName(saveBodyFilename);

            if (!Directory.Exists(saveBodyPath))
            {
                Directory.CreateDirectory(saveBodyPath);
            }

            File.WriteAllText(saveBodyFilename, workingBody);
        }
        public async Task <object> ActionAsync(CancellationToken cancelToken)
        {
            return(await FailableRun <Task <object> >(this, async delegate {
                ++this.ActionExecuteCount;

                if (this.sequenceItem.send == null)
                {
                    throw new NullReferenceException($"{nameof(this.sequenceItem)}.{nameof(this.sequenceItem.send)} missing");
                }

                var modelUrl = this.sequenceItem.send.url ?? "";
                var scribanModel = new
                {
                    run_id = this.state.RunId,
                    command_args = this.state.CommandLineOptions,
                    this.model,
                    sequence_item = this.sequenceItem,
                    unique_no = Program.unique_no++
                };
                this.WorkingUri = ScribanUtil.ScribanParse(this.sequenceItem.send.url, scribanModel);

                this.state.ProgressLog?.Progress($"Processing {this.WorkingUri}...");

                dynamic responseModel = null;
                using (var client = MakeClientWithHeaders(this.state.CommandLineOptions, this.state.YamlOptions, this.sequenceItem))
                {
                    var http_response = await DoSendAction(client, scribanModel);
                    this.IsFail = !http_response.IsSuccessStatusCode;

                    var responseContentLength = http_response?.Content?.Headers?.ContentLength ?? 0;
                    var responseContent = responseContentLength > 0
                        ? (await http_response?.Content?.ReadAsStringAsync())
                        : string.Empty;

                    this.state.ProgressLog?.Progress($" received {responseContentLength} bytes...");
                    responseModel = SequenceItemStatic.GetResponseItems(this.state, this.sequenceItem, responseContent);

                    SavingContentsEtc(Guid.NewGuid().ToString(), responseModel, http_response, responseContentLength, responseContent);
                }

                return responseModel;
            }));
        }