/// <summary>
 /// Creates a new instance of ODataRequestMessage. This constructor is used for top level requests.
 /// </summary>
 /// <param name="requestMessage">RequestMessage that needs to be wrapped.</param>
 /// <param name="requestInfo">Request Info.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 protected ODataRequestMessageWrapper(DataServiceClientRequestMessage requestMessage, RequestInfo requestInfo, Descriptor descriptor)
 {
     Debug.Assert(requestMessage != null, "requestMessage != null");
     Debug.Assert(requestInfo != null, "requestInfo != null");
     this.requestMessage = requestMessage;
     this.requestInfo = requestInfo;
     this.Descriptor = descriptor;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="BuildingRequestEventArgs"/> class.
 /// </summary>
 /// <param name="method">The method.</param>
 /// <param name="requestUri">The request URI.</param>
 /// <param name="headers">The request headers.</param>
 /// <param name="descriptor">Descriptor for this request; or null if there isn't one.</param>
 /// <param name="httpStack">The http stack.</param>
 internal BuildingRequestEventArgs(string method, Uri requestUri, HeaderCollection headers, Descriptor descriptor, HttpStack httpStack)
 {
     this.Method = method;
     this.RequestUri = requestUri;
     this.HeaderCollection = headers ?? new HeaderCollection();
     this.ClientHttpStack = httpStack;
     this.Descriptor = descriptor;
 }
 /// <summary>
 /// Creates a new instance of SendingRequest2EventsArgs
 /// </summary>
 /// <param name="requestMessage">request message.</param>
 /// <param name="descriptor">Descriptor that represents this change.</param>
 /// <param name="isBatchPart">True if this args represents a request within a batch, otherwise false.</param>
 internal SendingRequest2EventArgs(IODataRequestMessage requestMessage, Descriptor descriptor, bool isBatchPart)
 {
     this.RequestMessage = requestMessage;
     this.Descriptor = descriptor;
     this.IsBatchPart = isBatchPart;
 }
Example #4
0
 /// <summary>
 /// Asks the context to Fire the BuildingRequest event and get RequestMessageArgs.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <returns>A new RequestMessageArgs object for building the request message.</returns>
 internal BuildingRequestEventArgs CreateRequestArgsAndFireBuildingRequest(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor)
 {
     return this.Context.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, httpStack, descriptor);
 }
Example #5
0
        /// <summary>flag results as being processed</summary>
        /// <param name="descriptor">result descriptor being processed</param>
        /// <returns>count of related links that were also processed</returns>
        protected int SaveResultProcessed(Descriptor descriptor)
        {
            // media links will be processed twice
            descriptor.SaveResultWasProcessed = descriptor.State;

            int count = 0;
            if (descriptor.DescriptorKind == DescriptorKind.Entity && (EntityStates.Added == descriptor.State))
            {
                foreach (LinkDescriptor end in this.RelatedLinks((EntityDescriptor)descriptor))
                {
                    if (end.ContentGeneratedForSave)
                    {
                        Debug.Assert(0 == end.SaveResultWasProcessed, "this link already had a result");
                        end.SaveResultWasProcessed = end.State;
                        count++;
                    }
                }
            }

            return count;
        }
Example #6
0
 /// <summary>
 /// Handle operation response
 /// </summary>
 /// <param name="descriptor">descriptor whose response is getting processed.</param>
 /// <param name="contentHeaders">content headers as returned in the response.</param>
 /// <param name="statusCode">status code.</param>
 protected void HandleOperationResponse(Descriptor descriptor, HeaderCollection contentHeaders, HttpStatusCode statusCode)
Example #7
0
        /// <summary>Handle response to deleted entity.</summary>
        /// <param name="descriptor">deleted entity</param>
        private void HandleResponseDelete(Descriptor descriptor)
        {
            if (EntityStates.Deleted != descriptor.State)
            {
                Error.ThrowBatchUnexpectedContent(InternalError.EntityNotDeleted);
            }

            if (descriptor.DescriptorKind == DescriptorKind.Entity)
            {
                EntityDescriptor resource = (EntityDescriptor)descriptor;
                this.RequestInfo.EntityTracker.DetachResource(resource);
            }
            else
            {
                this.RequestInfo.EntityTracker.DetachExistingLink((LinkDescriptor)descriptor, false);
            }
        }
Example #8
0
 /// <summary>Initializes a new instance of the <see cref="T:Microsoft.OData.Client.ChangeOperationResponse" /> class. </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="descriptor">response object containing information about resources that got changed.</param>
 internal ChangeOperationResponse(HeaderCollection headers, Descriptor descriptor)
     : base(headers)
 {
     Debug.Assert(descriptor != null, "descriptor != null");
     this.descriptor = descriptor;
 }
        /// <summary>
        /// Loads the metadata and converts it into an EdmModel that is then used by a dataservice context
        /// This allows the user to use the DataServiceContext directly without having to manually pass an IEdmModel in the Format
        /// </summary>
        /// <returns>A service model to be used in format tracking</returns>
        internal IEdmModel LoadServiceModelFromNetwork()
        {
            HttpWebRequestMessage    httpRequest;
            BuildingRequestEventArgs requestEventArgs = null;

            // test hook for injecting a network request to use instead of the default
            if (InjectMetadataHttpNetworkRequest != null)
            {
                httpRequest = InjectMetadataHttpNetworkRequest();
            }
            else
            {
                requestEventArgs = new BuildingRequestEventArgs(
                    "GET",
                    context.GetMetadataUri(),
                    null,
                    null,
                    context.HttpStack);

                // fire the right events if they exist to allow user to modify the request
                if (context.HasBuildingRequestEventHandlers)
                {
                    requestEventArgs = context.CreateRequestArgsAndFireBuildingRequest(
                        requestEventArgs.Method,
                        requestEventArgs.RequestUri,
                        requestEventArgs.HeaderCollection,
                        requestEventArgs.ClientHttpStack,
                        requestEventArgs.Descriptor);
                }

                DataServiceClientRequestMessageArgs args = new DataServiceClientRequestMessageArgs(
                    requestEventArgs.Method,
                    requestEventArgs.RequestUri,
                    context.UseDefaultCredentials,
                    context.UsePostTunneling,
                    requestEventArgs.Headers);

                httpRequest = new HttpWebRequestMessage(args);
            }

            Descriptor descriptor = requestEventArgs != null ? requestEventArgs.Descriptor : null;

            // fire the right events if they exist
            if (context.HasSendingRequest2EventHandlers)
            {
                SendingRequest2EventArgs eventArgs = new SendingRequest2EventArgs(
                    httpRequest,
                    descriptor,
                    false);

                context.FireSendingRequest2(eventArgs);
            }

            Task <IODataResponseMessage> asyncResponse =
                Task <IODataResponseMessage> .Factory.FromAsync(httpRequest.BeginGetResponse, httpRequest.EndGetResponse,
                                                                httpRequest);

            IODataResponseMessage response = asyncResponse.GetAwaiter().GetResult();

            ReceivingResponseEventArgs responseEvent = new ReceivingResponseEventArgs(response, descriptor);

            context.FireReceivingResponseEvent(responseEvent);

            using (StreamReader streamReader = new StreamReader(response.GetStream()))
                using (XmlReader xmlReader = XmlReader.Create(streamReader))
                {
                    return(CsdlReader.Parse(xmlReader));
                }
        }
Example #10
0
        private Exception ProcessCurrentOperationResponse(ODataBatchReader batchReader, bool isChangesetOperation)
        {
            Debug.Assert(batchReader != null, "batchReader != null");
            Debug.Assert(batchReader.State == ODataBatchReaderState.Operation, "This method requires the batch reader to be on an operation.");

            ODataBatchOperationResponseMessage operationResponseMessage = batchReader.CreateOperationResponseMessage();
            Descriptor descriptor = null;

            if (isChangesetOperation)
            {
                // We need to peek at the content-Id before handing the response to the user, so we can expose the Descriptor them.
                // We're OK with this exception to our general rule of not using them before ReceivingResponse event is fired.
                this.entryIndex = this.ValidateContentID(operationResponseMessage.ContentId);
                descriptor      = this.ChangedEntries[entryIndex];
            }

            // If we hit en error inside a batch, we will never expose a descriptor since we don't know which one to return.
            // The descriptor we fetched above based on the content-ID is bogus because the server returns an errounous content-id when
            // it hits an error inside batch.
            if (!WebUtil.SuccessStatusCode((HttpStatusCode)operationResponseMessage.StatusCode))
            {
                descriptor = null;
            }

            this.RequestInfo.Context.FireReceivingResponseEvent(new ReceivingResponseEventArgs(operationResponseMessage, descriptor, true));

            // We need to know if the content of the operation response is empty or not.
            // We also need to cache the entire content, since in case of GET response the response itself will be parsed
            // lazily and so it can happen that we will move the batch reader after this operation before we actually read
            // the content of the operation.
            Stream originalOperationResponseContentStream = operationResponseMessage.GetStream();

            if (originalOperationResponseContentStream == null)
            {
                Error.ThrowBatchExpectedResponse(InternalError.NullResponseStream);
            }

            MemoryStream operationResponseContentStream;

            try
            {
                operationResponseContentStream = new MemoryStream();
                WebUtil.CopyStream(originalOperationResponseContentStream, operationResponseContentStream, ref this.streamCopyBuffer);
                operationResponseContentStream.Position = 0;
            }
            finally
            {
                originalOperationResponseContentStream.Dispose();
            }

            this.currentOperationResponse = new CurrentOperationResponse(
                (HttpStatusCode)operationResponseMessage.StatusCode,
                operationResponseMessage.Headers,
                operationResponseContentStream);

            Version responseVersion;
            string  headerName = XmlConstants.HttpODataVersion;

            return(BaseSaveResult.HandleResponse(
                       this.RequestInfo,
                       this.currentOperationResponse.StatusCode,
                       this.currentOperationResponse.Headers.GetHeader(headerName),
                       () => this.currentOperationResponse.ContentStream,
                       false,
                       out responseVersion));
        }
Example #11
0
        /// <summary>
        /// process the batch response
        /// </summary>
        /// <param name="batchReader">The batch reader to use for reading the batch response.</param>
        /// <returns>enumerable of QueryResponse or null</returns>
        /// <remarks>
        /// The batch message reader for the entire batch response is stored in this.batchMessageReader.
        /// Note that this method takes over the ownership of this reader and must Dispose it if it successfully returns.
        /// </remarks>
        private IEnumerable <OperationResponse> HandleBatchResponse(ODataBatchReader batchReader)
        {
            try
            {
                if (this.batchMessageReader == null)
                {
                    // The enumerable returned by this method can be enumerated multiple times.
                    // In that case it looks like if the method is called multiple times.
                    // This didn't fail in previous versions, it simply returned no results, so we need to do the same.
                    yield break;
                }

                Debug.Assert(batchReader != null, "batchReader != null");

                bool changesetFound  = false;
                bool insideChangeset = false;
                int  queryCount      = 0;
                int  operationCount  = 0;
                this.entryIndex = 0;
                while (batchReader.Read())
                {
                    switch (batchReader.State)
                    {
                        #region ChangesetStart
                    case ODataBatchReaderState.ChangesetStart:
                        if ((Util.IsBatchWithSingleChangeset(this.Options) && changesetFound) || (operationCount != 0))
                        {
                            // Throw if we encounter multiple changesets when running in batch with single changeset mode
                            // or if we encounter operations outside of a changeset.
                            Error.ThrowBatchUnexpectedContent(InternalError.UnexpectedBeginChangeSet);
                        }

                        insideChangeset = true;
                        break;
                        #endregion

                        #region ChangesetEnd
                    case ODataBatchReaderState.ChangesetEnd:
                        changesetFound  = true;
                        operationCount  = 0;
                        insideChangeset = false;
                        break;
                        #endregion

                        #region Operation
                    case ODataBatchReaderState.Operation:
                        Exception exception = this.ProcessCurrentOperationResponse(batchReader, insideChangeset);
                        if (!insideChangeset)
                        {
                            #region Get response
                            Debug.Assert(operationCount == 0, "missing an EndChangeSet 2");

                            QueryOperationResponse qresponse = null;
                            try
                            {
                                if (exception == null)
                                {
                                    DataServiceRequest query        = this.Queries[queryCount];
                                    ResponseInfo       responseInfo = this.RequestInfo.GetDeserializationInfo(null /*mergeOption*/);
                                    MaterializeAtom    materializer = DataServiceRequest.Materialize(
                                        responseInfo,
                                        query.QueryComponents(this.RequestInfo.Model),
                                        null,
                                        this.currentOperationResponse.Headers.GetHeader(XmlConstants.HttpContentType),
                                        this.currentOperationResponse.CreateResponseMessage(),
                                        query.PayloadKind);
                                    qresponse = QueryOperationResponse.GetInstance(query.ElementType, this.currentOperationResponse.Headers, query, materializer);
                                }
                            }
                            catch (ArgumentException e)
                            {
                                exception = e;
                            }
                            catch (FormatException e)
                            {
                                exception = e;
                            }
                            catch (InvalidOperationException e)
                            {
                                exception = e;
                            }

                            if (qresponse == null)
                            {
                                if (this.Queries != null)
                                {
                                    // this is the normal ExecuteBatch response
                                    DataServiceRequest query = this.Queries[queryCount];

                                    if (this.RequestInfo.IgnoreResourceNotFoundException && this.currentOperationResponse.StatusCode == HttpStatusCode.NotFound)
                                    {
                                        qresponse = QueryOperationResponse.GetInstance(query.ElementType, this.currentOperationResponse.Headers, query, MaterializeAtom.EmptyResults);
                                    }
                                    else
                                    {
                                        qresponse       = QueryOperationResponse.GetInstance(query.ElementType, this.currentOperationResponse.Headers, query, MaterializeAtom.EmptyResults);
                                        qresponse.Error = exception;
                                    }
                                }
                                else
                                {
                                    // This is top-level failure for SaveChanges(SaveChangesOptions.BatchWithSingleChangeset) or SaveChanges(SaveChangesOptions.BatchWithIndependentOperations) operations.
                                    // example: server doesn't support batching or number of batch objects exceeded an allowed limit.
                                    // ex could be null if the server responded to SaveChanges with an unexpected success with
                                    // response of batched GETS that did not correspond the original POST/PATCH/PUT/DELETE requests.
                                    // we expect non-null since server should have failed with a non-success code
                                    // and HandleResponse(status, ...) should generate the exception object
                                    throw exception;
                                }
                            }

                            qresponse.StatusCode = (int)this.currentOperationResponse.StatusCode;
                            queryCount++;
                            yield return(qresponse);

                            #endregion
                        }
                        else
                        {
                            #region Update response
                            try
                            {
                                Descriptor descriptor = this.ChangedEntries[this.entryIndex];
                                operationCount += this.SaveResultProcessed(descriptor);

                                if (exception != null)
                                {
                                    throw exception;
                                }

                                this.HandleOperationResponseHeaders(this.currentOperationResponse.StatusCode, this.currentOperationResponse.Headers);
#if DEBUG
                                this.HandleOperationResponse(descriptor, this.currentOperationResponse.Headers, this.currentOperationResponse.StatusCode);
#else
                                this.HandleOperationResponse(descriptor, this.currentOperationResponse.Headers);
#endif
                            }
                            catch (Exception e)
                            {
                                this.ChangedEntries[this.entryIndex].SaveError = e;
                                exception = e;

                                if (!CommonUtil.IsCatchableExceptionType(e))
                                {
                                    throw;
                                }
                            }

                            ChangeOperationResponse changeOperationResponse =
                                new ChangeOperationResponse(this.currentOperationResponse.Headers, this.ChangedEntries[this.entryIndex]);
                            changeOperationResponse.StatusCode = (int)this.currentOperationResponse.StatusCode;
                            if (exception != null)
                            {
                                changeOperationResponse.Error = exception;
                            }

                            operationCount++;
                            this.entryIndex++;
                            yield return(changeOperationResponse);

                            #endregion
                        }

                        break;
                        #endregion

                    default:
                        Error.ThrowBatchExpectedResponse(InternalError.UnexpectedBatchState);
                        break;
                    }
                }

                Debug.Assert(batchReader.State == ODataBatchReaderState.Completed, "unexpected batch state");

                // Check for a changeset without response (first line) or GET request without response (second line).
                // either all saved entries must be processed or it was a batch and one of the entries has the error
                if ((this.Queries == null &&
                     (!changesetFound ||
                      0 < queryCount ||
                      this.ChangedEntries.Any(o => o.ContentGeneratedForSave && o.SaveResultWasProcessed == 0) &&
                      (!this.IsBatchRequest || this.ChangedEntries.FirstOrDefault(o => o.SaveError != null) == null))) ||
                    (this.Queries != null && queryCount != this.Queries.Length))
                {
                    throw Error.InvalidOperation(Strings.Batch_IncompleteResponseCount);
                }
            }
            finally
            {
                // Note that this will be called only once the enumeration of all responses is finished and the Dispose
                // was called on the IEnumerator used for that enumeration. It is not called when the method returns,
                // since the compiler change this method to return the compiler-generated IEnumerable.
                Util.Dispose(ref this.batchMessageReader);
            }
        }
Example #12
0
        /// <summary>
        /// Generate the batch request for all changes to save.
        /// </summary>
        /// <returns>Returns the instance of ODataRequestMessage containing all the headers and payload for the batch request.</returns>
        private ODataRequestMessageWrapper GenerateBatchRequest()
        {
            if (this.ChangedEntries.Count == 0 && this.Queries == null)
            {
                this.SetCompleted();
                return(null);
            }

            ODataRequestMessageWrapper batchRequestMessage = this.CreateBatchRequest();

            // we need to fire request after the headers have been written, but before we write the payload
            batchRequestMessage.FireSendingRequest2(null);

            using (ODataMessageWriter messageWriter = Serializer.CreateMessageWriter(batchRequestMessage, this.RequestInfo, false /*isParameterPayload*/))
            {
                this.batchWriter = messageWriter.CreateODataBatchWriter();
                this.batchWriter.WriteStartBatch();

                if (this.Queries != null)
                {
                    foreach (DataServiceRequest query in this.Queries)
                    {
                        QueryComponents queryComponents = query.QueryComponents(this.RequestInfo.Model);
                        Uri             requestUri      = this.RequestInfo.BaseUriResolver.GetOrCreateAbsoluteUri(queryComponents.Uri);

                        Debug.Assert(requestUri != null, "request uri is null");
                        Debug.Assert(requestUri.IsAbsoluteUri, "request uri is not absolute uri");

                        HeaderCollection headers = new HeaderCollection();

                        headers.SetRequestVersion(queryComponents.Version, this.RequestInfo.MaxProtocolVersionAsVersion);

                        this.RequestInfo.Format.SetRequestAcceptHeaderForQuery(headers, queryComponents);

                        ODataRequestMessageWrapper batchOperationRequestMessage = this.CreateRequestMessage(XmlConstants.HttpMethodGet, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/, null /*contentId*/);

                        batchOperationRequestMessage.FireSendingEventHandlers(null /*descriptor*/);
                    }
                }
                else if (0 < this.ChangedEntries.Count)
                {
                    if (Util.IsBatchWithSingleChangeset(this.Options))
                    {
                        this.batchWriter.WriteStartChangeset();
                    }

                    var model = this.RequestInfo.Model;

                    for (int i = 0; i < this.ChangedEntries.Count; ++i)
                    {
                        if (Util.IsBatchWithIndependentOperations(this.Options))
                        {
                            this.batchWriter.WriteStartChangeset();
                        }

                        Descriptor descriptor = this.ChangedEntries[i];
                        if (descriptor.ContentGeneratedForSave)
                        {
                            continue;
                        }

                        EntityDescriptor entityDescriptor = descriptor as EntityDescriptor;
                        if (descriptor.DescriptorKind == DescriptorKind.Entity)
                        {
                            if (entityDescriptor.State == EntityStates.Added)
                            {
                                // We don't support adding MLE/MR in batch mode
                                ClientTypeAnnotation type = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType()));
                                if (type.IsMediaLinkEntry || entityDescriptor.IsMediaLinkEntry)
                                {
                                    throw Error.NotSupported(Strings.Context_BatchNotSupportedForMediaLink);
                                }
                            }
                            else if (entityDescriptor.State == EntityStates.Unchanged || entityDescriptor.State == EntityStates.Modified)
                            {
                                // We don't support PUT for the MR in batch mode
                                // It's OK to PUT the MLE alone inside a batch mode though
                                if (entityDescriptor.SaveStream != null)
                                {
                                    throw Error.NotSupported(Strings.Context_BatchNotSupportedForMediaLink);
                                }
                            }
                        }
                        else if (descriptor.DescriptorKind == DescriptorKind.NamedStream)
                        {
                            // Similar to MR, we do not support adding named streams in batch mode.
                            throw Error.NotSupported(Strings.Context_BatchNotSupportedForNamedStreams);
                        }

                        ODataRequestMessageWrapper operationRequestMessage;
                        if (descriptor.DescriptorKind == DescriptorKind.Entity)
                        {
                            operationRequestMessage = this.CreateRequest(entityDescriptor);
                        }
                        else
                        {
                            operationRequestMessage = this.CreateRequest((LinkDescriptor)descriptor);
                        }

                        // we need to fire request after the headers have been written, but before we write the payload
                        operationRequestMessage.FireSendingRequest2(descriptor);

                        this.CreateChangeData(i, operationRequestMessage);

                        if (Util.IsBatchWithIndependentOperations(this.Options))
                        {
                            this.batchWriter.WriteEndChangeset();
                        }
                    }

                    if (Util.IsBatchWithSingleChangeset(this.Options))
                    {
                        this.batchWriter.WriteEndChangeset();
                    }
                }

                this.batchWriter.WriteEndBatch();
                this.batchWriter.Flush();
            }

            Debug.Assert(this.ChangedEntries.All(o => o.ContentGeneratedForSave), "didn't generated content for all entities/links");
            return(batchRequestMessage);
        }
Example #13
0
        /// <summary>
        /// Returns the request message to write the headers and payload into.
        /// </summary>
        /// <param name="method">Http method for the request.</param>
        /// <param name="requestUri">Base Uri for the request.</param>
        /// <param name="headers">Request headers.</param>
        /// <param name="httpStack">HttpStack to use.</param>
        /// <param name="descriptor">Descriptor for the request, if there is one.</param>
        /// <param name="contentId">Content-ID header that could be used in batch request.</param>
        /// <returns>an instance of IODataRequestMessage.</returns>
        protected override ODataRequestMessageWrapper CreateRequestMessage(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor, string contentId)
        {
            BuildingRequestEventArgs args = this.RequestInfo.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, this.RequestInfo.HttpStack, descriptor);

            return(ODataRequestMessageWrapper.CreateBatchPartRequestMessage(this.batchWriter, args, this.RequestInfo, contentId));
        }
Example #14
0
 /// <summary>Initializes a new instance of the <see cref="T:Microsoft.OData.Client.ChangeOperationResponse" /> class. </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="descriptor">response object containing information about resources that got changed.</param>
 internal ChangeOperationResponse(HeaderCollection headers, Descriptor descriptor)
     : base(headers)
 {
     Debug.Assert(descriptor != null, "descriptor != null");
     this.descriptor = descriptor;
 }
        /// <summary>
        /// FireSendingRequest2 event.
        /// </summary>
        /// <param name="descriptor">Descriptor for which this request is getting generated.</param>
        internal void FireSendingRequest2(Descriptor descriptor)
        {
#if DEBUG
            Debug.Assert(!this.fireSendingRequest2MethodCalled, "!this.fireSendingRequest2MethodCalled");
            Debug.Assert(this.cachedRequestHeaders == null, "this.cachedRequestHeaders == null");

            // Currently for actions there are no descriptors and hence this assert needs to be disabled.
            // Once the actions have descriptors, we can enable this assert.
            // Debug.Assert(
            //    descriptor != null || this.requestMessage.Method == XmlConstants.HttpMethodGet || this.requestMessage.Url.AbsoluteUri.Contains("$batch"),
            //    "For CUD operations, decriptor must be specified in every SendingRequest2 event except top level batch request");
#endif

            // Do we need to fire these events if someone has replaced the transport layer? Maybe no.
            if (this.requestInfo.HasSendingRequest2EventHandlers)
            {
                // For now, we don't think this adds a lot of value exposing on the public DataServiceClientRequestMessage class
                // In future, we can always add it if customers ask for this. Erring on the side of keeping the public
                // class simple.
                var httpWebRequestMessage = this.requestMessage as HttpWebRequestMessage;
                if (httpWebRequestMessage != null)
                {
                    // For now we are saying that anyone who implements the transport layer do not get a chance to fire
                    // SendingRequest yet at all. That does not seem that bad.
                    httpWebRequestMessage.BeforeSendingRequest2Event();
                }

                try
                {
                    this.requestInfo.FireSendingRequest2(new SendingRequest2EventArgs(this.requestMessage, descriptor, this.IsBatchPartRequest));
                }
                finally
                {
                    if (httpWebRequestMessage != null)
                    {
                        httpWebRequestMessage.AfterSendingRequest2Event();
                    }
                }
            }
#if DEBUG
            else
            {
                // Cache the headers if there is no sending request 2 event subscribers. At the time of GetRequestStream
                // or GetSyncronousResponse, we will validate that the headers are the same.
                this.cachedRequestHeaders = new HeaderCollection();
                foreach (var header in this.requestMessage.Headers)
                {
                    this.cachedRequestHeaders.SetHeader(header.Key, header.Value);
                }
            }

            this.fireSendingRequest2MethodCalled = true;
#endif
        }
 /// <summary>
 /// Creates a new instance of ODataOuterRequestMessage.
 /// </summary>
 /// <param name="requestMessage">DataServiceClientRequestMessage instance.</param>
 /// <param name="requestInfo">RequestInfo instance.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 internal TopLevelRequestMessageWrapper(DataServiceClientRequestMessage requestMessage, RequestInfo requestInfo, Descriptor descriptor)
     : base(requestMessage, requestInfo, descriptor)
 {
     // Wrapper for the top-level request messages which caches the request stream as it is written. In order to keep the sync and non-async 
     // code the same, we write all requests into an cached stream and then copy it to the underlying network stream in sync or async manner.
     this.messageWithCachedStream = new RequestMessageWithCachedStream(this.requestMessage);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ReceivingResponseEventArgs"/> class for a
 /// non-batch or top level $batch response.
 /// </summary>
 /// <param name="responseMessage">The response message the client is receiving.</param>
 /// <param name="descriptor">Descriptor for the request that the client is receiving the response for.</param>
 public ReceivingResponseEventArgs(IODataResponseMessage responseMessage, Descriptor descriptor)
     : this(responseMessage, descriptor, false)
 {
 }
Example #18
0
 /// <summary>
 /// Returns the request message to write the headers and payload into.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <param name="contentId">Content-ID header that could be used in batch request.</param>
 /// <returns>an instance of IODataRequestMessage.</returns>
 protected override ODataRequestMessageWrapper CreateRequestMessage(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor, string contentId)
 {
     BuildingRequestEventArgs args = this.RequestInfo.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, this.RequestInfo.HttpStack, descriptor);
     return ODataRequestMessageWrapper.CreateBatchPartRequestMessage(this.batchWriter, args, this.RequestInfo, contentId);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ReceivingResponseEventArgs"/> class.
 /// </summary>
 /// <param name="responseMessage">The response message the client is receiving.</param>
 /// <param name="descriptor">Descriptor for the request that the client is receiving the response for.</param>
 /// <param name="isBatchPart">Indicates if this response is to an inner batch query or operation.</param>
 public ReceivingResponseEventArgs(IODataResponseMessage responseMessage, Descriptor descriptor, bool isBatchPart)
 {
     this.ResponseMessage = responseMessage;
     this.Descriptor = descriptor;
     this.IsBatchPart = isBatchPart;
 }
Example #20
0
        private void HandleResponsePut(Descriptor descriptor, HeaderCollection responseHeaders)
        {
            Debug.Assert(descriptor != null, "descriptor != null");
            if (descriptor.DescriptorKind == DescriptorKind.Entity)
            {
                string etag;
                responseHeaders.TryGetHeader(XmlConstants.HttpResponseETag, out etag);
                EntityDescriptor entityDescriptor = (EntityDescriptor)descriptor;

                // Only process the response if the resource is an entity resource and process update response is set to true
                if (this.ProcessResponsePayload)
                {
                    this.MaterializeResponse(entityDescriptor, this.CreateResponseInfo(entityDescriptor), etag);
                }
                else
                {
                    if (EntityStates.Modified != entityDescriptor.State && EntityStates.Modified != entityDescriptor.StreamState)
                    {
                        Error.ThrowBatchUnexpectedContent(InternalError.EntryNotModified);
                    }

                    // We MUST process the MR before the MLE since we always issue the requests in that order.
                    if (entityDescriptor.StreamState == EntityStates.Modified)
                    {
                        entityDescriptor.StreamETag = etag;
                        entityDescriptor.StreamState = EntityStates.Unchanged;
                    }
                    else
                    {
                        Debug.Assert(entityDescriptor.State == EntityStates.Modified, "descriptor.State == EntityStates.Modified");
                        entityDescriptor.ETag = etag;
                        entityDescriptor.State = EntityStates.Unchanged;
                        entityDescriptor.PropertiesToSerialize.Clear();
                    }
                }
            }
            else if (descriptor.DescriptorKind == DescriptorKind.Link)
            {
                if ((EntityStates.Added == descriptor.State) || (EntityStates.Modified == descriptor.State))
                {
                    descriptor.State = EntityStates.Unchanged;
                }
                else if (EntityStates.Detached != descriptor.State)
                {   // this link may have been previously detached by a detaching entity
                    Error.ThrowBatchUnexpectedContent(InternalError.LinkBadState);
                }
            }
            else
            {
                Debug.Assert(descriptor.DescriptorKind == DescriptorKind.NamedStream, "it must be named stream");
                Debug.Assert(descriptor.State == EntityStates.Modified, "named stream must only be in modified state");
                descriptor.State = EntityStates.Unchanged;

                StreamDescriptor streamDescriptor = (StreamDescriptor)descriptor;

                // The named stream has been updated, so the old ETag value is stale. Replace
                // it with the new value or clear it if no value was specified.
                string etag;
                responseHeaders.TryGetHeader(XmlConstants.HttpResponseETag, out etag);
                streamDescriptor.ETag = etag;
            }
        }
Example #21
0
 /// <summary>
 /// increment the resource change for sorting during submit changes
 /// </summary>
 /// <param name="descriptor">the resource to update the change order</param>
 internal void IncrementChange(Descriptor descriptor)
 {
     descriptor.ChangeOrder = ++this.nextChange;
 }
Example #22
0
 /// <summary>
 /// Returns the request message to write the headers and payload into.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <param name="contentId">Content-ID header that could be used in batch request.</param>
 /// <returns>an instance of IODataRequestMessage.</returns>
 protected abstract ODataRequestMessageWrapper CreateRequestMessage(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor, string contentId);
Example #23
0
 /// <summary>
 /// Asks the context to Fire the BuildingRequest event and get RequestMessageArgs.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <returns>A new RequestMessageArgs object for building the request message.</returns>
 internal BuildingRequestEventArgs CreateRequestArgsAndFireBuildingRequest(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor)
 {
     return(this.Context.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, httpStack, descriptor));
 }
Example #24
0
        /// <summary>
        /// Handle operation response
        /// </summary>
        /// <param name="descriptor">descriptor whose response is getting processed.</param>
        /// <param name="contentHeaders">content headers as returned in the response.</param>
        protected void HandleOperationResponse(Descriptor descriptor, HeaderCollection contentHeaders)
#endif
        {
            EntityStates streamState = EntityStates.Unchanged;
            if (descriptor.DescriptorKind == DescriptorKind.Entity)
            {
                EntityDescriptor entityDescriptor = (EntityDescriptor)descriptor;
                streamState = entityDescriptor.StreamState;
#if DEBUG
                if (entityDescriptor.StreamState == EntityStates.Added)
                {
                    // We do not depend anywhere for the status code to be Created (201). Hence changing the assert from checking for a specific status code
                    // to just checking for success status code.
                    Debug.Assert(
                        WebUtil.SuccessStatusCode(statusCode) && entityDescriptor.State == EntityStates.Modified && entityDescriptor.IsMediaLinkEntry,
                        "WebUtil.SuccessStatusCode(statusCode) && descriptor.State == EntityStates.Modified && descriptor.IsMediaLinkEntry -- Processing Post MR");
                }
                else if (entityDescriptor.StreamState == EntityStates.Modified)
                {
                    // We do not depend anywhere for the status code to be Created (201). Hence changing the assert from checking for a specific status code
                    // to just checking for success status code.
                    Debug.Assert(
                        WebUtil.SuccessStatusCode(statusCode) && entityDescriptor.IsMediaLinkEntry,
                        "WebUtil.SuccessStatusCode(statusCode) && descriptor.IsMediaLinkEntry -- Processing Put MR");
                }

                // if the entity is added state or modified state with patch requests
                if (streamState == EntityStates.Added || descriptor.State == EntityStates.Added ||
                    (descriptor.State == EntityStates.Modified && !Util.IsFlagSet(this.Options, SaveChangesOptions.ReplaceOnUpdate)))
                {
                    string location;
                    string odataEntityId;
                    contentHeaders.TryGetHeader(XmlConstants.HttpResponseLocation, out location);
                    contentHeaders.TryGetHeader(XmlConstants.HttpODataEntityId, out odataEntityId);

                    Debug.Assert(location == null || location == entityDescriptor.GetLatestEditLink().AbsoluteUri, "edit link must already be set to location header");
                    Debug.Assert((location == null && odataEntityId == null) || (odataEntityId ?? location) == UriUtil.UriToString(entityDescriptor.GetLatestIdentity()), "Identity must already be set");
                }
#endif
            }

            if (streamState == EntityStates.Added || descriptor.State == EntityStates.Added)
            {
                this.HandleResponsePost(descriptor, contentHeaders);
            }
            else if (streamState == EntityStates.Modified || descriptor.State == EntityStates.Modified)
            {
                this.HandleResponsePut(descriptor, contentHeaders);
            }
            else if (descriptor.State == EntityStates.Deleted)
            {
                this.HandleResponseDelete(descriptor);
            }

            // else condition is not interesting here and we intentionally do nothing.
        }
Example #25
0
 /// <summary>
 /// Fires the following events, in order
 /// 1. WritingRequest
 /// 2. SendingRequest2
 /// </summary>
 /// <param name="descriptor">Descriptor for which this request is getting generated.</param>
 internal void FireSendingEventHandlers(Descriptor descriptor)
 {
     this.FireSendingRequest2(descriptor);
 }
Example #26
0
 /// <summary>
 /// Returns the request message to write the headers and payload into.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <returns>an instance of IODataRequestMessage.</returns>
 protected ODataRequestMessageWrapper CreateTopLevelRequest(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor)
 {
     BuildingRequestEventArgs args = this.RequestInfo.CreateRequestArgsAndFireBuildingRequest(method, requestUri, headers, httpStack, descriptor);
     return this.RequestInfo.WriteHelper.CreateRequestMessage(args);
 }
Example #27
0
 /// <summary>
 /// Creates a new instance of ODataRequestMessage. This constructor is used for top level requests.
 /// </summary>
 /// <param name="requestMessage">RequestMessage that needs to be wrapped.</param>
 /// <param name="requestInfo">Request Info.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 protected ODataRequestMessageWrapper(DataServiceClientRequestMessage requestMessage, RequestInfo requestInfo, Descriptor descriptor)
 {
     Debug.Assert(requestMessage != null, "requestMessage != null");
     Debug.Assert(requestInfo != null, "requestInfo != null");
     this.requestMessage = requestMessage;
     this.requestInfo    = requestInfo;
     this.Descriptor     = descriptor;
 }
 private static BuildingRequestEventArgs SetupTest(string method, Uri uri, HeaderCollection headers, Descriptor descriptor)
 {
     return new BuildingRequestEventArgs(method, uri, headers, descriptor, HttpStack.Auto);
 }
Example #29
0
 /// <summary>
 /// Creates a new instance of ODataOuterRequestMessage.
 /// </summary>
 /// <param name="requestMessage">DataServiceClientRequestMessage instance.</param>
 /// <param name="requestInfo">RequestInfo instance.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 internal TopLevelRequestMessageWrapper(DataServiceClientRequestMessage requestMessage, RequestInfo requestInfo, Descriptor descriptor)
     : base(requestMessage, requestInfo, descriptor)
 {
     // Wrapper for the top-level request messages which caches the request stream as it is written. In order to keep the sync and non-async
     // code the same, we write all requests into an cached stream and then copy it to the underlying network stream in sync or async manner.
     this.messageWithCachedStream = new RequestMessageWithCachedStream(this.requestMessage);
 }
 /// <summary>
 /// Fires the following events, in order
 /// 1. WritingRequest
 /// 2. SendingRequest2
 /// </summary>
 /// <param name="descriptor">Descriptor for which this request is getting generated.</param>
 internal void FireSendingEventHandlers(Descriptor descriptor)
 {
     this.FireSendingRequest2(descriptor);
 }
Example #31
0
 /// <summary>
 /// Creates a new instance of InnerBatchRequestMessageWrapper;
 /// </summary>
 /// <param name="clientRequestMessage">Instance of DataServiceClientRequestMessage that represents this request.</param>
 /// <param name="odataRequestMessage">Instance of IODataRequestMessage created by ODataLib.</param>
 /// <param name="requestInfo">RequestInfo instance.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 internal InnerBatchRequestMessageWrapper(DataServiceClientRequestMessage clientRequestMessage, IODataRequestMessage odataRequestMessage, RequestInfo requestInfo, Descriptor descriptor)
     : base(clientRequestMessage, requestInfo, descriptor)
 {
     this.innerBatchRequestMessage = odataRequestMessage;
 }
Example #32
0
 /// <summary>
 /// Returns the request message to write the headers and payload into.
 /// </summary>
 /// <param name="method">Http method for the request.</param>
 /// <param name="requestUri">Base Uri for the request.</param>
 /// <param name="headers">Request headers.</param>
 /// <param name="httpStack">HttpStack to use.</param>
 /// <param name="descriptor">Descriptor for the request, if there is one.</param>
 /// <param name="contentId">Content-ID header that could be used in batch request.</param>
 /// <returns>an instance of IODataRequestMessage.</returns>
 protected override ODataRequestMessageWrapper CreateRequestMessage(string method, Uri requestUri, HeaderCollection headers, HttpStack httpStack, Descriptor descriptor, string contentId)
 {
     return this.CreateTopLevelRequest(method, requestUri, headers, httpStack, descriptor);
 }
Example #33
0
        /// <summary>
        /// Creates HTTP request for the media resource (MR)
        /// </summary>
        /// <param name="requestUri">The URI to request</param>
        /// <param name="method">The HTTP method to use (POST or PUT)</param>
        /// <param name="version">version to be sent in the DSV request header.</param>
        /// <param name="sendChunked">Send the request using chunked encoding to avoid buffering.</param>
        /// <param name="applyResponsePreference">If the response preference setting should be applied to the request
        /// (basically means if the response is expected to contain an entity or not).</param>
        /// <param name="headers">Collection of request headers</param>
        /// <param name="descriptor">Descriptor for this media resource request.</param>
        /// <returns>An instance of ODataRequestMessage.</returns>
        private ODataRequestMessageWrapper CreateMediaResourceRequest(Uri requestUri, string method, Version version, bool sendChunked, bool applyResponsePreference, HeaderCollection headers, Descriptor descriptor)
        {
            headers.SetHeaderIfUnset(XmlConstants.HttpContentType, XmlConstants.MimeAny);

            if (applyResponsePreference)
            {
                ApplyPreferences(headers, method, this.RequestInfo.AddAndUpdateResponsePreference, ref version);
            }

            // Set the request DSV and request MDSV headers
            headers.SetRequestVersion(version, this.RequestInfo.MaxProtocolVersionAsVersion);
            this.RequestInfo.Format.SetRequestAcceptHeader(headers);

            ODataRequestMessageWrapper requestMessage = this.CreateRequestMessage(method, requestUri, headers, this.RequestInfo.HttpStack, descriptor, null /*contentId*/);

            // TODO: since under the hood this is a header, we should put it in our dictionary of headers that the user gets in BuildingRequest
            // and later on handle the setting of the strongly named property on the underlying request
            requestMessage.SendChunked = sendChunked;
            return requestMessage;
        }
 /// <summary>
 /// Creates a new instance of InnerBatchRequestMessageWrapper;
 /// </summary>
 /// <param name="clientRequestMessage">Instance of DataServiceClientRequestMessage that represents this request.</param>
 /// <param name="odataRequestMessage">Instance of IODataRequestMessage created by ODataLib.</param>
 /// <param name="requestInfo">RequestInfo instance.</param>
 /// <param name="descriptor">Descriptor for this request.</param>
 internal InnerBatchRequestMessageWrapper(DataServiceClientRequestMessage clientRequestMessage, IODataRequestMessage odataRequestMessage, RequestInfo requestInfo, Descriptor descriptor)
     : base(clientRequestMessage, requestInfo, descriptor)
 {
     this.innerBatchRequestMessage = odataRequestMessage;
 }
Example #35
0
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="descriptor">descriptor whose response is getting processed.</param>
            /// <param name="headers">headers</param>
            /// <param name="statusCode">status code</param>
            /// <param name="responseVersion">Parsed response OData-Version header.</param>
            /// <param name="entry">atom entry, if there is a non-error response payload.</param>
            /// <param name="exception">exception, if the request threw an exception.</param>
            internal CachedResponse(Descriptor descriptor, HeaderCollection headers, HttpStatusCode statusCode, Version responseVersion, MaterializerEntry entry, Exception exception)
            {
                Debug.Assert(descriptor != null, "descriptor != null");
                Debug.Assert(headers != null, "headers != null");
                Debug.Assert(entry == null || (exception == null && descriptor.DescriptorKind == DescriptorKind.Entity), "if entry is specified, exception cannot be specified and entry must be a resource, since we expect responses only for entities");

                this.Descriptor = descriptor;
                this.MaterializerEntry = entry;
                this.Exception = exception;
                this.Headers = headers;
                this.StatusCode = statusCode;
                this.Version = responseVersion;
            }
        private void VerifyDescriptor(DescriptorData expected, Descriptor actual, int responseOrder)
        {
            EntityDescriptorData entityDescriptorData = expected as EntityDescriptorData;
            LinkDescriptorData linkDescriptorData = expected as LinkDescriptorData;
            StreamDescriptorData streamDescriptorData = expected as StreamDescriptorData;
            if (entityDescriptorData != null)
            {
                EntityDescriptor entityDescriptor = actual as EntityDescriptor;
                this.Assert.IsNotNull(entityDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(EntityDescriptor).Name, actual.GetType().Name, entityDescriptorData));

                this.Assert.AreSame(
                    entityDescriptorData.Entity,
                    entityDescriptor.Entity,
                    GetVerificationFailureMessage(responseOrder, "Entity verification failed for the entity descriptor data: {0}.", expected));
            }
            else if (linkDescriptorData != null)
            {
                LinkDescriptor linkDescriptor = actual as LinkDescriptor;
                this.Assert.IsNotNull(linkDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(LinkDescriptor).Name, actual.GetType().Name, linkDescriptorData));

                bool notMatch = linkDescriptorData.SourceDescriptor.Entity != linkDescriptor.Source ||
                    (linkDescriptorData.TargetDescriptor == null && linkDescriptor.Target != null) ||
                    (linkDescriptorData.TargetDescriptor != null && linkDescriptorData.TargetDescriptor.Entity != linkDescriptor.Target) ||
                    linkDescriptorData.SourcePropertyName != linkDescriptor.SourceProperty;

                this.Assert.IsFalse(notMatch, GetVerificationFailureMessage(responseOrder, "Link verification failed.\r\nExpected: {0}\r\nActual:   {1}", linkDescriptorData, linkDescriptor.ToTraceString()));
            }
            else
            {
#if WINDOWS_PHONE
                throw new TaupoNotSupportedException("StreamDescriptors are not supported on Windows Phone");
#else
                ExceptionUtilities.CheckObjectNotNull(streamDescriptorData, "Expected was not an entity, link, or stream descriptor: {0}", expected);

                StreamDescriptor streamDescriptor = actual as StreamDescriptor;

                this.Assert.IsNotNull(streamDescriptor, GetVerificationFailureMessage(responseOrder, "Unexpected descriptor type:\r\nExpected: {0}\r\nActual:   {1}\r\nExpected descriptor data: {2}.", typeof(StreamDescriptor).Name, actual.GetType().Name, streamDescriptorData));

                this.Assert.AreEqual(streamDescriptorData.State.ToProductEnum(), streamDescriptor.State, GetVerificationFailureMessage(responseOrder, "Stream descriptor state verification failed."));
                this.Assert.AreEqual(streamDescriptorData.Name, streamDescriptor.StreamLink.Name, GetVerificationFailureMessage(responseOrder, "Stream descriptor name verification failed."));
                this.Assert.AreEqual(streamDescriptorData.ETag, streamDescriptor.StreamLink.ETag, GetVerificationFailureMessage(responseOrder, "Stream descriptor etag verification failed."));
                this.Assert.AreEqual(streamDescriptorData.ContentType, streamDescriptor.StreamLink.ContentType, GetVerificationFailureMessage(responseOrder, "Stream descriptor content type verification failed."));
                this.Assert.AreEqual(streamDescriptorData.EditLink, streamDescriptor.StreamLink.EditLink, GetVerificationFailureMessage(responseOrder, "Stream descriptor edit link verification failed."));
                this.Assert.AreEqual(streamDescriptorData.SelfLink, streamDescriptor.StreamLink.SelfLink, GetVerificationFailureMessage(responseOrder, "Stream descriptor self link verification failed."));
#endif
            }
        }
Example #37
0
 /// <summary>Handle changeset response.</summary>
 /// <param name="descriptor">descriptor whose response is getting handled.</param>
 /// <param name="contentHeaders">response headers.</param>
 private void HandleResponsePost(Descriptor descriptor, HeaderCollection contentHeaders)
 {
     if (descriptor.DescriptorKind == DescriptorKind.Entity)
     {
         string etag;
         contentHeaders.TryGetHeader(XmlConstants.HttpResponseETag, out etag);
         this.HandleResponsePost((EntityDescriptor)descriptor, etag);
     }
     else
     {
         HandleResponsePost((LinkDescriptor)descriptor);
     }
 }
Example #38
0
 /// <summary>
 /// increment the resource change for sorting during submit changes
 /// </summary>
 /// <param name="descriptor">the resource to update the change order</param>
 internal void IncrementChange(Descriptor descriptor)
 {
     descriptor.ChangeOrder = ++this.nextChange;
 }
 /// <summary>
 /// Creates a new instance of SendingRequest2EventsArgs
 /// </summary>
 /// <param name="requestMessage">request message.</param>
 /// <param name="descriptor">Descriptor that represents this change.</param>
 /// <param name="isBatchPart">True if this args represents a request within a batch, otherwise false.</param>
 internal SendingRequest2EventArgs(IODataRequestMessage requestMessage, Descriptor descriptor, bool isBatchPart)
 {
     this.RequestMessage = requestMessage;
     this.Descriptor     = descriptor;
     this.IsBatchPart    = isBatchPart;
 }