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