/// <summary>
        /// Sets the request's content type header.
        /// </summary>
        /// <param name="headers">Dictionary of request headers.</param>
        /// <param name="mediaType">content type</param>
        private void SetRequestContentTypeHeader(HeaderCollection headers, string mediaType)
        {
            if (mediaType == MimeApplicationJsonODataLight)
            {
                // set the request version to 4.0
                headers.SetRequestVersion(Util.ODataVersion4, this.context.MaxProtocolVersionAsVersion);
            }

            headers.SetHeaderIfUnset(XmlConstants.HttpContentType, mediaType);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Synchronously executes the query and returns the value.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="parseQueryResultFunc">A function to process the query result.</param>
        /// <returns>The query result</returns>
        internal TElement GetValue <TElement>(DataServiceContext context, Func <QueryResult, TElement> parseQueryResultFunc)
        {
            Debug.Assert(context != null, "context is null");
            QueryComponents queryComponents = this.QueryComponents(context.Model);
            Version         requestVersion  = queryComponents.Version;

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

            Uri requestUri = queryComponents.Uri;
            DataServiceRequest <TElement> serviceRequest = new DataServiceRequest <TElement>(requestUri, queryComponents, 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*/);

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

            try
            {
                queryResult.ExecuteQuery();

                if (HttpStatusCode.NoContent != queryResult.StatusCode)
                {
                    TElement parsedResult = parseQueryResultFunc(queryResult);

                    return(parsedResult);
                }
                else
                {
                    throw new DataServiceQueryException(Strings.DataServiceRequest_FailGetValue, queryResult.Failure);
                }
            }
            catch (InvalidOperationException ex)
            {
                QueryOperationResponse operationResponse;
                operationResponse = queryResult.GetResponse <TElement>(MaterializeAtom.EmptyResults);
                if (operationResponse != null)
                {
                    operationResponse.Error = ex;
                    throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse);
                }

                throw;
            }
        }
Ejemplo n.º 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*/));
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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.º 6
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(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 ||
                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));
            }

#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.º 7
0
        /// <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;
            }
        }
Ejemplo n.º 8
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.º 9
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.º 10
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);
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
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;
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Sets the request's content type header.
        /// </summary>
        /// <param name="headers">Dictionary of request headers.</param>
        /// <param name="mediaType">content type</param>
        private void SetRequestContentTypeHeader(HeaderCollection headers, string mediaType)
        {
            if (mediaType == MimeApplicationJsonODataLight)
            {
                // set the request version to 4.0
                headers.SetRequestVersion(Util.ODataVersion4, this.context.MaxProtocolVersionAsVersion);
            }

            headers.SetHeaderIfUnset(XmlConstants.HttpContentType, mediaType);
        }
Ejemplo n.º 14
0
 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");
 }
Ejemplo n.º 15
0
 public void SetRequestVersionShouldSetCorrectValue()
 {
     var headers = new HeaderCollection();
     headers.SetRequestVersion(new Version(4, 0, 0, 1), new Version(5, 0, 0, 1));
     headers.GetHeader("OData-Version").Should().Be("4.0");
     headers.GetHeader("OData-MaxVersion").Should().Be("5.0");
 }