Beispiel #1
0
        /// <summary>
        /// Get specified count of entities from first feed of service document.
        /// </summary>
        /// <param name="context">The service document context.</param>
        /// <returns>Returns an entity URLs's list.</returns>
        public static bool GetBatchSupportedEntityUrls(out KeyValuePair <string, IEnumerable <string> > entityUrls)
        {
            entityUrls = new KeyValuePair <string, IEnumerable <string> >();
            var           svcStatus = ServiceStatus.GetInstance();
            List <string> vocDocs   = new List <string>()
            {
                TermDocuments.GetInstance().VocCapabilitiesDoc
            };
            var payloadFormat = svcStatus.ServiceDocument.GetFormatFromPayload();
            var batchSupportedEntitySetUrls  = new List <string>();
            var batchSupportedEntitySetNames = AnnotationsHelper.SelectEntitySetSupportBatch(svcStatus.MetadataDocument, vocDocs);

            batchSupportedEntitySetNames.ForEach(temp => { batchSupportedEntitySetUrls.Add(temp.MapEntitySetNameToEntitySetURL()); });
            var entitySetUrls = ContextHelper.GetFeeds(svcStatus.ServiceDocument, payloadFormat).ToArray();

            if (entitySetUrls.Any())
            {
                string entitySetUrl = string.Empty;
                foreach (var setUrl in entitySetUrls)
                {
                    try
                    {
                        string entityTypeShortName = setUrl.MapEntitySetURLToEntityTypeShortName();
                        if (batchSupportedEntitySetUrls.Contains(setUrl) && !entityTypeShortName.IsMediaType())
                        {
                            entitySetUrl = setUrl;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                        string test = ex.Message;
                    }
                }

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

                string   url      = string.Format("{0}/{1}?$top=1", svcStatus.RootURL.TrimEnd('/'), entitySetUrl);
                Response response = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                payloadFormat = response.ResponsePayload.GetFormatFromPayload();
                var payloadType = ContextHelper.GetPayloadType(response.ResponsePayload, payloadFormat, response.ResponseHeaders);
                if (payloadType == RuleEngine.PayloadType.Feed)
                {
                    entityUrls = new KeyValuePair <string, IEnumerable <string> >(entitySetUrl, ContextHelper.GetEntries(response.ResponsePayload, payloadFormat));

                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
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);
        }
Beispiel #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;
            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);

            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}.", reqData);
            }

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

            info = new ExtensionRuleViolationInfo(this.ErrorMessage, new Uri(serviceStatus.RootURL), 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;
            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"
            };
            var entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.CollectionValued);

            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, 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);
            }

            string            entitySet  = string.Empty;
            string            navigProp  = string.Empty;
            EntityTypeElement entityType = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                entitySet = en.EntitySetName;
                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetExpandRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };

                var restrictions = entitySet.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs, null, NavigationRoughType.CollectionValued);
                if (!string.IsNullOrEmpty(restrictions.Item1) &&
                    null != restrictions.Item2 && restrictions.Item2.Any() &&
                    null != restrictions.Item3 && restrictions.Item3.Any())
                {
                    navigProp  = restrictions.Item3.First().NavigationPropertyName;
                    entityType = en;
                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySet) || string.IsNullOrEmpty(navigProp))
            {
                detail1.ErrorMessage = "Cannot find an entity-set URL which can be execute the deep insert operation on it.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySet;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, new List <string>()
            {
                navigProp
            }, 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)
            {
                var entityId = additionalInfos.Last().EntityId;
                resp    = WebHelper.GetEntity(entityId);
                detail2 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                if (HttpStatusCode.OK == resp.StatusCode && additionalInfos.Count > 1)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Can not get the created entity. ";
                }

                // 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);
        }
Beispiel #5
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();
            ExtensionRuleResultDetail detail1          = new ExtensionRuleResultDetail(this.Name);
            ExtensionRuleResultDetail detail2          = new ExtensionRuleResultDetail(this.Name);
            ExtensionRuleResultDetail detail3          = new ExtensionRuleResultDetail(this.Name);
            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.CollectionValued).ToList();

            if (entityTypeElements == null || entityTypeElements.Count == 0)
            {
                detail1.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, 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
                });

                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 (resp.StatusCode.HasValue && HttpStatusCode.Created == resp.StatusCode)
                    {
                        string entityId = additionalInfos.Last().EntityId;
                        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, string.Empty, reqDataStr);
                        detail2.URI                = url;
                        detail2.ResponsePayload    = resp.ResponsePayload;
                        detail2.ResponseHeaders    = resp.ResponseHeaders;
                        detail2.HTTPMethod         = "GET";
                        detail2.ResponseStatusCode = resp.StatusCode.ToString();

                        if (null != resp && resp.StatusCode == HttpStatusCode.OK)
                        {
                            JObject feed;
                            resp.ResponsePayload.TryToJObject(out feed);
                            var entities = JsonParserHelper.GetEntries(feed);
                            if (entities.Count > 0)
                            {
                                // Use the HTTP method POST to link the navigation property for an entity.
                                reqDataStr = @"{""" + Constants.V4OdataId + @""" : """ + entities[0][Constants.V4OdataId].ToString() + @"""}";
                                url        = string.Format("{0}/{1}/$ref", entityId.TrimEnd('/'), navigPropName.TrimEnd('/'));
                                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)
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    detail3.ErrorMessage = "Created the new entity failed for above URI.";
                                }
                            }
                        }
                        else
                        {
                            passed = false;
                            detail2.ErrorMessage = "Get entity failed 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.";
                    }
                }

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

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

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

            return(passed);
        }
Beispiel #6
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);
            Dictionary <string, Dictionary <KeyValuePair <string, string>, List <string> > > entityTypeInfos;

            if (!MetadataHelper.GetEntityTypesWithComplexProperty(serviceStatus.MetadataDocument, "Edm.String", out entityTypeInfos))
            {
                detail1.ErrorMessage = "To verify this rule it expects complex type containing a property with string type, but there is no this complex type in metadata so cannot verify this rule.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            var    entityTypeInfo = new KeyValuePair <string, Dictionary <KeyValuePair <string, string>, List <string> > >();
            string entitySetName  = string.Empty;

            foreach (var etInfo in entityTypeInfos)
            {
                entitySetName = etInfo.Key.MapEntityTypeShortNameToEntitySetName();
                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };

                var restrictions = entitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs);
                if (!string.IsNullOrEmpty(restrictions.Item1) ||
                    null != restrictions.Item2 || restrictions.Item2.Any() ||
                    null != restrictions.Item3 || restrictions.Item3.Any())
                {
                    entityTypeInfo = etInfo;

                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySetName) ||
                string.IsNullOrEmpty(entityTypeInfo.Key) ||
                null == entityTypeInfo.Value ||
                !entityTypeInfo.Value.Any())
            {
                detail1.ErrorMessage = "Cannot find the entity-set which support insert, updata, delete restrictions at the same time.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            string entityTypeShortName           = entityTypeInfo.Key;
            string entitySetUrl                  = entitySetName.MapEntitySetNameToEntitySetURL();
            string complexPropName               = entityTypeInfo.Value.Keys.First().Key;
            string complexPropType               = entityTypeInfo.Value.Keys.First().Value;
            string propertyNameWithSpecifiedType = entityTypeInfo.Value[new KeyValuePair <string, string>(complexPropName, complexPropType)].First();

            // Create a entity
            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entitySetName, entityTypeShortName, null, out additionalInfos);

            reqData = dFactory.ReconstructNullableComplexData(reqData, new List <string>()
            {
                complexPropName
            });
            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 (resp.StatusCode == HttpStatusCode.Created)
            {
                var entityId = additionalInfos.Last().EntityId;
                var hasEtag  = additionalInfos.Last().HasEtag;

                // Get a complex property except key property
                string complexProUrl = entityId + @"/" + complexPropName;
                resp    = WebHelper.Get(new Uri(complexProUrl), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, serviceStatus.DefaultHeaders);
                detail2 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Get, StringHelper.MergeHeaders(Constants.AcceptHeaderJson, serviceStatus.DefaultHeaders), resp);

                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    JObject jo;
                    resp.ResponsePayload.TryToJObject(out jo);
                    //string newComplexProperty = VerificationHelper.ConstructUpdatedEntityData(jo, new List<string>() { propertyNameWithSpecifiedType }, out hasEtag);
                    string newComplexProperty = dFactory.ConstructUpdatedEntityData(jo, new List <string>()
                    {
                        propertyNameWithSpecifiedType
                    }).ToString();

                    // Update the complex property
                    resp    = WebHelper.UpdateEntity(complexProUrl, context.RequestHeaders, newComplexProperty, HttpMethod.Patch, hasEtag);
                    detail3 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Patch, string.Empty, resp, string.Empty, newComplexProperty);
                    if (resp.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Check whether the complex property is updated to new value
                        if (WebHelper.GetContent(complexProUrl, context.RequestHeaders, out resp))
                        {
                            detail4 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Get, string.Empty, resp);
                            resp.ResponsePayload.TryToJObject(out jo);

                            if (jo != null && jo[propertyNameWithSpecifiedType] != null && jo[propertyNameWithSpecifiedType].Value <string>().Equals(Constants.UpdateData))
                            {
                                passed = true;
                            }
                            else if (jo == null)
                            {
                                passed = false;
                                detail4.ErrorMessage = "Can not get complex property after Patch it. ";
                            }
                            else if (jo != null && jo[propertyNameWithSpecifiedType] == null)
                            {
                                passed = false;
                                detail4.ErrorMessage = string.Format("Can not get the value of {0} property in complex property {1}. ", propertyNameWithSpecifiedType, complexProUrl);
                            }
                            else if (jo != null && jo[propertyNameWithSpecifiedType] != null && !jo[propertyNameWithSpecifiedType].Value <string>().Equals(Constants.UpdateData))
                            {
                                passed = false;
                                detail4.ErrorMessage = string.Format("The value of {0} property in complex is not updated by {1}. ", propertyNameWithSpecifiedType, complexProUrl);
                            }
                        }
                    }
                    else
                    {
                        passed = false;
                        detail3.ErrorMessage = "Update complex property in the created entity failed. ";
                    }
                }
                else if (resp.StatusCode == HttpStatusCode.NoContent)
                {
                    detail2.ErrorMessage = "The value of property with complex type is null.";
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Get complex property in the created entity failed. ";
                }
                // Delete the entity
                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);
        }
        /// <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, navigPropName);

                                // 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>
        /// 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 <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.SingleValued).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, 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);
            }

            // Create a entity
            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    keyNames        = entityType.KeyProperties;
            string keyName         = keyNames.First().PropertyName;
            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 (resp.StatusCode == HttpStatusCode.Created)
            {
                var entityId = additionalInfos.Last().EntityId;
                var hasEtag  = additionalInfos.Last().HasEtag;

                // Get a individual property except key property
                string        toUpdatePropertyName = string.Empty;
                List <string> properties           = MetadataHelper.GetSortedPropertiesOfEntity(serviceStatus.MetadataDocument, entityType.EntityTypeShortName);
                foreach (string name in properties)
                {
                    if (!string.Equals(name.Split(',')[0], keyName))
                    {
                        if (name.Split(',')[1].Equals("Edm.String"))
                        {
                            toUpdatePropertyName = name.Split(',')[0];
                            break;
                        }
                    }
                }

                string individualProUrl = entityId + @"/" + toUpdatePropertyName;
                resp    = WebHelper.Get(new Uri(individualProUrl), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, serviceStatus.DefaultHeaders);
                detail2 = new ExtensionRuleResultDetail(this.Name, individualProUrl, HttpMethod.Get, StringHelper.MergeHeaders(Constants.AcceptHeaderJson, serviceStatus.DefaultHeaders), resp);
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    JObject jo;
                    resp.ResponsePayload.TryToJObject(out jo);
                    string valueOfIndividualProperty = jo[Constants.Value].ToString();
                    string newValue = valueOfIndividualProperty + "ToUpdate";
                    jo[Constants.Value] = newValue;

                    // Update the individual property
                    resp    = WebHelper.UpdateEntity(individualProUrl, jo.ToString(), HttpMethod.Put);
                    detail3 = new ExtensionRuleResultDetail(this.Name, individualProUrl, HttpMethod.Put, string.Empty, resp, string.Empty, jo.ToString());
                    if (resp.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Check whether the individual property is updated to new value
                        if (WebHelper.GetContent(individualProUrl, context.RequestHeaders, out resp))
                        {
                            detail4 = new ExtensionRuleResultDetail(this.Name, individualProUrl, HttpMethod.Get, string.Empty, resp);
                            resp.ResponsePayload.TryToJObject(out jo);

                            if (jo != null && jo[Constants.Value] != null && jo[Constants.Value].Value <string>().Equals(newValue))
                            {
                                passed = true;
                            }
                            else if (jo == null)
                            {
                                passed = false;
                                detail4.ErrorMessage = "Can not get individual property after PUT to it.";
                            }
                            else if (jo != null && jo[Constants.Value] == null)
                            {
                                passed = false;
                                detail4.ErrorMessage = "Can not get the value of individual property.";
                            }
                            else if (jo != null && jo[Constants.Value] != null && !jo[Constants.Value].Value <string>().Equals(newValue))
                            {
                                passed = false;
                                detail4.ErrorMessage = "The value of individual property is not updated.";
                            }
                        }
                    }
                    else
                    {
                        passed = false;
                        detail3.ErrorMessage = "Update individual property from the created entity failed.";
                    }
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Get individual property from the created entity failed.";
                }

                // Delete the entity
                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(this.ErrorMessage, new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Beispiel #9
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();
            ExtensionRuleResultDetail detail1          = new ExtensionRuleResultDetail(this.Name);
            ExtensionRuleResultDetail detail2          = new ExtensionRuleResultDetail(this.Name);
            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.CollectionValued).ToList();

            if (entityTypeElements == null || entityTypeElements.Count == 0)
            {
                detail1.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, detail1);

                return(passed);
            }

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

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

                string         navigPropName = null;
                string         navigPropRelatedEntityTypeShortName = null;
                string         navigPropRelatedEntitySetName       = null;
                string         navigPropRelatedEntitySetUrl        = null;
                NormalProperty navigPropRelatedEntityTypeKey       = null;

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

                    if (navigKeyProps.Count == 1 && keyPropertyTypes.Contains(navigKeyProps[0].PropertyType))
                    {
                        navigPropRelatedEntitySetName = navigPropRelatedEntityTypeShortName.MapEntityTypeShortNameToEntitySetName();
                        navigPropRelatedEntitySetUrl  = navigPropRelatedEntityTypeShortName.MapEntityTypeShortNameToEntitySetURL();
                        navigPropRelatedEntityTypeKey = navigKeyProps[0];
                        break;
                    }
                }

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

                    if (resp.StatusCode.HasValue && HttpStatusCode.Created == resp.StatusCode)
                    {
                        string entityId = additionalInfos1.Last().EntityId;
                        url = serviceStatus.RootURL.TrimEnd('/') + @"/" + navigPropRelatedEntitySetUrl;
                        if (string.IsNullOrEmpty(navigPropRelatedEntityTypeShortName))
                        {
                            continue;
                        }

                        var navigPropEntityType = navigPropRelatedEntityTypeShortName.GetSpecifiedEntityType(serviceStatus.MetadataDocument);
                        if (null == navigPropEntityType)
                        {
                            continue;
                        }

                        url = string.Format("{0}/{1}", entityId, navigPropName);
                        var additionalInfos2 = new List <AdditionalInfo>();
                        reqData     = dFactory.ConstructInsertedEntityData(navigPropRelatedEntitySetName, navigPropRelatedEntityTypeShortName, null, out additionalInfos2);
                        reqDataStr  = reqData.ToString();
                        isMediaType = !string.IsNullOrEmpty(additionalInfos2.Last().ODataMediaEtag);
                        resp        = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos2);
                        detail2     = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

                        if (resp.StatusCode.HasValue && resp.StatusCode == HttpStatusCode.Created)
                        {
                            passed = true;

                            // Restore the service.
                            var resps2 = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos2);
                        }
                        else
                        {
                            passed = false;
                            detail2.ErrorMessage = "Create entity failed for above URI.";
                        }

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

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

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

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

            return(passed);
        }
Beispiel #10
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;
            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"
            };
            var entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.SingleValued);

            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);
            }

            string            entitySet  = string.Empty;
            string            navigProp  = string.Empty;
            EntityTypeElement entityType = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                entitySet = en.EntitySetName;
                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetExpandRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };

                var restrictions = entitySet.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs, null, NavigationRoughType.SingleValued);
                if (!string.IsNullOrEmpty(restrictions.Item1) &&
                    null != restrictions.Item2 && restrictions.Item2.Any() &&
                    null != restrictions.Item3 && restrictions.Item3.Any())
                {
                    navigProp  = restrictions.Item3.First().NavigationPropertyName;
                    entityType = en;
                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySet) || string.IsNullOrEmpty(navigProp))
            {
                detail.ErrorMessage = "Cannot find an entity-set URL which can be executed the deep insert operation on it.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string url                = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySet;
            var    additionalInfos    = new List <AdditionalInfo>();
            var    additionalInfosAll = 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)
            {
                string nPropURL      = additionalInfos.Last().EntityId.TrimEnd('/') + @"/" + navigProp;
                string navigationUrl = additionalInfos.Last().EntityId.TrimEnd('/') + @"/" + navigProp + @"/$ref";
                resp = WebHelper.GetEntity(additionalInfos.Last().EntityId);

                if (HttpStatusCode.OK == resp.StatusCode && additionalInfos.Count > 0)
                {
                    string navigPropType          = MetadataHelper.GetNavigPropertyTypeFromMetadata(navigProp, entityType.EntityTypeShortName, serviceStatus.MetadataDocument);
                    string navigPropTypeShortName = navigPropType.GetLastSegment();
                    string nEntitySetName         = navigProp.MapNavigationPropertyNameToEntitySetName(entityType.EntityTypeShortName);
                    string nEntitySetUrl          = nEntitySetName.MapEntitySetNameToEntitySetURL();
                    nEntitySetUrl = serviceStatus.RootURL.TrimEnd('/') + @"/" + nEntitySetUrl;

                    additionalInfosAll = additionalInfos;

                    reqData = dFactory.ConstructInsertedEntityData(nEntitySetName, navigPropTypeShortName, null, out additionalInfos);

                    foreach (AdditionalInfo a in additionalInfos)
                    {
                        additionalInfosAll.Add(a);
                    }

                    reqDataStr  = reqData.ToString();
                    isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
                    resp        = WebHelper.CreateEntity(nEntitySetUrl, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
                    detail      = new ExtensionRuleResultDetail(this.Name, nEntitySetUrl, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);

                    if (HttpStatusCode.Created == resp.StatusCode)
                    {
                        string refEntityId = additionalInfos.Last().EntityId;

                        string refEntitySetNameWithEnityID = refEntityId.Split('/').Last();
                        string refEntityValue = serviceStatus.RootURL.TrimEnd('/') + @"/" + refEntitySetNameWithEnityID;

                        JObject navigationRefSet = new JObject();
                        navigationRefSet.Add(Constants.V4OdataId, refEntityValue);

                        resp   = WebHelper.UpdateEntity(navigationUrl, context.RequestHeaders, navigationRefSet.ToString(), HttpMethod.Put, false);
                        detail = new ExtensionRuleResultDetail(this.Name, navigationUrl, HttpMethod.Put, string.Empty, resp, string.Empty, refEntityValue.ToString());

                        if (HttpStatusCode.NoContent == resp.StatusCode)
                        {
                            resp = WebHelper.GetEntity(navigationUrl);

                            if (HttpStatusCode.OK == resp.StatusCode)
                            {
                                JObject value;
                                resp.ResponsePayload.TryToJObject(out value);

                                if (value != null && value.Type == JTokenType.Object)
                                {
                                    foreach (var row in value.Children <JProperty>())
                                    {
                                        if (row.Name.Equals(Constants.V4OdataId) && !string.IsNullOrEmpty(row.Value.ToString()))
                                        {
                                            passed = true;
                                            detail = new ExtensionRuleResultDetail(this.Name, navigationUrl, HttpMethod.Put, string.Empty, resp, string.Empty, refEntityValue.ToString());
                                            break;
                                        }
                                    }

                                    if (passed != true)
                                    {
                                        passed = false;
                                        detail.ErrorMessage = "Failed in updating the single reference of navigation property.";
                                    }
                                }
                            }
                            else
                            {
                                passed = false;
                                detail.ErrorMessage = "Failed to get the navigation property association link.";
                            }
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "Failed in HTTP Put to update the single reference of navigation property.";
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "Failed in creating the new referenced entity.";
                    }
                }
                else
                {
                    detail.ErrorMessage = "Can not get the created entity. ";
                }

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

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

            info = new ExtensionRuleViolationInfo(new Uri(url), 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;
            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);
            }


            EntityTypeElement eTypeElement = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                if (MetadataHelper.IsMediaEntity(serviceStatus.MetadataDocument, en.EntityTypeShortName, context) && !string.IsNullOrEmpty(en.EntitySetName))
                {
                    eTypeElement = en;
                    break;
                }
            }

            if (eTypeElement.EntityTypeShortName == null)
            {
                detail.ErrorMessage = "Cannot find the appropriate media entity type 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);
            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 (HttpStatusCode.Created == resp.StatusCode || HttpStatusCode.NoContent == resp.StatusCode)
            {
                url = additionalInfos.Last().EntityId.TrimEnd('/') + "/$value";
                if (url.Equals("/$value"))
                {
                    detail.ErrorMessage = string.Format("Fail to find the image read and edit URL.", resp.StatusCode);
                    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);
                if (resp.StatusCode.HasValue && HttpStatusCode.OK == resp.StatusCode)
                {
                    resp   = WebHelper.UpdateMediaTypeEntity(url, context.RequestHeaders, additionalInfos.Last().HasEtag);
                    detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Put, string.Empty, resp, string.Empty, "Successfully updated the stream of the image.");

                    if (null != resp && (HttpStatusCode.NoContent == resp.StatusCode || resp.StatusCode == HttpStatusCode.OK))
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = string.Format("HTTP PUT to update the image failed with the error {0}.", resp.StatusCode);
                    }
                }
                else
                {
                    detail.ErrorMessage = "Get entity image failed from above URI.";
                }

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

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

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

            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;

            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"
            };
            var entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.CollectionValued);

            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);
            }

            string            entitySet  = string.Empty;
            EntityTypeElement entityType = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                entitySet = en.EntitySetName;
                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };

                var restrictions = entitySet.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs, null, NavigationRoughType.None);
                if (!string.IsNullOrEmpty(restrictions.Item1) &&
                    null != restrictions.Item2 && restrictions.Item2.Any() &&
                    null != restrictions.Item3 && restrictions.Item3.Any())
                {
                    entityType = en;
                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySet))
            {
                detail.ErrorMessage = "Cannot find an entity-set URL which can be execute the deep insert operation on it.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string entitySetUrl = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySet;
            string rootUrl      = serviceStatus.RootURL.TrimEnd('/') + @"/";
            string url          = entitySetUrl;

            Response resp = null;

            bool   gotDeltaLink = false;
            string deltaLink    = string.Empty;

            while (!gotDeltaLink)
            {
                resp = WebHelper.GetDeltaLink(url, context.RequestHeaders);
                JObject payload;
                if (resp.StatusCode == HttpStatusCode.OK)
                {
                    bool hasNextOrDelta = false;
                    resp.ResponsePayload.TryToJObject(out payload);
                    foreach (JProperty child in payload.Children <JProperty>())
                    {
                        if (child.Name.Equals(Constants.V4OdataDeltaLink))
                        {
                            gotDeltaLink   = true;
                            hasNextOrDelta = true;
                            deltaLink      = child.Value.ToString();

                            if (Uri.IsWellFormedUriString(deltaLink, UriKind.Relative))
                            {
                                deltaLink = rootUrl + deltaLink;
                            }

                            break;
                        }

                        if (child.Name.Equals(Constants.V4OdataNextLink))
                        {
                            url            = child.Value.ToString();
                            hasNextOrDelta = true;

                            if (Uri.IsWellFormedUriString(url, UriKind.Relative))
                            {
                                url = rootUrl + deltaLink;
                            }

                            break;
                        }
                    }

                    if (!hasNextOrDelta)
                    {
                        break;
                    }
                }
            }

            if (!gotDeltaLink)
            {
                detail.ErrorMessage = "The service does not support delta tracking.";
                info   = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);
                passed = false;

                return(passed);
            }

            bool   isCreated       = false;
            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);

            resp   = WebHelper.CreateEntity(entitySetUrl, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
            detail = new ExtensionRuleResultDetail(this.Name, entitySetUrl, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
            if (HttpStatusCode.Created == resp.StatusCode)
            {
                var entityId = additionalInfos.Last().EntityId;
                resp   = WebHelper.GetEntity(entityId);
                detail = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                if (HttpStatusCode.OK == resp.StatusCode)
                {
                    isCreated = true;
                }
            }

            resp = WebHelper.GetEntity(deltaLink);

            if ((isCreated && resp.StatusCode == HttpStatusCode.OK) || resp.StatusCode == HttpStatusCode.NoContent)
            {
                passed = true;
                detail = new ExtensionRuleResultDetail(this.Name, deltaLink, HttpMethod.Get, string.Empty, resp, string.Empty, null);
            }
            else
            {
                passed = false;
                detail = new ExtensionRuleResultDetail(this.Name, deltaLink, HttpMethod.Get, string.Empty, resp, string.Empty, null);
                detail.ErrorMessage = "Cannot get delta changes from the delta link.";
            }

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


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

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

            return(passed);
        }
Beispiel #13
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();
            ExtensionRuleResultDetail detail1          = new ExtensionRuleResultDetail(this.Name);
            ExtensionRuleResultDetail detail2          = new ExtensionRuleResultDetail(this.Name);
            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())
            {
                detail1.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, detail1);

                return(passed);
            }

            // To get test entity which is deleteable and insertable
            EntityTypeElement entityType = null;

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

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

            if (null == entityType)
            {
                detail1.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, 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();
            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 create successfully, the resource is updatable and deletable.
            if (resp.StatusCode.HasValue && resp.StatusCode == HttpStatusCode.Created)
            {
                // Get feed response.
                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.HasValue && resp.StatusCode == HttpStatusCode.OK)
                {
                    JObject jo;
                    resp.ResponsePayload.TryToJObject(out jo);
                    var entries = JsonParserHelper.GetEntries(jo);
                    foreach (JObject entry in entries)
                    {
                        if (entry[Constants.V4OdataEditLink] == null)
                        {
                            passed = false;
                            detail2.ErrorMessage = "Not all entities from above URI contain edit links.";
                            break;
                        }
                    }

                    if (passed == null)
                    {
                        passed = true;
                    }
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Get feed resource failed from above URI.";
                }

                // Restore the service.
                var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos);
            }
            else
            {
                passed = null;
                detail1.ErrorMessage = "Created new entity failed, it is not an updatable resource and can not verify this rule.";
            }

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

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), 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;
            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);
        }
        /// <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);
            var           detail5       = new ExtensionRuleResultDetail(this.Name);
            var           detail6       = new ExtensionRuleResultDetail(this.Name);
            var           entityType    = MetadataHelper.GetConcurrencyEntityType(serviceStatus.MetadataDocument);

            if (null == entityType)
            {
                detail1.ErrorMessage = "Cannot find an entity which contains a concurrency property in the service.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1);

                return(passed);
            }

            var normalPropNames = entityType.NormalProperties.Where(np => "Edm.String" == np.PropertyType && !np.IsKey).Select(np => np.PropertyName);

            if (normalPropNames.Any())
            {
                string entitySetUrl    = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();
                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)
                {
                    var entityId = additionalInfos.Last().EntityId;
                    var hasEtag  = additionalInfos.Last().HasEtag;
                    if (!hasEtag)
                    {
                        detail1.ErrorMessage = "The new inserted entity does not contain an @odata.etag annotation.";
                        info = new ExtensionRuleViolationInfo(new Uri(entityId), resp.ResponsePayload, detail2);

                        return(passed);
                    }

                    resp    = WebHelper.GetEntity(entityId, serviceStatus.DefaultHeaders);
                    detail2 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, StringHelper.MergeHeaders(string.Empty, serviceStatus.DefaultHeaders), resp);
                    if (HttpStatusCode.OK == resp.StatusCode)
                    {
                        reqDataStr = dFactory.ConstructUpdatedEntityData(reqData, normalPropNames).ToString();
                        var header  = new KeyValuePair <string, string>("If-Match", additionalInfos.Last().ODataEtag);
                        var headers = new List <KeyValuePair <string, string> >()
                        {
                            header
                        };
                        resp    = WebHelper.UpdateEntity(entityId, reqDataStr, HttpMethod.Patch, headers);
                        detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Patch, StringHelper.MergeHeaders(string.Empty, headers), resp, string.Empty, reqDataStr);
                        if (HttpStatusCode.NoContent == resp.StatusCode)
                        {
                            resp    = WebHelper.GetEntity(entityId, serviceStatus.DefaultHeaders);
                            detail4 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, StringHelper.MergeHeaders(string.Empty, serviceStatus.DefaultHeaders), resp);
                            if (HttpStatusCode.OK == resp.StatusCode)
                            {
                                resp    = WebHelper.DeleteEntity(entityId, context.RequestHeaders, hasEtag);
                                detail5 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Delete, StringHelper.MergeHeaders(string.Empty, new List <KeyValuePair <string, string> >()
                                {
                                    header
                                }), resp);
                                if (HttpStatusCode.NoContent == resp.StatusCode)
                                {
                                    resp    = WebHelper.GetEntity(entityId);
                                    detail6 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp);
                                    if (HttpStatusCode.NotFound == resp.StatusCode)
                                    {
                                        passed = true;
                                    }
                                    else
                                    {
                                        passed = false;
                                        detail6.ErrorMessage = "It still can get the deleted entity from above URI.";
                                    }
                                }
                                else
                                {
                                    passed = false;
                                    detail5.ErrorMessage = "Delete entity failed.";
                                }
                            }
                            else
                            {
                                passed = false;
                                detail4.ErrorMessage = "Can not get the created entity from above URI.";
                            }
                        }
                        else
                        {
                            passed = false;
                            detail3.ErrorMessage = "Update entity failed.";
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail1.ErrorMessage = "Created the new entity failed for above URI.";
                }
            }

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

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

            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;

            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"
            };
            var entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None);

            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);
            }

            string entitySet = string.Empty;
            string navigProp = string.Empty;
            NavigationRoughType navigRoughType = NavigationRoughType.None;
            EntityTypeElement   entityType     = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                if (!string.IsNullOrEmpty(en.EntitySetName) && en.NavigationProperties.Count > 0)
                {
                    foreach (NavigProperty np in en.NavigationProperties)
                    {
                        string npTypeFullName = np.NavigationPropertyType.RemoveCollectionFlag();

                        XmlDocument metadata = new XmlDocument();
                        metadata.LoadXml(context.MetadataDocument);
                        if (context.ContainsExternalSchema)
                        {
                            metadata.LoadXml(context.MergedMetadataDocument);
                        }
                        XmlNode npXmlNode;
                        MetadataHelper.GetTypeNode(npTypeFullName, metadata, out npXmlNode);
                        if (!(npXmlNode.Attributes["HasStream"] != null ? npXmlNode.Attributes["HasStream"].Value.Equals("true") : false))
                        {
                            navigProp      = np.NavigationPropertyName;
                            navigRoughType = np.NavigationRoughType;
                            entityType     = en;
                            entitySet      = en.EntitySetName;
                            break;
                        }
                    }

                    if (!string.IsNullOrEmpty(entitySet))
                    {
                        break;
                    }
                }
            }

            if (string.IsNullOrEmpty(entitySet) || string.IsNullOrEmpty(navigProp))
            {
                detail.ErrorMessage = "Cannot find an entity-set URL which can be execute the deep insert operation on it.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySet;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, new List <string>()
            {
                navigProp
            }, 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    mainEntityID = additionalInfos.Last().EntityId;
                string entityId     = additionalInfos.First().EntityId;

                string refUrl = mainEntityID.TrimEnd('/') + "/" + navigProp + "/$ref";
                string refEntitySetNameWithEnityID = entityId.Split('/').Last();
                string refEntityValue = serviceStatus.RootURL.TrimEnd('/') + @"/" + refEntitySetNameWithEnityID;
                string refEntityID    = refEntitySetNameWithEnityID.Contains("'") ? refEntitySetNameWithEnityID.Split('\'')[1] : refEntitySetNameWithEnityID.Split('(')[1].TrimEnd(')');

                resp   = WebHelper.GetEntity(mainEntityID);
                detail = new ExtensionRuleResultDetail(this.Name, mainEntityID, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                if (HttpStatusCode.OK == resp.StatusCode && additionalInfos.Count > 1)
                {
                    resp   = WebHelper.GetEntity(refUrl);
                    detail = new ExtensionRuleResultDetail(this.Name, refUrl, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                    if (HttpStatusCode.OK == resp.StatusCode)
                    {
                        JObject refPayload;
                        resp.ResponsePayload.TryToJObject(out refPayload);
                        bool created = false;

                        if (navigRoughType == NavigationRoughType.CollectionValued)
                        {
                            var entries = JsonParserHelper.GetEntries(refPayload);

                            if (entries != null)
                            {
                                foreach (JObject entry in entries)
                                {
                                    foreach (JProperty prop in entry.Children())
                                    {
                                        if (prop.Name.Equals(Constants.V4OdataId))
                                        {
                                            created = prop.Value.ToString().Contains(refEntityID);
                                            if (created)
                                            {
                                                passed = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            foreach (JProperty prop in refPayload.Children())
                            {
                                if (prop.Name.Equals(Constants.V4OdataId))
                                {
                                    created = prop.Value.ToString().Contains(refEntityID);
                                    if (created)
                                    {
                                        passed = true;
                                        break;
                                    }
                                }
                            }
                        }

                        if (!created)
                        {
                            passed = false;
                            detail.ErrorMessage = string.Format("The HTTP deep insert failed to add a reference to a collection-valued navigation property failed.");
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail.ErrorMessage = "Can not get the created entity. ";
                }

                // 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(url), serviceStatus.ServiceDocument, details);

            return(passed);
        }
Beispiel #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;
            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"
            };
            var entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, NavigationRoughType.None);

            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);
            }

            string entitySet     = string.Empty;
            string navigPropName = string.Empty;
            NavigationRoughType navigPropRoughType = NavigationRoughType.None;
            EntityTypeElement   entityType         = new EntityTypeElement();

            foreach (var en in entityTypeElements)
            {
                entitySet = en.EntitySetName;
                var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                {
                    AnnotationsHelper.GetExpandRestrictions, AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetDeleteRestrictions
                };

                var restrictions = entitySet.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs, null, NavigationRoughType.None);
                if (!string.IsNullOrEmpty(restrictions.Item1) &&
                    null != restrictions.Item2 && restrictions.Item2.Any() &&
                    null != restrictions.Item3 && restrictions.Item3.Any())
                {
                    navigPropName      = restrictions.Item3.First().NavigationPropertyName;
                    navigPropRoughType = restrictions.Item3.First().NavigationRoughType;
                    entityType         = en;
                    break;
                }
            }

            if (string.IsNullOrEmpty(entitySet) || string.IsNullOrEmpty(navigPropName))
            {
                detail.ErrorMessage = "Cannot find an entity set whose entity type has navigation property.";
                info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail);

                return(passed);
            }

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

            additionalInfosAll = 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)
            {
                string entityId = additionalInfos.Last().EntityId;
                string nPropUrl = entityId.TrimEnd('/') + "/" + navigPropName;
                updateUrl = entityId.TrimEnd('/') + "/" + navigPropName + "/$ref";
                bool hasEtag = additionalInfos.Last().HasEtag;

                string navigPropType          = MetadataHelper.GetNavigPropertyTypeFromMetadata(navigPropName, entityType.EntityTypeShortName, serviceStatus.MetadataDocument);
                string navigPropTypeShortName = string.Empty;
                if (navigPropRoughType == NavigationRoughType.CollectionValued)
                {
                    navigPropTypeShortName = navigPropType.Substring(navigPropType.IndexOf("(")).GetLastSegment().TrimEnd(')');
                }
                else
                {
                    navigPropTypeShortName = navigPropType.GetLastSegment();
                }
                string nEntitySetName = navigPropName.MapNavigationPropertyNameToEntitySetName(entityType.EntityTypeShortName);
                string nEntitySetUrl  = nEntitySetName.MapEntitySetNameToEntitySetURL();
                nEntitySetUrl = serviceStatus.RootURL.TrimEnd('/') + @"/" + nEntitySetUrl;

                reqData = dFactory.ConstructInsertedEntityData(nEntitySetName, navigPropTypeShortName, null, out additionalInfos);

                reqDataStr                = reqData.ToString();
                isMediaType               = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag);
                resp                      = WebHelper.CreateEntity(nEntitySetUrl, context.RequestHeaders, reqData, isMediaType, ref additionalInfos);
                detail                    = new ExtensionRuleResultDetail(this.Name, nEntitySetUrl, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr);
                detail.URI                = nEntitySetUrl;
                detail.ResponsePayload    = resp.ResponsePayload;
                detail.ResponseHeaders    = resp.ResponseHeaders;
                detail.HTTPMethod         = "GET";
                detail.ResponseStatusCode = resp.StatusCode.ToString();

                if (HttpStatusCode.Created == resp.StatusCode)
                {
                    foreach (AdditionalInfo a in additionalInfos)
                    {
                        additionalInfosAll.Add(a);
                    }

                    string refEntityId = additionalInfos.Last().EntityId;

                    resp   = WebHelper.GetEntity(refEntityId);
                    detail = new ExtensionRuleResultDetail(this.Name, refEntityId, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                    if (HttpStatusCode.OK == resp.StatusCode)
                    {
                        string addedNavigRefUrl = string.Empty;

                        if (navigPropRoughType == NavigationRoughType.CollectionValued)
                        {
                            addedNavigRefUrl = updateUrl + @"?$id=" + refEntityId;

                            string refEntitySetNameWithEnityID = refEntityId.Split('/').Last();
                            string refEntityValue = serviceStatus.RootURL.TrimEnd('/') + @"/" + refEntitySetNameWithEnityID;
                            string refEntityID    = refEntitySetNameWithEnityID.Contains("'") ? refEntitySetNameWithEnityID.Split('\'')[1] : refEntitySetNameWithEnityID.Split('(')[1].TrimEnd(')');

                            JObject navigationRefSet = new JObject();
                            navigationRefSet.Add(Constants.V4OdataId, refEntityValue);

                            resp   = WebHelper.CreateEntity(updateUrl, context.RequestHeaders, navigationRefSet, isMediaType, ref additionalInfosAll);
                            detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Patch, string.Empty, resp, string.Empty, reqDataStr);
                        }
                        else if (navigPropRoughType == NavigationRoughType.SingleValued)
                        {
                            addedNavigRefUrl = updateUrl;

                            string refEntityIdUrl = additionalInfos.Last().EntityId;

                            string refEntitySetNameWithEnityID = refEntityIdUrl.Split('/').Last();
                            string refEntityValue = serviceStatus.RootURL.TrimEnd('/') + @"/" + refEntitySetNameWithEnityID;

                            JObject navigationRefSet = new JObject();
                            navigationRefSet.Add(Constants.V4OdataId, refEntityValue);

                            resp                      = WebHelper.UpdateEntity(updateUrl, context.RequestHeaders, navigationRefSet.ToString(), HttpMethod.Put, false);
                            detail                    = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Put, string.Empty, resp, string.Empty, refEntityValue.ToString());
                            detail.URI                = updateUrl;
                            detail.ResponsePayload    = resp.ResponsePayload;
                            detail.ResponseHeaders    = resp.ResponseHeaders;
                            detail.HTTPMethod         = "PUT";
                            detail.ResponseStatusCode = resp.StatusCode.ToString();
                        }

                        if (HttpStatusCode.NoContent == resp.StatusCode)
                        {
                            resp   = WebHelper.GetEntity(addedNavigRefUrl);
                            detail = new ExtensionRuleResultDetail(this.Name, addedNavigRefUrl, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

                            if (HttpStatusCode.OK == resp.StatusCode)
                            {
                                resp = WebHelper.DeleteEntity(addedNavigRefUrl, context.RequestHeaders, false);

                                if (HttpStatusCode.NoContent == resp.StatusCode)
                                {
                                    passed = true;
                                    detail = new ExtensionRuleResultDetail(this.Name, addedNavigRefUrl, HttpMethod.Delete, string.Empty, resp, string.Empty, null);
                                }
                                else
                                {
                                    passed = false;
                                    detail.ErrorMessage = "Cannot remove the reference to the entity.";
                                }
                            }
                            else
                            {
                                passed = false;
                                detail.ErrorMessage = "HTTP Get to the navigation property reference failed.";
                            }
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "HTTP Post to add the navigation property reference failed.";
                        }
                    }
                    else
                    {
                        detail.ErrorMessage = "Can not get the created navigation entity set entity.";
                    }
                }
                else
                {
                    detail.ErrorMessage = "Creating navigation entity failes from above URI.";
                }

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

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

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

            return(passed);
        }
Beispiel #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           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 <EntityTypeElement> entityTypeElements = MetadataHelper.GetEntityTypes(serviceStatus.MetadataDocument, 1, keyPropertyTypes, null, 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, 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);
            }

            // To get test entity which is deleteable and insertable
            EntityTypeElement entityType = null;

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

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

            if (null == entityType)
            {
                detail1.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, detail1);

                return(passed);
            }

            // Map 'entity-set name' to 'entity-set URL'.
            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 (resp.StatusCode.HasValue && HttpStatusCode.Created == resp.StatusCode)
            {
                string entityId = additionalInfos.Last().EntityId;
                resp                       = WebHelper.GetEntity(entityId);
                detail2                    = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp);
                detail2.URI                = url;
                detail2.ResponsePayload    = resp.ResponsePayload;
                detail2.ResponseHeaders    = resp.ResponseHeaders;
                detail2.HTTPMethod         = "GET";
                detail2.ResponseStatusCode = resp.StatusCode.ToString();

                if (resp.StatusCode.HasValue && HttpStatusCode.OK == resp.StatusCode)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Can not get 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
            }.RemoveNullableDetails();

            info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), 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;
            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);
            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.SingleValued).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, 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);
            }

            string entityTypeShortName = string.Empty;
            string entitySetName       = string.Empty;
            string entitySetUrl        = string.Empty;
            string navigPropName       = string.Empty;

            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.GetExpandRestrictions, AnnotationsHelper.GetInsertRestrictions
                    , AnnotationsHelper.GetDeleteRestrictions, AnnotationsHelper.GetUpdateRestrictions
                });

                if (!string.IsNullOrEmpty(matchEntity.Item1) &&
                    matchEntity.Item2 != null && matchEntity.Item2.Any() &&
                    matchEntity.Item3 != null && matchEntity.Item3.Any())
                {
                    entityTypeShortName = en.EntityTypeShortName;
                    entitySetName       = matchEntity.Item1;
                    entitySetUrl        = entitySetName.MapEntitySetNameToEntitySetURL();
                    foreach (NavigProperty np in matchEntity.Item3)
                    {
                        string nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                        if (np.NavigationRoughType == NavigationRoughType.SingleValued && !nEntityTypeShortName.IsMediaType())
                        {
                            navigPropName = np.NavigationPropertyName;
                            break;
                        }
                    }
                }
                if (!string.IsNullOrEmpty(entitySetName) && !string.IsNullOrEmpty(navigPropName))
                {
                    break;
                }
            }

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

                return(passed);
            }

            string navigPropEntitySet = navigPropName.MapNavigationPropertyNameToEntitySetURL(entityTypeShortName);
            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entitySetName, entityTypeShortName, new List <string>()
            {
                navigPropName
            }, 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;
                url     = serviceStatus.RootURL.TrimEnd('/') + @"/" + navigPropEntitySet;
                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.HasValue && HttpStatusCode.OK == resp.StatusCode)
                {
                    JObject feed;
                    resp.ResponsePayload.TryToJObject(out feed);
                    var entities = JsonParserHelper.GetEntries(feed);
                    if (entities.Any())
                    {
                        string v4OdataIdVal = string.Empty;
                        if (entities.First[Constants.V4OdataId] != null)
                        {
                            v4OdataIdVal = entities.First[Constants.V4OdataId].ToString();
                        }

                        url        = string.Format("{0}/{1}/$ref", entityId, navigPropName);
                        reqDataStr =
                            @"{
                                """ + Constants.V4OdataId + @""" : """ + v4OdataIdVal + @"""
                        }";
                        bool hasEtag = additionalInfos.Last().HasEtag;
                        resp    = WebHelper.UpdateEntity(url, context.RequestHeaders, reqDataStr, HttpMethod.Put, hasEtag);
                        detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Put, string.Empty, resp, string.Empty, reqDataStr);

                        if (null != resp && HttpStatusCode.NoContent == resp.StatusCode)
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail3.ErrorMessage = "PUT to $ref failed by above URI";
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Get entity failed 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
            }.RemoveNullableDetails();

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

            return(passed);
        }