/// <summary> /// Make a call to the HttpRequest and populate the Value property of /// every PlaceholderValue in Values based on the result. /// </summary> /// <param name="storedValues"></param> /// <param name="documents"></param> /// <param name="scenario"></param> /// <param name="account"></param> /// <param name="parentOutputValues"></param> /// <returns></returns> public async Task <ValidationResult <bool> > MakeSetupRequestAsync( Dictionary <string, string> storedValues, DocSet documents, ScenarioDefinition scenario, IServiceAccount account, Dictionary <string, string> parentOutputValues = null) { // Copy the output values from parentOutputValues into our own if (null != parentOutputValues) { foreach (var key in parentOutputValues.Keys) { this.OutputValues.Add(key, parentOutputValues[key]); } } var errors = new List <ValidationError>(); if (!string.IsNullOrEmpty(this.CannedRequestName)) { // We need to make a canned request setup request instead. Look up the canned request and then execute it, returning the results here. var cannedRequest = (from cr in documents.CannedRequests where cr.Name == this.CannedRequestName select cr) .FirstOrDefault(); if (null == cannedRequest) { errors.Add(new ValidationError(ValidationErrorCode.InvalidRequestFormat, null, "Couldn't locate the canned-request named: {0}", this.CannedRequestName)); return(new ValidationResult <bool>(false, errors)); } // Need to make a copy of the canned request here so that our state doesn't continue to pile up var cannedRequestInstance = cannedRequest.CopyInstance(); return(await cannedRequestInstance.MakeSetupRequestAsync(storedValues, documents, scenario, account, this.OutputValues)); } // Get the HttpRequest, either from MethodName or by parsing HttpRequest HttpRequest request; var issues = new IssueLogger(); try { request = this.GetHttpRequest(documents, account, issues); } catch (Exception ex) { errors.Add(new ValidationError(ValidationErrorCode.InvalidRequestFormat, null, "An error occured creating the http request: {0}", ex.Message)); return(new ValidationResult <bool>(false, errors)); } MethodDefinition.AddTestHeaderToRequest(scenario, request); MethodDefinition.AddAdditionalHeadersToRequest(account, request); // If this is a canned request, we need to merge the parameters / placeholders here var placeholderValues = this.RequestParameters.ToPlaceholderValuesArray(storedValues); // Update the request with the parameters in request-parameters try { request.RewriteRequestWithParameters(placeholderValues); } catch (Exception ex) { errors.Add(new ValidationError(ValidationErrorCode.ParameterParserError, SourceName, "Error rewriting the request with parameters from the scenario: {0}", ex.Message)); return(new ValidationResult <bool>(false, errors)); } MethodDefinition.AddAccessTokenToRequest(account.CreateCredentials(), request); errors.Add(new ValidationMessage(null, "Test-setup request:\n{0}", request.FullHttpText())); try { var response = await request.GetResponseAsync(account, issues); errors.AddRange(issues.Issues); if (response.RetryCount > 0) { errors.Add(new ValidationWarning(ValidationErrorCode.RequestWasRetried, null, "HTTP request was retried {0} times.", response.RetryCount)); } errors.Add(new ValidationMessage(null, "HTTP Response:\n{0}\n\n", response.FullText())); // Check to see if this request is "successful" or not if ((this.AllowedStatusCodes == null && response.WasSuccessful) || (this.AllowedStatusCodes != null && this.AllowedStatusCodes.Contains(response.StatusCode))) { string expectedContentType = (null != this.OutputValues) ? ExpectedResponseContentType(this.OutputValues.Values) : null; // Check for content type mismatch if (string.IsNullOrEmpty(response.ContentType) && expectedContentType != null) { return(new ValidationResult <bool>(false, new ValidationError(ValidationErrorCode.UnsupportedContentType, SourceName, "No Content-Type found for a non-204 response"))); } // Load requested values into stored values if (null != this.OutputValues) { foreach (var outputKey in this.OutputValues.Keys) { var source = this.OutputValues[outputKey]; storedValues[outputKey] = response.ValueForKeyedIdentifier(source); } } return(new ValidationResult <bool>(!errors.Any(x => x.IsError), errors)); } else { if ((this.AllowedStatusCodes != null && !this.AllowedStatusCodes.Contains(response.StatusCode)) || !response.WasSuccessful) { string expectedCodes = "200-299"; if (this.AllowedStatusCodes != null) { expectedCodes = this.AllowedStatusCodes.ComponentsJoinedByString(","); } errors.Add(new ValidationError(ValidationErrorCode.HttpStatusCodeDifferent, SourceName, "Http response status code {0} didn't match expected values: {1}", response.StatusCode, expectedCodes)); } else { errors.Add(new ValidationError(ValidationErrorCode.HttpStatusCodeDifferent, SourceName, "Http response content type was invalid: {0}", response.ContentType)); } return(new ValidationResult <bool>(false, errors)); } } catch (Exception ex) { errors.Add(new ValidationError(ValidationErrorCode.Unknown, SourceName, "Exception while making request: {0}", ex.Message)); return(new ValidationResult <bool>(false, errors)); } }