/// <summary> /// Verifies the extension rule. /// </summary> /// <param name="context">The Interop service context</param> /// <param name="info">out parameter to return violation information when rule does not pass</param> /// <returns>true if rule passes; false otherwise</returns> public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info) { if (context == null) { throw new ArgumentNullException("context"); } bool?passed = null; ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name); var expandRestrictions = AnnotationsHelper.GetExpandRestrictions(context.MetadataDocument, context.VocCapabilities); if (string.IsNullOrEmpty(expandRestrictions.Item1) || null == expandRestrictions.Item3 || !expandRestrictions.Item3.Any()) { detail.ErrorMessage = "Cannot find an appropriate entity-set which supports $expand system query options."; info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail); return(passed); } string entitySet = expandRestrictions.Item1; string navigProp = expandRestrictions.Item3.First().NavigationPropertyName; string url = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet); var resp = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders); detail.URI = url; detail.ResponsePayload = resp.ResponsePayload; detail.ResponseHeaders = resp.ResponseHeaders; detail.HTTPMethod = "GET"; detail.ResponseStatusCode = resp.StatusCode.ToString(); if (null == resp || HttpStatusCode.OK != resp.StatusCode) { detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload); info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail); return(passed); } JObject feed; resp.ResponsePayload.TryToJObject(out feed); var entities = JsonParserHelper.GetEntriesThatHaveAValue(feed); if (null == entities || 0 == entities.Count) { detail.ErrorMessage = string.Format("The entity-set {0} has no entity.", entitySet); info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail); return(passed); } var entity = entities.First; string entityURL = null != entity[Constants.V4OdataId] ? entity[Constants.V4OdataId].ToString() : string.Empty; if (string.IsNullOrEmpty(entityURL)) { detail.ErrorMessage = "Cannot find the annotation @odata.id in the current entity."; info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail); return(passed); } url = string.Format("{0}?$expand={1}/$ref", entityURL, navigProp); if (url.IndexOf(context.ServiceBaseUri.OriginalString) < 0) { url = context.ServiceBaseUri.OriginalString + url; } resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders); detail = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp); detail.URI = url; detail.ResponsePayload = resp.ResponsePayload; detail.ResponseHeaders = resp.ResponseHeaders; detail.HTTPMethod = "GET"; detail.ResponseStatusCode = resp.StatusCode.ToString(); if (resp.StatusCode == HttpStatusCode.OK) { JObject entry; resp.ResponsePayload.TryToJObject(out entry); if (entry != null && JTokenType.Object == entry.Type) { bool entity_error = false; try { entity = entry[navigProp].First; } catch { entity_error = true; passed = false; detail.ErrorMessage = "The service does not execute an accurate result, because the value of the Navigation (" + navigProp + ") does not exist in the entity. Request attempted: " + url + " Response: " + resp.ResponsePayload; } if (!entity_error) { try { var test = entity; var test1 = entity[Constants.V4OdataId]; url = entity[Constants.V4OdataId].ToString(); } catch (Exception ex) { entity_error = true; passed = false; detail.ErrorMessage = ex.Message + " Attempt to access: " + Constants.V4OdataId + " Response: " + resp.ResponsePayload; } if (!entity_error) { if (url.IndexOf(context.ServiceBaseUri.OriginalString) < 0) { url = context.ServiceBaseUri.OriginalString + url; } Uri testurl = null; try { testurl = new Uri(url); } catch { } if (testurl != null) { resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders); detail.URI = url; detail.ResponsePayload = resp.ResponsePayload; detail.ResponseHeaders = resp.ResponseHeaders; detail.HTTPMethod = "GET"; detail.ResponseStatusCode = resp.StatusCode.ToString(); if (resp.StatusCode == HttpStatusCode.OK) { passed = true; } else { passed = false; detail.ErrorMessage = "The service does not execute an accurate result, because the value of the annotation '@odata.id' (" + url + ") is a bad link."; } } else { passed = false; detail.ErrorMessage = "The service does not execute an accurate result, because the value of the annotation '@odata.id' (" + url + ") is a bad link."; } } } } } else { passed = false; detail.ErrorMessage = "The service does not support the '$ref' segment for expanded properties."; } info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail); return(passed); }