private async Task <Core.Models.ExecutionContext> ExecuteAsync <T>(Core.Models.ExecutionContext execContext, T httpExecRequest,
                                                                           HttpExtensionSettings httpSettings)
        {
            logger.LogInformation($"Posting execution request [{execContext.ExecutionId}] to [{httpSettings.ExecutionUrl}]...");

            // POST the request to the extension...

            var httpExecResponse = await this.jsonHttpClient.PostAsync <HttpExecutionResponse>(
                httpSettings.ExecutionUrl, httpExecRequest);

            // Gather all the appropriate information returned from the extension...

            execContext.ResultData            = httpExecResponse.Content?.ResponseData;
            execContext.ProvidedOutputObjects = httpExecResponse.Content?.ProvidedOutputObjects;
            execContext.ValidationErrors      = httpExecResponse.Content?.ValidationErrors?.Select(ve => ve.ToCoreModel()).ToList();

            switch (httpExecResponse.StatusCode)
            {
            // If the extension responded with a [202 Accepted], the execution is long-running. Mark the execution as [Processing].
            // The extension is expected to call back to the execution API with status updates.

            case HttpStatusCode.Accepted:
                logger.LogInformation($"Execution [{execContext.ExecutionId}] is long-running.");
                execContext.UpdateStatus(ExecutionStatus.Processing);
                break;

            // If the extension responded with a [200 OK], execution was succesful. Mark the execution as such.

            case HttpStatusCode.OK:
                logger.LogInformation($"Execution [{execContext.ExecutionId}] complete.");
                execContext.UpdateStatus(ExecutionStatus.Succeeded);
                break;

            // If the extension responded with a [400 Bad Request], either we called the extension wrong OR the client
            // called the extension wrong. The extension may have provided further information as [validationErrors].
            // If [validationErrors] were provided, mark the execution as [ValidationFailed].
            // If [validationErrors] were not provided, something else went wrong, so mark the execution as [Failed].

            case HttpStatusCode.BadRequest:
                logger.LogWarning($"Execution request [{execContext.ExecutionId}] is invalid.");
                ProcessBadRequest(execContext, httpExecResponse.Content);
                break;

            // The extension responded with a status code that we didn't expect. Throw an exception...

            default:
                throw new HttpRequestException($"Extension returned an unexpected status code: [{httpExecResponse.StatusCode}].");
            }

            return(execContext);
        }
        private Core.Models.ExecutionContext ProcessBadRequest(Core.Models.ExecutionContext execContext,
                                                               HttpExecutionResponse httpExecResponse)
        {
            execContext.ValidationErrors = httpExecResponse?.ValidationErrors.Select(e => e.ToCoreModel()).ToList();

            if (execContext.ValidationErrors.Any())
            {
                return(execContext.UpdateStatus(ExecutionStatus.ValidationFailed));
            }
            else
            {
                throw new HttpRequestException($"Extension returned an unexpected status code: [{HttpStatusCode.BadRequest}].");
            }
        }
        private async Task <Core.Models.ExecutionContext> ValidateAsync <T>(Core.Models.ExecutionContext execContext, T httpExecRequest,
                                                                            HttpExtensionSettings httpSettings)

        {
            logger.LogInformation($"Posting execution validation request [{execContext.ExecutionId}] to [{httpSettings.ValidationUrl}]...");

            // POST the validation request to the extension...

            var httpExecResponse = await this.jsonHttpClient.PostAsync <HttpExecutionResponse>(
                httpSettings.ValidationUrl, httpExecRequest);

            // Grab any validation errors...

            execContext.ValidationErrors = httpExecResponse.Content?.ValidationErrors?.Select(ve => ve.ToCoreModel()).ToList();

            switch (httpExecResponse.StatusCode)
            {
            // If the extension responded with a [200 OK], mark the execution [ValidationSucceeded].

            case HttpStatusCode.OK:
                logger.LogInformation($"Execution request [{execContext.ExecutionId}] is valid.");
                execContext.UpdateStatus(ExecutionStatus.ValidationSucceeded);
                break;

            // If the extension responded with a [400 Bad Request], either we called the extension wrong OR the client
            // called the extension wrong. The extension may have provided further information as [validationErrors].
            // If [validationErrors] were provided, mark the execution as [ValidationFailed].
            // If [validationErrors] were not provided, something else went wrong, so mark the execution as [Failed].

            case HttpStatusCode.BadRequest:
                logger.LogInformation($"Execution request [{execContext.ExecutionId}] is invalid.");
                ProcessBadRequest(execContext, httpExecResponse.Content);
                break;

            // The extension responded with a status code that we didn't expect. Throw an exception...

            default:
                throw new HttpRequestException($"Extension returned an unexpected status code: [{httpExecResponse.StatusCode}].");
            }

            return(execContext);
        }