Beispiel #1
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;

            Dictionary <string, Dictionary <KeyValuePair <string, string>, List <string> > > entityTypeInfo = new Dictionary <string, Dictionary <KeyValuePair <string, string>, List <string> > >();

            bool foundEntity = MetadataHelper.GetEntityTypesWithComplexProperty(serviceStatus.MetadataDocument, "Edm.String", out entityTypeInfo);

            if (foundEntity)
            {
                foreach (var en in entityTypeElements)
                {
                    if (entityTypeInfo.Keys.Contains(en.EntityTypeShortName) && !string.IsNullOrEmpty(en.EntitySetName))
                    {
                        entityType = en;
                        break;
                    }
                }
            }
            else
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with complex 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);
            }

            if (entityType == null)
            {
                detail.ErrorMessage = "To verify this rule it expects an entity type with complex 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);
            }

            Dictionary <KeyValuePair <string, string>, List <string> >   complexProps = entityTypeInfo[entityType.EntityTypeShortName];
            KeyValuePair <KeyValuePair <string, string>, List <string> > complexPop   = complexProps.First();
            string complexPropName = complexPop.Key.Key;

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

            updateUrl = entitySetUrl;

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

            updateUrl = url;
            var     additionalInfos = new List <AdditionalInfo>();
            JObject reqData         = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos);

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

                return(passed);
            }

            string reqDataStr  = reqData.ToString();
            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('/') + "/" + complexPropName;
                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 || HttpStatusCode.NoContent == resp.StatusCode)
                {
                    JProperty complexPropContent = null;

                    foreach (JProperty prop in reqData.Children <JProperty>())
                    {
                        if (prop.Name.Equals(complexPropName))
                        {
                            complexPropContent = prop;
                            break;
                        }
                    }

                    resp   = WebHelper.UpdateComplexProperty(updateUrl, context.RequestHeaders, complexPropContent, hasEtag, complexPop.Value);
                    detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Patch, string.Empty, resp, string.Empty, reqDataStr);
                    if (HttpStatusCode.NoContent == resp.StatusCode)
                    {
                        resp   = WebHelper.GetPropertyValue(updateUrl);
                        detail = new ExtensionRuleResultDetail(this.Name, updateUrl, HttpMethod.Get, string.Empty, resp, string.Empty, reqDataStr);

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

                            bool updated = true;

                            if (value != null && value.Type == JTokenType.Object)
                            {
                                foreach (var prop in value.Children <JProperty>())
                                {
                                    if (complexPop.Value.Contains(prop.Name))
                                    {
                                        updated = prop.Value.ToString().Equals(Constants.UpdateData);
                                    }

                                    if (!updated)
                                    {
                                        passed = false;
                                        detail.ErrorMessage = string.Format("The compelex property in request fails in HTTP patch updating.");
                                        break;
                                    }
                                }

                                if (updated)
                                {
                                    passed = true;
                                }
                            }
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "Can not get the updated entity.";
                        }
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = "HTTP Patch the complex 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.";
            }

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

            bool?passed = null;

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

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

                return(passed);
            }

            EntityTypeElement entityType    = null;
            NormalProperty    primitiveProp = null;

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

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

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

                return(passed);
            }

            string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL();

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

                return(passed);
            }

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

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

                return(passed);
            }

            string reqDataStr = reqData.ToString();

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

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

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

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

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

            return(passed);
        }