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

            bool?passed = null;

            info = null;

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

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

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

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

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

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

                return(passed);
            }

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

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

                return(passed);
            }
            ;

            string reqDataStr = reqData.ToString();

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

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

                    resp   = WebHelper.Get(new Uri(url), null, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, null);
                    detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Get, StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, serviceStatus.DefaultHeaders), resp);
                    if ((resp.StatusCode.HasValue && HttpStatusCode.OK == resp.StatusCode) || HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp   = WebHelper.DeleteEntity(url, context.RequestHeaders, additionalInfos.Last().HasEtag);
                        detail = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Delete, string.Empty, resp, string.Empty, "Successfully updated the stream of the image.");

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

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

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

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

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

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

                return(passed);
            }

            EntityTypeElement entityType    = null;
            NormalProperty    primitiveProp = null;

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

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

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

                return(passed);
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

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

                return(passed);
            }

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

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

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

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

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

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

            return(passed);
        }
Example #4
0
 set => SetValue(NormalProperty, value);