/// <summary>
        /// Verify the rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater 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    qs      = HttpUtility.ParseQueryString(context.Destination.Query);
            string qExpand = qs["$expand"];

            if (!string.IsNullOrEmpty(qExpand))
            {
                JObject jo      = JObject.Parse(context.ResponsePayload);
                var     version = JsonParserHelper.GetPayloadODataVersion(jo);

                var        edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
                EntityType et;
                edmxHelper.TryGetItem(context.EntityTypeFullName, out et);

                var branches = ResourcePathHelper.GetBranchedSegments(qExpand);
                foreach (var paths in branches)
                {
                    var    navStack           = ODataUriAnalyzer.GetNavigationStack(et, paths).ToArray();
                    bool[] targetIsCollection = (from n in navStack select n.RelationshipMultiplicity == RelationshipMultiplicity.Many).ToArray();

                    // to verify each single entity type expanded along the navigation path to have proper properties
                    TestResult result = null;
                    for (int i = 0; i < paths.Length; i++)
                    {
                        string jSchema = null;

                        if (!targetIsCollection[i])
                        {
                            var    etShort = navStack[i].GetEntityType().FullName.GetLastSegment();
                            string jsET    = JsonSchemaHelper.GetSchemaForEntityType(etShort, context.MetadataDocument);
                            string jsCore  = string.Format(@"""{0}"" : {1}", paths[i], jsET);
                            jSchema = JsonSchemaHelper.GetJsonSchema(paths, i, version, jsCore, targetIsCollection);

                            passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out result);
                            if (!passed.Value)
                            {
                                break;
                            }
                        }
                    }

                    if (!passed.Value)
                    {
                        info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                        break;
                    }
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify Entry.Core.4657
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater 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;

            if (string.Empty != context.Destination.Query)
            {
                List <string> expandQueryVals = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");
                List <string> collectionTypeNavigPropNames = MetadataHelper.GetAppropriateNavigationPropertyNames(context, NavigationPropertyType.Entity);

                string      xpath  = @"/atom:entry/atom:link[@type='application/atom+xml;type=feed' or @type='application/atom+xml;type=entry']";
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(context.ResponsePayload);
                XmlNodeList linkElements = xmlDoc.SelectNodes(xpath, ODataNamespaceManager.Instance);

                if (linkElements.Count > 0)
                {
                    string metadataNp = ODataVersion.V4 == context.Version ?
                                        linkElements[0].ParentNode.GetPrefixOfNamespace(Constants.NSMetadata) :
                                        linkElements[0].ParentNode.GetPrefixOfNamespace(Constants.V3NSMetadata);

                    foreach (XmlNode le in linkElements)
                    {
                        if (null == le.Attributes["title"])
                        {
                            continue;
                        }

                        if (collectionTypeNavigPropNames.Contains(le.Attributes["title"].Value) &&
                            expandQueryVals.Contains(le.Attributes["title"].Value))
                        {
                            if (le.FirstChild == le.LastChild && metadataNp + @":inline" == le.FirstChild.Name)
                            {
                                XmlNode inlineNode = le.FirstChild;

                                if (!inlineNode.HasChildNodes)
                                {
                                    passed = true;
                                }
                            }
                            else
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                break;
                            }
                        }
                    }
                }
            }

            return(passed);
        }
예제 #3
0
        /// <summary>
        /// Verifies the semantic 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");
            }

            info = null;
            bool passed = true;

            // if query option of $expand is present, rule shall be verified
            // get the leftmost navigation property of expand query option
            var    qs      = HttpUtility.ParseQueryString(context.Destination.Query);
            string qExpand = qs["$expand"];

            if (!string.IsNullOrEmpty(qExpand))
            {
                var        edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
                EntityType et;
                edmxHelper.TryGetItem(context.EntityTypeFullName, out et);

                var     segments = ResourcePathHelper.GetPathSegments(context);
                UriType uriType;
                var     target = edmxHelper.GetTargetType(segments, out uriType);
                bool    isColletcionResource = uriType == UriType.URI1 || uriType == UriType.URI_CollEt;

                var branches = ResourcePathHelper.GetBranchedSegments(qExpand);
                foreach (var paths in branches)
                {
                    var    navStack           = ODataUriAnalyzer.GetNavigationStack(et, paths).ToArray();
                    bool[] targetIsCollection = (from n in navStack select n.RelationshipMultiplicity == RelationshipMultiplicity.Many).ToArray();

                    string rngCore = @"<ref name=""anyContent"" />";
                    for (int i = paths.Length - 1; i >= 0; i--)
                    {
                        rngCore = targetIsCollection[i] ? GetRngOfInlineFeed(paths[i], rngCore) : GetRngOfInlineEntry(paths[i], rngCore);
                    }

                    // construct the desired srng schema and verify
                    string rngSchema = isColletcionResource
                        ? string.Format(formatRngOfColl, rngCore, RngCommonPattern.CommonPatterns)
                        : string.Format(formatRngSingle, rngCore, RngCommonPattern.CommonPatterns);

                    RngVerifier verifier = new RngVerifier(rngSchema);
                    TestResult  result;
                    passed = verifier.Verify(context, out result);
                    if (!passed)
                    {
                        info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result.LineNumberInError);
                        break;
                    }
                }
            }

            return(passed);
        }
        /// <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;

            info = null;

            List <string> expandVals    = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");
            List <string> entity        = MetadataHelper.GetAppropriateNavigationPropertyNames(context, NavigationPropertyType.Entity);
            List <string> setOfEntities = MetadataHelper.GetAppropriateNavigationPropertyNames(context, NavigationPropertyType.SetOfEntities);

            if (expandVals.Count != 0)
            {
                JObject entry;
                context.ResponsePayload.TryToJObject(out entry);

                if (entry != null && entry.Type == JTokenType.Object)
                {
                    // Get all the properties in current entry.
                    var jProps = entry.Children();

                    foreach (JProperty jP in jProps)
                    {
                        if (jP.Value.Type == JTokenType.Object)
                        {
                            passed = true;

                            if (!entity.Contains(jP.Name) && expandVals.Contains(jP.Name))
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                break;
                            }
                        }
                        else if (jP.Value.Type == JTokenType.Array)
                        {
                            passed = true;

                            if (!setOfEntities.Contains(jP.Name) && expandVals.Contains(jP.Name))
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                break;
                            }
                        }
                    }
                }
            }

            return(passed);
        }
        /// <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;

            info = null;
            JObject   entry = null;
            JProperty expandAssociationProp = null;

            context.ResponsePayload.TryToJObject(out entry);
            List <string> expandProps = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");

            if (entry == null || entry.Type != JTokenType.Object || expandProps == null)
            {
                return(null);
            }

            var jProps = entry.Children();

            foreach (JProperty jProp in jProps)
            {
                if (!jProp.Name.Contains(Constants.OdataNavigationLinkPropertyNameSuffix))
                {
                    continue;
                }

                if (!jProp.Name.Contains(@"@"))
                {
                    continue;
                }

                int    index = jProp.Name.IndexOf(@"@");
                string temp  = jProp.Name.Remove(index, jProp.Name.Length - index);

                if (!expandProps.Contains(temp))
                {
                    continue;
                }

                if (jProp.Previous == null)
                {
                    continue;
                }

                expandAssociationProp = jProp.Previous as JProperty;
                if (expandAssociationProp.Name.Contains(Constants.OdataAssociationLinkPropertyNameSuffix))
                {
                    if (!expandAssociationProp.Name.Contains(@"@"))
                    {
                        continue;
                    }

                    index = expandAssociationProp.Name.IndexOf(@"@");
                    temp  = expandAssociationProp.Name.Remove(index, expandAssociationProp.Name.Length - index);

                    if (expandProps.Contains(temp))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                        break;
                    }
                }
            }

            return(passed);
        }
        /// <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;

            info = null;

            JObject entry;

            context.ResponsePayload.TryToJObject(out entry);

            List <string> expandProps = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");

            if (entry != null && entry.Type == JTokenType.Object && expandProps.Count > 0)
            {
                var props = entry.Children();

                foreach (JProperty prop in props)
                {
                    if (expandProps.Contains(prop.Name))
                    {
                        passed = null;

                        if (prop.Value.Type == JTokenType.Object)
                        {
                            JObject jObj = prop.Value as JObject;
                            JsonParserHelper.ClearPropertiesList();

                            if (JsonParserHelper.GetSpecifiedPropertiesFromEntryPayload(jObj, Constants.OdataV4JsonIdentity).Count > 0)
                            {
                                passed = true;
                                break;
                            }
                            else
                            {
                                passed = false;
                            }
                        }
                        else if (prop.Value.Type == JTokenType.Array)
                        {
                            JArray jArr = prop.Value as JArray;

                            if (JsonParserHelper.GetSpecifiedPropertiesFromFeedPayload(jArr, Constants.OdataV4JsonIdentity).Count > 0)
                            {
                                passed = true;
                                break;
                            }
                            else
                            {
                                passed = false;
                            }
                        }
                    }
                }

                if (passed == false)
                {
                    info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                }
            }

            return(passed);
        }
예제 #7
0
        /// <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;

            info = null;

            JObject entry;

            context.ResponsePayload.TryToJObject(out entry);

            XElement metadata = XElement.Parse(context.MetadataDocument);

            // Use the XPath query language to access the metadata document and get the node which will be used.
            string xpath = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", context.EntityTypeShortName);
            IEnumerable <XElement> props     = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance);
            List <string>          propNames = new List <string>();

            foreach (var prop in props)
            {
                propNames.Add(prop.Attribute("Name").Value);
            }

            List <string> queryOptionVals = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), "expand");

            if (entry != null && entry.Type == JTokenType.Object && queryOptionVals.Count != 0)
            {
                // Get all the properties in current entry.
                var jProps = entry.Children();

                foreach (JProperty jProp in jProps)
                {
                    bool mark = false;

                    if (propNames.Contains(jProp.Name) && queryOptionVals.Contains(jProp.Name))
                    {
                        passed = null;

                        if (jProp.Value.Type == JTokenType.Object)
                        {
                            passed = null;
                            mark   = true;
                        }
                        else if (jProp.Value.Type == JTokenType.Array)
                        {
                            passed = null;
                            mark   = true;
                        }
                        else if (jProp.Value.Type == JTokenType.Null)
                        {
                            passed = true;
                        }

                        if (passed == null && !mark)
                        {
                            passed = false;
                            info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                            break;
                        }
                    }
                }
            }

            return(passed);
        }
        /// <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;

            info = null;

            XElement metadata = XElement.Parse(context.MetadataDocument);

            // Use the XPath query language to access the metadata document and get the node which will be used.
            string xpath = @"//*[local-name()='EntityType']/*[local-name()='Property' or local-name()='NavigationProperty']";
            IEnumerable <XElement> propNameElements = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance);
            List <string>          propNames        = new List <string>();

            foreach (var propNameElement in propNameElements)
            {
                propNames.Add(propNameElement.Attribute("Name").Value);
            }

            List <string> queryOptionVals = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");
            bool          isQueryRefVals  = context.Destination.ToString().Contains(@"$ref");

            if (queryOptionVals.Count != 0)
            {
                JObject entry;
                context.ResponsePayload.TryToJObject(out entry);

                if (entry != null && entry.Type == JTokenType.Object)
                {
                    // Get all the properties in current entry.
                    var jProps = entry.Children();

                    // If the url contains the "$ref" marker, the program can verify the condition that each element must be represented as an entity reference.
                    // If the url does not contain the "$ref" marker, the program can verify the condition that each element must be represented as an entity.
                    if (isQueryRefVals)
                    {
                        foreach (JProperty jProp in jProps)
                        {
                            if (queryOptionVals.Contains(jProp.Name) && JTokenType.Array == jProp.Value.Type)
                            {
                                JEnumerable <JObject> jObjs = jProp.Value.Children <JObject>();

                                foreach (JObject jObj in jObjs)
                                {
                                    passed = null;
                                    var subProps = jObj.Children();

                                    foreach (JProperty subProp in subProps)
                                    {
                                        if (JsonSchemaHelper.IsAnnotation(subProp.Name) && subProp.Name.Contains(@"id"))
                                        {
                                            passed = true;
                                            break;
                                        }
                                    }

                                    if (passed == null)
                                    {
                                        passed = false;
                                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        foreach (JProperty jProp in jProps)
                        {
                            if (queryOptionVals.Contains(jProp.Name) && JTokenType.Array == jProp.Value.Type)
                            {
                                JEnumerable <JObject> jObjs = jProp.Value.Children <JObject>();

                                foreach (JObject jObj in jObjs)
                                {
                                    passed = null;

                                    // Get all the expand properties from current entity's property.
                                    var subProps = jObj.Children();

                                    foreach (JProperty subProp in subProps)
                                    {
                                        if (!JsonSchemaHelper.IsAnnotation(subProp.Name) && propNames.Contains(subProp.Name))
                                        {
                                            passed = true;
                                        }
                                        else if (!JsonSchemaHelper.IsAnnotation(subProp.Name) && !propNames.Contains(subProp.Name))
                                        {
                                            passed = false;
                                            info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(passed);
        }
예제 #9
0
        /// <summary>
        /// Verify Entry.Core.4110 rule logic
        /// </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: // If passed is true mean an empty set of entities is represented as an empty JSON array, passed is false means error, passed is null means an empty JSON array is not be found.</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            List <string> queryOptionVals = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), "expand");

            if (queryOptionVals.Count != 0)
            {
                // Use the XPath query language to access the metadata document and get the node which will be used.
                XElement metadata            = XElement.Parse(context.MetadataDocument);
                string   xpath               = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", context.EntityTypeShortName);
                IEnumerable <XElement> props = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance);

                JObject entry;
                context.ResponsePayload.TryToJObject(out entry);
                var o      = (JObject)entry;
                var jProps = o.Children();

                foreach (JProperty jProp in jProps)
                {
                    if (!queryOptionVals.Contains(jProp.Name))
                    {
                        continue;
                    }

                    // Whether the type of entities is array.
                    if (jProp.Value.Type == JTokenType.Array)
                    {
                        JArray jValues = jProp.Value as JArray;

                        // if the count of jProp.Value is 0, it means this entities is an empty set of entities.
                        if (jValues.Count == 0)
                        {
                            foreach (var prop in props)
                            {
                                // Whether expanded navigation property defined in metadata.
                                if (prop.Attribute("Name").Value.Contains(jProp.Name))
                                {
                                    passed = true;
                                    break;
                                }
                                else
                                {
                                    passed = false;
                                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                }
                            }
                        }
                    }
                }
            }

            return(passed);
        }
예제 #10
0
        /// <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;

            info = null;

            JObject entry;

            context.ResponsePayload.TryToJObject(out entry);

            List <string> expandProps = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");

            if (entry != null && entry.Type == JTokenType.Object && expandProps.Count != 0)
            {
                var jProps = entry.Children();

                foreach (JProperty jProp in jProps)
                {
                    if (jProp.Name.Contains(Constants.OdataAssociationLinkPropertyNameSuffix))
                    {
                        if (jProp.Next != null)
                        {
                            JProperty nextJProperty = ((JProperty)jProp.Next);

                            // Prase the annotation name to two parts.
                            string annotatedPro = jProp.Name.Remove(jProp.Name.LastIndexOf("@"), (jProp.Name.Length - jProp.Name.LastIndexOf("@")));

                            if (!nextJProperty.Name.Contains(Constants.OdataNavigationLinkPropertyNameSuffix))
                            {
                                if (nextJProperty.Name.Equals(annotatedPro))
                                {
                                    passed = true;
                                }
                                else
                                {
                                    foreach (JProperty jProRest in jProps)
                                    {
                                        if (jProRest.Name.Equals(annotatedPro))
                                        {
                                            passed = false;
                                            info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                            break;
                                        }
                                        else
                                        {
                                            passed = true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(passed);
        }
예제 #11
0
        /// <summary>
        /// Verify Entry.Core.4653
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater 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;

            List <string> expandNavigationPropNames = ODataUriAnalyzer.GetQueryOptionValsFromUrl(context.Destination.ToString(), @"expand");

            string        xpath          = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", context.EntityTypeShortName);
            XElement      metadata       = XElement.Parse(context.MetadataDocument);
            var           navigProps     = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance);
            List <string> navigPropNames = new List <string>();

            foreach (var np in navigProps)
            {
                navigPropNames.Add(np.Attribute(@"Name").Value);
            }

            xpath = @"/atom:entry/atom:link[@type='application/atom+xml;type=entry' or @type='application/atom+xml;type=feed']";
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.ResponsePayload);
            XmlNodeList linkElements = xmlDoc.SelectNodes(xpath, ODataNamespaceManager.Instance);

            if (0 == linkElements.Count)
            {
                return(null);
            }

            string metadataNpName = string.Empty;

            if (ODataVersion.V4 == context.Version)
            {
                metadataNpName = linkElements[0].ParentNode.GetPrefixOfNamespace(Constants.NSMetadata);
            }
            else
            {
                metadataNpName = linkElements[0].ParentNode.GetPrefixOfNamespace(Constants.V3NSMetadata);
            }

            foreach (XmlNode le in linkElements)
            {
                if (null == le.Attributes[@"title"])
                {
                    continue;
                }

                if (expandNavigationPropNames.Contains(le.Attributes[@"title"].Value) &&
                    navigPropNames.Contains(le.Attributes["title"].Value))
                {
                    if (1 == le.ChildNodes.Count && metadataNpName + @":inline" == le.FirstChild.Name)
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                        break;
                    }
                }
            }

            return(passed);
        }