/// <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);
        }
Ejemplo n.º 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           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);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Verifies the extension rule.
        /// </summary>
        /// <param name="context">The Interop service context</param>
        /// <param name="info">out parameter to return violation information when rule does not pass</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

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

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

                return(passed);
            }

            EntityTypeElement entityType = null;

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

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

                return(passed);
            }

            string url             = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl;
            var    additionalInfos = new List <AdditionalInfo>();
            var    reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);
            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;
                updateUrl = entityId;
                bool hasEtag = additionalInfos.Last().HasEtag;
                resp   = WebHelper.GetEntity(entityId);
                detail = 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);
                    detail     = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Patch, string.Empty, resp, string.Empty, reqDataStr);
                    if (HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp   = WebHelper.GetEntity(entityId);
                        detail = 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;
                                detail.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;
                            detail.ErrorMessage = "Can not get the updated entity.";
                        }
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = "Patch the entity failed.";
                    }
                }
                else
                {
                    detail.ErrorMessage = "Can not get the created entity from above URI.";
                }

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

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

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

            return(passed);
        }
        /// <summary>
        /// Verifies the extension rule.
        /// </summary>
        /// <param name="context">The Interop service context</param>
        /// <param name="info">out parameter to return violation information when rule does not pass</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;
            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);
        }