public static async Task <ValidationResult> Validate(string baseUrl, string id, APIValidatorSettings settings = null) { settings = settings ?? new APIValidatorSettings(); if (string.IsNullOrEmpty(baseUrl)) { return(new ValidationResult() { Error = "Invalid base URL" }); } if (!Uri.TryCreate(baseUrl, UriKind.Absolute, out _)) { return(new ValidationResult() { Error = "Invalid base URL" }); } WebServiceReader webServiceReader = new WebServiceReader(settings); var result = new ValidationResult(); try { var paginator = new Paginator(); var paginationResults = await paginator.GetServices(baseUrl, id, webServiceReader, settings); result.IsUp = true; result.IsServiceFound = paginationResults.Items.Count > 0; if (paginationResults.Items.Count == 0) { result.HasPagination = false; } if (!paginationResults.HasAllowOrigin) { result.Warnings.Add("The 'Access-Control-Allow-Origin: *' response header is missing this limits how the API can be read."); } result.HasDetailPage = (paginationResults.MissingDetailIDs.Count != paginationResults.Items.Count || paginationResults.Items.Count == 0); result.MissingPaginationMetaData = paginationResults.MissingPaginationMetaData; result.HasInvalidTotalPages = paginationResults.HasInvalidTotalPages; if (paginationResults.Items.Count > 0) { var items = paginationResults.Items; result.RandomServiceIdentifier = items.ElementAt(rand.Next(items.Count)).id; } ResourceReader resourceReader = new ResourceReader(); List <string> resourceNames = await resourceReader.GetResourceNames().ConfigureAwait(false); List <IFeatureTest> featureTests = new List <IFeatureTest>(); Dictionary <string, Resource> allRequired = GetFields(await resourceReader.GetResources().ConfigureAwait(false)); foreach (var item in paginationResults.Items) { ValidateItems(item, resourceNames, allRequired); featureTests = FindFeatureTests(item, resourceNames, featureTests, allRequired); } foreach (KeyValuePair <string, Resource> kvp in allRequired) { result.AddResourceCount(kvp.Value); if (!kvp.Value.Exists) { continue; } foreach (Field field in kvp.Value.Fields) { if (field.IsRequired && field.Count == 0) { result.MissingRequiredFields.Add(kvp.Key + "." + field.Name); } if (field.IsUnique && field.Values.Distinct().Count() != field.Values.Count()) { result.InvalidUniqueFields.Add(kvp.Key + "." + field.Name); } if (!field.IsValidFormat()) { result.InvalidFormats.Add(kvp.Key + "." + field.Name + " should be in " + field.Format + " format"); } if (!field.IsValidDataType()) { result.InvalidDataTypes.Add(kvp.Key + "." + field.Name + " should be in the " + field.DataType + " data type"); } if (!field.IsValidEnum()) { result.InvalidValues.Add(kvp.Key + "." + field.Name + " should be one of the following values " + string.Join(", ", field.AllowedValues)); } } } result.Level2Results = await RunLevel2Tests(baseUrl, result, featureTests, webServiceReader); } catch (ServiceDirectoryException e) { result.Error = e.Message; result.SetException(e); } catch (Exception e) { result.Error = e.Message; result.SetException(e); } try { result.PerformFinalReview(); return(result); } catch (Exception e) { result.Error = e.Message; result.SetException(e); return(result); } }