protected void HandleOperationResponseHeaders(HttpStatusCode statusCode, Dictionary <string, string> headers) { Descriptor descriptor = this.ChangedEntries[this.entryIndex]; if (descriptor.DescriptorKind == DescriptorKind.Entity) { EntityDescriptor descriptor2 = (EntityDescriptor)descriptor; if ((((descriptor.State == EntityStates.Added) || (this.streamRequestKind == StreamRequestKind.PostMediaResource)) || Util.IsFlagSet(this.Options, SaveChangesOptions.PatchOnUpdate)) && WebUtil.SuccessStatusCode(statusCode)) { string str; string str2; Uri editLink = null; headers.TryGetValue("Location", out str); headers.TryGetValue("DataServiceId", out str2); if (str != null) { editLink = WebUtil.ValidateLocationHeader(str); } else if ((descriptor.State == EntityStates.Added) || (this.streamRequestKind == StreamRequestKind.PostMediaResource)) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Deserialize_NoLocationHeader); } if (str2 != null) { if (str == null) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BothLocationAndIdMustBeSpecified); } WebUtil.ValidateIdentityValue(str2); } else { str2 = str; } if (null != editLink) { this.RequestInfo.EntityTracker.AttachLocation(descriptor2.Entity, str2, editLink); } } if (this.streamRequestKind != StreamRequestKind.None) { if (!WebUtil.SuccessStatusCode(statusCode)) { if (this.streamRequestKind == StreamRequestKind.PostMediaResource) { descriptor.State = EntityStates.Added; } this.streamRequestKind = StreamRequestKind.None; descriptor.ContentGeneratedForSave = true; } else { string str3; if ((this.streamRequestKind == StreamRequestKind.PostMediaResource) && headers.TryGetValue("ETag", out str3)) { descriptor2.ETag = str3; } } } } }
/// <summary>operation with HttpWebResponse</summary> /// <param name="statusCode">status code of the response.</param> /// <param name="headers">response headers.</param> protected void HandleOperationResponseHeaders(HttpStatusCode statusCode, HeaderCollection headers) { Descriptor descriptor = this.ChangedEntries[this.entryIndex]; // in the first pass, the http response is packaged into a batch response (which is then processed in second pass). // in this first pass, (all added entities and first call of modified media link entities) update their edit location // added entities - so entities that have not sent content yet w/ reference links can inline those reference links in their payload // media entities - because they can change edit location which is then necessary for second call that includes property content if (descriptor.DescriptorKind == DescriptorKind.Entity) { EntityDescriptor entityDescriptor = (EntityDescriptor)descriptor; Debug.Assert(this.streamRequestKind != StreamRequestKind.PostMediaResource || descriptor.State == EntityStates.Modified, "For the POST MR, the entity state must be modified"); // For POST and PATCH scenarios if (descriptor.State == EntityStates.Added || this.streamRequestKind == StreamRequestKind.PostMediaResource || !Util.IsFlagSet(this.Options, SaveChangesOptions.ReplaceOnUpdate)) { if (WebUtil.SuccessStatusCode(statusCode)) { string location; string odataEntityId; Uri editLink = null; headers.TryGetHeader(XmlConstants.HttpResponseLocation, out location); headers.TryGetHeader(XmlConstants.HttpODataEntityId, out odataEntityId); if (location != null) { // Verify the location header is an absolute uri editLink = WebUtil.ValidateLocationHeader(location); } else if (descriptor.State == EntityStates.Added || this.streamRequestKind == StreamRequestKind.PostMediaResource) { // For POST scenarios, location header must be specified. throw Error.NotSupported(Strings.Deserialize_NoLocationHeader); } // Verify the id value if present. Otherwise we should use the location header // as identity. This was done to avoid breaking change, since in V1/V2, we used // to do this. Uri odataId = null; if (odataEntityId != null) { odataId = WebUtil.ValidateIdentityValue(odataEntityId); if (location == null) { throw Error.NotSupported(Strings.Context_BothLocationAndIdMustBeSpecified); } } else { // we already verified that the location must be an absolute uri odataId = UriUtil.CreateUri(location, UriKind.Absolute); } if (null != editLink) { this.RequestInfo.EntityTracker.AttachLocation(entityDescriptor.Entity, odataId, editLink); } } } if (this.streamRequestKind != StreamRequestKind.None) { if (!WebUtil.SuccessStatusCode(statusCode)) { // If the request failed and it was the MR request we should not try to send the PUT MLE after it // for one we don't have the location to send it to (if it was POST MR) if (this.streamRequestKind == StreamRequestKind.PostMediaResource) { // If this was the POST MR it means we tried to add the entity. Now its state is Modified but we need // to revert back to Added so that user can retry by calling SaveChanges again. Debug.Assert(descriptor.State == EntityStates.Modified, "Entity state should be set to Modified once we've sent the POST MR"); descriptor.State = EntityStates.Added; } // Just reset the streamRequestKind flag - that means that we will not try to PUT the MLE and instead skip over // to the next change (if we are to ignore errors that is) this.streamRequestKind = StreamRequestKind.None; // And we also need to mark it such that we generated the save content (which we did before the POST request in fact) // to workaround the fact that we use the same descriptor object to track two requests. descriptor.ContentGeneratedForSave = true; } else if (this.streamRequestKind == StreamRequestKind.PostMediaResource) { // We just finished a POST MR request and the PUT MLE coming immediately after it will // need the new etag value from the server to succeed. string etag; if (headers.TryGetHeader(XmlConstants.HttpResponseETag, out etag)) { entityDescriptor.ETag = etag; } // else is not interesting and we intentionally do nothing. } } } }
protected void HandleOperationResponseHeaders(HttpStatusCode statusCode, Dictionary<string, string> headers) { Descriptor descriptor = this.ChangedEntries[this.entryIndex]; if (descriptor.DescriptorKind == DescriptorKind.Entity) { EntityDescriptor descriptor2 = (EntityDescriptor) descriptor; if ((((descriptor.State == EntityStates.Added) || (this.streamRequestKind == StreamRequestKind.PostMediaResource)) || Util.IsFlagSet(this.Options, SaveChangesOptions.PatchOnUpdate)) && WebUtil.SuccessStatusCode(statusCode)) { string str; string str2; Uri editLink = null; headers.TryGetValue("Location", out str); headers.TryGetValue("DataServiceId", out str2); if (str != null) { editLink = WebUtil.ValidateLocationHeader(str); } else if ((descriptor.State == EntityStates.Added) || (this.streamRequestKind == StreamRequestKind.PostMediaResource)) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Deserialize_NoLocationHeader); } if (str2 != null) { if (str == null) { throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BothLocationAndIdMustBeSpecified); } WebUtil.ValidateIdentityValue(str2); } else { str2 = str; } if (null != editLink) { this.RequestInfo.EntityTracker.AttachLocation(descriptor2.Entity, str2, editLink); } } if (this.streamRequestKind != StreamRequestKind.None) { if (!WebUtil.SuccessStatusCode(statusCode)) { if (this.streamRequestKind == StreamRequestKind.PostMediaResource) { descriptor.State = EntityStates.Added; } this.streamRequestKind = StreamRequestKind.None; descriptor.ContentGeneratedForSave = true; } else { string str3; if ((this.streamRequestKind == StreamRequestKind.PostMediaResource) && headers.TryGetValue("ETag", out str3)) { descriptor2.ETag = str3; } } } } }