/// <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); }
/// <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; } }
/// <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*/)); }
/// <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> /// 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); }
/// <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 }
/// <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> /// 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; }
/// <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*/); }
/// <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> /// 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> /// 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> /// 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); }
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"); }
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"); }