Esempio n. 1
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       = string.Empty;

            if (svcStatus == null)
            {
                url = context.ServiceBaseUri.OriginalString;
            }
            else
            {
                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()='ActionImport']");
            XElement md           = XElement.Parse(svcStatus.MetadataDocument);
            XElement actionImport = md.XPathSelectElement(xpath, ODataNamespaceManager.Instance);

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

            string actionShortName = actionImport.Attribute("Action").Value.GetLastSegment();

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

            JObject parameterEntity = new JObject();
            List <KeyValuePair <string, string> > paralist = new List <KeyValuePair <string, string> >();

            if (action != null)
            {
                IEnumerable <XElement> parameters = action.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++)
            {
                parameterEntity.Add(paralist[i].Key, paralist[i].Value);
            }

            url += @"/" + actionShortName;

            Response response = WebHelper.CreateEntity(url, parameterEntity.ToString(), context.RequestHeaders);

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

            info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
            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;

            ServiceStatus serviceStatus    = ServiceStatus.GetInstance();
            DataFactory   dFactory         = DataFactory.Instance();
            var           detail           = new ExtensionRuleResultDetail(this.Name, serviceStatus.RootURL, HttpMethod.Post, string.Empty);
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count())
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);
                return(passed);
            }

            EntityTypeElement eTypeElement    = null;
            NormalProperty    prop            = null;
            string            propReltivePath = string.Empty;

            foreach (var en in entityTypeElements)
            {
                foreach (NormalProperty np in en.NormalProperties)
                {
                    if (!np.IsKey && !en.HasStream && np.IsNullable)
                    {
                        eTypeElement = en;
                        prop         = np;
                        if (!np.PropertyType.Contains("Collection(") && np.PropertyType.Contains("Edm."))
                        {
                            propReltivePath = prop.PropertyName + @"/$value";
                        }
                        else
                        {
                            propReltivePath = prop.PropertyName;
                        }
                        break;
                    }
                }

                if (prop != null)
                {
                    break;
                }
            }

            if (eTypeElement == null || string.IsNullOrEmpty(eTypeElement.EntitySetName))
            {
                detail.ErrorMessage = "Cannot find the appropriate entity-set URL to verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + eTypeElement.EntitySetName;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(eTypeElement.EntitySetName, eTypeElement.EntityTypeShortName, null, out additionalInfos);

            if (!dFactory.CheckOrAddTheMissingPropertyData(eTypeElement.EntitySetName, prop.PropertyName, ref reqData))
            {
                detail.ErrorMessage = "The property to delete does not have value, and cannot be deleted.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }
            ;

            string reqDataStr = reqData.ToString();

            if (reqDataStr.Length > 2)
            {
                bool isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
                var  resp        = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
                detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
                if (HttpStatusCode.Created == resp.StatusCode || HttpStatusCode.NoContent == resp.StatusCode)
                {
                    url = additionalInfos.Last().EntityId.TrimEnd('/') + "/" + propReltivePath;
                    if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
                    {
                        detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

                        // Restore the service.
                        var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                        return(passed);
                    }

                    resp                      = WebHelper.Get(new Uri(url), null, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, null);
                    detail                    = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, serviceStatus.DefaultHeaders), resp);
                    detail.URI                = url;
                    detail.ResponsePayload    = resp.ResponsePayload;
                    detail.ResponseHeaders    = resp.ResponseHeaders;
                    detail.HTTPMethod         = "GET";
                    detail.ResponseStatusCode = resp.StatusCode.ToString();

                    if ((resp.StatusCode.HasValue && HttpStatusCode.OK == resp.StatusCode) || HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp   = WebHelper.DeleteEntity(url, context.RequestHeaders, additionalInfos.Last().HasEtag);
                        detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Delete, string.Empty, resp, string.Empty, "Successfully updated the stream of the image.");

                        if (null != resp && (HttpStatusCode.NoContent == resp.StatusCode))
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = string.Format("HTTP delete to delete the structural or primitive property value to null failed with the error {0}.", resp.StatusCode);
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "Get property failed from above URI.";
                    }

                    // Restore the service.
                    WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                }
                else
                {
                    detail.ErrorMessage = "Created the new entity failed for above URI.";
                }
            }
            else
            {
                detail.ErrorMessage = "Constructing the new entity to create failed.";
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail
            };

            info = new ExtensionRuleViolationInfo(new Uri(url), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Esempio n. 3
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;
            ServiceStatus serviceStatus    = ServiceStatus.GetInstance();
            TermDocuments termDocs         = TermDocuments.GetInstance();
            DataFactory   dFactory         = DataFactory.Instance();
            var           detail1          = new ExtensionRuleResultDetail(this.Name);
            var           detail2          = new ExtensionRuleResultDetail(this.Name);
            var           detail3          = new ExtensionRuleResultDetail(this.Name);
            var           detail4          = new ExtensionRuleResultDetail(this.Name);
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <string> norPropertyTypes = new List <string>()
            {
                "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, norPropertyTypes, NavigationRoughType.CollectionValued).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count())
            {
                detail1.ErrorMessage = "It expects an entity type with Int32 key property and containing a string property to Patch/Post, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            foreach (var et in entityTypeElements)
            {
                string navigPropName = null;
                string navigPropRelatedEntitySetUrl      = null;
                string navigPropRelatedEntityTypeKeyName = null;
                var    matchEntity = et.EntitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc,
                                                                      new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetDeleteRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions
                });

                if (string.IsNullOrEmpty(matchEntity.Item1) ||
                    matchEntity.Item2 == null || !matchEntity.Item2.Any() ||
                    matchEntity.Item3 == null || !matchEntity.Item3.Any())
                {
                    continue;
                }

                foreach (var np in matchEntity.Item3)
                {
                    navigPropName = np.NavigationPropertyName;
                    string navigEntityTypeShortName     = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    List <NormalProperty> navigKeyProps = MetadataHelper.GetKeyProperties(serviceStatus.MetadataDocument, navigEntityTypeShortName).ToList();

                    if (navigKeyProps.Count == 1 && keyPropertyTypes.Contains(navigKeyProps[0].PropertyType))
                    {
                        navigPropRelatedEntitySetUrl      = navigEntityTypeShortName.MapEntityTypeShortNameToEntitySetURL();
                        navigPropRelatedEntityTypeKeyName = navigKeyProps[0].PropertyName;

                        break;
                    }
                }

                if (!string.IsNullOrEmpty(navigPropRelatedEntityTypeKeyName) && !string.IsNullOrEmpty(navigPropRelatedEntitySetUrl))
                {
                    string entitySetUrl    = et.EntitySetName.MapEntitySetNameToEntitySetURL();
                    string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
                    var    additionalInfos = new List <AdditionalInfo>();
                    var    reqData         = dFactory.ConstructInsertedEntityData(et.EntitySetName, et.EntityTypeShortName, null, out additionalInfos);
                    string reqDataStr      = reqData.ToString();
                    bool   isMediaType     = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
                    var    resp            = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
                    detail1 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

                    if (null != resp && HttpStatusCode.Created == resp.StatusCode)
                    {
                        string  entityId  = additionalInfos.Last().EntityId;
                        bool    hasEtag   = additionalInfos.Last().HasEtag;
                        JObject newEntity = JObject.Parse(resp.ResponsePayload);
                        url     = serviceStatus.RootURL.TrimEnd('/') + @"/" + navigPropRelatedEntitySetUrl;
                        resp    = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, serviceStatus.DefaultHeaders);
                        detail2 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, serviceStatus.DefaultHeaders), resp);
                        if (resp.StatusCode == HttpStatusCode.OK)
                        {
                            JObject feed;
                            resp.ResponsePayload.TryToJObject(out feed);
                            var entities = JsonParserHelper.GetEntries(feed);

                            if (entities.Count > 0 && entities[0][Constants.V4OdataId] != null)
                            {
                                reqDataStr = @"{""" + Constants.V4OdataId + @""" : """ + entities[0][Constants.V4OdataId].ToString() + @"""}";
                                url        = string.Format("{0}/{1}/$ref", entityId.TrimEnd('/'), navigPropName.TrimEnd('/'));

                                // Verify to send a POST Http request and response with a 204 No Content status code.
                                resp    = WebHelper.CreateEntity(url, reqDataStr);
                                detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

                                if (null != resp && resp.StatusCode == HttpStatusCode.NoContent)
                                {
                                    if (resp.ResponseHeaders.Contains("OData-EntityId"))
                                    {
                                        // Verify to send a PATCH Http request and response with a 204 No Content status code.
                                        List <string> norPropertyNames = et.NormalProperties
                                                                         .Where(np => norPropertyTypes.Contains(np.PropertyType) && !np.IsKey)
                                                                         .Select(np => np.PropertyName).ToList();
                                        if (!norPropertyNames.Any())
                                        {
                                            detail3.ErrorMessage = "The entity-type does not contain any properties can be updated.";
                                            info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail3);

                                            return(passed);
                                        }

                                        reqData = dFactory.ConstructUpdatedEntityData(newEntity, norPropertyNames);
                                        resp    = WebHelper.UpdateEntity(entityId, context.RequestHeaders, reqDataStr, HttpMethod.Patch, hasEtag);
                                        detail4 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Patch, string.Empty, resp, string.Empty, reqDataStr);

                                        if (HttpStatusCode.NoContent == resp.StatusCode)
                                        {
                                            if (resp.ResponseHeaders.Contains("OData-EntityId"))
                                            {
                                                passed = true;
                                            }
                                            else
                                            {
                                                passed = false;
                                                detail4.ErrorMessage = "The response headers does not contain OData-EntityId header for above patch request.";
                                            }
                                        }
                                        else
                                        {
                                            passed = false;
                                            detail4.ErrorMessage = "Patch HTTP request failed.";
                                        }
                                    }
                                    else
                                    {
                                        passed = false;
                                        detail3.ErrorMessage = "The response headers does not contain OData-EntityId header for above POST request.";
                                    }
                                }
                                else
                                {
                                    passed = false;
                                    detail3.ErrorMessage = "POST HTTP request failed for above URI.";
                                }
                            }
                        }

                        // Restore the service.
                        var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                    }
                    else
                    {
                        passed = false;
                        detail1.ErrorMessage = "Created the new entity failed for above URI.";
                    }

                    break;
                }
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail1, detail2, detail3, detail4
            }.RemoveNullableDetails();

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

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

            // Adding all AtomPub mappings to a list
            List <string> atomPubMapping = new List <string>(new string[]
            {
                "SyndicationAuthorName",
                "SyndicationAuthorEmail",
                "SyndicationAuthorUri",
                "SyndicationPublished",
                "SyndicationRights",
                "SyndicationTitle",
                "SyndicationUpdated",
                "SyndicationContributorName",
                "SyndicationContributorEmail",
                "SyndicationContributorUri",
                "SyndicationSource",
                "SyndicationSummary"
            });

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

            xmlDoc.LoadXml(context.MetadataDocument);

            // Find all nodes
            XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//*[@*[name()='m:FC_TargetPath']]");

            if (xmlNodeList.Count != 0)
            {
                foreach (XmlNode node in xmlNodeList)
                {
                    if (atomPubMapping.Exists(item => item == node.Attributes["m:FC_TargetPath"].Value))
                    {
                        if (node.ParentNode.Name.Equals("EntityType", StringComparison.OrdinalIgnoreCase))
                        {
                            if (node.ParentNode.Attributes["m:FC_NsUri"] != null)
                            {
                                passed = false;
                                break;
                            }
                            else
                            {
                                passed = true;
                            }
                        }
                        else if (node.ParentNode.Name.Equals("Schema", StringComparison.OrdinalIgnoreCase))
                        {
                            if (node.Attributes["m:FC_NsUri"] != null)
                            {
                                passed = false;
                            }
                            else
                            {
                                passed = true;
                            }
                        }
                    }
                }
            }

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

            return(passed);
        }
        /// <summary>
        /// Verify Metadata.Core.4353
        /// </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()='FunctionImport']";
            var    functionImportElems = metadata.XPathSelectElements(xPath, ODataNamespaceManager.Instance);

            foreach (var functionImportElem in functionImportElems)
            {
                bool EntitySetAttNoValue = false;
                if (functionImportElem.Attribute("EntitySet") == null ||
                    functionImportElem.Attribute("EntitySet") != null && string.IsNullOrEmpty(functionImportElem.Attribute("EntitySet").Value))
                {
                    EntitySetAttNoValue = true;
                }

                if (null != functionImportElem.Attribute("Function"))
                {
                    XElement functionXElemnt = MetadataHelper.GetTypeDefinitionEleInScope("Function", functionImportElem.Attribute("Function").Value, context);
                    xPath = string.Format("//*[local-name()='Function' and @Name='{0}']/*[local-name()='ReturnType']", functionXElemnt.Attribute("Name").Value);
                    XElement returnTypeXEle = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);
                    if (functionXElemnt != null && returnTypeXEle == null)
                    {
                        passed = EntitySetAttNoValue;
                        if (passed == false)
                        {
                            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                            break;
                        }
                        continue;
                    }

                    if (functionXElemnt != null && returnTypeXEle != null)
                    {
                        string returnType = returnTypeXEle.Attribute("Type").Value;
                        returnType = returnType.RemoveCollectionFlag();

                        XElement entityType = MetadataHelper.GetTypeDefinitionEleInScope("EntityType", returnType, context);

                        XElement entitySetType = MetadataHelper.GetTypeDefinitionEleInScope("EntitySet", returnType, context);

                        if (entitySetType == null && entityType == null)
                        {
                            passed = EntitySetAttNoValue;
                        }
                    }

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

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

            // Adding all AtomPub mappings to a list
            List <string> atomPubMapping = new List <string>(new string[]
            {
                "SyndicationAuthorName",
                "SyndicationAuthorEmail",
                "SyndicationAuthorUri",
                "SyndicationPublished",
                "SyndicationRights",
                "SyndicationTitle",
                "SyndicationUpdated",
                "SyndicationContributorName",
                "SyndicationContributorEmail",
                "SyndicationContributorUri",
                "SyndicationSource",
                "SyndicationSummary"
            });

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

            xmlDoc.LoadXml(context.MetadataDocument);

            // Find the namespace(s) in order to query for EntitySet name
            XmlNodeList namespaceList = xmlDoc.SelectNodes("//*[@*[name()='Namespace']]");

            // Find all nodes
            XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//*[@*[name()='m:FC_TargetPath']]");

            if (xmlNodeList.Count != 0)
            {
                XmlNode entitySetNode = null;
                foreach (XmlNode node in xmlNodeList)
                {
                    // Find the EntitySet node
                    bool foundEntitySet = false;
                    foreach (XmlNode nsNode in namespaceList)
                    {
                        if (!foundEntitySet)
                        {
                            entitySetNode = xmlDoc.SelectSingleNode("//*[@*[name()='EntityType'] = '" + nsNode.Attributes["Namespace"].Value + "." + node.ParentNode.Attributes["Name"].Value + "']");

                            if (entitySetNode != null)
                            {
                                foundEntitySet = true;
                            }
                        }
                    }

                    List <string> pathList = new List <string>();
                    if (!atomPubMapping.Exists(item => item == node.Attributes["m:FC_TargetPath"].Value))
                    {
                        // Construct the XPath query
                        pathList = node.Attributes["m:FC_TargetPath"].Value.Split('/').ToList();
                        StringBuilder xpathQuery = new StringBuilder();
                        xpathQuery.Append("//*/*[local-name()='entry']");

                        foreach (string path in pathList)
                        {
                            xpathQuery.Append("/*[local-name()='");
                            xpathQuery.Append(path);
                            xpathQuery.Append("']");
                        }

                        // Query to find the first entity in the EntitySet
                        Uri      absoluteUri = new Uri(context.Destination.OriginalString);
                        Uri      relativeUri = new Uri(entitySetNode.Attributes["Name"].Value + "?$top=1", UriKind.Relative);
                        Uri      combinedUri = new Uri(absoluteUri, relativeUri);
                        Response response    = WebHelper.Get(combinedUri, Constants.AcceptHeaderAtom, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            XmlDocument xmlDoc2 = new XmlDocument();
                            xmlDoc2.LoadXml(response.ResponsePayload);

                            if (xmlDoc2.SelectSingleNode(xpathQuery.ToString()) != null)
                            {
                                passed = true;
                            }
                            else
                            {
                                passed = false;
                                break;
                            }
                        }
                    }
                }
            }

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

            return(passed);
        }
        /// <summary>
        /// Verify Metadata.Core.4288
        /// </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))
                        {
                            if (separations[i].IsSimpleIdentifier())
                            {
                                passed = true;
                            }
                            else
                            {
                                passed = false;
                                break;
                            }
                        }
                    }
                }
            }

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

            return(passed);
        }
Esempio n. 8
0
        /// <summary>
        /// Verify Metadata.Core.4101
        /// </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;

            XElement metaXml = XElement.Parse(context.MetadataDocument);
            string   xpath   = "//*[local-name()='NavigationProperty']/parent::*";
            IEnumerable <XElement> navPropertyParentElements = metaXml.XPathSelectElements(xpath, ODataNamespaceManager.Instance);

            foreach (XElement navPropParent in navPropertyParentElements)
            {
                passed = true;

                HashSet <string> childrenSet = new HashSet <string>(StringComparer.Ordinal);

                if (!MetadataHelper.IsNameUniqueInChildren(navPropParent, ref childrenSet))
                {
                    passed = false;
                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                    break;
                }

                if (navPropParent.Attribute("BaseType") != null)
                {
                    string baseTypeName = navPropParent.Attribute("BaseType").Value;

                    XElement baseTypeElement = MetadataHelper.GetTypeDefinitionEleByDoc(navPropParent.Name.LocalName, baseTypeName, context.MetadataDocument);

                    if (baseTypeElement != null)
                    {
                        if (!MetadataHelper.IsNameUniqueInChildren(baseTypeElement, ref childrenSet))
                        {
                            passed = false;
                            info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                            break;
                        }
                    }
                    else
                    {
                        string docString = MetadataHelper.GetReferenceDocByDefinedType(baseTypeName, context);

                        if (!string.IsNullOrEmpty(docString))
                        {
                            baseTypeElement = MetadataHelper.GetTypeDefinitionEleByDoc(navPropParent.Name.LocalName, baseTypeName, docString);

                            if (baseTypeElement != null)
                            {
                                if (!MetadataHelper.IsNameUniqueInChildren(baseTypeElement, ref childrenSet))
                                {
                                    passed = false;
                                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                    break;
                                }
                            }
                            else
                            {
                                passed = false;
                                info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                                break;
                            }
                        }
                    }
                }
            }

            return(passed);
        }
Esempio n. 9
0
        /// <summary>
        /// Verify Common.Core.3100
        /// </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;
            bool IsodatametadataParameter = false;

            info = null;

            if (!string.IsNullOrEmpty(context.ResponseHttpHeaders))
            {
                // Extracts content type value from ResponseHttpHeaders.
                var contentType = context.ResponseHttpHeaders.GetHeaderValue(Constants.ContentType);

                if (!string.IsNullOrEmpty(contentType))
                {
                    if (context.OdataMetadataType.Equals(RuleEngine.ODataMetadataType.FullOnly))
                    {
                        // Verify whether the value of odata.metadata is in response.
                        string[] pairs = contentType.Split(';');
                        if (pairs.Length >= 1)
                        {
                            foreach (string pair in pairs)
                            {
                                if (pair.Equals("odata=fullmetadata"))
                                {
                                    IsodatametadataParameter = true;
                                    break;
                                }
                            }
                        }
                    }
                    else if (context.OdataMetadataType.Equals(RuleEngine.ODataMetadataType.MinOnly))
                    {
                        // Verify whether the value of odata.metadata is in response.
                        string[] pairs = contentType.Split(';');
                        if (pairs.Length >= 1)
                        {
                            foreach (string pair in pairs)
                            {
                                if (pair.Equals("odata=minimalmetadata"))
                                {
                                    IsodatametadataParameter = true;
                                    break;
                                }
                            }
                        }
                    }
                    else if (context.OdataMetadataType.Equals(RuleEngine.ODataMetadataType.None))
                    {
                        // Verify whether the value of odata.metadata is in response.
                        string[] pairs = contentType.Split(';');
                        if (pairs.Length >= 1)
                        {
                            foreach (string pair in pairs)
                            {
                                if (pair.Equals("odata=nonemetadata"))
                                {
                                    IsodatametadataParameter = true;
                                    break;
                                }
                            }
                        }
                    }
                }

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

            return(passed);
        }
Esempio n. 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;
            var           termDocs         = TermDocuments.GetInstance();
            var           serviceStatus    = ServiceStatus.GetInstance();
            var           dFactory         = DataFactory.Instance();
            var           detail1          = new ExtensionRuleResultDetail(this.Name);
            var           detail2          = new ExtensionRuleResultDetail(this.Name);
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <string> norPropertyTypes = new List <string>()
            {
                "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, norPropertyTypes, NavigationRoughType.None).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count)
            {
                detail1.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property and a normal property with string type, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            EntityTypeElement entityType = null;

            foreach (var ele in entityTypeElements)
            {
                if (ele.EntityTypeShortName.IsMediaType())
                {
                    continue;
                }

                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };
                var methods = new List <Func <string, string, List <string>, bool?> >()
                {
                    SupportiveFeatureHelper.IsSupportBatchOperation
                };
                var restrictions = ele.EntitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs, null, NavigationRoughType.None, methods);

                if (!string.IsNullOrEmpty(restrictions.Item1) ||
                    null != restrictions.Item2 || restrictions.Item2.Any() ||
                    null != restrictions.Item3 || restrictions.Item3.Any())
                {
                    entityType = ele;
                    break;
                }
            }

            if (null == entityType || string.IsNullOrEmpty(entityType.EntitySetName))
            {
                detail1.ErrorMessage = "The service does not support batch operation.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

            if (string.IsNullOrEmpty(entitySetUrl))
            {
                detail1.ErrorMessage = string.Format("Cannot find the entity-set URL which is matched with {0}", entityType.EntityTypeShortName);
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);
            string reqDataStr      = reqData.ToString();
            var    resp            = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, false, ref additionalInfos);

            detail1                 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
            detail1.URI             = url;
            detail1.ResponsePayload = resp.ResponsePayload;
            detail1.ResponseHeaders = resp.ResponseHeaders;
            detail1.HTTPMethod      = "POST";
            if (null != resp && HttpStatusCode.Created == resp.StatusCode)
            {
                string entityId = additionalInfos.Last().EntityId;
                bool   hasEtag  = additionalInfos.Last().HasEtag;
                resp = WebHelper.GetEntity(entityId);

                if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                {
                    JObject       entity           = JObject.Parse(resp.ResponsePayload);
                    List <string> norPropertyNames = entityType.NormalProperties.Where(norProp => norPropertyTypes.Contains(norProp.PropertyType)).Select(norProp => norProp.PropertyName).ToList();
                    reqDataStr = dFactory.ConstructUpdatedEntityData(entity, norPropertyNames).ToString();

                    string boundary     = "batch_4e1a76dc-b738-4aa4-9f93-df661d0a4c9f";
                    string batchReqData = string.Format(
                        @"
--batch_4e1a76dc-b738-4aa4-9f93-df661d0a4c9f
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621
Content-Type: application/http 
Content-Transfer-Encoding: binary 
Content-ID: 1

PATCH {0} HTTP/1.1
Content-Type: application/json
"
                        + (hasEtag ? "If-Match: *" : string.Empty) +
                        @"

{1}

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621
Content-Type: application/http 
Content-Transfer-Encoding: binary 
Content-ID: 2

DELETE {0} HTTP/1.1
"
                        + (hasEtag ? "If-Match: *" : string.Empty) +
                        @"

--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621--

--batch_4e1a76dc-b738-4aa4-9f93-df661d0a4c9f--
", entityId, reqDataStr);
                    resp    = WebHelper.BatchOperation(serviceStatus.RootURL, batchReqData, boundary);
                    detail2 = new ExtensionRuleResultDetail(this.Name, serviceStatus.RootURL + "/$batch", HttpMethod.Post, string.Empty, resp, string.Empty, batchReqData);

                    if (HttpStatusCode.OK == resp.StatusCode)
                    {
                        if (batchReqData.Filtration("\nContent-ID:") ==
                            resp.ResponsePayload.Filtration("\nContent-ID:"))
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail2.ErrorMessage = "The Content-ID in response and request are not consistent";
                        }
                    }
                    else
                    {
                        passed = false;
                        detail2.ErrorMessage = "The OData service does not return a 200 OK HTTP status code.";
                    }

                    // Restore the service.
                    var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                }
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = string.Format("Created entity failed for above URI with entity data {0}.  Server Response:  {1}", reqDataStr, resp.StatusCode);
                //detail1.ErrorMessage = string.Format("Created entity failed for above URI with entity data {0}.", reqData);
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail1, detail2
            }.RemoveNullableDetails();

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Esempio n. 11
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;

            string url = context.ServiceBaseUri.ToString();

            // If specified the service MUST generate a response with an OData-Version less than or equal to the specified OData-MaxVersion.
            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add("OData-MaxVersion", "4.0");
            var resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, headers);
            ExtensionRuleResultDetail detail1 = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, headers), resp);

            if (null != resp && HttpStatusCode.OK == resp.StatusCode)
            {
                string odataVersion  = resp.ResponseHeaders.GetHeaderValue(Constants.ODataVersion).Trim();
                double versionNumber = 0.0;

                try
                {
                    versionNumber = Convert.ToDouble(odataVersion);
                }
                catch (Exception)
                {
                    detail1.ErrorMessage = string.Format("Parse value {0} of OData-Version to a number failed from response header", odataVersion);
                    info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                    return(false);
                }

                if (versionNumber <= 4.0)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    detail1.ErrorMessage = string.Format("The OData-Version is {0}, which should be less than or equal to the specified OData-MaxVersion 4.0.", versionNumber);
                }
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = string.Format("Request failed with header 'OData-MaxVersion: 4.0'. The error is {0}.", resp.ResponsePayload.GetErrorMessage());
            }

            headers["OData-MaxVersion"] = "3.0";
            resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, headers);
            ExtensionRuleResultDetail detail2 = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, headers), resp);

            if (null != resp && HttpStatusCode.OK == resp.StatusCode)
            {
                passed = false;
                detail2.ErrorMessage = "Request should failed because set 'OData-MaxVersion:3.0' in request header and the service is version 4.0.";
            }
            else
            {
                passed = true && false != passed;
            }

            List <ExtensionRuleResultDetail> details = new List <ExtensionRuleResultDetail>()
            {
                detail1, detail2
            };

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

            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;
            var serviceStatus = ServiceStatus.GetInstance();
            var detail        = new ExtensionRuleResultDetail(this.Name);

            string[] entitySetUrls       = ContextHelper.GetFeeds(serviceStatus.ServiceDocument, this.PayloadFormat.Value).ToArray();
            string   entitySetName       = entitySetUrls.First().MapEntitySetURLToEntitySetName();
            string   entityTypeShortName = entitySetName.MapEntitySetNameToEntityTypeShortName();
            string   url      = string.Format("{0}/{1}", serviceStatus.RootURL.TrimEnd('/'), entitySetName);
            Response response = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, null);

            detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty, response);
            if (response.StatusCode != HttpStatusCode.OK)
            {
                detail.ErrorMessage = "The service does not have any entity.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            JObject feed;

            response.ResponsePayload.TryToJObject(out feed);
            var entries  = JsonParserHelper.GetEntries(feed);
            var entry    = entries.First();
            var entryUrl = string.Empty;

            if (null != entry[Constants.V4OdataId])
            {
                entryUrl = entry[Constants.V4OdataId].ToString().TrimEnd('\\');
            }
            else
            {
                detail.ErrorMessage = "Cannot get the entity-id from the current entity.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            // Use the XPath query language to access the metadata document and get all NavigationProperty.
            XElement metadata                = XElement.Parse(serviceStatus.MetadataDocument);
            string   xpath                   = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='Property']", 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);
            }

            url      = string.Format("{0}/{1}/$value", entryUrl.TrimEnd('/'), propNames[0]);
            response = WebHelper.Get(url, null, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail   = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty, response);

            // Get the value of propNames[0] property in entry payload and verify whether this value is equal to /$value payload value.
            if (response.StatusCode == HttpStatusCode.OK && entry[propNames[0]].ToString().Equals(response.ResponsePayload))
            {
                passed = true;
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support '/$value' segment.";
            }

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);
            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;
            ServiceStatus serviceStatus    = ServiceStatus.GetInstance();
            DataFactory   dFactory         = DataFactory.Instance();
            var           detail           = new ExtensionRuleResultDetail(this.Name, serviceStatus.RootURL, HttpMethod.Post, string.Empty);
            string        updateUrl        = serviceStatus.RootURL;
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <string> norPropertyTypes = new List <string>()
            {
                "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count)
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property and a string type normal property, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            EntityTypeElement entityType    = null;
            NormalProperty    primitiveProp = null;

            foreach (var en in entityTypeElements)
            {
                foreach (NormalProperty np in en.NormalProperties)
                {
                    if (!np.IsKey && np.PropertyType.Equals("Edm.String"))
                    {
                        entityType    = en;
                        primitiveProp = np;
                        break;
                    }
                }

                if (primitiveProp != null)
                {
                    break;
                }
            }

            if (entityType == null)
            {
                detail.ErrorMessage = "To verify this rule it expects an Edm.String type property in an entity, but there is no such entity in metadata. So can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

            updateUrl = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            if (string.IsNullOrEmpty(entitySetUrl))
            {
                detail.ErrorMessage = string.Format("Cannot find the entity-set URL which is matched with {0}", entityType.EntityTypeShortName);
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);

            if (!dFactory.CheckOrAddTheMissingPropertyData(entityType.EntitySetName, primitiveProp.PropertyName, ref reqData))
            {
                detail.ErrorMessage = "The property to update does not exist, and cannot be updated.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string reqDataStr = reqData.ToString();

            if (reqDataStr.Length > 2)
            {
                bool isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
                var  resp        = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
                detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
                if (HttpStatusCode.Created == resp.StatusCode)
                {
                    string entityId = additionalInfos.Last().EntityId;
                    updateUrl = entityId.TrimEnd('/') + "/" + primitiveProp.PropertyName + @"/$value";
                    bool hasEtag = additionalInfos.Last().HasEtag;
                    resp   = WebHelper.GetPropertyValue(updateUrl);
                    detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Get, string.Empty, resp);
                    if (HttpStatusCode.OK == resp.StatusCode || HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp   = WebHelper.UpdateAStringProperty(updateUrl, context.RequestHeaders, hasEtag);
                        detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Put, string.Empty, resp, string.Empty, reqDataStr);
                        if (HttpStatusCode.NoContent == resp.StatusCode)
                        {
                            resp   = WebHelper.GetPropertyValue(updateUrl);
                            detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                            if (HttpStatusCode.OK == resp.StatusCode)
                            {
                                if (resp.ResponsePayload == Constants.UpdateData)
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    detail.ErrorMessage = string.Format("The primitive property in request is not updated.");
                                }
                            }
                            else
                            {
                                passed = false;
                                detail.ErrorMessage = "Can not get the updated entity.";
                            }
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "Put the primitive property failed.";
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "Can not get the created entity from above URI.";
                    }

                    // Restore the service.
                    var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                }
                else
                {
                    detail.ErrorMessage = "Created the new entity failed for above URI.";
                }
            }
            else
            {
                detail.ErrorMessage = "Constructing the testing entity failed.";
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail
            };

            info = new ExtensionRuleViolationInfo(new Uri(updateUrl), serviceStatus.ServiceDocument, details);

            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;
            string entitiesName = string.Empty;

            JObject feed;

            context.ResponsePayload.TryToJObject(out feed);
            var entries = JsonParserHelper.GetEntries(feed);

            var o             = (JObject)feed;
            var odatametadata = (JProperty)o.First;

            if (odatametadata.Name.Equals(Constants.OdataV3JsonIdentity))
            {
                // Get entities name.
                string odatametadataValue = odatametadata.Value.ToString().StripOffDoubleQuotes().Split(new string[] { Constants.JsonFeedIdentity }, StringSplitOptions.RemoveEmptyEntries)[1];

                foreach (JObject entry in entries)
                {
                    if (entry != null && entry.Type == JTokenType.Object)
                    {
                        var jProps = entry.Children();

                        foreach (JProperty jProp in jProps)
                        {
                            if (jProp.Name.Equals(Constants.OdataV3JsonIdentity))
                            {
                                string entitysetName = string.Empty;
                                string splitPart     = jProp.Value.ToString().StripOffDoubleQuotes().Split(new string[] { Constants.JsonFeedIdentity }, StringSplitOptions.RemoveEmptyEntries)[1];

                                // Get the entity set name.
                                if (splitPart.EndsWith(Constants.V3JsonEntityIdentity))
                                {
                                    entitysetName = splitPart.Remove(splitPart.IndexOf("/"));
                                }

                                if (!odatametadataValue.Equals(entitysetName))
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    break;
                                }
                            }
                        }

                        if (passed != null)
                        {
                            break;
                        }
                    }
                }
            }

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

            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = null;

            List <string> entitySetURLs = MetadataHelper.GetEntitySetURLs();

            foreach (string entitySetUrl in entitySetURLs)
            {
                string entityTypeShortName = entitySetUrl.MapEntitySetNameToEntityTypeShortName();
                Tuple <string, string> key = MetadataHelper.GetKeyProperty(entityTypeShortName);
                Response resp = WebHelper.Get(new Uri(context.ServiceBaseUri.OriginalString.TrimEnd('/') + @"/" + entitySetUrl), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                if (null == resp || HttpStatusCode.OK != resp.StatusCode)
                {
                    continue;
                }

                JObject feed;
                resp.ResponsePayload.TryToJObject(out feed);

                if (feed == null || JTokenType.Object != feed.Type)
                {
                    continue;
                }

                JArray entities = JsonParserHelper.GetEntries(feed);
                string identity = entities[0][key.Item1].ToString();

                string url = context.ServiceBaseUri.OriginalString.TrimEnd('/') + @"/" + entitySetUrl + "(" + (key.Item2.Equals("Edm.String") ? "\'" + identity + "\'" : identity) + ")/" + key.Item1;

                resp   = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, resp.ResponseHeaders, resp);

                if (null == resp || HttpStatusCode.OK != resp.StatusCode)
                {
                    passed = false; break;
                }

                resp.ResponsePayload.TryToJObject(out feed);

                if (feed == null || JTokenType.Object != feed.Type)
                {
                    passed = false; break;
                }


                if (feed["value"] != null && feed["value"].ToString().Equals(identity))
                {
                    passed = true; break;
                }
                passed = false; break;
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <summary>
        /// Verify SvcDoc.Core.4631
        /// </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        xpath          = @"//*[local-name()='EntityContainer']/*[local-name()='Singleton']";
            List <string> singletonNames = Helper.MetadataHelper.GetPropertyValues(context, xpath, "Name");

            if (singletonNames.Count > 0)
            {
                XmlDocument xmlDoc = new XmlDocument();
                //                xmlDoc.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
                //                <service xml:base=""http://services.odata.org/V4/OData/OData.svc/"" xmlns=""http://www.w3.org/2007/app"" xmlns:atom=""http://www.w3.org/2005/Atom"" xmlns:m=""http://docs.oasis-open.org/odata/ns/metadata"" m:context=""http://services.odata.org/V4/OData/OData.svc/$metadata"">
                //                  <workspace>
                //                    <atom:title type=""text"">Default</atom:title>
                //                    <collection href=""Products"">
                //                      <atom:title type=""text"">Products</atom:title>
                //                    </collection>
                //                    <collection href=""ProductDetails"">
                //                      <atom:title type=""text"">ProductDetails</atom:title>
                //                    </collection>
                //                    <collection href=""Categories"">
                //                      <atom:title type=""text"">Categories</atom:title>
                //                    </collection>
                //                    <collection href=""Suppliers"">
                //                      <atom:title type=""text"">Suppliers</atom:title>
                //                    </collection>
                //                    <collection href=""Persons"">
                //                      <atom:title type=""text"">Persons</atom:title>
                //                    </collection>
                //                    <collection href=""PersonDetails"">
                //                      <atom:title type=""text"">PersonDetails</atom:title>
                //                    </collection>
                //                    <collection href=""Advertisements"">
                //                      <atom:title type=""text"">Advertisements</atom:title>
                //                    </collection>
                //                  <m:function-import href=""TopProducts"" m:name=""TopProducts"">
                //                      <atom:title>Best-Selling Products</atom:title>
                //                    </m:function-import>
                //                  <m:singleton href=""http://ODatademo.Contoso"" m:name=""Contoso"">
                //                      <atom:title>Contoso Ltd.</atom:title>
                //                    </m:singleton>
                //                  </workspace>
                //                </service>");
                xmlDoc.LoadXml(context.ResponsePayload);
                XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
                nsmgr.AddNamespace("app", Constants.NSApp);
                nsmgr.AddNamespace("metadata", Constants.NSMetadata);
                XmlNodeList nodes = xmlDoc.SelectNodes(@"//app:workspace/metadata:singleton", nsmgr);

                if (nodes.Count == singletonNames.Count)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                }
            }

            return(passed);
        }
Esempio n. 17
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 entityTypeShortName;
            var    propTypes = new string[1] {
                "Edm.DateTimeOffset"
            };
            var propNames = MetadataHelper.GetPropertyNames(propTypes, out entityTypeShortName);

            if (null == propNames || !propNames.Any())
            {
                return(passed);
            }

            string propName     = propNames[0];
            var    entitySetUrl = entityTypeShortName.GetAccessEntitySetURL();

            if (string.IsNullOrEmpty(entitySetUrl))
            {
                return(passed);
            }

            string url  = svcStatus.RootURL.TrimEnd('/') + "/" + entitySetUrl;
            var    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);

            if (null != resp && HttpStatusCode.OK == resp.StatusCode)
            {
                JObject jObj   = JObject.Parse(resp.ResponsePayload);
                JArray  jArr   = jObj.GetValue(Constants.Value) as JArray;
                var     entity = jArr.First as JObject;


                var propVal = Convert.ToDecimal(-1.000000001);

                for (int i = 0; i < propNames.Count - 1; i++)
                {
                    try
                    {
                        if (entity[propNames[i]] != null)
                        {
                            propVal = Convert.ToDecimal(Convert.ToDateTime(entity[propNames[i].ToString()]).Millisecond) / 100.0m;
                        }
                    }
                    catch
                    {
                    }
                    if (propVal >= 0)
                    {
                        propName = propNames[i].ToString();
                        break;
                    }
                }
                if (propVal < 0)
                {
                    passed = false;
                }
                else
                {
                    url  = string.Format("{0}?$filter=fractionalseconds({1}) eq {2}", url, propName, propVal);
                    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                    var detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                    info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                    if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                    {
                        jObj = JObject.Parse(resp.ResponsePayload);
                        jArr = jObj.GetValue(Constants.Value) as JArray;
                        foreach (JObject et in jArr)
                        {
                            if (entity[propName] != null)
                            {
                                passed = Convert.ToDecimal(Convert.ToDateTime(entity[propName]).Millisecond) / 100.0m == propVal;
                            }
                        }
                    }
                    else
                    {
                        passed = false;
                    }
                }
            }

            return(passed);
        }
Esempio n. 18
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;
            ServiceStatus serviceStatus    = ServiceStatus.GetInstance();
            TermDocuments termDocs         = TermDocuments.GetInstance();
            DataFactory   dFactory         = DataFactory.Instance();
            var           detail           = new ExtensionRuleResultDetail(this.Name, serviceStatus.RootURL, HttpMethod.Post, string.Empty);
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count())
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            // To get test entity which is of media type
            EntityTypeElement entityType = null;

            foreach (var entityEle in entityTypeElements)
            {
                if (MetadataHelper.IsMediaEntity(serviceStatus.MetadataDocument, entityEle.EntityTypeShortName, context))
                {
                    entityType = entityEle;
                    break;
                }
            }

            if (null == entityType)
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with deleteable and insertable restrictions, but there is no entity type in metadata which is insertable and deleteable.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            // Map 'entity-set name' to 'entity-set URL'.
            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

            if (string.IsNullOrEmpty(entitySetUrl))
            {
                detail.ErrorMessage = string.Format("Cannot find the entity-set URL which is matched with {0}", entityType.EntityTypeShortName);
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);
            string reqDataStr      = reqData.ToString();
            var    resp            = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, true, ref additionalInfos);

            detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
            if (resp.StatusCode.HasValue && (HttpStatusCode.Created == resp.StatusCode || HttpStatusCode.NoContent == resp.StatusCode))
            {
                string entityId = additionalInfos.Last().EntityId;
                resp                      = WebHelper.GetEntity(entityId);
                detail                    = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp);
                detail.URI                = entityId;
                detail.ResponsePayload    = resp.ResponsePayload;
                detail.ResponseHeaders    = resp.ResponseHeaders;
                detail.HTTPMethod         = "GET";
                detail.ResponseStatusCode = resp.StatusCode.ToString();

                if (resp.StatusCode.HasValue && HttpStatusCode.OK == resp.StatusCode)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    detail.ErrorMessage = "Can not get created entity from above URI.";
                }

                // Restore the service.
                var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "Created the new entity failed for above URI.";
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail
            };

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Esempio n. 19
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;
            ServiceStatus serviceStatus    = ServiceStatus.GetInstance();
            TermDocuments termDocs         = TermDocuments.GetInstance();
            DataFactory   dFactory         = DataFactory.Instance();
            var           detail           = new ExtensionRuleResultDetail(this.Name, serviceStatus.RootURL, HttpMethod.Post, string.Empty);
            string        upsertUrl        = serviceStatus.RootURL;
            List <string> keyPropertyTypes = new List <string>()
            {
                "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String"
            };
            List <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None).ToList();

            if (null == entityTypeElements || 0 == entityTypeElements.Count())
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            EntityTypeElement entityType = null;

            foreach (var en in entityTypeElements)
            {
                var matchEntity = en.EntitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc,
                                                                   new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetDeleteRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions
                });

                if (!string.IsNullOrEmpty(matchEntity.Item1) &&
                    matchEntity.Item2 != null && matchEntity.Item2.Any() &&
                    matchEntity.Item3 != null && matchEntity.Item3.Any())
                {
                    entityType = en;
                    break;
                }
            }

            if (entityType == null)
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type insertable, updatable and deletable, but at least one of these condition is lack for all the entities in metadata. So can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

            upsertUrl = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            if (string.IsNullOrEmpty(entitySetUrl))
            {
                detail.ErrorMessage = string.Format("Cannot find the entity-set URL which is matched with {0}", entityType.EntityTypeShortName);
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            // Create a entity
            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);
            string reqDataStr      = reqData.ToString();
            bool   isMediaType     = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
            var    resp            = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);

            detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

            if (HttpStatusCode.Created == resp.StatusCode)
            {
                var entityId = additionalInfos.Last().EntityId;
                upsertUrl = entityId;
                var hasEtag = additionalInfos.Last().HasEtag;
                resp   = WebHelper.DeleteEntity(entityId, context.RequestHeaders, hasEtag);
                detail = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Delete, string.Empty, resp);
                if (HttpStatusCode.NoContent == resp.StatusCode)
                {
                    var header  = new KeyValuePair <string, string>("If-None-Match", "*");
                    var headers = new List <KeyValuePair <string, string> >()
                    {
                        header
                    };
                    resp   = WebHelper.UpsertEntity(entityId, reqDataStr, HttpMethod.Put, hasEtag ? headers : null);
                    detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Put, string.Empty, resp, string.Empty, reqDataStr);

                    if (HttpStatusCode.Created == resp.StatusCode)
                    {
                        resp   = WebHelper.GetEntity(entityId);
                        detail = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp);
                        if (HttpStatusCode.OK == resp.StatusCode)
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "Can not Upsert the entity from above URI.";
                        }

                        // Restore the service.
                        var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = "Upsert the entity failed.";
                    }
                }
                else
                {
                    detail.ErrorMessage = "Delete the entity failed.";
                }
            }
            else
            {
                detail.ErrorMessage = "Created the new entity failed for above URI.";
            }

            var details = new List <ExtensionRuleResultDetail>()
            {
                detail
            };

            info = new ExtensionRuleViolationInfo(new Uri(upsertUrl), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Esempio n. 20
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;
            string  acceptHeader = string.Empty;
            JObject jo;

            context.ResponsePayload.TryToJObject(out jo);

            string odataCountAnnotation    = Constants.V4OdataCount;
            string odataNextLinkAnnotation = Constants.V4OdataNextLink;

            if (context.Version == ODataVersion.V3)
            {
                odataCountAnnotation    = Constants.OdataCount;
                odataNextLinkAnnotation = Constants.OdataNextLink;
            }

            // The odata.nextLink annotation is applied for feed or a collection of entity references.
            if (context.PayloadType == RuleEngine.PayloadType.Feed || (context.PayloadType == RuleEngine.PayloadType.EntityRef && jo[Constants.Value] != null))
            {
                Uri absoluteUri = new Uri(context.Destination.OriginalString.Split('?')[0]);
                Uri relativeUri = null;

                if (context.Version == ODataVersion.V3)
                {
                    acceptHeader = Constants.V3AcceptHeaderJsonMinimalMetadata;
                    relativeUri  = new Uri("?$inlinecount=allpages", UriKind.Relative);
                }
                else if (context.Version == ODataVersion.V4)
                {
                    acceptHeader = Constants.V4AcceptHeaderJsonMinimalMetadata;
                    relativeUri  = new Uri("?$count=true", UriKind.Relative);
                }

                Uri combinedUri = new Uri(absoluteUri, relativeUri);

                // Send request with query parameter "inlinecount=allpages" for v3 and "count=true" for v4.
                Response response = WebHelper.Get(combinedUri, acceptHeader, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    response.ResponsePayload.TryToJObject(out jo);

                    if (jo[odataCountAnnotation] != null)
                    {
                        Int64 odataCountValue = Int64.Parse(jo[odataCountAnnotation].Value <string>().ToString().StripOffDoubleQuotes());

                        // if count of value array less than value of odata.count, the odata.nextLink must appear.
                        if (((JArray)jo[Constants.Value]).Count < odataCountValue)
                        {
                            foreach (JProperty jProp in jo.Children())
                            {
                                if (jProp.Name.Equals(odataNextLinkAnnotation))
                                {
                                    passed = true;
                                    break;
                                }
                            }

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

            return(passed);
        }
Esempio n. 21
0
        /// <summary>
        /// Verify Metadata.Core.4163
        /// </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' and @Namespace]/*[local-name()='EntityType' and @BaseType and @Name]";
            XmlNodeList entityTypes = metadata.SelectNodes(xpath);

            // Get all the type names in current schema that need to check.
            List <string> typesToCheck = new List <string>();

            foreach (XmlNode type in entityTypes)
            {
                typesToCheck.Add(type.ParentNode.Attributes["Namespace"].Value + "." + type.Attributes["Name"].Value);
            }

            // Get the complete CSDL.
            if (context.ContainsExternalSchema)
            {
                metadata.LoadXml(context.MergedMetadataDocument);
            }

            // Get Alias Namespace map.
            Dictionary <string, string> aliasNamespaceMap = new Dictionary <string, string>();
            XmlNodeList schemasWithAlias = metadata.SelectNodes(@"/*[local-name()='Edmx']/*[local-name()='DataServices']/*[local-name()='Schema' and @Namespace and @Alias]");

            foreach (XmlNode schema in schemasWithAlias)
            {
                aliasNamespaceMap.Add(schema.Attributes["Alias"].Value, schema.Attributes["Namespace"].Value);
            }

            // Create a list that contains the type -> basetype relationship. And convert all the alias to full namespace.
            List <Item> typeInheritTable = new List <Item>();

            entityTypes = metadata.SelectNodes(xpath);
            foreach (XmlNode type in entityTypes)
            {
                string baseTypeNs   = string.Empty;
                string baseTypeName = type.Attributes["BaseType"].Value;
                int    dotIndex     = baseTypeName.LastIndexOf('.');
                if (dotIndex != -1 && dotIndex != 0 && dotIndex != baseTypeName.Length - 1)
                {
                    baseTypeNs = baseTypeName.Substring(0, dotIndex);
                }
                else
                {
                    continue;
                }

                if (aliasNamespaceMap.ContainsKey(baseTypeNs))
                {
                    baseTypeName = aliasNamespaceMap[baseTypeNs] + baseTypeName.Substring(dotIndex + 1);
                }

                typeInheritTable.Add(new Item(type.ParentNode.Attributes["Namespace"].Value + "." + type.Attributes["Name"].Value, baseTypeName, false));
            }

            // Check the cycle.
            foreach (string type in typesToCheck)
            {
                passed = true;
                if (ChecCycle(type, typeInheritTable))
                {
                    passed = false;
                    break;
                }
            }

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
            return(passed);
        }
Esempio n. 22
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;
            var    serviceStatus = ServiceStatus.GetInstance();
            var    detail1       = new ExtensionRuleResultDetail(this.Name);
            var    detail2       = new ExtensionRuleResultDetail(this.Name);
            var    detail3       = new ExtensionRuleResultDetail(this.Name);
            string feedUrl       = string.Empty;
            string entityUrl     = string.Empty;

            KeyValuePair <string, IEnumerable <string> > entityUrls;

            if (JsonParserHelper.GetBatchSupportedEntityUrls(out entityUrls))
            {
                feedUrl   = string.Format("{0}/{1}", serviceStatus.RootURL, entityUrls.Key);
                entityUrl = entityUrls.Value.First();
            }

            string relativeUrl = new Uri(entityUrl).LocalPath;
            string host        = entityUrl.Remove(entityUrl.IndexOf(relativeUrl));

            string format1Request = string.Format(@"
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http 
Content-Transfer-Encoding:binary


GET {0} HTTP/1.1

--batch_36522ad7-fc75-4b56-8c71-56071383e77b--", entityUrl);

            string format2Request = string.Format(@"
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http 
Content-Transfer-Encoding:binary


GET {0} HTTP/1.1
Host: {1}

--batch_36522ad7-fc75-4b56-8c71-56071383e77b--", relativeUrl, host);

            string format3Reuqest = string.Format(@"
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http 
Content-Transfer-Encoding:binary


GET {0} HTTP/1.1

--batch_36522ad7-fc75-4b56-8c71-56071383e77b--", relativeUrl);

            string   boundary        = @"batch_36522ad7-fc75-4b56-8c71-56071383e77b";
            Response format1Response = WebHelper.BatchOperation(serviceStatus.RootURL.TrimEnd('/') + @"/", format1Request, boundary);

            detail1 = new ExtensionRuleResultDetail(this.Name, feedUrl + "/$batch", HttpMethod.Post, string.Empty, format1Response, string.Empty, format1Request);

            Response format2Response = WebHelper.BatchOperation(serviceStatus.RootURL.TrimEnd('/') + @"/", format2Request, boundary);

            detail2 = new ExtensionRuleResultDetail(this.Name, feedUrl + "/$batch", HttpMethod.Post, string.Empty, format2Response, string.Empty, format2Request);

            Response format3Response = WebHelper.BatchOperation(serviceStatus.RootURL.TrimEnd('/') + @"/", format3Reuqest, boundary);

            detail3 = new ExtensionRuleResultDetail(this.Name, feedUrl + "/$batch", HttpMethod.Post, string.Empty, format3Response, string.Empty, format3Reuqest);

            if (format1Response != null && !string.IsNullOrEmpty(format1Response.ResponsePayload))
            {
                if (!format1Response.ResponsePayload.Contains(@"HTTP/1.1 200 OK"))
                {
                    passed = false;
                    detail1.ErrorMessage = string.Format("Batch request failed by above URI.");
                }
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = "No response returned from above URI.";
            }

            if (format2Response != null && !string.IsNullOrEmpty(format2Response.ResponsePayload))
            {
                if (!format2Response.ResponsePayload.Contains(@"HTTP/1.1 200 OK"))
                {
                    passed = false;
                    detail2.ErrorMessage = string.Format("Batch request failed by above URI and host : {0}. ", host);
                }
            }
            else
            {
                passed = false;
                detail2.ErrorMessage = string.Format("No response returned from above URI and host : {0}. ", host);
            }

            if (format3Response != null && !string.IsNullOrEmpty(format3Response.ResponsePayload))
            {
                if (!format3Response.ResponsePayload.Contains(@"HTTP/1.1 200 OK"))
                {
                    passed = false;
                    detail3.ErrorMessage = string.Format("Batch request failed by above URI and Batch request host : {0}.", host);
                }
            }
            else
            {
                passed = false;
                detail3.ErrorMessage = string.Format("No response returned from above URI and Batch request host : {0}. ", host);
            }

            if (passed == null)
            {
                passed = true;
            }

            List <ExtensionRuleResultDetail> details = new List <ExtensionRuleResultDetail>()
            {
                detail1, detail2, detail3
            };

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

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

            // Get all properties.
            XmlDocument xmlDoc = new XmlDocument();

            xmlDoc.LoadXml(context.ResponsePayload);
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);

            nsmgr.AddNamespace("m", Constants.V3NSMetadata);
            string MeataNS = Constants.V3NSMetadata;
            string DataNs  = Constants.V3NSData;

            if (context.Version == ODataVersion.V4)
            {
                nsmgr.AddNamespace("m", Constants.NSMetadata);
                MeataNS = Constants.NSMetadata;
                DataNs  = Constants.V4NSData;
            }

            XmlNodeList xmlNodeList = xmlDoc.SelectNodes(@"//m:properties/*", nsmgr);

            List <string> namesWithCollectionType = AtomSchemaHelper.GetAllComplexNameWithCollectionType(context.MetadataDocument, context.EntityTypeShortName);

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                if (namesWithCollectionType.Contains(xmlNode.LocalName) && xmlNode.NamespaceURI.Equals(DataNs) && xmlNode.ChildNodes.Count > 0)
                {
                    foreach (XmlElement xElement in xmlNode)
                    {
                        if (xElement.NamespaceURI.Equals(MeataNS) &&
                            xElement.LocalName.Equals("element") &&
                            xElement.Attributes["type", MeataNS] != null)
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            info   = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload);
                            break;
                        }
                    }

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

            return(passed);
        }
Esempio n. 24
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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var entitySets = MetadataHelper.GetFeeds(context.MetadataDocument);

            if (null == entitySets || !entitySets.Any())
            {
                detail.ErrorMessage = "Cannot find any entity-sets in metadata document.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string entitySet = string.Empty;

            foreach (var set in entitySets)
            {
                if (true == set.IsSupportAsynchronousOperation(context.MetadataDocument, new List <string>()
                {
                    context.VocCapabilities
                }))
                {
                    entitySet = set;
                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySet))
            {
                detail.ErrorMessage = "Cannot find an appropriate entity-set which supports asynchronous operation in metadata document.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string url = string.Format("{0}/{1}", context.ServiceBaseUri, entitySet);
            List <KeyValuePair <string, string> > requestHeaders = new List <KeyValuePair <string, string> >();

            foreach (KeyValuePair <string, string> kvp in context.RequestHeaders)
            {
                requestHeaders.Add(new KeyValuePair <string, string>(kvp.Key, kvp.Value));
            }

            // Add respond-async preference in request header.
            KeyValuePair <string, string> prefer = new KeyValuePair <string, string>("Prefer", "respond-async");

            requestHeaders.Add(prefer);
            Response response = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, requestHeaders);

            detail = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, requestHeaders), response);

            if (response != null && !string.IsNullOrEmpty(response.ResponseHeaders))
            {
                string preferHeader = response.ResponseHeaders.GetHeaderValue("Preference-Applied");

                if (string.IsNullOrEmpty(preferHeader))
                {
                    passed = false;
                    detail.ErrorMessage = "The response header returned by the service does not contain 'respond-async', when request with the header 'Prefer: respond-async'.";
                }
                else if (preferHeader.Contains("respond-async"))
                {
                    passed = true;
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support Asynchronous operations.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <summary>
        /// Verify Metadata.Core.2015
        /// </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 the namespace(s) in order to query for EntitySet name
            XmlNodeList namespaceList = xmlDoc.SelectNodes("//*[@*[name()='Namespace']]");

            // Find all nodes
            XmlNodeList xmlNodeList = xmlDoc.SelectNodes("//*[@*[name()='m:FC_KeepInContent']]");

            if (xmlNodeList.Count != 0)
            {
                XmlNode entitySetNode = null;
                foreach (XmlNode node in  xmlNodeList)
                {
                    // Find the EntitySet node
                    bool foundEntitySet = false;
                    foreach (XmlNode nsNode in namespaceList)
                    {
                        if (!foundEntitySet)
                        {
                            entitySetNode = xmlDoc.SelectSingleNode("//*[@*[name()='EntityType'] = '" + nsNode.Attributes["Namespace"].Value + "." + node.ParentNode.Attributes["Name"].Value + "']");

                            if (entitySetNode != null)
                            {
                                foundEntitySet = true;
                            }
                        }
                    }

                    // Query to find the first entity in the EntitySet
                    Uri      absoluteUri = new Uri(context.Destination.OriginalString);
                    Uri      relativeUri = new Uri(entitySetNode.Attributes["Name"].Value + "?$top=1&$select=" + node.Attributes["Name"].Value, UriKind.Relative);
                    Uri      combinedUri = new Uri(absoluteUri, relativeUri);
                    Response response    = WebHelper.Get(combinedUri, Constants.AcceptHeaderAtom, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        XmlDocument xmlDoc2 = new XmlDocument();
                        xmlDoc2.LoadXml(response.ResponsePayload);
                        XmlNode node2 = xmlDoc2.SelectSingleNode("//*/*[local-name()='" + node.Attributes["Name"].Value + "']");

                        if (node.Attributes["m:FC_KeepInContent"].Value.Equals("false", StringComparison.OrdinalIgnoreCase) && node2 == null)
                        {
                            passed = true;
                        }
                        else if (node.Attributes["m:FC_KeepInContent"].Value.Equals("true", StringComparison.OrdinalIgnoreCase) && node2 != null)
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            break;
                        }
                    }
                }
            }

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

            return(passed);
        }
Esempio n. 26
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 = true;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);

            var payloadFormat = context.ServiceDocument.GetFormatFromPayload();

            string[] feeds            = ContextHelper.GetFeeds(context.ServiceDocument, payloadFormat).ToArray();
            string   entitySetName    = feeds.First().MapEntitySetURLToEntitySetName();
            Uri      firstFeedFullUrl = new Uri(string.Format("{0}/{1}", context.DestinationBasePath, entitySetName));
            Response response         = WebHelper.Get(firstFeedFullUrl, Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            detail = new ExtensionRuleResultDetail(this.Name, firstFeedFullUrl.AbsoluteUri, "GET", StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, context.RequestHeaders), response);

            if (response != null && response.StatusCode != null)
            {
                JObject feed;
                response.ResponsePayload.TryToJObject(out feed);
                var entries = JsonParserHelper.GetEntries(feed);

                foreach (JObject entry in entries)
                {
                    var jProps = entry.Children();

                    foreach (JProperty jProp in jProps)
                    {
                        if (JsonSchemaHelper.IsAnnotation(jProp.Name) && jProp.Name.EndsWith("@" + Constants.OdataType) && !jProp.Name.StartsWith("@" + Constants.OdataType))
                        {
                            string typeValue = jProp.Value.ToString().TrimStart('#');

                            if (typeValue.Contains("Collection("))
                            {
                                typeValue = typeValue.Substring(typeValue.IndexOf("(") + 1, typeValue.LastIndexOf(")") - typeValue.IndexOf("(") - 1);
                            }

                            // Don't contains dot means it is primitive value or collection.
                            if (!typeValue.Contains("."))
                            {
                                if (PrimitiveDataTypes.NonQualifiedTypes.Contains(typeValue))
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    detail.ErrorMessage += string.Format("The type {0} is not defined in OData-CSDL.", typeValue);
                                    break;
                                }
                            }
                        }
                    }

                    if (passed == false)  // Break to foreach all if anyone of them cannot match the rule
                    {
                        break;
                    }
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = string.Format(Constants.ErrorURI, "GET", firstFeedFullUrl.AbsoluteUri, "failed");
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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;

            Response resp = WebHelper.Get(new Uri(context.ServiceBaseUri.OriginalString.TrimEnd('/') + @"/" + "$all"), Constants.AcceptHeaderJson,
                                          RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name, context.ServiceBaseUri.OriginalString.TrimEnd('/') + @"/" + "$all",
                                                                             HttpMethod.Get, context.RequestHeaders.ToString());

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

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                return(passed = false);
            }

            JObject allFeed;

            resp.ResponsePayload.TryToJObject(out allFeed);

            if (allFeed == null || JTokenType.Object != allFeed.Type)
            {
                return(passed = false);
            }

            JArray allEntities = JsonParserHelper.GetEntries(allFeed);

            passed = true;

            List <string> entitySetURLs = MetadataHelper.GetEntitySetURLs();

            foreach (string entitySetUrl in entitySetURLs)
            {
                string entityTypeShortName = entitySetUrl.MapEntitySetNameToEntityTypeShortName();
                Tuple <string, string> key = MetadataHelper.GetKeyProperty(entityTypeShortName);

                resp = WebHelper.Get(new Uri(context.ServiceBaseUri.OriginalString.TrimEnd('/') + @"/" + entitySetUrl),
                                     Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                if (null == resp || HttpStatusCode.OK != resp.StatusCode)
                {
                    continue;
                }

                JObject feed;
                resp.ResponsePayload.TryToJObject(out feed);

                if (feed == null || JTokenType.Object != feed.Type)
                {
                    continue;
                }

                JArray entities = JsonParserHelper.GetEntries(feed);
                foreach (JToken entity in entities)
                {
                    if (!Find(allEntities, key.Item1, entity[key].ToString()))
                    {
                        return(passed = false);
                    }
                }
            }

            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;
            ServiceStatus serviceStatus = ServiceStatus.GetInstance();
            TermDocuments termDocs = TermDocuments.GetInstance();
            DataFactory dFactory = DataFactory.Instance();
            var detail1 = new ExtensionRuleResultDetail(this.Name);
            var detail2 = new ExtensionRuleResultDetail(this.Name);
            var detail3 = new ExtensionRuleResultDetail(this.Name);
            var detail4 = new ExtensionRuleResultDetail(this.Name);
            List<string> keyPropertyTypes = new List<string>() { "Edm.Int32", "Edm.Int16", "Edm.Int64", "Edm.Guid", "Edm.String" };
            List<string> norPropertyTypes = new List<string>() { "Edm.String" };
            List<EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.CollectionValued).ToList();
            if (null == entityTypeElements || 0 == entityTypeElements.Count)
            {
                detail1.ErrorMessage = "To verify this rule it expects an entity type with Int32/Int64/Int16/Guid/String key property and a string type normal property, but there is no this entity type in metadata so can not verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return passed;
            }

            EntityTypeElement entityType = null;
            foreach (var en in entityTypeElements)
            {
                var matchEntity = en.EntitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc,
                    new List<Func<string, string, string, List<NormalProperty>, List<NavigProperty>, bool>>()
                    {
                        AnnotationsHelper.GetDeleteRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions
                    });

                if (!string.IsNullOrEmpty(matchEntity.Item1)
                     && matchEntity.Item2 != null && matchEntity.Item2.Any()
                     && matchEntity.Item3 != null && matchEntity.Item3.Any())
                {
                    entityType = en;
                    break;
                }
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();
            if (string.IsNullOrEmpty(entitySetUrl))
            {
                detail1.ErrorMessage = string.Format("Cannot find the entity-set URL which is matched with {0}", entityType.EntityTypeShortName);
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return passed;
            }

            string url = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var additionalInfos = new List<AdditionalInfo>();
            var reqData = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);
            string reqDataStr = reqData.ToString();
            bool isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
            var resp = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
            detail1 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
            if (HttpStatusCode.Created == resp.StatusCode)
            {
                string entityId = additionalInfos.Last().EntityId;
                bool hasEtag = additionalInfos.Last().HasEtag;
                resp = WebHelper.GetEntity(entityId);
                detail2 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp);
                if (HttpStatusCode.OK == resp.StatusCode)
                {
                    JObject entity = JObject.Parse(resp.ResponsePayload);
                    List<string> norPropertyNames = entityType.NormalProperties
                        .Where(norProp => norPropertyTypes.Contains(norProp.PropertyType) && !norProp.IsKey)
                        .Select(norProp => norProp.PropertyName)
                        .ToList();
                    reqDataStr = dFactory.ConstructUpdatedEntityData(entity, norPropertyNames).ToString();
                    resp = WebHelper.UpdateEntity(entityId, context.RequestHeaders, reqDataStr, HttpMethod.Patch, hasEtag);
                    detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Patch, string.Empty, resp, string.Empty, reqDataStr);
                    if (HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp = WebHelper.GetEntity(entityId);
                        detail4 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                        if (HttpStatusCode.OK == resp.StatusCode)
                        {
                            entity = JObject.Parse(resp.ResponsePayload);
                            var jProps = entity.Children<JProperty>();
                            int counter = 0;

                            foreach (var jP in jProps)
                            {
                                if (norPropertyNames.Contains(jP.Name) && Constants.UpdateData == jP.Value.ToString())
                                {
                                    counter++;
                                }
                            }

                            if (norPropertyNames.Count == counter)
                            {
                                passed = true;
                            }
                            else
                            {
                                passed = false;
                                detail4.ErrorMessage = string.Format("Not all properties in request are updated, there are {0} properties in request to be updated but {1} properties are updated. ", norPropertyNames.Count, counter);
                            }
                        }
                        else
                        {
                            passed = false;
                            detail4.ErrorMessage = "Can not get the updated entity.";
                        }
                    }
                    else
                    {
                        passed = false;
                        detail3.ErrorMessage = "Patch the entity failed.";
                    }
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Can not get the created entity from above URI.";
                }

                // Restore the service.
                var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = "Created the new entity failed for above URI.";
            }

            var details = new List<ExtensionRuleResultDetail>() { detail1, detail2, detail3, detail4 }.RemoveNullableDetails();
            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

            return passed;
        }
Esempio n. 29
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 entityTypeShortName;
            var    propTypes = new string[2] {
                "Edm.Date", "Edm.DateTimeOffset"
            };
            var propNames = MetadataHelper.GetPropertyNames(propTypes, out entityTypeShortName);

            if (null == propNames || !propNames.Any())
            {
                return(passed);
            }

            string propName     = propNames[0];
            var    entitySetUrl = entityTypeShortName.GetAccessEntitySetURL();

            if (string.IsNullOrEmpty(entitySetUrl))
            {
                return(passed);
            }

            string url  = svcStatus.RootURL.TrimEnd('/') + "/" + entitySetUrl;
            var    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);

            if (null != resp && HttpStatusCode.OK == resp.StatusCode)
            {
                var settings = new JsonSerializerSettings();
                settings.DateParseHandling = DateParseHandling.None;
                JObject jObj    = JsonConvert.DeserializeObject(resp.ResponsePayload, settings) as JObject;
                JArray  jArr    = jObj.GetValue(Constants.Value) as JArray;
                var     entity  = jArr.First as JObject;
                var     propVal = entity[propName].ToString();
                int     index   = propVal.IndexOf('-');
                propVal = propVal.Substring(index + 1, 2);
                url     = string.Format("{0}?$filter=month({1}) eq {2}", url, propName, propVal);
                resp    = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                var detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                {
                    jObj = JsonConvert.DeserializeObject(resp.ResponsePayload, settings) as JObject;
                    jArr = jObj.GetValue(Constants.Value) as JArray;
                    foreach (JObject et in jArr)
                    {
                        passed = et[propName].ToString().Substring(index + 1, 2) == propVal;
                    }
                }
                else
                {
                    passed = false;
                }
            }

            return(passed);
        }
Esempio n. 30
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 entityTypeShortName;
            var    propTypes = new string[2] {
                "Edm.Double", "Edm.Decimal"
            };
            var props = MetadataHelper.GetProperties(propTypes, out entityTypeShortName);

            if (null == props || !props.Any())
            {
                return(passed);
            }

            string propName     = props[0].Item1;
            string propType     = props[0].Item2;
            var    entitySetUrl = entityTypeShortName.GetAccessEntitySetURL();

            if (string.IsNullOrEmpty(entitySetUrl))
            {
                return(passed);
            }

            string url  = svcStatus.RootURL.TrimEnd('/') + "/" + entitySetUrl;
            var    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);

            if (null != resp && HttpStatusCode.OK == resp.StatusCode)
            {
                JObject jObj     = JObject.Parse(resp.ResponsePayload);
                JArray  jArr     = jObj.GetValue(Constants.Value) as JArray;
                var     entity   = jArr.First as JObject;
                var     datatest = Convert.ToString(entity[propName]);
                if (string.IsNullOrEmpty(datatest))
                {
                    for (int n = 1; n < props.Count; n++)
                    {
                        propName = props[n].Item1;
                        if (entity[propName] != null)
                        {
                            datatest = Convert.ToString(entity[propName]);
                            if (!string.IsNullOrEmpty(datatest))
                            {
                                propType = props[n].Item2;
                                break;
                            }
                        }
                        propName = string.Empty;
                    }
                }
                if (string.IsNullOrEmpty(propName))
                {
                    var detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                    detail3.ErrorMessage = "None of the properties of type Edm.Double or Edm.Decimal had any data to test for entity " + entityTypeShortName;
                    info   = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail3);
                    passed = false;
                    return(passed);
                }
                if ("Edm.Double" == propType)
                {
                    var propVal = Math.Floor(Convert.ToDouble(entity[propName]));
                    url  = string.Format("{0}?$filter=floor({1}) eq {2}", url, propName, propVal);
                    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                    var detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                    detail.URI                = url;
                    detail.ResponsePayload    = resp.ResponsePayload;
                    detail.ResponseHeaders    = resp.ResponseHeaders;
                    detail.HTTPMethod         = "GET";
                    detail.ResponseStatusCode = resp.StatusCode.ToString();

                    info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                    if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                    {
                        jObj = JObject.Parse(resp.ResponsePayload);
                        jArr = jObj.GetValue(Constants.Value) as JArray;
                        foreach (JObject et in jArr)
                        {
                            if (Math.Floor(Convert.ToDouble(et[propName])) == propVal)
                            {
                                passed = true;
                            }
                            else
                            {
                                detail.ErrorMessage = "The Math.Floor test failed for " + et[propName] + " it did not equal " + propVal;
                                passed = false;
                                break;
                            }
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "The server returned an error response:  " + detail.ResponseStatusCode;
                        passed = false;
                    }
                }
                else // The property type is Edm.Decimal.
                {
                    var propVal = Math.Floor(Convert.ToDecimal(entity[propName]));
                    url  = string.Format("{0}?$filter=floor({1}) eq {2}", url, propName, propVal);
                    resp = WebHelper.Get(new Uri(url), string.Empty, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                    var detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, string.Empty);
                    detail.URI                = url;
                    detail.ResponsePayload    = resp.ResponsePayload;
                    detail.ResponseHeaders    = resp.ResponseHeaders;
                    detail.HTTPMethod         = "GET";
                    detail.ResponseStatusCode = resp.StatusCode.ToString();

                    info = new ExtensionRuleViolationInfo(new Uri(url), string.Empty, detail);
                    if (null != resp && HttpStatusCode.OK == resp.StatusCode)
                    {
                        jObj = JObject.Parse(resp.ResponsePayload);
                        jArr = jObj.GetValue(Constants.Value) as JArray;
                        foreach (JObject et in jArr)
                        {
                            if (Math.Floor(Convert.ToDecimal(et[propName])) == propVal)
                            {
                                passed = true;
                            }
                            else
                            {
                                detail.ErrorMessage = "The Math.Floor test failed for " + et[propName] + " it did not equal " + propVal;
                                passed = false;
                                break;
                            }
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "The server returned an error response:  " + detail.ResponseStatusCode;
                        passed = false;
                    }
                }
            }

            return(passed);
        }