/// <summary> /// Verify Metadata.Core.4287 /// </summary> /// <param name="context">Service context</param> /// <param name="info">out parameter to return violation information when rule fail</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; info = null; var metadata = XElement.Parse(context.MetadataDocument); string xPath = "//*[local-name()='Schema']/*[local-name()='Function' and @IsBound='true']"; var functionElems = metadata.XPathSelectElements(xPath, ODataNamespaceManager.Instance); foreach (var functionElem in functionElems) { xPath = "./*[local-name()='Parameter']"; var parameterElem = functionElem.XPathSelectElement(xPath, ODataNamespaceManager.Instance); if (null == parameterElem || null == parameterElem.Attribute("Type")) { continue; } string entityTypeShortName = parameterElem.GetAttributeValue("Type").RemoveCollectionFlag().GetLastSegment(); if (null != functionElem.Attribute("EntitySetPath") && !string.IsNullOrEmpty(entityTypeShortName)) { string entitySetPathVal = functionElem.GetAttributeValue("EntitySetPath"); string[] separations = entitySetPathVal.Split('/'); var navigTree = NavigateTreeNode.Parse(entityTypeShortName); for (int i = 1; i < separations.Length; i++) { if (i > 1 && !separations[i - 1].IsTypeCastSegment()) { if (null != navigTree.Search(separations[i - 1])) { entityTypeShortName = navigTree.Search(separations[i - 1]).Data.TypeShortName; } } else if (i > 1 && separations[i - 1].IsTypeCastSegment()) { entityTypeShortName = separations[i - 1].GetLastSegment(); } if (null != navigTree.Search(separations[i], entityTypeShortName) || separations[i].IsTypeCastSegment()) { passed = true; } else { passed = false; break; } } } } info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload); return(passed); }
/// <summary> /// Verify Metadata.Core.4330 /// </summary> /// <param name="context">Service context</param> /// <param name="info">out parameter to return violation information when rule fail</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; info = null; var metadata = XElement.Parse(context.MetadataDocument); string xPath = "//*[local-name()='NavigationPropertyBinding']"; var navigationPropertyBindingElems = metadata.XPathSelectElements(xPath, ODataNamespaceManager.Instance); if (null == navigationPropertyBindingElems || !navigationPropertyBindingElems.Any()) { return(passed); } navigationPropertyBindingElems = navigationPropertyBindingElems .Where(elem => null != elem.Attribute("Path")) .Select(elem => elem); if (null == navigationPropertyBindingElems || !navigationPropertyBindingElems.Any()) { return(passed); } foreach (var navigationPropertyBindingElem in navigationPropertyBindingElems) { string pathAttribVal = navigationPropertyBindingElem.GetAttributeValue("Path"); int slashIndex = pathAttribVal.LastIndexOf('/'); string navigationPropertyName = pathAttribVal.Remove(0, slashIndex + 1); string nTypeShortName = string.Empty; if (slashIndex != -1) { nTypeShortName = pathAttribVal.Substring(0, slashIndex).GetLastSegment(); if (nTypeShortName.IsSpecifiedComplexTypeShortNameExist()) { nTypeShortName = null; } } var parentElement = navigationPropertyBindingElem.Parent; if (null == parentElement) { return(passed); } string entityTypeShortName = string.Empty; if ("EntitySet" == parentElement.Name.LocalName && null != parentElement.Attribute("EntityType")) { entityTypeShortName = parentElement.GetAttributeValue("EntityType").GetLastSegment(); if (slashIndex == -1) { nTypeShortName = entityTypeShortName; } } else if ("Singleton" == parentElement.Name.LocalName && null != parentElement.Attribute("Type")) { entityTypeShortName = parentElement.GetAttributeValue("Type").GetLastSegment(); if (slashIndex == -1) { nTypeShortName = entityTypeShortName; } } if (!entityTypeShortName.IsSpecifiedEntityTypeShortNameExist()) { return(null); } var navigTreeNode = NavigateTreeNode.Parse(entityTypeShortName); var node = navigTreeNode.Search(navigationPropertyName, nTypeShortName); while (null != node && null != node.Parent) { if (node.Parent.Data.ContainsTarget || "root" == node.Parent.Data.Name) { passed = true; } else { passed = false; break; } node = node.Parent; } } info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload); return(passed); }