/// <summary> /// Verifies the extension rule. /// </summary> /// <param name="context">The Interop service context</param> /// <param name="info">out parameter to return violation information when rule does not pass</param> /// <returns>true if rule passes; false otherwise</returns> public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info) { if (context == null) { throw new ArgumentNullException("context"); } bool?passed = null; info = null; ServiceStatus serviceStatus = ServiceStatus.GetInstance(); TermDocuments termDocs = TermDocuments.GetInstance(); DataFactory dFactory = DataFactory.Instance(); var detail1 = new ExtensionRuleResultDetail(this.Name); var detail2 = new ExtensionRuleResultDetail(this.Name); var detail3 = new ExtensionRuleResultDetail(this.Name); var detail4 = new ExtensionRuleResultDetail(this.Name); var detail5 = new ExtensionRuleResultDetail(this.Name); var detail6 = new ExtensionRuleResultDetail(this.Name); var entityType = MetadataHelper.GetConcurrencyEntityType(serviceStatus.MetadataDocument); if (null == entityType) { detail1.ErrorMessage = "Cannot find an entity which contains a concurrency property in the service."; info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1); return(passed); } var normalPropNames = entityType.NormalProperties.Where(np => "Edm.String" == np.PropertyType && !np.IsKey).Select(np => np.PropertyName); if (normalPropNames.Any()) { string entitySetUrl = entityType.EntitySetName.MapEntitySetNameToEntitySetURL(); string url = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl; var additionalInfos = new List <AdditionalInfo>(); var reqData = dFactory.ConstructInsertedEntityData(entityType.EntitySetName, entityType.EntityTypeShortName, null, out additionalInfos); string reqDataStr = reqData.ToString(); bool isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag); var resp = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos); detail1 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr); if (HttpStatusCode.Created == resp.StatusCode) { var entityId = additionalInfos.Last().EntityId; var hasEtag = additionalInfos.Last().HasEtag; if (!hasEtag) { detail1.ErrorMessage = "The new inserted entity does not contain an @odata.etag annotation."; info = new ExtensionRuleViolationInfo(new Uri(entityId), resp.ResponsePayload, detail2); return(passed); } resp = WebHelper.GetEntity(entityId, serviceStatus.DefaultHeaders); detail2 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, StringHelper.MergeHeaders(string.Empty, serviceStatus.DefaultHeaders), resp); if (HttpStatusCode.OK == resp.StatusCode) { reqDataStr = dFactory.ConstructUpdatedEntityData(reqData, normalPropNames).ToString(); var header = new KeyValuePair <string, string>("If-Match", additionalInfos.Last().ODataEtag); var headers = new List <KeyValuePair <string, string> >() { header }; resp = WebHelper.UpdateEntity(entityId, reqDataStr, HttpMethod.Patch, headers); detail3 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Patch, StringHelper.MergeHeaders(string.Empty, headers), resp, string.Empty, reqDataStr); if (HttpStatusCode.NoContent == resp.StatusCode) { resp = WebHelper.GetEntity(entityId, serviceStatus.DefaultHeaders); detail4 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, StringHelper.MergeHeaders(string.Empty, serviceStatus.DefaultHeaders), resp); if (HttpStatusCode.OK == resp.StatusCode) { resp = WebHelper.DeleteEntity(entityId, context.RequestHeaders, hasEtag); detail5 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Delete, StringHelper.MergeHeaders(string.Empty, new List <KeyValuePair <string, string> >() { header }), resp); if (HttpStatusCode.NoContent == resp.StatusCode) { resp = WebHelper.GetEntity(entityId); detail6 = new ExtensionRuleResultDetail(this.Name, entityId, HttpMethod.Get, string.Empty, resp); if (HttpStatusCode.NotFound == resp.StatusCode) { passed = true; } else { passed = false; detail6.ErrorMessage = "It still can get the deleted entity from above URI."; } } else { passed = false; detail5.ErrorMessage = "Delete entity failed."; } } else { passed = false; detail4.ErrorMessage = "Can not get the created entity from above URI."; } } else { passed = false; detail3.ErrorMessage = "Update entity failed."; } } } else { passed = false; detail1.ErrorMessage = "Created the new entity failed for above URI."; } } var details = new List <ExtensionRuleResultDetail>() { detail1, detail2, detail3, detail4, detail5, detail6 }.RemoveNullableDetails(); info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details); return(passed); }
/// <summary> /// Verifies the extension rule. /// </summary> /// <param name="context">The Interop service context</param> /// <param name="info">out parameter to return violation information when rule does not pass</param> /// <returns>true if rule passes; false otherwise</returns> public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info) { if (context == null) { throw new ArgumentNullException("context"); } bool?passed = null; info = null; ServiceStatus serviceStatus = ServiceStatus.GetInstance(); TermDocuments termDocs = TermDocuments.GetInstance(); DataFactory dFactory = DataFactory.Instance(); var detail1 = new ExtensionRuleResultDetail(this.Name); var detail2 = new ExtensionRuleResultDetail(this.Name); var detail3 = new ExtensionRuleResultDetail(this.Name); var detail4 = new ExtensionRuleResultDetail(this.Name); Dictionary <string, Dictionary <KeyValuePair <string, string>, List <string> > > entityTypeInfos; if (!MetadataHelper.GetEntityTypesWithComplexProperty(serviceStatus.MetadataDocument, "Edm.String", out entityTypeInfos)) { detail1.ErrorMessage = "To verify this rule it expects complex type containing a property with string type, but there is no this complex type in metadata so cannot verify this rule."; info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1); return(passed); } var entityTypeInfo = new KeyValuePair <string, Dictionary <KeyValuePair <string, string>, List <string> > >(); string entitySetName = string.Empty; foreach (var etInfo in entityTypeInfos) { entitySetName = etInfo.Key.MapEntityTypeShortNameToEntitySetName(); var funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >() { AnnotationsHelper.GetInsertRestrictions, AnnotationsHelper.GetUpdateRestrictions, AnnotationsHelper.GetDeleteRestrictions }; var restrictions = entitySetName.GetRestrictions(serviceStatus.MetadataDocument, termDocs.VocCapabilitiesDoc, funcs); if (!string.IsNullOrEmpty(restrictions.Item1) || null != restrictions.Item2 || restrictions.Item2.Any() || null != restrictions.Item3 || restrictions.Item3.Any()) { entityTypeInfo = etInfo; break; } } if (string.IsNullOrEmpty(entitySetName) || string.IsNullOrEmpty(entityTypeInfo.Key) || null == entityTypeInfo.Value || !entityTypeInfo.Value.Any()) { detail1.ErrorMessage = "Cannot find the entity-set which support insert, updata, delete restrictions at the same time."; info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, detail1); return(passed); } string entityTypeShortName = entityTypeInfo.Key; string entitySetUrl = entitySetName.MapEntitySetNameToEntitySetURL(); string complexPropName = entityTypeInfo.Value.Keys.First().Key; string complexPropType = entityTypeInfo.Value.Keys.First().Value; string propertyNameWithSpecifiedType = entityTypeInfo.Value[new KeyValuePair <string, string>(complexPropName, complexPropType)].First(); // Create a entity string url = serviceStatus.RootURL.TrimEnd('/') + @"/" + entitySetUrl; var additionalInfos = new List <AdditionalInfo>(); var reqData = dFactory.ConstructInsertedEntityData(entitySetName, entityTypeShortName, null, out additionalInfos); reqData = dFactory.ReconstructNullableComplexData(reqData, new List <string>() { complexPropName }); string reqDataStr = reqData.ToString(); bool isMediaType = !string.IsNullOrEmpty(additionalInfos.Last().ODataMediaEtag); var resp = WebHelper.CreateEntity(url, context.RequestHeaders, reqData, isMediaType, ref additionalInfos); detail1 = new ExtensionRuleResultDetail(this.Name, url, HttpMethod.Post, string.Empty, resp, string.Empty, reqDataStr); if (resp.StatusCode == HttpStatusCode.Created) { var entityId = additionalInfos.Last().EntityId; var hasEtag = additionalInfos.Last().HasEtag; // Get a complex property except key property string complexProUrl = entityId + @"/" + complexPropName; resp = WebHelper.Get(new Uri(complexProUrl), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, serviceStatus.DefaultHeaders); detail2 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Get, StringHelper.MergeHeaders(Constants.AcceptHeaderJson, serviceStatus.DefaultHeaders), resp); if (resp.StatusCode == HttpStatusCode.OK) { JObject jo; resp.ResponsePayload.TryToJObject(out jo); //string newComplexProperty = VerificationHelper.ConstructUpdatedEntityData(jo, new List<string>() { propertyNameWithSpecifiedType }, out hasEtag); string newComplexProperty = dFactory.ConstructUpdatedEntityData(jo, new List <string>() { propertyNameWithSpecifiedType }).ToString(); // Update the complex property resp = WebHelper.UpdateEntity(complexProUrl, context.RequestHeaders, newComplexProperty, HttpMethod.Patch, hasEtag); detail3 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Patch, string.Empty, resp, string.Empty, newComplexProperty); if (resp.StatusCode == HttpStatusCode.NoContent) { // Check whether the complex property is updated to new value if (WebHelper.GetContent(complexProUrl, context.RequestHeaders, out resp)) { detail4 = new ExtensionRuleResultDetail(this.Name, complexProUrl, HttpMethod.Get, string.Empty, resp); resp.ResponsePayload.TryToJObject(out jo); if (jo != null && jo[propertyNameWithSpecifiedType] != null && jo[propertyNameWithSpecifiedType].Value <string>().Equals(Constants.UpdateData)) { passed = true; } else if (jo == null) { passed = false; detail4.ErrorMessage = "Can not get complex property after Patch it. "; } else if (jo != null && jo[propertyNameWithSpecifiedType] == null) { passed = false; detail4.ErrorMessage = string.Format("Can not get the value of {0} property in complex property {1}. ", propertyNameWithSpecifiedType, complexProUrl); } else if (jo != null && jo[propertyNameWithSpecifiedType] != null && !jo[propertyNameWithSpecifiedType].Value <string>().Equals(Constants.UpdateData)) { passed = false; detail4.ErrorMessage = string.Format("The value of {0} property in complex is not updated by {1}. ", propertyNameWithSpecifiedType, complexProUrl); } } } else { passed = false; detail3.ErrorMessage = "Update complex property in the created entity failed. "; } } else if (resp.StatusCode == HttpStatusCode.NoContent) { detail2.ErrorMessage = "The value of property with complex type is null."; } else { passed = false; detail2.ErrorMessage = "Get complex property in the created entity failed. "; } // Delete the entity var resps = WebHelper.DeleteEntities(context.RequestHeaders, additionalInfos); } else { passed = false; detail1.ErrorMessage = "Created the new entity failed for above URI. "; } var details = new List <ExtensionRuleResultDetail>() { detail1, detail2, detail3, detail4 }.RemoveNullableDetails(); info = new ExtensionRuleViolationInfo(new Uri(serviceStatus.RootURL), serviceStatus.ServiceDocument, details); return(passed); }
/// <summary> /// Verifies the extension rule. /// </summary> /// <param name="context">The Interop service context</param> /// <param name="info">out parameter to return violation information when rule does not pass</param> /// <returns>true if rule passes; false otherwise</returns> public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info) { if (context == null) { throw new ArgumentNullException("context"); } bool?passed = null; info = null; ServiceStatus serviceStatus = ServiceStatus.GetInstance(); TermDocuments termDocs = TermDocuments.GetInstance(); DataFactory dFactory = DataFactory.Instance(); var 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); }