/// <summary>
        /// Verify Metadata.Core.4234
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            XmlNodeList typeDefNodeList = xmlDoc.SelectNodes("//*[local-name()='TypeDefinition']");

            foreach (XmlNode typeDef in typeDefNodeList)
            {
                if (typeDef.Attributes["UnderlyingType"] != null && EdmTypeManager.IsEdmSimpleType(typeDef.Attributes["UnderlyingType"].Value))
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                    break;
                }
            }

            return(passed);
        }
        /// <summary>
        /// Construct a complex type value according to its metadata definition.
        /// </summary>
        /// <param name="complexName">The name of the complex type.</param>
        /// <returns>The JSON object value of the complex type.</returns>
        public JObject ConstructAComplexTypeValue(string complexName)
        {
            string        metadataDoc              = ServiceStatus.GetInstance().MetadataDocument;
            JObject       result                   = new JObject();
            List <string> complextTypeNames        = MetadataHelper.GetAllComplexNameFromMetadata(metadataDoc);
            Dictionary <string, string> properties = MetadataHelper.GetAllPropertiesOfComplexType(metadataDoc, complexName);

            foreach (string prop in properties.Keys)
            {
                string type = properties[prop];
                if (EdmTypeManager.IsEdmSimpleType(type))
                {
                    IEdmType edmType = EdmTypeManager.GetEdmType(type);
                    result[prop] = edmType.GetJsonValueTemplate();
                }
                else if (type.Contains("Collection"))
                {
                    string itemType = type.Substring(type.IndexOf('(') + 1, type.Length - 12).GetLastSegment();

                    result[prop] = ConstructCollectionTypeValue(itemType);
                }
                else if (MetadataHelper.IsEnumType(metadataDoc, type))
                {
                    result[prop] = ConstructEnumTypeValue(type);
                }
                else if (complextTypeNames != null && complextTypeNames.Contains(type))
                {
                    result[prop] = ConstructAComplexTypeValue(type);
                }
            }

            return(result);
        }
Example #3
0
        /// <summary>
        /// Verify IndividualProperty.Core.4607
        /// </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;

            XmlDocument xmlDoc = new XmlDocument();

            // Test Data
            // 1. Collection of string. Url:http://services.odata.org/V4/OData/OData.svc/Products(0)/Description?$format=xml
            // xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value m:context=\"http://services.odata.org/V4/OData/OData.svc/$metadata#Collection(Edm.String)\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element>Whole grain</m:element> <m:element>bread</m:element></m:value>");
            // 2. Collection of complext type. Url: http://services.odata.org/V4/OData/OData.svc/PersonDetails(0)/Address?$format=xml
            // xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value m:context=\"http://services.odata.org/V4/OData/OData.svc/$metadata#Collection(ODataDemo.Address)\" m:type=\"#Collection(ODataDemo.Address)\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element><d:Street>2817 Milton Dr.</d:Street><d:City>Albuquerque</d:City><d:State>NM</d:State><d:ZipCode>87110</d:ZipCode><d:Country>USA</d:Country></m:element><m:element><d:Street>2817 Milton Dr.</d:Street><d:City>Detorlee</d:City><d:State>UT</d:State><d:ZipCode>124450</d:ZipCode><d:Country>USA</d:Country></m:element></m:value>");
            // Metadata: modify PersonDatail 's Address Type to Collection(ODataDemo.Address)
            xmlDoc.LoadXml(context.ResponsePayload);
            XmlElement root = xmlDoc.DocumentElement;

            if (root.LocalName.Equals("value") && root.NamespaceURI.Equals(Constants.NSMetadata))
            {
                if (root.Attributes["context", Constants.NSMetadata] != null)
                {
                    string contextURI      = root.Attributes["context", Constants.NSMetadata].Value;
                    string propertyTypeCol = contextURI.Remove(0, contextURI.IndexOf('#') + 1);

                    if (!propertyTypeCol.Contains("Collection("))
                    {
                        return(null);
                    }

                    string propertyType          = propertyTypeCol.Substring(propertyTypeCol.IndexOf('(') + 1, propertyTypeCol.Length - 12);
                    string propertyTypeShortName = propertyType.GetLastSegment();
                    var    metadata = XElement.Parse(context.MetadataDocument);

                    // Built-in primitive types.
                    if (propertyType.Contains("Edm.") && EdmTypeManager.IsEdmSimpleType(propertyType))
                    {
                        return(true);
                    }

                    // Complex type.
                    List <string> complextTypes = MetadataHelper.GetAllComplexNameFromMetadata(context.MetadataDocument);
                    if (complextTypes.Contains(propertyTypeShortName))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                    }
                }
            }

            return(passed);
        }
        /// <summary>
        /// Provide the value tempalte of a collection.
        /// </summary>
        /// <param name="type">The name of the collection content type.</param>
        /// <returns>The JSON array of the collection.</returns>
        public JArray ConstructCollectionTypeValue(string type)
        {
            string        metadataDoc       = ServiceStatus.GetInstance().MetadataDocument;
            JArray        array             = new JArray();
            List <string> complextTypeNames = MetadataHelper.GetAllComplexNameFromMetadata(metadataDoc);

            if (EdmTypeManager.IsEdmSimpleType(type))
            {
                string value = ConstructPrimitiveTypeValue(type);
                array.Add(value);
                array.Add(value);
            }
            else if (complextTypeNames != null && complextTypeNames.Count > 0 && complextTypeNames.Contains(type))
            {
                JObject objValue = ConstructAComplexTypeValue(type);
                array.Add(objValue);
                array.Add(objValue);
            }
            else if (MetadataHelper.IsEnumType(metadataDoc, type))
            {
                array.Add(ConstructEnumTypeValue(type));
                array.Add(ConstructEnumTypeValue(type));
            }

            return(array);
        }
        /// <summary>
        /// Get property type and type class.
        /// </summary>
        /// <param name="entityTypeShortName"> The short name of entity type.</param>
        /// <param name="propertyName">The name of the property in the entity type.</param>
        /// <returns>The key value pair in which key is the property type short name and the value is the property type class.</returns>
        private KeyValuePair <string, PropertyTypeClass>?GetPropertyTypeClass(string entityTypeShortName, string propertyName)
        {
            string pattern        = "//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='Property' and @Name='{1}']";
            string metadataString = ServiceStatus.GetInstance().MetadataDocument;
            var    metadata       = XElement.Parse(metadataString);

            string   xPath = string.Format(pattern, entityTypeShortName, propertyName);
            XElement prop  = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

            if (prop == null)
            {
                return(null);
            }

            string propType          = prop.GetAttributeValue("Type");
            string propTypeShortName = propType.RemoveCollectionFlag().GetLastSegment();

            PropertyTypeClass typeClass = PropertyTypeClass.Unknown;
            string            type      = propTypeShortName;

            if (propType.Contains("Collection("))
            {
                typeClass = PropertyTypeClass.CollectionType;
            }
            else if (EdmTypeManager.IsEdmSimpleType(propType))
            {
                typeClass = PropertyTypeClass.PrimitiveType;
                type      = propType;
            }
            else
            {
                xPath = string.Format("//*[@Name = '{0}']", propTypeShortName);

                XElement typeDefElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                if (typeDefElement == null)
                {
                    return(null);
                }

                switch (typeDefElement.Name.LocalName)
                {
                case "ComplexType":
                    typeClass = PropertyTypeClass.ComplexType;
                    break;

                case "EnumType":
                    typeClass = PropertyTypeClass.EnumType;
                    break;

                default:
                    typeClass = PropertyTypeClass.Unknown;
                    break;
                }
            }

            return(new KeyValuePair <string, PropertyTypeClass>(type, typeClass));
        }
Example #6
0
        /// <summary>
        /// Verify Entry.Core.2018
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            // Get all the properties
            XmlNodeList   propertyNodeList      = xmlDoc.SelectNodes("//*[local-name()='EntityType' and @Name = '" + context.EntityTypeShortName + "']/*[local-name()='Property']");
            List <string> complexTypeProperties = new List <string>();

            // Get all Complex Type properties
            foreach (XmlNode node in propertyNodeList)
            {
                if (!EdmTypeManager.IsEdmSimpleType(node.Attributes["Type"].Value))
                {
                    complexTypeProperties.Add(node.Attributes["Type"].Value);
                }
            }

            if (complexTypeProperties.Count > 0)
            {
                var complexTypePropertyList = complexTypeProperties.GroupBy(c => c);

                XmlDocument xmlDoc2 = new XmlDocument();
                xmlDoc2.LoadXml(context.ResponsePayload);
                XmlNodeList nodeList;

                // Verify that all Complex Type properties are represent under m:properties
                foreach (var complexTypeProperty in complexTypePropertyList)
                {
                    nodeList = xmlDoc2.SelectNodes("//*[@*[local-name()='type'] = '" + complexTypeProperty.Key + "']");

                    if (nodeList.Count == complexTypeProperty.Count())
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        break;
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);

            return(passed);
        }
Example #7
0
        /// <summary>
        /// Verify Common.Core.4624
        /// </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;

            XmlDocument xmlDoc = new XmlDocument();

            // Single primitive individual property is not allowed to have instance annotation.
            if (VerificationHelper.IsIndividualPropertySinglePrimitiveType(context.ResponsePayload, context.PayloadType))
            {
                return(null);
            }

            // Test Data
            // Url:http://services.odata.org/V4/OData/OData.svc/Products(0)/Description?$format=xml
            // xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value m:context=\"http://services.odata.org/V4/OData/OData.svc/$metadata#Products(0)/Description\" xmlns:atom=\"http://www.w3.org/2005/Atom\"  xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\">Whole grain bread <m:annotation atom:term=\"ODataDemo.Product.Display\" m:target=\"Description\" m:type=\"Boolean\">true</m:annotation></m:value>");
            xmlDoc.LoadXml(context.ResponsePayload);

            XmlNodeList annotationElements = xmlDoc.SelectNodes(@"//*[local-name()='annotation']", ODataNamespaceManager.Instance);

            foreach (XmlNode annotatEle in annotationElements)
            {
                if (annotatEle.Attributes["type", Constants.NSMetadata] != null)
                {
                    string typeName = annotatEle.Attributes["type", Constants.NSMetadata].Value;

                    if (!typeName.Contains("."))
                    {
                        typeName = "Edm." + typeName;
                    }

                    if (!EdmTypeManager.IsEdmSimpleType(typeName))
                    {
                        continue;
                    }

                    if (typeName != "Edm.String")
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                        break;
                    }
                }
            }

            return(passed);
        }
        /// <summary>
        /// Provide value template for a primitive type.
        /// </summary>
        /// <param name="type">The primitive type name.</param>
        /// <returns>The template value of the primitive type.</returns>
        public string ConstructPrimitiveTypeValue(string type)
        {
            if (EdmTypeManager.IsEdmSimpleType(type))
            {
                IEdmType edmType = EdmTypeManager.GetEdmType(type);
                return(edmType.GetJsonValueTemplate());
            }

            return(null);
        }
Example #9
0
        /// <summary>
        /// Verify the code 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     segments   = ResourcePathHelper.GetPathSegments(context).ToArray();
            var     edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
            UriType uriType;
            var     target = edmxHelper.GetTargetType(segments, out uriType);

            if (uriType == UriType.URI4 || uriType == UriType.URI5)
            {
                passed = false;
                string  targetType = ((EdmProperty)target).TypeUsage.EdmType.FullName;
                string  property   = segments.LastOrDefault(s => !s.StartsWith("$"));
                JObject jo         = JObject.Parse(context.ResponsePayload);
                var     inner      = jo.ReachInnerToken();
                if (inner.Type == JTokenType.Object)
                {
                    JObject innerObj = (JObject)inner;
                    if (innerObj.Properties() != null && innerObj.Properties().Count() == 1)
                    {
                        var    value        = innerObj.Properties().First().Value;
                        string valueLiteral = value.ToString();

                        IEdmType type = EdmTypeManager.GetEdmType(targetType);

                        bool isValidJsonData = type.IsGoodInJsonWith(valueLiteral);
                        if (isValidJsonData)
                        {
                            passed = true;
                        }
                        else
                        {
                            // target type may allow null
                            //TODO: allow null only when the target type is nullable
                            passed = valueLiteral.Equals("null", StringComparison.Ordinal);
                        }
                    }
                }
            }

            if (passed.HasValue && !passed.Value)
            {
                info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, -1);
            }

            return(passed);
        }
        /// <summary>
        /// Verify 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</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            // Load MetadataDocument into XMLDOM
            XmlDocument mdDoc = new XmlDocument();

            mdDoc.LoadXml(context.MetadataDocument);

            // Load payload into XMLDOM and find all properties marked m:null as true
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.ResponsePayload);
            XmlNodeList nullPropertyList = xmlDoc.SelectNodes("//*[@*[name()='m:null'] = 'true']");

            XmlNode propertyNode;

            foreach (XmlNode node in nullPropertyList)
            {
                if (node.ParentNode.LocalName.Equals("properties", StringComparison.InvariantCultureIgnoreCase))
                {
                    propertyNode = mdDoc.SelectSingleNode("//*[local-name()='EntityType' and @Name = '" + context.EntityTypeShortName + "']/*[local-name()='Property' and @Name = '" + node.LocalName + "']");
                }
                else
                {
                    var tempNode = mdDoc.SelectSingleNode("//*[local-name()='EntityType' and @Name = '" + context.EntityTypeShortName + "']/*[local-name()='Property' and @Name = '" + node.ParentNode.LocalName + "']");
                    propertyNode = mdDoc.SelectSingleNode("//*[local-name()='ComplexType' and @Name = '" + tempNode.Attributes["Type"].Value.Split('.').Last() + "']/*[local-name()='Property' and @Name = '" + node.LocalName + "']");
                }

                if (node.InnerText == "")
                {
                    if (EdmTypeManager.IsEdmSimpleType(propertyNode.Attributes["Type"].Value))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        break;
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);

            return(passed);
        }
Example #11
0
        /// <summary>
        /// Verify Metadata.Core.2013
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            // Find all EntityType nodes
            XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//*/*[local-name()='EntityType']");

            foreach (XmlNode entityTypeNode in xmlNodeList)
            {
                if (entityTypeNode.Attributes["m:FC_TargetPath"] != null)
                {
                    if (entityTypeNode.Attributes["m:FC_SourcePath"] != null)
                    {
                        string  typeName = entityTypeNode.Attributes["m:FC_SourcePath"].Value.Split('/').Last();
                        XmlNode node     = entityTypeNode.SelectSingleNode("//*[local-name()='Property' and @Name = '" + typeName + "']");

                        if (EdmTypeManager.IsEdmSimpleType(node.Attributes["Type"].Value))
                        {
                            passed = false;
                            break;
                        }
                        else
                        {
                            passed = true;
                        }
                    }
                    else
                    {
                        passed = false;
                        break;
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);

            return(passed);
        }
Example #12
0
        /// <summary>
        /// Verify the code 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 segments = ResourcePathHelper.GetPathSegments(context).ToArray();

            if (segments.Length > 0)
            {
                string lastSeg = segments[segments.Length - 1];
                if (lastSeg.Equals("$value", StringComparison.Ordinal))
                {
                    var     edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
                    UriType uriType;
                    var     target = edmxHelper.GetTargetType(segments, out uriType);
                    if (uriType == UriType.URI4 || uriType == UriType.URI5)
                    {
                        string targetType = ((EdmProperty)target).TypeUsage.EdmType.FullName;
                        if (!string.IsNullOrEmpty(targetType))
                        {
                            // do the validation here
                            IEdmType type = EdmTypeManager.GetEdmType(targetType);
                            if (type != null)
                            {
                                passed = type.IsGoodWith(context.ResponsePayload);
                                if (passed.HasValue && !passed.Value)
                                {
                                    info = new ExtensionRuleViolationInfo("pattern not matched", context.Destination, context.ResponsePayload, 1);
                                }
                            }
                            else
                            {
                                // type unknown
                                info   = new ExtensionRuleViolationInfo("unrecognized Edm type", context.Destination, targetType, 1);
                                passed = false;
                            }
                        }
                    }
                }
            }

            return(passed);
        }
Example #13
0
        /// <summary>
        /// Checks whether the value is well-formatted based on the type
        /// </summary>
        /// <param name="value">The value</param>
        /// <param name="typeName">Name of the type</param>
        /// <returns>bool indicating value being well-formatted</returns>
        protected bool VerifyValueByPrimitiveType(string value, string typeName)
        {
            bool result = true;

            if (!string.IsNullOrEmpty(value))
            {
                IEdmType type = EdmTypeManager.GetEdmType(typeName);
                if (type == null)
                {
                    //unrecognized primitive type
                    result = false;
                }
                else
                {
                    result = type.IsGoodWith(value);
                }
            }

            return(result);
        }
Example #14
0
        /// <summary>
        /// Verify Metadata.Core.4076
        /// </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;

            XmlDocument metadata = new XmlDocument();

            metadata.LoadXml(context.MetadataDocument);
            string xpath = @"/*[local-name()='Edmx']/*[local-name()='DataServices']/*[local-name()='Schema']/*[local-name()='EntityType' or local-name()='ComplexType']/*[local-name()='Property']";

            XmlNodeList propertyCollection = metadata.SelectNodes(xpath, ODataNamespaceManager.Instance);

            foreach (XmlNode property in propertyCollection)
            {
                if (property.Attributes["Precision"] == null ||
                    (property.Attributes["Type"] != null && !EdmTypeManager.IsTemporalTypeName(property.Attributes["Type"].Value))
                    )
                {
                    continue;
                }

                int precision;
                if (Int32.TryParse(property.Attributes["Precision"].Value, out precision) && precision >= 0 && precision < 12)
                {
                    passed = true;
                }
                else
                {
                    passed = false; break;
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
            return(passed);
        }
        /// <summary>
        /// Verify Entry.Core.2018
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            XmlNode keyNode = xmlDoc.SelectSingleNode("//*[local-name()='EntityType' and @Name = '" + context.EntityTypeShortName + "']/*[local-name()='Key']");

            if (keyNode != null)
            {
                foreach (XmlNode node in keyNode.ChildNodes)
                {
                    XmlNode propertyNode = xmlDoc.SelectSingleNode("//*[local-name()='EntityType' and @Name = '" + context.EntityTypeShortName + "']/*[local-name()='Property' and @Name='" + node.Attributes["Name"].Value + "']");

                    if (EdmTypeManager.IsEdmSimpleType(propertyNode.Attributes["Type"].Value))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        break;
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);

            return(passed);
        }
        /// <summary>
        /// Verify Metadata.Core.2017
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            // Find all Proeprty nodes with ConcurrencyMode = "Fixed"
            XmlNodeList propertyNodeList = xmlDoc.SelectNodes("//*[@*[name()='ConcurrencyMode'] = 'Fixed']");

            if (propertyNodeList.Count != 0)
            {
                foreach (XmlNode propertyNode in propertyNodeList)
                {
                    if (EdmTypeManager.IsEdmSimpleType(propertyNode.Attributes["Type"].Value))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        break;
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);

            return(passed);
        }
Example #17
0
        /// <summary>
        /// Verify IndividualProperty.Core.4606
        /// </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;

            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.ResponsePayload);
            XmlElement root = xmlDoc.DocumentElement;

            XElement metadata            = XElement.Parse(context.MetadataDocument);
            string   xpath               = string.Empty;
            string   individualPropType  = string.Empty;
            string   entityTypeShortName = string.Empty;

            if (root.LocalName.Equals("value") && root.NamespaceURI.Equals(Constants.NSMetadata))
            {
                if (root.Attributes["context", Constants.NSMetadata] != null)
                {
                    string contextURI   = root.Attributes["context", Constants.NSMetadata].Value;
                    string propertyType = contextURI.Remove(0, contextURI.IndexOf('#') + 1);

                    if (propertyType.Contains("Collection("))
                    {
                        return(null);
                    }

                    string[] types = propertyType.Split('/');
                    if (types.Length == 2)
                    {
                        if (types[0].Contains("("))
                        {
                            string entitySetName = types[0].Remove(types[0].IndexOf('('));
                            entityTypeShortName = entitySetName.MapEntitySetNameToEntityTypeShortName();
                        }
                        else
                        {
                            xpath = string.Format(@"//*[local-name()='Singleton' and @Name='{0}']", types[0]);
                            XElement singleton = metadata.XPathSelectElement(xpath, ODataNamespaceManager.Instance);
                            entityTypeShortName = singleton.GetAttributeValue("Type").GetLastSegment();
                        }

                        individualPropType = MetadataHelper.GetPropertyTypeFromMetadata(types[1], entityTypeShortName, context.MetadataDocument);
                    }
                    else if (types.Length < 2)
                    {
                        individualPropType = propertyType;
                    }

                    if (!individualPropType.Equals("Edm.String"))
                    {
                        xpath = @"//*[local-name()='DataServices']/*[local-name()='Schema']";
                        List <string> qualitifiedNamespaces = MetadataHelper.GetPropertyValues(context, xpath, "Namespace");
                        List <string> qualitifiedAliases    = MetadataHelper.GetPropertyValues(context, xpath, "Alias");
                        if (root.Attributes["type", Constants.NSMetadata] != null)
                        {
                            string typeName = root.Attributes["type", Constants.NSMetadata].Value;
                            if (!typeName.Contains("."))
                            {
                                typeName = "Edm." + typeName;
                            }

                            if ((this.IsContainsSpecialStrings(qualitifiedNamespaces, typeName) || this.IsContainsSpecialStrings(qualitifiedAliases, typeName)) ||
                                EdmTypeManager.IsEdmSimpleType(typeName))
                            {
                                passed = true;
                            }
                            else
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                            }
                        }
                    }
                }
            }

            return(passed);
        }
Example #18
0
        /// <summary>
        /// Verifies the service implementation feature.
        /// </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 the service implementation feature 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 svcStatus = ServiceStatus.GetInstance();

            string url    = svcStatus.RootURL.TrimEnd('/');
            var    detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);

            JObject serviceJO;

            svcStatus.ServiceDocument.TryToJObject(out serviceJO);

            JArray serviceOA = JsonParserHelper.GetEntries(serviceJO);

            string   xpath          = string.Format(@"//*[local-name()='FunctionImport']");
            XElement md             = XElement.Parse(svcStatus.MetadataDocument);
            XElement functionImport = md.XPathSelectElement(xpath, ODataNamespaceManager.Instance);

            if (functionImport == null)
            {
                detail.ErrorMessage = "The service has no function Import.";
                info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                return(passed);
            }

            string functionShortName = functionImport.Attribute("Function").Value.GetLastSegment();

            XElement function = md.XPathSelectElement(string.Format(@"//*[local-name()='Function' and @Name='{0}' and not (@IsBound='true')]", functionShortName), ODataNamespaceManager.Instance);

            string parameterString = string.Empty;
            List <KeyValuePair <string, string> > paralist = new List <KeyValuePair <string, string> >();

            if (function != null)
            {
                IEnumerable <XElement> parameters = function.XPathSelectElements(@"./*[local-name()='Parameter' and @Nullable='false']");
                foreach (XElement pa in parameters)
                {
                    string value = string.Empty;

                    if (EdmTypeManager.IsEdmSimpleType(pa.Attribute("Type").Value))
                    {
                        IEdmType typeInterface = EdmTypeManager.GetEdmType(pa.Attribute("Type").Value);
                        if (typeInterface != null)
                        {
                            value = typeInterface.GetXmlValueTemplate();
                        }
                    }

                    if (!string.IsNullOrEmpty(value))
                    {
                        KeyValuePair <string, string> kv = new KeyValuePair <string, string>(pa.Attribute("Name").Value, value);
                        paralist.Add(kv);
                    }
                    else
                    {
                        detail.ErrorMessage = "Parameter type is not supported by this test.";
                        info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                        return(passed);
                    }
                }
            }

            for (int i = 0; i < paralist.Count; i++)
            {
                if (i == 0)
                {
                    parameterString = "(" + paralist[i].Key + "=" + paralist[i].Value;
                }
                else if (i < paralist.Count - 1)
                {
                    parameterString += "," + paralist[i].Key + "=" + paralist[i].Value;
                }
                else if (i == paralist.Count - 1)
                {
                    parameterString += "," + paralist[i].Key + "=" + paralist[i].Value + ")";
                }
            }

            url += @"/" + functionShortName + parameterString;

            Response response = WebHelper.GetEntity(url);

            if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.NoContent)
            {
                detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                passed = true;
            }
            else
            {
                passed = false;
            }

            info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
            return(passed);
        }
Example #19
0
        /// <summary>
        /// Verify Metadata.Core.4486
        /// </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;

            string      mergedMetadata        = context.ContainsExternalSchema ? context.MergedMetadataDocument : context.MetadataDocument;
            XmlDocument xmlDoc_MergedMetadata = new XmlDocument();

            xmlDoc_MergedMetadata.LoadXml(mergedMetadata);

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            List <XmlNode> NvPropNodeList = new List <XmlNode>();

            XmlNodeList NodeList          = xmlDoc.SelectNodes("//*[local-name()='PropertyPath']");
            XmlNodeList AttributeNodeList = xmlDoc.SelectNodes("//*[@PropertyPath]");

            foreach (XmlNode NvProp in AttributeNodeList)
            {
                NvPropNodeList.Add(NvProp);
            }

            foreach (XmlNode NvProp in NodeList)
            {
                NvPropNodeList.Add(NvProp);
            }

            foreach (XmlNode NvPropPath in NvPropNodeList)
            {
                string path;
                if (NvPropPath.Attributes["PropertyPath"] != null)
                {
                    path = NvPropPath.Attributes["PropertyPath"].Value;
                }
                else
                {
                    path = NvPropPath.InnerText;
                }

                XmlNode parentOrTarget = NvPropPath;

                while (!parentOrTarget.LocalName.Equals("Annotation") && parentOrTarget.ParentNode != null)
                {
                    parentOrTarget = parentOrTarget.ParentNode;
                }

                parentOrTarget = parentOrTarget.ParentNode;

                if (parentOrTarget.LocalName.Equals("Annotations"))
                {
                    string parentTargetPath = parentOrTarget.Attributes["Target"].Value;
                    parentOrTarget = parentOrTarget.ParentNode;
                    if (MetadataHelper.Path(parentTargetPath, xmlDoc_MergedMetadata, context, ref parentOrTarget))
                    {
                        // For annotations targeting a property of an entity type or complex type,
                        // the path expression is evaluated starting at the outermost entity type or complex type
                        // named in the Target of the enclosing edm:Annotations element.
                        if (parentOrTarget.LocalName.Equals("Property") ||
                            parentOrTarget.LocalName.Equals("NavigationProperty"))
                        {
                            while (!(parentOrTarget.LocalName.Equals("EntityType") ||
                                     parentOrTarget.LocalName.Equals("ComplexType")))
                            {
                                parentOrTarget = parentOrTarget.ParentNode;
                            }
                        }

                        XmlNode resolveNode = parentOrTarget;

                        if (MetadataHelper.Path(path, xmlDoc_MergedMetadata, context, ref resolveNode))
                        {
                            if (resolveNode.LocalName.Equals("Property"))
                            {
                                passed = true;
                            }
                            else if (resolveNode.LocalName.Equals("Term"))
                            {
                                if (resolveNode.Attributes["Type"].Value.RemoveCollectionFlag().Equals("Edm.ComplexType") ||
                                    resolveNode.Attributes["Type"].Value.RemoveCollectionFlag().Equals("Edm.PrimitiveType"))
                                {
                                    passed = true;
                                }
                                else if (EdmTypeManager.IsEdmSimpleType(resolveNode.Attributes["Type"].Value.RemoveCollectionFlag()))
                                {
                                    passed = true;
                                }
                                else
                                {
                                    string   type = resolveNode.Attributes["Type"].Value.RemoveCollectionFlag();
                                    XElement termTypeEle;

                                    termTypeEle = MetadataHelper.GetTypeDefinitionEleInScope(@"ComplexType' or 'EnumType' or 'TypeDefinition", type, context);
                                    if (termTypeEle != null)
                                    {
                                        passed = true;
                                    }
                                    else
                                    {
                                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                        passed = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    XmlNode resolveNode = parentOrTarget;
                    if (MetadataHelper.Path(path, xmlDoc_MergedMetadata, context, ref resolveNode))
                    {
                        if (resolveNode.LocalName.Equals("Property"))
                        {
                            passed = true;
                        }
                        else if (resolveNode.LocalName.Equals("Term"))
                        {
                            if (resolveNode.Attributes["Type"].Value.RemoveCollectionFlag().Equals("Edm.ComplexType") ||
                                resolveNode.Attributes["Type"].Value.RemoveCollectionFlag().Equals("Edm.PrimitiveType"))
                            {
                                passed = true;
                            }
                            else if (EdmTypeManager.IsEdmSimpleType(resolveNode.Attributes["Type"].Value.RemoveCollectionFlag()))
                            {
                                passed = true;
                            }
                            else
                            {
                                string   type = resolveNode.Attributes["Type"].Value.RemoveCollectionFlag();
                                XElement termTypeEle;

                                termTypeEle = MetadataHelper.GetTypeDefinitionEleInScope(@"ComplexType' or 'EnumType' or 'TypeDefinition", type, context);
                                if (termTypeEle != null)
                                {
                                    passed = true;
                                }
                                else
                                {
                                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                    passed = false;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            return(passed);
        }
Example #20
0
        /// <summary>
        /// Verify Metadata.Core.4228
        /// </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;

            // Load MetadataDocument into XMLDOM
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.MetadataDocument);

            string      xpath            = "//*[local-name()='EnumType']";
            XmlNodeList enumTypeNodeList = xmlDoc.SelectNodes(xpath);

            foreach (XmlNode enumType in enumTypeNodeList)
            {
                string underlyingType = string.Empty;
                if (enumType.Attributes["UnderlyingType"] != null)
                {
                    underlyingType = enumType.Attributes["UnderlyingType"].Value;
                }
                else
                {
                    underlyingType = "Edm.Int32";
                }

                foreach (XmlNode member in enumType.ChildNodes)
                {
                    if (!member.Name.Equals("Member"))
                    {
                        continue;
                    }
                    else
                    {
                        if (member.Attributes["Value"] != null)
                        {
                            IEdmType edmType = EdmTypeManager.GetEdmType(underlyingType);

                            if (edmType.IsGoodWith(member.Attributes["Value"].Value))
                            {
                                passed = true;
                            }
                            else
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                break;
                            }
                        }
                    }
                }

                if (passed == false)
                {
                    break;
                }
            }

            return(passed);
        }
Example #21
0
        /// <summary>
        /// Verify IndividualProperty.Core.4610
        /// </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;

            XmlDocument xmlDoc = new XmlDocument();

            // Test Data
            // 1. Collection of string. Url:http://services.odata.org/V4/OData/OData.svc/Products(0)/Description?$format=xml
            // xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value m:context=\"http://services.odata.org/V4/OData/OData.svc/$metadata#Collection(Edm.String)\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element>Whole grain</m:element> <m:element>bread</m:element></m:value>");
            // 2. Collection of complext type. Url: http://services.odata.org/V4/OData/OData.svc/PersonDetails(0)/Address?$format=xml
            // xmlDoc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><m:value m:context=\"http://services.odata.org/V4/OData/OData.svc/$metadata#Collection(ODataDemo.Address)\" m:type=\"#Collection(ODataDemo.Address)\" xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\"><m:element><d:Street>2817 Milton Dr.</d:Street><d:City>Albuquerque</d:City><d:State>NM</d:State><d:ZipCode>87110</d:ZipCode><d:Country>USA</d:Country></m:element><m:element><d:Street>2817 Milton Dr.</d:Street><d:City>Detorlee</d:City><d:State>UT</d:State><d:ZipCode>124450</d:ZipCode><d:Country>USA</d:Country></m:element></m:value>");
            xmlDoc.LoadXml(context.ResponsePayload);
            XmlElement root = xmlDoc.DocumentElement;

            if (root.LocalName.Equals("value") && root.NamespaceURI.Equals(Constants.NSMetadata))
            {
                if (root.Attributes["context", Constants.NSMetadata] != null)
                {
                    string contextURL = root.Attributes["context", Constants.NSMetadata].Value;

                    string propertyTypeCol = contextURL.Remove(0, contextURL.IndexOf('#') + 1);

                    if (!propertyTypeCol.Contains("Collection("))
                    {
                        return(null);
                    }

                    string propertyTypeFullName  = propertyTypeCol.Substring(propertyTypeCol.IndexOf('(') + 1, propertyTypeCol.Length - 12);
                    string propertyTypeShortName = propertyTypeFullName.GetLastSegment();

                    // Verify whether the context URL is a valid url.
                    if (!Uri.IsWellFormedUriString(contextURL, UriKind.Absolute))
                    {
                        passed = false;
                        info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                        return(passed);
                    }

                    string metadataUrl = contextURL.Remove(contextURL.IndexOf('#'));

                    var resp = WebHelper.Get(new Uri(metadataUrl), Constants.AcceptHeaderAtom, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                    if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                    {
                        var metadata = XElement.Parse(resp.ResponsePayload);

                        if (null != metadata && "Edmx" == metadata.Name.LocalName)
                        {
                            passed = false;

                            if (propertyTypeFullName.Contains("Edm.") && EdmTypeManager.IsEdmSimpleType(propertyTypeFullName))
                            {
                                return(true);
                            }

                            string   xpath       = string.Format(@"//*[local-name()='ComplexType' and @Name='{0}']", propertyTypeShortName);
                            XElement complexType = metadata.XPathSelectElement(xpath, ODataNamespaceManager.Instance);
                            if (complexType != null)
                            {
                                return(true);
                            }
                        }

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

            return(passed);
        }