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*");
 }
Beispiel #2
0
        /// <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(context != null, "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 ||
                string.CompareOrdinal(XmlConstants.HttpMethodDelete, qc.HttpMethod) == 0,
                "Only get, post and delete 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, context.EntityParameterSendOption);
                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));
            }

            return(new QueryResult(source, method, this, requestMessage, requestInfo, callback, state));
        }
Beispiel #3
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*/));
        }
Beispiel #4
0
        /// <summary>
        /// Sets the content and the headers of the media resource request
        /// </summary>
        /// <param name="headers">The header collection to setup.</param>
        /// <param name="saveStream">DataServiceSaveStream instance containing all information about the stream.</param>
        /// <param name="etag">ETag header value to be set. If passed null, etag header is not set.</param>
        /// <remarks>This only works with the V2 MR support (SetSaveStream), this will not setup
        /// the request for V1 property based MRs.</remarks>
        private void SetupMediaResourceRequest(HeaderCollection headers, DataServiceSaveStream saveStream, string etag)
        {
            // Get the write stream for this MR
            this.mediaResourceRequestStream = saveStream.Stream;

            // Copy over headers for the request, except the accept header
            headers.SetHeaders(saveStream.Args.Headers.Where(h => !string.Equals(h.Key, XmlConstants.HttpRequestAccept, StringComparison.OrdinalIgnoreCase)));

            if (etag != null)
            {
                headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag);
            }

            // Do NOT set the ContentLength since we don't know if the stream even supports reporting its length
        }
Beispiel #5
0
        /// <summary>operation with exception</summary>
        /// <param name="e">exception object</param>
        /// <param name="response">response object</param>
        private void HandleOperationException(InvalidOperationException e, IODataResponseMessage response)
        {
            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));

            Descriptor       current    = this.ChangedEntries[this.entryIndex];
            HeaderCollection headers    = null;
            HttpStatusCode   statusCode = HttpStatusCode.InternalServerError;

            Version responseVersion = null;

            if (response != null)
            {
                headers    = new HeaderCollection(response);
                statusCode = (HttpStatusCode)response.StatusCode;

                this.HandleOperationResponseHeaders(statusCode, headers);
                e = BaseSaveResult.HandleResponse(
                    this.RequestInfo,
                    statusCode,
                    response.GetHeader(XmlConstants.HttpODataVersion),
                    response.GetStream,
                    false /*throwOnFailure*/,
                    out responseVersion);
            }
            else
            {
                headers = new HeaderCollection();
                headers.SetHeader(XmlConstants.HttpContentType, XmlConstants.MimeTextPlain);

                // In V2 we used to merge individual responses from a call to SaveChanges() into a single batch response payload and then process that.
                // When we encounter an exception at this point in V2, we used to write the exception to the batch response payload and later on when we
                // process through the batch response, we create a DataServiceClientException for each failed operation.
                // For backcompat reason, we will always convert the exception type to DataServiceClientException here.
                Debug.Assert(e != null, "e != null");
                if (e.GetType() != typeof(DataServiceClientException))
                {
                    e = new DataServiceClientException(e.Message, e);
                }
            }

            // For error scenarios, we never invoke the ReadingEntity event.
            this.cachedResponses.Add(new CachedResponse(current, headers, statusCode, responseVersion, null, e));
            this.perRequest = null;
            this.CheckContinueOnError();
        }
Beispiel #6
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*/);
        }
            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;
            }
Beispiel #8
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);
        }
Beispiel #9
0
        /// <summary>
        /// Apply the response preferences for the client.
        /// </summary>
        /// <param name="headers">Headers to which preferences will be added.</param>
        /// <param name="method">HTTP method.</param>
        /// <param name="responsePreference">Response preference.</param>
        /// <param name="requestVersion">Request version so far for the request. The method may modify it.</param>
        protected static void ApplyPreferences(HeaderCollection headers, string method, DataServiceResponsePreference responsePreference, ref Version requestVersion)
        {
            // The AddAndUpdateResponsePreference only applies to POST/PUT/PATCH requests
            if (string.CompareOrdinal(XmlConstants.HttpMethodPost, method) != 0 &&
                string.CompareOrdinal(XmlConstants.HttpMethodPut, method) != 0 &&
                string.CompareOrdinal(XmlConstants.HttpMethodPatch, method) != 0)
            {
                return;
            }

            string preferHeaderValue = WebUtil.GetPreferHeaderAndRequestVersion(responsePreference, ref requestVersion);
            if (preferHeaderValue != null)
            {
                headers.SetHeader(XmlConstants.HttpPrefer, preferHeaderValue);
            }
        }
Beispiel #10
0
        /// <summary>operation with exception</summary>
        /// <param name="e">exception object</param>
        /// <param name="response">response object</param>
        private void HandleOperationException(InvalidOperationException e, IODataResponseMessage response)
        {
            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()));

            Descriptor current = this.ChangedEntries[this.entryIndex];
            HeaderCollection headers = null;
            HttpStatusCode statusCode = HttpStatusCode.InternalServerError;

            Version responseVersion = null;
            if (null != response)
            {
                headers = new HeaderCollection(response);
                statusCode = (HttpStatusCode)response.StatusCode;

                this.HandleOperationResponseHeaders(statusCode, headers);
                e = BaseSaveResult.HandleResponse(
                    this.RequestInfo,
                    statusCode,
                    response.GetHeader(XmlConstants.HttpODataVersion),
                    response.GetStream,
                    false/*throwOnFailure*/,
                    out responseVersion);
            }
            else
            {
                headers = new HeaderCollection();
                headers.SetHeader(XmlConstants.HttpContentType, XmlConstants.MimeTextPlain);

                // In V2 we used to merge individual responses from a call to SaveChanges() into a single batch response payload and then process that.
                // When we encounter an exception at this point in V2, we used to write the exception to the batch response payload and later on when we
                // process through the batch response, we create a DataServiceClientException for each failed operation.
                // For backcompat reason, we will always convert the exception type to DataServiceClientException here.
                Debug.Assert(e != null, "e != null");
                if (e.GetType() != typeof(DataServiceClientException))
                {
                    e = new DataServiceClientException(e.Message, e);
                }
            }

            // For error scenarios, we never invoke the ReadingEntity event.
            this.cachedResponses.Add(new CachedResponse(current, headers, statusCode, responseVersion, null, e));
            this.perRequest = null;
            this.CheckContinueOnError();
        }
Beispiel #11
0
        /// <summary>
        /// Sets the content and the headers of the media resource request
        /// </summary>
        /// <param name="headers">The header collection to setup.</param>
        /// <param name="saveStream">DataServiceSaveStream instance containing all information about the stream.</param>
        /// <param name="etag">ETag header value to be set. If passed null, etag header is not set.</param>
        /// <remarks>This only works with the V2 MR support (SetSaveStream), this will not setup
        /// the request for V1 property based MRs.</remarks>
        private void SetupMediaResourceRequest(HeaderCollection headers, DataServiceSaveStream saveStream, string etag)
        {
            // Get the write stream for this MR
            this.mediaResourceRequestStream = saveStream.Stream;

            // Copy over headers for the request, except the accept header
            headers.SetHeaders(saveStream.Args.Headers.Where(h => !string.Equals(h.Key, XmlConstants.HttpRequestAccept, StringComparison.OrdinalIgnoreCase)));

            if (etag != null)
            {
                headers.SetHeader(XmlConstants.HttpRequestIfMatch, etag);
            }

            // Do NOT set the ContentLength since we don't know if the stream even supports reporting its length
        }
Beispiel #12
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;

#if PORTABLELIB
                    // Win8 doesn't allow accessing the buffer, so the constructor we normally use doesn't exist
                    this.mediaResourceRequestStream = new MemoryStream(buffer, 0, buffer.Length, false);
#else
                    // 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);
#endif
                }

                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;
        }
Beispiel #13
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);
        }
 public void SetRequestVersionShouldSetCorrectValueWhenHeaderCollectionContainsODataVersionGreaterThan40()
 {
     var headers = new HeaderCollection();
     headers.SetHeader("OData-Version", "5.0.0");
     headers.SetHeader("OData-MaxVersion", "5.0.0");
     headers.SetRequestVersion(new Version(4, 0, 0, 1), new Version(5, 0, 0, 1));
     headers.GetHeader("OData-Version").Should().Be("5.0.0");
     headers.GetHeader("OData-MaxVersion").Should().Be("5.0");
 }
        private void TestSetRequestHeader(Action<DataServiceClientFormat> configureFormat, Action<DataServiceClientFormat, HeaderCollection> setRequestHeader, string expectedHeaderToSet, string initialHeaderValue, string expectedValueAfterSet)
        {
            var headers = new HeaderCollection();

            configureFormat(this.v3TestSubject);

            headers.SetHeader(expectedHeaderToSet, initialHeaderValue);

            // Verify header has the expected initial value. This ensures that SetHeader above actually what we expect, and didn't use a default value or ignore the set request.
            headers.GetHeader(expectedHeaderToSet).Should().Be(initialHeaderValue);

            // Try to set header to new value and verify
            setRequestHeader(this.v3TestSubject, headers);
            headers.GetHeader(expectedHeaderToSet).Should().Be(expectedValueAfterSet);

            if (expectedHeaderToSet == "Content-Type")
            {
                if (!this.v3TestSubject.UsingAtom || expectedValueAfterSet == TestConstants.MimeApplicationJsonODataMinimalMetadata)
                {
                    headers.GetHeader("OData-Version").Should().Be("4.0");
                }
                else
                {
                    headers.GetHeader("OData-Version").Should().BeNull();
                }
            }

            if (expectedHeaderToSet == "Accept")
            {
                headers.GetHeader("Accept-Charset").Should().Be("UTF-8");
            }
        }
        public void SerializeEnity_EnumProperty()
        {
            MyEntity1 myEntity1 = new MyEntity1()
            {
                ID = 2,
                MyColorValue = MyColor.Yellow,
                MyFlagsColorValue = MyFlagsColor.Blue,
                ComplexValue1Value = new ComplexValue1() { MyColorValue = MyColor.Green, MyFlagsColorValue = MyFlagsColor.Red },
                MyFlagsColorCollection1 = new List<MyFlagsColor>() { MyFlagsColor.Blue, MyFlagsColor.Red, MyFlagsColor.Red },
                MyColorCollection = new List<MyColor?>()
            };

            DataServiceContext dataServiceContext = new DataServiceContext(new Uri("http://www.odata.org/service.svc"));
            dataServiceContext.EnableAtom = true;
            dataServiceContext.Format.UseAtom();
            dataServiceContext.AttachTo("MyEntitySet1", myEntity1);

            var requestInfo = new RequestInfo(dataServiceContext);
            var serializer = new Serializer(requestInfo);
            var headers = new HeaderCollection();
            headers.SetHeader("Content-Type", "application/atom+xml;odata.metadata=minimal");
            var clientModel = new ClientEdmModel(ODataProtocolVersion.V4);
            var entityDescriptor = new EntityDescriptor(clientModel);
            entityDescriptor.State = EntityStates.Added;
            entityDescriptor.Entity = myEntity1;
            var requestMessageArgs = new BuildingRequestEventArgs("POST", new Uri("http://www.foo.com/Northwind"), headers, entityDescriptor, HttpStack.Auto);
            var linkDescriptors = new LinkDescriptor[] { };
            var odataRequestMessageWrapper = ODataRequestMessageWrapper.CreateRequestMessageWrapper(requestMessageArgs, requestInfo);

            serializer.WriteEntry(entityDescriptor, linkDescriptors, odataRequestMessageWrapper);

            // read result:
            MemoryStream stream = (MemoryStream)(odataRequestMessageWrapper.CachedRequestStream.Stream);
            stream.Position = 0;

            string payload = (new StreamReader(stream)).ReadToEnd();
            payload = Regex.Replace(payload, "<updated>[^<]*</updated>", "");
            payload.Should().Be(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?><entry xmlns=\"http://www.w3.org/2005/Atom\" " +
                    "xmlns:d=\"http://docs.oasis-open.org/odata/ns/data\" xmlns:m=\"http://docs.oasis-open.org/odata/ns/metadata\" " +
                    "xmlns:georss=\"http://www.georss.org/georss\" xmlns:gml=\"http://www.opengis.net/gml\">" +
                    "<id />" +
                    "<title />" +
                //"<updated>2013-11-11T19:29:54Z</updated>" +
                    "<author><name /></author>" +
                    "<content type=\"application/xml\">" +
                        "<m:properties>" +
                            "<d:ComplexValue1Value>" +
                                "<d:MyColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyColor\">Green</d:MyColorValue>" +
                                "<d:MyFlagsColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyFlagsColor\">Red</d:MyFlagsColorValue>" +
                                "<d:StringValue m:null=\"true\" />" +
                            "</d:ComplexValue1Value>" +
                            "<d:ID m:type=\"Int64\">2</d:ID>" +
                            "<d:MyColorCollection />" +
                            "<d:MyColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyColor\">Yellow</d:MyColorValue>" +
                            "<d:MyFlagsColorCollection1>" +
                                "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Blue</m:element>" +
                                "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Red</m:element>" +
                                "<m:element m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests+MyFlagsColor\">Red</m:element>" +
                            "</d:MyFlagsColorCollection1>" +
                            "<d:MyFlagsColorValue m:type=\"#AstoriaUnitTests.TDD.Tests.Client.ODataWriterWrapperUnitTests_MyFlagsColor\">Blue</d:MyFlagsColorValue>" +
                        "</m:properties>" +
                    "</content>" +
                    "</entry>");
        }