public void InitialHeadersComesFromConstructor()
 {
     var headers = new HeaderCollection();
     headers.SetHeader("Header1", "Value1");
     headers.SetHeader("Header #2", "A Second *value*");
     SetupTest("ABCD", new Uri("https://www.example.com/odata.svc/"), headers).Headers.Should().Contain("Header1", "Value1").And.Contain("Header #2", "A Second *value*");
 }
        /// <summary>
        /// Instantiates a new Serializer class and calls WriteEntry method on it.
        /// </summary>
        /// <param name="dataServiceContext"></param>
        /// <returns></returns>
        private static Person SetupSerializerAndCallWriteEntry(DataServiceContext dataServiceContext)
        {
            Person person = new Person();
            Address address = new Address();
            Car car1 = new Car();
            person.Cars.Add(car1);
            person.HomeAddress = address;

            dataServiceContext.AttachTo("Cars", car1);
            dataServiceContext.AttachTo("Addresses", address);

            var requestInfo = new RequestInfo(dataServiceContext);
            var serializer = new Serializer(requestInfo);
            var headers = new HeaderCollection();
            var clientModel = new ClientEdmModel(ODataProtocolVersion.V4);
            var entityDescriptor = new EntityDescriptor(clientModel);
            entityDescriptor.State = EntityStates.Added;
            entityDescriptor.Entity = person;
            var requestMessageArgs = new BuildingRequestEventArgs("POST", new Uri("http://www.foo.com/Northwind"), headers, entityDescriptor, HttpStack.Auto);
            var linkDescriptors = new LinkDescriptor[] { new LinkDescriptor(person, "Cars", car1, clientModel), new LinkDescriptor(person, "HomeAddress", address, clientModel) };
            var odataRequestMessageWrapper = ODataRequestMessageWrapper.CreateRequestMessageWrapper(requestMessageArgs, requestInfo);

            serializer.WriteEntry(entityDescriptor, linkDescriptors, odataRequestMessageWrapper);
            return person;
        }
Ejemplo n.º 3
0
 public HttpWebResponseMessage(HttpWebResponse httpResponse)
 {
     Util.CheckArgumentNull(httpResponse, "httpResponse");
     this.headers = new HeaderCollection(httpResponse.Headers);
     this.statusCode = (int)httpResponse.StatusCode;
     this.getResponseStream = httpResponse.GetResponseStream;
     this.httpWebResponse = httpResponse;
 }
 /// <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;
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="headers">The headers.</param>
        /// <param name="statusCode">The status code.</param>
        /// <param name="getResponseStream">A function returning the response stream.</param>
        internal HttpWebResponseMessage(HeaderCollection headers, int statusCode, Func<Stream> getResponseStream)
        {
            Debug.Assert(headers != null, "headers != null");
            Debug.Assert(getResponseStream != null, "getResponseStream != null");

            this.headers = headers;
            this.statusCode = statusCode;
            this.getResponseStream = getResponseStream;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="headers">The headers.</param>
        /// <param name="statusCode">The status code.</param>
        /// <param name="getResponseStream">A function returning the response stream.</param>
        public HttpWebResponseMessage(IDictionary<string, string> headers, int statusCode, Func<Stream> getResponseStream)
        {
            Debug.Assert(headers != null, "headers != null");
            Debug.Assert(getResponseStream != null, "getResponseStream != null");

            this.headers = new HeaderCollection(headers);
            this.statusCode = statusCode;
            this.getResponseStream = getResponseStream;
        }
Ejemplo n.º 7
0
        public void HeaderDictionaryKeysShouldBeUnchanged()
        {
            var expectedKeys = GetInterestingHeaderNames().Select(InvertCase).ToList();

            var headers = new WebHeaderCollection();
            foreach (var header in expectedKeys)
            {
                headers[header] = "some value";
            }

            var dictionary = new HeaderCollection(headers);
            dictionary.HeaderNames.Should().BeEquivalentTo(expectedKeys);
        }
        /// <summary>
        /// The reason for adding this method is that we have seen a couple of asserts that we were not able to figure out why they are getting fired.
        /// So added this method which returns the current headers as well as cached headers as string and we display that in the assert message.
        /// </summary>
        /// <param name="currentHeaders">current header values.</param>
        /// <param name="cachedHeaders">cached header values.</param>
        /// <returns>returns a string which contains both current and cached header names.</returns>
        private static string GetHeaderValues(IEnumerable <KeyValuePair <string, string> > currentHeaders, HeaderCollection cachedHeaders)
        {
            StringBuilder sb        = new StringBuilder();
            string        separator = String.Empty;

            sb.Append("Current Headers: ");
            foreach (var header in currentHeaders)
            {
                sb.Append(separator);
                sb.Append(header.Key);
                separator = ", ";
            }

            sb.Append(". Headers fired in SendingRequest: ");
            separator = String.Empty;
            foreach (string name in cachedHeaders.HeaderNames)
            {
                sb.Append(separator);
                sb.Append(name);
                separator = ", ";
            }

            return(sb.ToString());
        }
Ejemplo n.º 9
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 (this.ChangedEntries.Count > 0)
                {
                    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);
        }
Ejemplo n.º 10
0
 public void DefaultConventionShouldNotAddAnyHeaders()
 {
     var headers = new HeaderCollection();
     this.defaultConvention.AddRequiredHeaders(headers);
     headers.UnderlyingDictionary.Should().BeEmpty();
 }
Ejemplo n.º 11
0
        /// <summary>
        /// process the batch response
        /// </summary>
        /// <param name="batchReader">The batch reader to use for reading the batch response.</param>
        /// <returns>an instance of the DataServiceResponse, containing individual operation responses for this batch request.</returns>
        /// <remarks>
        /// The message reader for the entire batch response is stored in the this.batchMessageReader.
        /// The message reader is disposable, but this method should not dispose it itself. It will be either disposed by the caller (in case of exception)
        /// or the ownership will be passed to the returned response object (in case of success).
        /// In could also be diposed indirectly by this method when it enumerates through the responses.
        /// </remarks>
        private DataServiceResponse HandleBatchResponseInternal(ODataBatchReader batchReader)
        {
            Debug.Assert(this.batchMessageReader != null, "this.batchMessageReader != null");
            Debug.Assert(batchReader != null, "batchReader != null");

            DataServiceResponse response;
            HeaderCollection headers = new HeaderCollection(this.batchResponseMessage);

            IEnumerable<OperationResponse> responses = this.HandleBatchResponse(batchReader);
            if (this.Queries != null)
            {
                // ExecuteBatch, EndExecuteBatch
                response = new DataServiceResponse(
                    headers,
                    (int)this.batchResponseMessage.StatusCode,
                    responses,
                    true /*batchResponse*/);
            }
            else
            {
                List<OperationResponse> operationResponses = new List<OperationResponse>();
                response = new DataServiceResponse(headers, (int)this.batchResponseMessage.StatusCode, operationResponses, true /*batchResponse*/);
                Exception exception = null;

                // SaveChanges, EndSaveChanges
                // enumerate the entire response
                foreach (ChangeOperationResponse changeOperationResponse in responses)
                {
                    operationResponses.Add(changeOperationResponse);
                    if (Util.IsBatchWithSingleChangeset(this.Options) && exception == null && changeOperationResponse.Error != null)
                    {
                        exception = changeOperationResponse.Error;
                    }

                    // Note that this will dispose the enumerator and this release the batch message reader which is owned
                    // by the enumerable of responses by now.
                }

                // Note that if we encounter any error in a batch request with a single changeset, 
                // we throw here since all change operations in the changeset are rolled back on the server.  
                // If we encounter any error in a batch request with independent operations, we don't want to throw 
                // since some of the operations might succeed. 
                // Users need to inspect each OperationResponse to get the exception information from the failed operations.
                if (exception != null)
                {
                    throw new DataServiceRequestException(Strings.DataServiceException_GeneralError, exception, response);
                }
            }

            return response;
        }
        /// <summary>
        /// This method validates that headers values are identical to what they originally were when the request was configured.
        /// DataServiceContext.CachedRequestHeaders is populated in the DataServiceContext.CreateGetRequest method.
        /// </summary>
        private void ValidateHeaders()
        {
            Debug.Assert(this.fireSendingRequest2MethodCalled, "In ValidateHeaders - FireSendingRequest2 method must have been called");

            if (this.cachedRequestHeaders != null)
            {
                Debug.Assert(this.Headers.Count() == this.cachedRequestHeaders.Count, "The request headers count must match" + GetHeaderValues(this.Headers, this.cachedRequestHeaders));

                foreach (KeyValuePair<string, string> header in this.Headers)
                {
                    if (!this.cachedRequestHeaders.HasHeader(header.Key))
                    {
                        Debug.Assert(false, "Missing header: " + GetHeaderValues(this.Headers, this.cachedRequestHeaders));
                    }

                    Debug.Assert(
                        header.Value == this.cachedRequestHeaders.GetHeader(header.Key),
                        String.Format(CultureInfo.InvariantCulture, "The header '{0}' has a different value. Old Value: '{1}', Current Value: '{2}' Please make sure to set the header before SendingRequest event is fired", header.Key, header.Value, this.cachedRequestHeaders.GetHeader(header.Key)));
                }

                this.cachedRequestHeaders = null;
            }
        }
        /// <summary>
        /// Synchronizely get the query set count from the server by executing the $count=value query
        /// </summary>
        /// <param name="context">The context</param>
        /// <returns>The server side count of the query set</returns>
        internal long GetQuerySetCount(DataServiceContext context)
        {
            Debug.Assert(null != context, "context is null");
            Version requestVersion = this.QueryComponents(context.Model).Version;

            if (requestVersion == null)
            {
                requestVersion = Util.ODataVersion4;
            }

            QueryResult               response       = null;
            QueryComponents           qc             = this.QueryComponents(context.Model);
            Uri                       requestUri     = qc.Uri;
            DataServiceRequest <long> serviceRequest = new DataServiceRequest <long>(requestUri, qc, null);

            HeaderCollection headers = new HeaderCollection();

            // Validate and set the request DSV header
            headers.SetRequestVersion(requestVersion, context.MaxProtocolVersionAsVersion);
            context.Format.SetRequestAcceptHeaderForCount(headers);

            string httpMethod = XmlConstants.HttpMethodGet;
            ODataRequestMessageWrapper request = context.CreateODataRequestMessage(
                context.CreateRequestArgsAndFireBuildingRequest(httpMethod, requestUri, headers, context.HttpStack, null /*descriptor*/),
                null /*descriptor*/);

            response = new QueryResult(this, Util.ExecuteMethodName, serviceRequest, request, new RequestInfo(context), null, null);

            try
            {
                response.ExecuteQuery();

                if (HttpStatusCode.NoContent != response.StatusCode)
                {
                    StreamReader sr = new StreamReader(response.GetResponseStream());
                    long         r  = -1;
                    try
                    {
                        r = XmlConvert.ToInt64(sr.ReadToEnd());
                    }
                    finally
                    {
                        sr.Close();
                    }

                    return(r);
                }
                else
                {
                    throw new DataServiceQueryException(Strings.DataServiceRequest_FailGetCount, response.Failure);
                }
            }
            catch (InvalidOperationException ex)
            {
                QueryOperationResponse operationResponse = null;
                operationResponse = response.GetResponse <long>(MaterializeAtom.EmptyResults);
                if (null != operationResponse)
                {
                    operationResponse.Error = ex;
                    throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse);
                }

                throw;
            }
        }
 /// <summary>
 /// Sets the value of the Accept header for a count request (will set it to 'multipart/mixed').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForBatch(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, MimeMultiPartMixed);
 }
Ejemplo n.º 15
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));
 }
Ejemplo n.º 16
0
 /// <summary>
 /// Sets the value of the ContentType header on the specified links request to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">Dictionary of request headers.</param>
 internal void SetRequestContentTypeForLinks(HeaderCollection headers)
 {
     this.SetRequestContentTypeHeader(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationXml, false));
 }
 /// <summary>
 /// Sets the value of the Accept header to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeader(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, ChooseMediaType(false));
 }
 /// <summary>
 /// Sets the value of the Accept header for a stream request (will set it to '*/*').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForStream(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, XmlConstants.MimeAny);
 }
Ejemplo n.º 19
0
        /// <summary>
        /// Check to see if the resource to be inserted is a media descriptor, and if so
        /// setup a POST request for the media content first and turn the rest of
        /// the operation into a PUT to update the rest of the properties.
        /// </summary>
        /// <param name="entityDescriptor">The resource to check/process</param>
        /// <returns>An instance of ODataRequestMessage to do POST to the media resource</returns>
        private ODataRequestMessageWrapper CheckAndProcessMediaEntryPost(EntityDescriptor entityDescriptor)
        {
            // TODO: Revisit the design of how media link entries are handled during update
            ClientEdmModel       model = this.RequestInfo.Model;
            ClientTypeAnnotation type  = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType()));

            if (!type.IsMediaLinkEntry && !entityDescriptor.IsMediaLinkEntry)
            {
                // this is not a media link descriptor, process normally
                return(null);
            }

            if (type.MediaDataMember == null && entityDescriptor.SaveStream == null)
            {
                // The entity is marked as MLE but we don't have the content property
                //   and the user didn't set the save stream.
                throw Error.InvalidOperation(Strings.Context_MLEWithoutSaveStream(type.ElementTypeName));
            }

            Debug.Assert(
                (type.MediaDataMember != null && entityDescriptor.SaveStream == null) ||
                (type.MediaDataMember == null && entityDescriptor.SaveStream != null),
                "Only one way of specifying the MR content is allowed.");

            ODataRequestMessageWrapper mediaRequest = null;

            if (type.MediaDataMember != null)
            {
                string contentType   = null;
                int    contentLength = 0;

                if (type.MediaDataMember.MimeTypeProperty == null)
                {
                    contentType = XmlConstants.MimeApplicationOctetStream;
                }
                else
                {
                    object mimeTypeValue = type.MediaDataMember.MimeTypeProperty.GetValue(entityDescriptor.Entity);
                    String mimeType      = mimeTypeValue != null?mimeTypeValue.ToString() : null;

                    if (String.IsNullOrEmpty(mimeType))
                    {
                        throw Error.InvalidOperation(
                                  Strings.Context_NoContentTypeForMediaLink(
                                      type.ElementTypeName,
                                      type.MediaDataMember.MimeTypeProperty.PropertyName));
                    }

                    contentType = mimeType;
                }

                object value = type.MediaDataMember.GetValue(entityDescriptor.Entity);
                if (value == null)
                {
                    this.mediaResourceRequestStream = null;
                }
                else
                {
                    byte[] buffer = value as byte[];
                    if (buffer == null)
                    {
                        string   mime;
                        Encoding encoding;
                        ContentTypeUtil.ReadContentType(contentType, out mime, out encoding);

                        if (encoding == null)
                        {
                            encoding     = Encoding.UTF8;
                            contentType += XmlConstants.MimeTypeUtf8Encoding;
                        }

                        buffer = encoding.GetBytes(ClientConvert.ToString(value));
                    }

                    contentLength = buffer.Length;

                    // Need to specify that the buffer is publicly visible as we need to access it later on
                    this.mediaResourceRequestStream = new MemoryStream(buffer, 0, buffer.Length, false, true);
                }

                HeaderCollection headers = new HeaderCollection();
                headers.SetHeader(XmlConstants.HttpContentLength, contentLength.ToString(CultureInfo.InvariantCulture));
                headers.SetHeader(XmlConstants.HttpContentType, contentType);

                mediaRequest = this.CreateMediaResourceRequest(
                    entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/),
                    XmlConstants.HttpMethodPost,
                    Util.ODataVersion4,
                    type.MediaDataMember == null, // sendChunked
                    true,                         // applyResponsePreference
                    headers,
                    entityDescriptor);
            }
            else
            {
                HeaderCollection headers = new HeaderCollection();
                this.SetupMediaResourceRequest(headers, entityDescriptor.SaveStream, null /*etag*/);

                mediaRequest = this.CreateMediaResourceRequest(
                    entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/),
                    XmlConstants.HttpMethodPost,
                    Util.ODataVersion4,
                    type.MediaDataMember == null, // sendChunked
                    true,                         // applyResponsePreference
                    headers,
                    entityDescriptor);
            }

            // Convert the insert into an update for the media link descriptor we just created
            // (note that the identity still needs to be fixed up on the resbox once
            // the response comes with the 'location' header; that happens during processing
            // of the response in SavedResource())
            entityDescriptor.State = EntityStates.Modified;

            return(mediaRequest);
        }
 /// <summary>
 /// Sets the value of the ContentType header on the specified links request to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">Dictionary of request headers.</param>
 internal void SetRequestContentTypeForLinks(HeaderCollection headers)
 {
     this.SetRequestContentTypeHeader(headers, ChooseMediaType(false));
 }
Ejemplo n.º 21
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>
        /// 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
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Handle the response payload.
        /// </summary>
        /// <param name="responseMsg">httpwebresponse instance.</param>
        /// <param name="responseStream">stream containing the response payload.</param>
        private void HandleOperationResponseData(IODataResponseMessage responseMsg, Stream responseStream)
        {
            Debug.Assert(this.entryIndex >= 0 && this.entryIndex < this.ChangedEntries.Count, string.Format(System.Globalization.CultureInfo.InvariantCulture, "this.entryIndex = '{0}', this.ChangedEntries.Count() = '{1}'", this.entryIndex, this.ChangedEntries.Count));

            // Parse the response
            Descriptor        current = this.ChangedEntries[this.entryIndex];
            MaterializerEntry entry   = default(MaterializerEntry);
            Version           responseVersion;
            Exception         exception = BaseSaveResult.HandleResponse(this.RequestInfo, (HttpStatusCode)responseMsg.StatusCode, responseMsg.GetHeader(XmlConstants.HttpODataVersion), () => { return(responseStream); }, false /*throwOnFailure*/, out responseVersion);

            var headers = new HeaderCollection(responseMsg);

            if (responseStream != null && current.DescriptorKind == DescriptorKind.Entity && exception == null)
            {
                // Only process the response if the current resource is an entity and it's an insert or update scenario
                EntityDescriptor entityDescriptor = (EntityDescriptor)current;

                // We were ignoring the payload for non-insert and non-update scenarios. We need to keep doing that.
                if (entityDescriptor.State == EntityStates.Added || entityDescriptor.StreamState == EntityStates.Added ||
                    entityDescriptor.State == EntityStates.Modified || entityDescriptor.StreamState == EntityStates.Modified)
                {
                    try
                    {
                        ResponseInfo responseInfo           = this.CreateResponseInfo(entityDescriptor);
                        var          responseMessageWrapper = new HttpWebResponseMessage(
                            headers,
                            responseMsg.StatusCode,
                            () => responseStream);

                        entry = ODataReaderEntityMaterializer.ParseSingleEntityPayload(responseMessageWrapper, responseInfo, entityDescriptor.Entity.GetType());
                        entityDescriptor.TransientEntityDescriptor = entry.EntityDescriptor;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;

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

            this.cachedResponses.Add(new CachedResponse(
                                         current,
                                         headers,
                                         (HttpStatusCode)responseMsg.StatusCode,
                                         responseVersion,
                                         entry,
                                         exception));

            if (exception != null)
            {
                current.SaveError = exception;

                // DEVNOTE(pqian):
                // There are two possible scenario here:
                // 1. We are in the sync code path, and there's an in stream error on the server side, or there are bad xml thrown
                // 2. We are in the async code path, there's a error thrown on the server side (any error)
                // Ideally, we need to check whether we want to continue to the next changeset. (Call this.CheckContinueOnError)
                // However, in V1/V2, we did not do this. Thus we will always continue on error on these scenarios
            }
        }
Ejemplo n.º 24
0
 /// <summary>
 /// Sets the value of the Accept header for a query.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 /// <param name="components">The query components for the request.</param>
 internal void SetRequestAcceptHeaderForQuery(HeaderCollection headers, QueryComponents components)
 {
     this.SetAcceptHeaderAndCharset(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationAtomOrXml, components.HasSelectQueryOption));
 }
Ejemplo n.º 25
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 internal OperationResponse(HeaderCollection headers)
 {
     Debug.Assert(null != headers, "null headers");
     this.headers = headers;
 }
Ejemplo n.º 26
0
        public void RequestInfoShouldCreateTunneledPatchRequestMessagePostMethodAndPatchInHttpXMethodHeader()
        {
            bool previousPostTunnelingValue = ctx.UsePostTunneling;
            ctx.UsePostTunneling = true;
            HeaderCollection headersCollection = new HeaderCollection();
            var descriptor = new EntityDescriptor(this.clientEdmModel) { ServerTypeName = this.serverTypeName, Entity = new Customer() };
            var buildingRequestArgs = new BuildingRequestEventArgs("PATCH", new Uri("http://localhost/fakeService.svc/"), headersCollection, descriptor, HttpStack.Auto);

            var requestMessage = (HttpWebRequestMessage)testSubject.CreateRequestMessage(buildingRequestArgs);

            requestMessage.GetHeader(XmlConstants.HttpXMethod).Should().Be("PATCH");
            requestMessage.Method.Should().Be("PATCH");
            requestMessage.HttpWebRequest.Method.Should().Be("POST");

            // undoing change so this is applicable only for this test.
            ctx.UsePostTunneling = previousPostTunnelingValue;
        }
Ejemplo n.º 27
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);
Ejemplo n.º 28
0
        /// <summary>
        /// Sets the value of the Accept header for a batch request
        /// Will set it to 'multipart/mixed' for a multipart batch request
        /// Will set it to 'application/json' for a json batch request
        /// </summary>
        /// <param name="headers">The headers to modify.</param>
        internal void SetRequestAcceptHeaderForBatch(HeaderCollection headers)
        {
            bool useJsonBatch = headers.GetHeader(XmlConstants.HttpContentType).Equals(MimeApplicationJson);

            this.SetAcceptHeaderAndCharset(headers, useJsonBatch? MimeApplicationJson : MimeMultiPartMixed);
        }
Ejemplo n.º 29
0
        /// <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.
                    }
                }
            }
        }
Ejemplo n.º 30
0
        /// <summary>
        /// process the batch response
        /// </summary>
        /// <returns>an instance of the DataServiceResponse, containing individual operation responses for this batch request.</returns>
        private DataServiceResponse HandleBatchResponse()
        {
            bool batchMessageReaderOwned = true;

            try
            {
                if ((this.batchResponseMessage == null) || (this.batchResponseMessage.StatusCode == (int)HttpStatusCode.NoContent))
                {   // we always expect a response to our batch POST request
                    throw Error.InvalidOperation(Strings.Batch_ExpectedResponse(1));
                }

                Func <Stream> getResponseStream = () => this.ResponseStream;

                // We are not going to use the responseVersion returned from this call, as the $batch request itself doesn't apply versioning
                // of the responses on the root level. The responses are versioned on the part level. (Note that the version on the $batch level
                // is actually used to version the batch itself, but we for now we only recognize a single version so to keep it backward compatible
                // we don't check this here. Also note that the HandleResponse method will verify that we can support the version, that is it's
                // lower than the highest version we understand).
                Version responseVersion;
                BaseSaveResult.HandleResponse(
                    this.RequestInfo,
                    (HttpStatusCode)this.batchResponseMessage.StatusCode,               // statusCode
                    this.batchResponseMessage.GetHeader(XmlConstants.HttpODataVersion), // responseVersion
                    getResponseStream,                                                  // getResponseStream
                    true,                                                               // throwOnFailure
                    out responseVersion);

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

                // Create the message and the message reader.
                this.batchResponseMessage = new HttpWebResponseMessage(new HeaderCollection(this.batchResponseMessage), this.batchResponseMessage.StatusCode, getResponseStream);
                ODataMessageReaderSettings messageReaderSettings = this.RequestInfo.GetDeserializationInfo(/*mergeOption*/ null).ReadHelper.CreateSettings();

                // No need to pass in any model to the batch reader.
                this.batchMessageReader = new ODataMessageReader(this.batchResponseMessage, messageReaderSettings);
                ODataBatchReader batchReader;
                try
                {
                    batchReader = this.batchMessageReader.CreateODataBatchReader();
                }
                catch (ODataContentTypeException contentTypeException)
                {
                    string    mime;
                    Encoding  encoding;
                    Exception inner = contentTypeException;
                    ContentTypeUtil.ReadContentType(this.batchResponseMessage.GetHeader(XmlConstants.HttpContentType), out mime, out encoding);
                    if (String.Equals(XmlConstants.MimeTextPlain, mime, StringComparison.Ordinal))
                    {
                        inner = GetResponseText(
                            this.batchResponseMessage.GetStream,
                            (HttpStatusCode)this.batchResponseMessage.StatusCode);
                    }

                    throw Error.InvalidOperation(Strings.Batch_ExpectedContentType(this.batchResponseMessage.GetHeader(XmlConstants.HttpContentType)), inner);
                }

                DataServiceResponse response = this.HandleBatchResponseInternal(batchReader);

                // In case of successful processing of at least the beginning of the batch, the message reader is owned by the returned response
                // (or rather by the IEnumerable of operation responses inside it).
                // It will be disposed once the operation responses are enumerated (since the IEnumerator should be disposed once used).
                // In that case we must NOT dispose it here, since that enumeration can exist long after we return from this method.
                batchMessageReaderOwned = false;

                return(response);
            }
            catch (DataServiceRequestException)
            {
                throw;
            }
            catch (InvalidOperationException ex)
            {
                HeaderCollection headers     = new HeaderCollection(this.batchResponseMessage);
                int statusCode               = this.batchResponseMessage == null ? (int)HttpStatusCode.InternalServerError : (int)this.batchResponseMessage.StatusCode;
                DataServiceResponse response = new DataServiceResponse(headers, statusCode, new OperationResponse[0], this.IsBatchRequest);
                throw new DataServiceRequestException(Strings.DataServiceException_GeneralError, ex, response);
            }
            finally
            {
                if (batchMessageReaderOwned)
                {
                    Util.Dispose(ref this.batchMessageReader);
                }
            }
        }
Ejemplo n.º 31
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)
Ejemplo n.º 32
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers)
 {
     this.query   = query;
     this.results = results;
 }
Ejemplo n.º 33
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.
        }
 /// <summary>
 /// Sets the value of the Accept header for a query.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 /// <param name="components">The query components for the request.</param>
 internal void SetRequestAcceptHeaderForQuery(HeaderCollection headers, QueryComponents components)
 {
     this.SetAcceptHeaderAndCharset(headers, ChooseMediaType(components.HasSelectQueryOption));
 }
Ejemplo n.º 35
0
        /// <summary>
        /// Generate the link payload.
        /// </summary>
        /// <param name="binding">binding</param>
        /// <returns>An instance of ODataRequestMessage for the link request.</returns>
        protected ODataRequestMessageWrapper CreateRequest(LinkDescriptor binding)
        {
            Debug.Assert(null != binding, "null binding");
            if (binding.ContentGeneratedForSave)
            {
                return null;
            }

            EntityDescriptor sourceEntityDescriptor = this.RequestInfo.EntityTracker.GetEntityDescriptor(binding.Source);
            EntityDescriptor targetEntityDescriptor = (null != binding.Target) ? this.RequestInfo.EntityTracker.GetEntityDescriptor(binding.Target) : null;

            // We allow the source and target to be in Added state, i.e. without identities, for batch with single changeset.
            if (!Util.IsBatchWithSingleChangeset(this.Options))
            {
                ValidateLinkDescriptorSourceAndTargetHaveIdentities(binding, sourceEntityDescriptor, targetEntityDescriptor);
            }

            Debug.Assert(this.IsBatchRequest || null != sourceEntityDescriptor.GetLatestIdentity(), "missing sourceResource.Identity in non-batch");

            Uri requestUri = null;
            LinkInfo linkInfo = null;

            if (sourceEntityDescriptor.TryGetLinkInfo(binding.SourceProperty, out linkInfo)
                && linkInfo.AssociationLink != null)
            {
                Debug.Assert(null != sourceEntityDescriptor.GetLatestIdentity(), "Source must have an identity in order to have link info");

                // If there is already an Association link from the payload, use that
                requestUri = linkInfo.AssociationLink;
            }
            else
            {
                Uri sourceEntityUri;
                if (null == sourceEntityDescriptor.GetLatestIdentity())
                {
                    Debug.Assert(this.IsBatchRequest && Util.IsBatchWithSingleChangeset(this.Options), "Source must have an identity outside of batch with single changeset");

                    // if the source hasn't yet been inserted (because its in batch), then create a uri based on its content-ID
                    sourceEntityUri = UriUtil.CreateUri("$" + sourceEntityDescriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture), UriKind.Relative);
                }
                else
                {
                    // otherwise use the edit link of the source
                    sourceEntityUri = sourceEntityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/);
                }

                // get the source property Uri
                string sourcePropertyUri = GetSourcePropertyUri(binding, sourceEntityDescriptor);

                // get the convention-based relative uri for the association
                Uri conventionalRelativeUri = UriUtil.CreateUri(sourcePropertyUri, UriKind.Relative);

                // add $ref at the end
                conventionalRelativeUri = UriUtil.CreateUri(UriUtil.UriToString(conventionalRelativeUri) + UriHelper.FORWARDSLASH + XmlConstants.UriLinkSegment, UriKind.Relative);

                // combine the association uri with the source entity uri
                requestUri = UriUtil.CreateUri(sourceEntityUri, conventionalRelativeUri);
            }

            // in the case of deleting a link from a collection, the key of the target must be appended
            requestUri = AppendTargetEntityKeyIfNeeded(requestUri, binding, targetEntityDescriptor);

            string method = GetLinkHttpMethod(binding);

            HeaderCollection headers = new HeaderCollection();

            headers.SetRequestVersion(Util.ODataVersion4, this.RequestInfo.MaxProtocolVersionAsVersion);
            this.RequestInfo.Format.SetRequestAcceptHeader(headers);

            // if (EntityStates.Deleted || (EntityState.Modifed && null == TargetResource))
            // then the server will fail the batch section if content type exists
            if ((EntityStates.Added == binding.State) || (EntityStates.Modified == binding.State && (null != binding.Target)))
            {
                this.RequestInfo.Format.SetRequestContentTypeForLinks(headers);
            }

            return this.CreateRequestMessage(method, requestUri, headers, this.RequestInfo.HttpStack, binding, this.IsBatchRequest ? binding.ChangeOrder.ToString(CultureInfo.InvariantCulture) : null);
        }
 /// <summary>
 /// Sets the value of the Accept header for a count request (will set it to 'text/plain').
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeaderForCount(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, XmlConstants.MimeTextPlain);
 }
Ejemplo n.º 37
0
        /// <summary>
        /// Create ODataRequestMessage for the given entity.
        /// </summary>
        /// <param name="entityDescriptor">resource</param>
        /// <returns>An instance of ODataRequestMessage for the given entity.</returns>
        protected ODataRequestMessageWrapper CreateRequest(EntityDescriptor entityDescriptor)
        {
            Debug.Assert(null != entityDescriptor, "null entityDescriptor");
            Debug.Assert(entityDescriptor.State == EntityStates.Added || entityDescriptor.State == EntityStates.Deleted || entityDescriptor.State == EntityStates.Modified, "the entity must be in one of the 3 possible states");

            EntityStates state = entityDescriptor.State;
            Uri requestUri = entityDescriptor.GetResourceUri(this.RequestInfo.BaseUriResolver, false /*queryLink*/);

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

            ClientEdmModel model = this.RequestInfo.Model;
            ClientTypeAnnotation clientType = model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType()));
            Version requestVersion = DetermineRequestVersion(clientType);
            string httpMethod = this.GetHttpMethod(state, ref requestVersion);

            HeaderCollection headers = new HeaderCollection();

            // Set the content type
            if (EntityStates.Deleted != entityDescriptor.State)
            {
                this.RequestInfo.Context.Format.SetRequestContentTypeForEntry(headers);
            }

            // Set IfMatch (etag) header for update and delete requests
            if ((EntityStates.Deleted == state) || (EntityStates.Modified == state))
            {
                string etag = entityDescriptor.GetLatestETag();
                if (etag != null)
                {
                    headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag);
                }
            }

            // Set the prefer header if required
            ApplyPreferences(headers, httpMethod, this.RequestInfo.AddAndUpdateResponsePreference, ref requestVersion);

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

            this.RequestInfo.Format.SetRequestAcceptHeader(headers);
            return this.CreateRequestMessage(httpMethod, requestUri, headers, this.RequestInfo.HttpStack, entityDescriptor, this.IsBatchRequest ? entityDescriptor.ChangeOrder.ToString(CultureInfo.InvariantCulture) : null);
        }
 /// <summary>
 /// Sets the value of the  Content-Type header a request with operation parameters to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">Dictionary of request headers.</param>
 internal void SetRequestContentTypeForOperationParameters(HeaderCollection headers)
 {
     // Note: There has never been an atom or xml format for parameters.
     this.SetRequestContentTypeHeader(headers, MimeApplicationJsonODataLight);
 }
Ejemplo n.º 39
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);
 }
Ejemplo n.º 40
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="headers">HTTP headers</param>
 /// <param name="query">original query</param>
 /// <param name="results">retrieved objects</param>
 internal QueryOperationResponse(HeaderCollection headers, DataServiceRequest query, MaterializeAtom results)
     : base(headers, query, results)
 {
 }
Ejemplo n.º 41
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);
 }
        /// <summary>
        /// Creates the result object for the specified query parameters.
        /// </summary>
        /// <param name="source">The source object for the request.</param>
        /// <param name="context">The data service context.</param>
        /// <param name="callback">The AsyncCallback delegate.</param>
        /// <param name="state">The state object for the callback.</param>
        /// <param name="method">async method name at the source.</param>
        /// <returns>Result representing the create request. The request has not been initiated yet.</returns>
        private QueryResult CreateExecuteResult(object source, DataServiceContext context, AsyncCallback callback, object state, string method)
        {
            Debug.Assert(null != context, "context is null");

            QueryComponents qc          = this.QueryComponents(context.Model);
            RequestInfo     requestInfo = new RequestInfo(context);

            Debug.Assert(
                string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0 ||
                string.CompareOrdinal(XmlConstants.HttpMethodGet, qc.HttpMethod) == 0,
                "Only get and post are supported in the execute pipeline, which should have been caught earlier");

            if (qc.UriOperationParameters != null)
            {
                Debug.Assert(qc.UriOperationParameters.Any(), "qc.UriOperationParameters.Any()");
                Serializer serializer = new Serializer(requestInfo);
                this.RequestUri = serializer.WriteUriOperationParametersToUri(this.RequestUri, qc.UriOperationParameters);
            }

            HeaderCollection headers = new HeaderCollection();

            if (string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0)
            {
                if (qc.BodyOperationParameters == null)
                {
                    // set the content length to be 0 if there are no operation parameters.
                    headers.SetHeader(XmlConstants.HttpContentLength, "0");
                }
                else
                {
                    context.Format.SetRequestContentTypeForOperationParameters(headers);
                }
            }

            // Validate and set the request DSV and MDSV header
            headers.SetRequestVersion(qc.Version, requestInfo.MaxProtocolVersionAsVersion);

            requestInfo.Format.SetRequestAcceptHeaderForQuery(headers, qc);

            // We currently do not have a descriptor to expose to the user for invoking something through Execute. Ideally we could expose an OperationDescriptor.
            ODataRequestMessageWrapper requestMessage = new RequestInfo(context).WriteHelper.CreateRequestMessage(context.CreateRequestArgsAndFireBuildingRequest(qc.HttpMethod, this.RequestUri, headers, context.HttpStack, null /*descriptor*/));

            requestMessage.FireSendingRequest2(null /*descriptor*/);

            if (qc.BodyOperationParameters != null)
            {
                Debug.Assert(string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0, "qc.HttpMethod == XmlConstants.HttpMethodPost");
                Debug.Assert(qc.BodyOperationParameters.Any(), "unexpected body operation parameter count of zero.");

                Serializer serializer = new Serializer(requestInfo);
                serializer.WriteBodyOperationParameters(qc.BodyOperationParameters, requestMessage);

                // pass in the request stream so that request payload can be written to the http webrequest.
                return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state, requestMessage.CachedRequestStream));
            }

#if PORTABLELIB
            // Empty Memorystream will be set when posting null operation parameters
            return(string.CompareOrdinal(XmlConstants.HttpMethodPost, qc.HttpMethod) == 0
                ? new QueryResult(source, method, this, requestMessage, requestInfo, callback, state, new ContentStream(new MemoryStream(), false /*isKnownMemoryStream*/))
                : new QueryResult(source, method, this, requestMessage, requestInfo, callback, state));
#else
            return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state));
#endif
        }
Ejemplo n.º 43
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));
 }
        /// <summary>
        /// The reason for adding this method is that we have seen a couple of asserts that we were not able to figure out why they are getting fired.
        /// So added this method which returns the current headers as well as cached headers as string and we display that in the assert message.
        /// </summary>
        /// <param name="currentHeaders">current header values.</param>
        /// <param name="cachedHeaders">cached header values.</param>
        /// <returns>returns a string which contains both current and cached header names.</returns>
        private static string GetHeaderValues(IEnumerable<KeyValuePair<string, string>> currentHeaders, HeaderCollection cachedHeaders)
        {
            StringBuilder sb = new StringBuilder();
            string separator = String.Empty;
            sb.Append("Current Headers: ");
            foreach (var header in currentHeaders)
            {
                sb.Append(separator);
                sb.Append(header.Key);
                separator = ", ";
            }

            sb.Append(". Headers fired in SendingRequest: ");
            separator = String.Empty;
            foreach (string name in cachedHeaders.HeaderNames)
            {
                sb.Append(separator);
                sb.Append(name);
                separator = ", ";
            }

            return sb.ToString();
        }
Ejemplo n.º 45
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);
 }
Ejemplo n.º 46
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;
        }
Ejemplo n.º 47
0
 /// <summary>
 /// Sets the value of the Accept header to the appropriate value for the current format.
 /// </summary>
 /// <param name="headers">The headers to modify.</param>
 internal void SetRequestAcceptHeader(HeaderCollection headers)
 {
     this.SetAcceptHeaderAndCharset(headers, this.ChooseMediaType(/*valueIfUsingAtom*/ MimeApplicationAtomOrXml, false));
 }
Ejemplo n.º 48
0
        /// <summary>
        /// Creates a ODataRequestMessage for batch request.
        /// </summary>
        /// <returns>Returns an instance of ODataRequestMessage for the batch request.</returns>
        private ODataRequestMessageWrapper CreateBatchRequest()
        {
            Uri requestUri = UriUtil.CreateUri(this.RequestInfo.BaseUriResolver.GetBaseUriWithSlash(), UriUtil.CreateUri("$batch", UriKind.Relative));
            HeaderCollection headers = new HeaderCollection();
            headers.SetRequestVersion(Util.ODataVersion4, this.RequestInfo.MaxProtocolVersionAsVersion);
            headers.SetHeader(XmlConstants.HttpContentType, CreateMultiPartMimeContentType());
            this.RequestInfo.Format.SetRequestAcceptHeaderForBatch(headers);

            return this.CreateTopLevelRequest(XmlConstants.HttpMethodPost, requestUri, headers, this.RequestInfo.HttpStack, null /*descriptor*/);
        }
Ejemplo n.º 49
0
 private static BuildingRequestEventArgs SetupTest(string method, Uri uri, HeaderCollection headers)
 {
     return new BuildingRequestEventArgs(method, uri, headers, null, HttpStack.Auto);
 }
Ejemplo n.º 50
0
        /// <summary>
        /// process the batch response
        /// </summary>
        /// <returns>an instance of the DataServiceResponse, containing individual operation responses for this batch request.</returns>
        private DataServiceResponse HandleBatchResponse()
        {
            bool batchMessageReaderOwned = true;

            try
            {
                if ((this.batchResponseMessage == null) || (this.batchResponseMessage.StatusCode == (int)HttpStatusCode.NoContent))
                {   // we always expect a response to our batch POST request
                    throw Error.InvalidOperation(Strings.Batch_ExpectedResponse(1));
                }

                Func<Stream> getResponseStream = () => this.ResponseStream;

                // We are not going to use the responseVersion returned from this call, as the $batch request itself doesn't apply versioning
                // of the responses on the root level. The responses are versioned on the part level. (Note that the version on the $batch level 
                // is actually used to version the batch itself, but we for now we only recognize a single version so to keep it backward compatible
                // we don't check this here. Also note that the HandleResponse method will verify that we can support the version, that is it's
                // lower than the highest version we understand).
                Version responseVersion;
                BaseSaveResult.HandleResponse(
                    this.RequestInfo,
                    (HttpStatusCode)this.batchResponseMessage.StatusCode,                      // statusCode
                    this.batchResponseMessage.GetHeader(XmlConstants.HttpODataVersion),  // responseVersion
                    getResponseStream,                                                  // getResponseStream
                    true,                                                               // throwOnFailure
                    out responseVersion);

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

                // Create the message and the message reader.
                this.batchResponseMessage = new HttpWebResponseMessage(new HeaderCollection(this.batchResponseMessage), this.batchResponseMessage.StatusCode, getResponseStream);
                ODataMessageReaderSettings messageReaderSettings = this.RequestInfo.GetDeserializationInfo(/*mergeOption*/ null).ReadHelper.CreateSettings();

                // No need to pass in any model to the batch reader.
                this.batchMessageReader = new ODataMessageReader(this.batchResponseMessage, messageReaderSettings);
                ODataBatchReader batchReader;
                try
                {
                    batchReader = this.batchMessageReader.CreateODataBatchReader();
                }
                catch (ODataContentTypeException contentTypeException)
                {
                    string mime;
                    Encoding encoding;
                    Exception inner = contentTypeException;
                    ContentTypeUtil.ReadContentType(this.batchResponseMessage.GetHeader(XmlConstants.HttpContentType), out mime, out encoding);
                    if (String.Equals(XmlConstants.MimeTextPlain, mime))
                    {
                        inner = GetResponseText(
                            this.batchResponseMessage.GetStream,
                            (HttpStatusCode)this.batchResponseMessage.StatusCode);
                    }

                    throw Error.InvalidOperation(Strings.Batch_ExpectedContentType(this.batchResponseMessage.GetHeader(XmlConstants.HttpContentType)), inner);
                }

                DataServiceResponse response = this.HandleBatchResponseInternal(batchReader);

                // In case of successful processing of at least the beginning of the batch, the message reader is owned by the returned response
                // (or rather by the IEnumerable of operation responses inside it).
                // It will be disposed once the operation responses are enumerated (since the IEnumerator should be disposed once used).
                // In that case we must NOT dispose it here, since that enumeration can exist long after we return from this method.
                batchMessageReaderOwned = false;

                return response;
            }
            catch (DataServiceRequestException)
            {
                throw;
            }
            catch (InvalidOperationException ex)
            {
                HeaderCollection headers = new HeaderCollection(this.batchResponseMessage);
                int statusCode = this.batchResponseMessage == null ? (int)HttpStatusCode.InternalServerError : (int)this.batchResponseMessage.StatusCode;
                DataServiceResponse response = new DataServiceResponse(headers, statusCode, new OperationResponse[0], this.IsBatchRequest);
                throw new DataServiceRequestException(Strings.DataServiceException_GeneralError, ex, response);
            }
            finally
            {
                if (batchMessageReaderOwned)
                {
                    Util.Dispose(ref this.batchMessageReader);
                }
            }
        }
            internal List<Stream> GetChangeStream()
            {
                List<Stream> stream = new List<Stream>();
                HeaderCollection headers = new HeaderCollection();
                headers.SetHeader("Content-Type", "application/atom+xml;odata.metadata=minimal");
                for (int i = 0; i < this.ChangedEntries.Count; ++i)
                {
                    ODataRequestMessageWrapper requestMessage = ODataRequestMessageWrapper.CreateRequestMessageWrapper(
                        new BuildingRequestEventArgs("GET", new Uri("http://service.svc/randomuri"), headers, null, HttpStack.Auto),
                        this.RequestInfo);
                    this.CreateChangeData(i, requestMessage);
                    stream.Add(requestMessage.CachedRequestStream.Stream);
                }

                return stream;
            }
Ejemplo n.º 52
0
            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="statusCode">The status code of the response.</param>
            /// <param name="headers">The response headers.</param>
            /// <param name="contentStream">An in-memory copy of the response stream.</param>
            public CurrentOperationResponse(HttpStatusCode statusCode, IEnumerable<KeyValuePair<string, string>> headers, MemoryStream contentStream)
            {
                Debug.Assert(headers != null, "headers != null");
                Debug.Assert(contentStream != null, "contentStream != null");
                Debug.Assert(contentStream.Position == 0, "The stream should have been reset to the begining.");

                this.statusCode = statusCode;
                this.contentStream = contentStream;

                this.headers = new HeaderCollection();
                foreach (KeyValuePair<string, string> operationResponseHeader in headers)
                {
                    this.headers.SetHeader(operationResponseHeader.Key, operationResponseHeader.Value);
                }
            }
Ejemplo n.º 53
0
 /// <summary>
 /// Adds the required headers for the url convention.
 /// </summary>
 /// <param name="requestHeaders">The request headers to add to.</param>
 internal void AddRequiredHeaders(HeaderCollection requestHeaders)
 {
     this.urlConvention.AddRequiredHeaders(requestHeaders);
 }
Ejemplo n.º 54
0
        public void PostTunnelingDeleteRequestShouldNotHaveContentTypeHeader()
        {
            bool previousPostTunnelingValue = ctx.UsePostTunneling;
            ctx.UsePostTunneling = true;
            HeaderCollection headersCollection = new HeaderCollection();
            var descriptor = new EntityDescriptor(this.clientEdmModel) { ServerTypeName = this.serverTypeName, Entity = new Customer() };
            var buildingRequestArgs = new BuildingRequestEventArgs("DELETE", new Uri("http://localhost/fakeService.svc/"), headersCollection, descriptor, HttpStack.Auto);

            ctx.Configurations.RequestPipeline.OnMessageCreating = (args) =>
            {
                buildingRequestArgs.Headers.Keys.Should().NotContain(XmlConstants.HttpContentType);
                return new HttpWebRequestMessage(args);
            };

            testSubject.CreateRequestMessage(buildingRequestArgs);

            // undoing change so this is applicable only for this test.
            ctx.UsePostTunneling = previousPostTunnelingValue;
            ctx.Configurations.RequestPipeline.OnMessageCreating = null;
        }
Ejemplo n.º 55
0
 /// <summary>Initializes a new instance of the <see cref="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;
 }
Ejemplo n.º 56
0
 public void KeyAsSegmentConventionShouldAddHeader()
 {
     var headers = new HeaderCollection();
     this.keyAsSegmentConvention.AddRequiredHeaders(headers);
     headers.UnderlyingDictionary.Should().ContainKey(UrlConventionsConstants.UrlConventionHeaderName, "KeyAsSegment");
 }
Ejemplo n.º 57
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, this.useRelativeUri));
        }