Пример #1
0
        /// <summary>
        /// copy the response data
        /// </summary>
        /// <param name="response">response object</param>
        private void HandleOperationResponseData(IODataResponseMessage response)
        {
            Debug.Assert(response != null, "response != null");

            using (Stream stream = response.GetStream())
            {
                if (stream != null)
                {
                    // we need to check for whether the incoming stream was data or not. Hence we need to copy it to a temporary memory stream
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        if (WebUtil.CopyStream(stream, memoryStream, ref this.buildBatchBuffer) != 0)
                        {
                            // set the memory stream position to zero again.
                            memoryStream.Position = 0;
                            this.HandleOperationResponseData(response, memoryStream);
                        }
                        else
                        {
                            this.HandleOperationResponseData(response, null);
                        }
                    }
                }
            }
        }
Пример #2
0
        public Task SerializeToStreamAsync(Stream stream)
        {
            // how to dispose it?
            IODataResponseMessage responseMessage = ODataMessageWrapperHelper.Create(stream, Headers, _requestContainer);

            return(WriteToResponseMessageAsync(responseMessage));
        }
        public async Task WriteMessageAsync_AsynchronouslyWritesResponseMessage()
        {
            // Arrange
            HeaderDictionary headers = new HeaderDictionary
            {
                { "Content-Type", $"multipart/mixed;charset=utf-8;boundary={Guid.NewGuid()}" },
            };
            MemoryStream          ms            = new MemoryStream();
            IODataResponseMessage odataResponse = ODataMessageWrapperHelper.Create(ms, headers);

            HeaderDictionary responseHeaders = new HeaderDictionary
            {
                { "customHeader", "bar" }
            };
            HttpResponse response = CreateResponse("example content", responseHeaders, "text/example");

            // Act
            ODataBatchWriter batchWriter = await new ODataMessageWriter(odataResponse).CreateODataBatchWriterAsync();
            await batchWriter.WriteStartBatchAsync();

            await ODataBatchResponseItem.WriteMessageAsync(batchWriter, response.HttpContext);

            await batchWriter.WriteEndBatchAsync();

            ms.Position = 0;
            string result = new StreamReader(ms).ReadToEnd();

            // Assert
            Assert.Contains("example content", result);
            Assert.Contains("text/example", result);
            Assert.Contains("customHeader", result);
            Assert.Contains("bar", result);
        }
Пример #4
0
        public async Task WriteMessageAsync_WritesResponseMessage()
        {
            MemoryStream ms      = new MemoryStream();
            HttpContent  content = new StringContent(String.Empty, Encoding.UTF8, "multipart/mixed");

            content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", Guid.NewGuid().ToString()));
            IODataResponseMessage odataResponse = ODataMessageWrapperHelper.Create(ms, content.Headers);
            var batchWriter = new ODataMessageWriter(odataResponse).CreateODataBatchWriter();
            HttpResponseMessage response = new HttpResponseMessage()
            {
                Content = new StringContent("example content", Encoding.UTF8, "text/example")
            };

            response.Headers.Add("customHeader", "bar");

            batchWriter.WriteStartBatch();
            await ODataBatchResponseItem.WriteMessageAsync(batchWriter, response, CancellationToken.None);

            batchWriter.WriteEndBatch();

            ms.Position = 0;
            string result = new StreamReader(ms).ReadToEnd();

            Assert.Contains("example content", result);
            Assert.Contains("text/example", result);
            Assert.Contains("customHeader", result);
            Assert.Contains("bar", result);
        }
        public void WriteMessageAsync_SynchronousResponseContainsContentId_IfHasContentIdInRequestChangeSet()
        {
            // Arrange
            HeaderDictionary headers = new HeaderDictionary
            {
                { "Content-Type", $"multipart/mixed;charset=utf-8;boundary={Guid.NewGuid()}" },
            };

            MemoryStream          ms            = new MemoryStream();
            IODataResponseMessage odataResponse = ODataMessageWrapperHelper.Create(ms, headers);

            string       contentId    = Guid.NewGuid().ToString();
            HttpResponse httpResponse = CreateResponse("any", new HeaderDictionary(), "text/example;charset=utf-8");

            httpResponse.HttpContext.Request.SetODataContentId(contentId);

            // Act
            ODataBatchWriter batchWriter = new ODataMessageWriter(odataResponse).CreateODataBatchWriter();

            batchWriter.WriteStartBatch();
            batchWriter.WriteStartChangeset();

            // Assert
            Action         test      = () => ODataBatchResponseItem.WriteMessageAsync(batchWriter, httpResponse.HttpContext).Wait();
            ODataException exception = ExceptionAssert.Throws <ODataException>(test);

            Assert.Equal("An asynchronous operation was called on a synchronous batch writer. Calls on a batch writer instance must be either all synchronous or all asynchronous.",
                         exception.Message);
        }
        public void WriteMessage_SynchronouslyWritesResponseMessage_Throws()
        {
            HeaderDictionary headers = new HeaderDictionary
            {
                { "Content-Type", $"multipart/mixed;charset=utf-8;boundary={Guid.NewGuid()}" },
            };

            MemoryStream          ms            = new MemoryStream();
            IODataResponseMessage odataResponse = ODataMessageWrapperHelper.Create(ms, headers);

            HeaderDictionary responseHeaders = new HeaderDictionary
            {
                { "customHeader", "bar" }
            };
            HttpResponse response = CreateResponse("example content", responseHeaders, "text/example");

            // Act
            ODataBatchWriter batchWriter = new ODataMessageWriter(odataResponse).CreateODataBatchWriter();

            batchWriter.WriteStartBatch();

            // Assert
            Action         test      = () => ODataBatchResponseItem.WriteMessageAsync(batchWriter, response.HttpContext).Wait();
            ODataException exception = ExceptionAssert.Throws <ODataException>(test);

            Assert.Equal("An asynchronous operation was called on a synchronous batch writer. Calls on a batch writer instance must be either all synchronous or all asynchronous.",
                         exception.Message);
        }
Пример #7
0
        internal static IODataResponseMessage PrepareResponseMessage(IWebApiRequestMessage internalRequest, IWebApiHeaders internalRequestHeaders, Func <IServiceProvider, ODataMessageWrapper> getODataMessageWrapper)
        {
            string preferHeader     = RequestPreferenceHelpers.GetRequestPreferHeader(internalRequestHeaders);
            string annotationFilter = null;
            string omitValues       = null;
            int?   maxPageSize      = null;

            if (!String.IsNullOrEmpty(preferHeader))
            {
                ODataMessageWrapper messageWrapper = getODataMessageWrapper(null);
                messageWrapper.SetHeader(RequestPreferenceHelpers.PreferHeaderName, preferHeader);
                annotationFilter = messageWrapper.PreferHeader().AnnotationFilter;
                omitValues       = messageWrapper.PreferHeader().OmitValues;
                maxPageSize      = messageWrapper.PreferHeader().MaxPageSize;
            }

            IODataResponseMessage responseMessage = getODataMessageWrapper(internalRequest.RequestContainer);

            if (annotationFilter != null)
            {
                responseMessage.PreferenceAppliedHeader().AnnotationFilter = annotationFilter;
            }

            if (omitValues != null)
            {
                responseMessage.PreferenceAppliedHeader().OmitValues = omitValues;
            }

            if (maxPageSize != null)
            {
                responseMessage.PreferenceAppliedHeader().MaxPageSize = maxPageSize;
            }

            return(responseMessage);
        }
Пример #8
0
        public async Task WriteMessageAsync_ResponseContainsContentId_IfHasContentIdInRequestChangeSet()
        {
            MemoryStream ms      = new MemoryStream();
            HttpContent  content = new StringContent(String.Empty, Encoding.UTF8, "multipart/mixed");

            content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", Guid.NewGuid().ToString()));
            IODataResponseMessage odataResponse = ODataMessageWrapperHelper.Create(ms, content.Headers);
            var batchWriter = new ODataMessageWriter(odataResponse).CreateODataBatchWriter();
            HttpResponseMessage response = new HttpResponseMessage
            {
                Content = new StringContent("any", Encoding.UTF8, "text/example")
            };
            var request   = new HttpRequestMessage();
            var contentId = Guid.NewGuid().ToString();

            request.SetODataContentId(contentId);
            response.RequestMessage = request;

            batchWriter.WriteStartBatch();
            batchWriter.WriteStartChangeset();
            await ODataBatchResponseItem.WriteMessageAsync(batchWriter, response, CancellationToken.None);

            batchWriter.WriteEndChangeset();
            batchWriter.WriteEndBatch();

            ms.Position = 0;
            string result = new StreamReader(ms).ReadToEnd();

            Assert.Contains("any", result);
            Assert.Contains("text/example", result);
            Assert.Contains("Content-ID", result);
            Assert.Contains(contentId, result);
        }
Пример #9
0
        private void ProcessUpsertEntity(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath)
        {
            if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity && !this.QueryContext.Target.IsReference)
            {
                Uri          parentUri     = this.QueryContext.Target.BuildContainerUri(this.ServiceRootUri);
                QueryContext parentContext = new QueryContext(this.ServiceRootUri, parentUri, this.DataSource.Model);

                if (parentContext.Target.IsEntitySet)
                {
                    // Update a entity under a entity set => Upsert

                    // TODO: Do we need to preserver the key value?
                    new CreateHandler(this, parentContext.QueryUri).Process(requestMessage, responseMessage);
                }
                else
                {
                    // Update Singleton or single value entity from null value.
                    var parent = parentContext.ResolveQuery(this.DataSource);

                    // TODO: It might not correct here, since the last segment could be type segment.
                    NavigationPropertySegment navSegment = (NavigationPropertySegment)odataPath.LastSegment;
                    var targetObject = Utility.CreateResource(this.QueryContext.Target.Type);
                    parent.GetType().GetProperty(navSegment.NavigationProperty.Name).SetValue(parent, targetObject, null);

                    ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, true);
                }
            }
            else
            {
                throw Utility.BuildException(HttpStatusCode.NotFound);
            }
        }
Пример #10
0
        /// <summary>
        /// Constructs an internal wrapper around the <paramref name="responseMessage"/>
        /// that isolates the internal implementation of the ODataLib from the interface.
        /// </summary>
        /// <param name="responseMessage">The response message to wrap.</param>
        internal ODataResponseMessage(IODataResponseMessage responseMessage)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(responseMessage != null, "responseMessage != null");

            this.responseMessage = responseMessage;
        }
Пример #11
0
        public void ResponseMessageHeaderTest()
        {
            const bool useMimeWriterAsListener = true;

            Func <bool, bool, IODataResponseMessage>[] responseMessageFuncs = new Func <bool, bool, IODataResponseMessage>[]
            {
                (writing, mimeWriterAsListener) => CreateBatchOperationResponseMessage(writing, mimeWriterAsListener),
                (writing, notUsed) => new ODataResponseMessageWrapper(new TestResponseMessage(new TestStream()), writing, false)
            };

            // ODataMultipartMixedBatchWriter as listener
            this.CombinatorialEngineProvider.RunCombinations(
                new bool[] { true, false },
                responseMessageFuncs,
                (writing, func) =>
            {
                IODataResponseMessage responseMessage = func(writing, useMimeWriterAsListener);
                RunHeaderTest(() => responseMessage.Headers, writing, responseMessage.GetHeader, responseMessage.SetHeader, this.Assert, this.ExceptionVerifier);
            });

            // ODataJsonLightBatchWriter as listener
            this.CombinatorialEngineProvider.RunCombinations(
                new bool[] { true, false },
                responseMessageFuncs,
                (writing, func) =>
            {
                IODataResponseMessage responseMessage = func(writing, !useMimeWriterAsListener);
                RunHeaderTest(() => responseMessage.Headers, writing, responseMessage.GetHeader, responseMessage.SetHeader, this.Assert, this.ExceptionVerifier);
            });
        }
Пример #12
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            string    asyncToken = this.QueryContext.AsyncToken;
            AsyncTask asyncTask  = AsyncTask.GetTask(asyncToken);

            if (asyncTask == null)
            {
                // token is invalid or expired.
                throw Utility.BuildException(HttpStatusCode.NotFound);
            }
            else
            {
                if (!asyncTask.Ready)
                {
                    ResponseWriter.WriteAsyncPendingResponse(responseMessage, asyncToken);
                }
                else
                {
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentType, "application/http");
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentTransferEncoding, ServiceConstants.HttpHeaderValues.Binary);
                    using (var messageWriter = this.CreateMessageWriter(responseMessage))
                    {
                        var asyncWriter   = messageWriter.CreateODataAsynchronousWriter();
                        var innerResponse = asyncWriter.CreateResponseMessage();
                        asyncTask.Execute(innerResponse);
                    }
                }
            }
        }
Пример #13
0
 /// <summary>
 /// Internal constructor to instantiate an <see cref="ODataPreferenceHeader"/> from an <see cref="IODataResponseMessage"/>.
 /// </summary>
 /// <param name="responseMessage">The response message to get and set the "Preference-Applied" header.</param>
 internal ODataPreferenceHeader(IODataResponseMessage responseMessage)
 {
     DebugUtils.CheckNoExternalCallers();
     Debug.Assert(responseMessage != null, "responseMessage != null");
     this.message = new ODataResponseMessage(responseMessage, /*writing*/ true, /*disableMessageStreamDisposal*/ false, /*maxMessageSize*/ -1);
     this.preferenceHeaderName = PreferenceAppliedHeaderName;
 }
Пример #14
0
        /// <summary>
        /// Creates an <see cref="ODataMessageReader"/> for a given message and context using
        /// WCF DS client settings.
        /// </summary>
        /// <param name="responseMessage">The response message</param>
        /// <param name="responseInfo">The response context</param>
        /// <param name="payloadKind">Type of the message.</param>
        /// <returns>The message reader.</returns>
        protected static ODataMessageReader CreateODataMessageReader(IODataResponseMessage responseMessage, ResponseInfo responseInfo, ref ODataPayloadKind payloadKind)
        {
            ODataMessageReaderSettings settings = responseInfo.ReadHelper.CreateSettings();

            ODataMessageReader odataMessageReader = responseInfo.ReadHelper.CreateReader(responseMessage, settings);

            if (payloadKind == ODataPayloadKind.Unsupported)
            {
                var payloadKinds = odataMessageReader.DetectPayloadKind().ToList();

                if (payloadKinds.Count == 0)
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidResponsePayload(XmlConstants.DataWebNamespace));
                }

                // Pick the first payload kind detected by ODataLib and use that to parse the exception.
                // The only exception being payload with entity reference link(s). If one of the payload kinds
                // is reference links, then we need to give preference to reference link payloads.
                ODataPayloadKindDetectionResult detectionResult = payloadKinds.FirstOrDefault(k => k.PayloadKind == ODataPayloadKind.EntityReferenceLink || k.PayloadKind == ODataPayloadKind.EntityReferenceLinks);

                if (detectionResult == null)
                {
                    detectionResult = payloadKinds.First();
                }

                if (detectionResult.Format != ODataFormat.Json && detectionResult.Format != ODataFormat.RawValue)
                {
                    throw DSClient.Error.InvalidOperation(DSClient.Strings.AtomMaterializer_InvalidContentTypeEncountered(responseMessage.GetHeader(XmlConstants.HttpContentType)));
                }

                payloadKind = detectionResult.PayloadKind;
            }

            return(odataMessageReader);
        }
        /// <summary>
        /// Constructs a new instance of DataServiceTransportException.
        /// </summary>
        /// <param name="response">ResponseMessage from the exception so that the error payload can be read.</param>
        /// <param name="innerException">Actual exception that this exception is wrapping.</param>
        public DataServiceTransportException(IODataResponseMessage response, Exception innerException)
            : base(innerException.Message, innerException)
        {
            Util.CheckArgumentNull(innerException, "innerException");

            this.ResponseMessage = response;
        }
Пример #16
0
 internal static MaterializerEntry ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType)
 {
     ODataPayloadKind payloadKind = ODataPayloadKind.Entry;
     using (ODataMessageReader reader = ODataMaterializer.CreateODataMessageReader(message, responseInfo, false, ref payloadKind))
     {
         IEdmType orCreateEdmType = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion).GetOrCreateEdmType(expectedType);
         ODataReader reader2 = ODataMaterializer.CreateODataReader(reader, payloadKind, orCreateEdmType, responseInfo.MaxProtocolVersion);
         ODataFeedOrEntryReader reader3 = new ODataFeedOrEntryReader(reader2, responseInfo);
         ODataEntry currentEntry = null;
         bool flag = false;
         while (reader3.Read())
         {
             flag |= reader3.CurrentFeed != null;
             if (reader3.CurrentEntry != null)
             {
                 if (currentEntry != null)
                 {
                     throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_MultipleFound);
                 }
                 currentEntry = reader3.CurrentEntry;
             }
         }
         if (currentEntry == null)
         {
             if (flag)
             {
                 throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_NoneFound);
             }
             throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry);
         }
         return MaterializerEntry.GetEntry(currentEntry);
     }
 }
Пример #17
0
 internal override IEnumerable<ODataPayloadKind> DetectPayloadKind(IODataResponseMessage responseMessage, ODataPayloadKindDetectionInfo detectionInfo)
 {
     ExceptionUtils.CheckArgumentNotNull<IODataResponseMessage>(responseMessage, "responseMessage");
     ExceptionUtils.CheckArgumentNotNull<ODataPayloadKindDetectionInfo>(detectionInfo, "detectionInfo");
     Stream messageStream = ((ODataMessage) responseMessage).GetStream();
     return this.DetectPayloadKindImplementation(messageStream, true, true, detectionInfo);
 }
Пример #18
0
 protected virtual ODataMessageWriter CreateMessageWriter(IODataResponseMessage message)
 {
     return(new ODataMessageWriter(
                message,
                this.GetWriterSettings(),
                this.DataSource.Model));
 }
            internal void HandleResponse(object response)
            {
                ExceptionUtilities.CheckArgumentNotNull(response, "response");
                ExceptionUtilities.Assert(this.CurrentResponse == null, "Current response was not null");
                this.CurrentResponse = new HttpResponseData();

                HttpStatusCode statusCode;
                string         statusCodeString = null;

                IODataResponseMessage odataResponse = response as IODataResponseMessage;

                if (odataResponse != null)
                {
                    statusCodeString = odataResponse.StatusCode.ToString();
                }
                else
                {
                    HttpWebResponse httpWebRespnse = (HttpWebResponse)response;
                    statusCodeString = httpWebRespnse.StatusCode.ToString();
                }

                ExceptionUtilities.Assert(Enum.TryParse <HttpStatusCode>(statusCodeString, false, out statusCode), "Unrecognized status code '{0}'", statusCodeString);
                this.CurrentResponse.StatusCode = statusCode;
                PopulateHeaders(response, this.CurrentResponse.Headers);
            }
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            string asyncToken = this.QueryContext.AsyncToken;
            AsyncTask asyncTask = AsyncTask.GetTask(asyncToken);

            if (asyncTask == null)
            {
                // token is invalid or expired. 
                throw Utility.BuildException(HttpStatusCode.NotFound);
            }
            else
            {
                if (!asyncTask.Ready)
                {
                    ResponseWriter.WriteAsyncPendingResponse(responseMessage, asyncToken);
                }
                else
                {
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentType, "application/http");
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.ContentTransferEncoding, ServiceConstants.HttpHeaderValues.Binary);
                    using (var messageWriter = this.CreateMessageWriter(responseMessage))
                    {
                        var asyncWriter = messageWriter.CreateODataAsynchronousWriter();
                        var innerResponse = asyncWriter.CreateResponseMessage();
                        asyncTask.Execute(innerResponse);
                    }
                }
            }
        }
Пример #21
0
        private void ProcessUpdateEntityReference(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath)
        {
            // This is for change the reference in single-valued navigation property
            // PUT ~/Person(0)/Parent/$ref
            // {
            //     "@odata.context": "http://host/service/$metadata#$ref",
            //     "@odata.id": "Orders(10643)"
            // }

            if (this.HttpMethod == HttpMethod.PATCH)
            {
                throw Utility.BuildException(HttpStatusCode.MethodNotAllowed, "PATCH on a reference link is not supported.", null);
            }

            // Get the parent first
            var level = this.QueryContext.QueryPath.Count - 2;
            var parent = this.QueryContext.ResolveQuery(this.DataSource, level);

            var navigationPropertyName = ((NavigationPropertyLinkSegment)odataPath.LastSegment).NavigationProperty.Name;

            using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model))
            {
                var referenceLink = messageReader.ReadEntityReferenceLink();
                var queryContext = new QueryContext(this.ServiceRootUri, referenceLink.Url, this.DataSource.Model);
                var target = queryContext.ResolveQuery(this.DataSource);

                this.DataSource.UpdateProvider.UpdateLink(parent, navigationPropertyName, target);
                this.DataSource.UpdateProvider.SaveChanges();
            }

            ResponseWriter.WriteEmptyResponse(responseMessage);
        }
Пример #22
0
        private void ProcessDeleteLink(IODataResponseMessage responseMessage)
        {
            var segment      = (NavigationPropertyLinkSegment)this.QueryContext.QueryPath.LastSegment;
            var propertyName = segment.NavigationProperty.Name;
            var parent       = default(object);
            var target       = default(object);

            if (this.QueryContext.QueryEntityIdSegment == null)
            {
                // single-valued navigation property
                parent = this.QueryContext.ResolveQuery(this.DataSource, this.QueryContext.QueryPath.Count - 2);
            }
            else
            {
                // collection-valued navigation property
                var queryUri      = this.QueryContext.QueryUri;
                var parentUri     = queryUri.AbsoluteUri.Substring(0, queryUri.AbsoluteUri.Length - queryUri.Query.Length);
                var parentContext = new QueryContext(this.ServiceRootUri, new Uri(parentUri, UriKind.Absolute), this.DataSource.Model);
                parent = parentContext.ResolveQuery(this.DataSource, parentContext.QueryPath.Count - 2);
                target = this.QueryContext.ResolveQuery(this.DataSource);
            }

            this.DataSource.UpdateProvider.DeleteLink(parent, propertyName, target);
            this.DataSource.UpdateProvider.SaveChanges();

            ResponseWriter.WriteEmptyResponse(responseMessage);
        }
Пример #23
0
        /// <summary>
        /// Constructs an internal wrapper around the <paramref name="responseMessage"/>
        /// that isolates the internal implementation of the ODataLib from the interface.
        /// </summary>
        /// <param name="responseMessage">The response message to wrap.</param>
        internal ODataResponseMessage(IODataResponseMessage responseMessage)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(responseMessage != null, "responseMessage != null");

            this.responseMessage = responseMessage;
        }
Пример #24
0
        internal static MaterializerEntry ParseSingleEntityPayload(IODataResponseMessage message, ResponseInfo responseInfo, Type expectedType)
        {
            ODataPayloadKind payloadKind = ODataPayloadKind.Entry;

            using (ODataMessageReader reader = ODataMaterializer.CreateODataMessageReader(message, responseInfo, false, ref payloadKind))
            {
                IEdmType               orCreateEdmType = ClientEdmModel.GetModel(responseInfo.MaxProtocolVersion).GetOrCreateEdmType(expectedType);
                ODataReader            reader2         = ODataMaterializer.CreateODataReader(reader, payloadKind, orCreateEdmType, responseInfo.MaxProtocolVersion);
                ODataFeedOrEntryReader reader3         = new ODataFeedOrEntryReader(reader2, responseInfo);
                ODataEntry             currentEntry    = null;
                bool flag = false;
                while (reader3.Read())
                {
                    flag |= reader3.CurrentFeed != null;
                    if (reader3.CurrentEntry != null)
                    {
                        if (currentEntry != null)
                        {
                            throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_MultipleFound);
                        }
                        currentEntry = reader3.CurrentEntry;
                    }
                }
                if (currentEntry == null)
                {
                    if (flag)
                    {
                        throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_NoneFound);
                    }
                    throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomParser_SingleEntry_ExpectedFeedOrEntry);
                }
                return(MaterializerEntry.GetEntry(currentEntry));
            }
        }
Пример #25
0
        internal DataServiceStreamResponse Execute()
        {
            try
            {
                this.responseMessage = this.requestInfo.GetSyncronousResponse(this.requestMessage, true);
                Debug.Assert(this.responseMessage != null, "Can't set a null response.");
            }
            catch (Exception e)
            {
                this.HandleFailure(e);
                throw;
            }
            finally
            {
                this.SetCompleted();
                this.CompletedRequest();
            }

            if (null != this.Failure)
            {
                throw this.Failure;
            }

            return(this.End());
        }
Пример #26
0
        /// <summary>
        /// Constructs an internal wrapper around the <paramref name="responseMessage"/>
        /// that isolates the internal implementation of the ODataLib from the interface.
        /// </summary>
        /// <param name="responseMessage">The response message to wrap.</param>
        /// <param name="writing">true if the message is being written; false when it is read.</param>
        /// <param name="enableMessageStreamDisposal">true if the stream returned should be disposed calls.</param>
        /// <param name="maxMessageSize">The maximum size of the message in bytes (or a negative number if no maximum applies).</param>
        internal ODataResponseMessage(IODataResponseMessage responseMessage, bool writing, bool enableMessageStreamDisposal, long maxMessageSize)
            : base(writing, enableMessageStreamDisposal, maxMessageSize)
        {
            Debug.Assert(responseMessage != null, "responseMessage != null");

            this.responseMessage = responseMessage;
        }
 public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
 {
     responseMessage.SetStatusCode(HttpStatusCode.OK);
     using (var writer = this.CreateMessageWriter(responseMessage))
     {
         writer.WriteServiceDocument(this.GenerateServiceDocument());
     }
 }
Пример #28
0
        private void ProcessDelete(object target, IODataResponseMessage responseMessage)
        {
            this.DataSource.UpdateProvider.Delete(target);

            // Protocol 11.4.5 Delete an Entity
            // On successful completion of the delete, the response MUST be 204 No Content and contain an empty body.
            ResponseWriter.WriteEmptyResponse(responseMessage);
        }
        public static void InitClass(TestContext testContext)
        {
            RequestWithApplicationJson = new ODataRequestMessageSimulator();
            RequestWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN");

            ResponseWithApplicationJson = new ODataResponseMessageSimulator();
            ResponseWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN");
        }
        public static void InitClass(TestContext testContext)
        {
            RequestWithApplicationJson = new ODataRequestMessageSimulator();
            RequestWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN");

            ResponseWithApplicationJson = new ODataResponseMessageSimulator();
            ResponseWithApplicationJson.SetHeader(XmlConstants.HttpContentType, "aPPlicaTion/jSoN");
        }
Пример #31
0
 /// <summary>
 /// Initializes a new instance of <see cref="HeaderCollection"/>.
 /// </summary>
 /// <param name="responseMessage">The response message to pull the headers from.</param>
 internal HeaderCollection(IODataResponseMessage responseMessage)
     : this()
 {
     if (responseMessage != null)
     {
         this.SetHeaders(responseMessage.Headers);
     }
 }
Пример #32
0
        internal override IEnumerable <ODataPayloadKind> DetectPayloadKind(IODataResponseMessage responseMessage, ODataPayloadKindDetectionInfo detectionInfo)
        {
            ExceptionUtils.CheckArgumentNotNull <IODataResponseMessage>(responseMessage, "responseMessage");
            ExceptionUtils.CheckArgumentNotNull <ODataPayloadKindDetectionInfo>(detectionInfo, "detectionInfo");
            Stream messageStream = ((ODataMessage)responseMessage).GetStream();

            return(this.DetectPayloadKindImplementation(messageStream, true, true, detectionInfo));
        }
Пример #33
0
 private ODataAsynchronousWriter TestInit()
 {
     responseMessage = new InMemoryMessage {
         Stream = responseStream
     };
     messageWriter = new ODataMessageWriter(responseMessage);
     return(messageWriter.CreateODataAsynchronousWriter());
 }
Пример #34
0
        /// <summary>
        /// Constructs an internal wrapper around the <paramref name="responseMessage"/>
        /// that isolates the internal implementation of the ODataLib from the interface.
        /// </summary>
        /// <param name="responseMessage">The response message to wrap.</param>
        /// <param name="writing">true if the message is being written; false when it is read.</param>
        /// <param name="disableMessageStreamDisposal">true if the stream returned should ignore dispose calls.</param>
        /// <param name="maxMessageSize">The maximum size of the message in bytes (or a negative number if no maximum applies).</param>
        internal ODataResponseMessage(IODataResponseMessage responseMessage, bool writing, bool disableMessageStreamDisposal, long maxMessageSize)
            : base(writing, disableMessageStreamDisposal, maxMessageSize)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(responseMessage != null, "responseMessage != null");

            this.responseMessage = responseMessage;
        }
Пример #35
0
 /// <summary>
 /// Create a new feed generator
 /// </summary>
 /// <param name="requestMessage">The OData request message that was received</param>
 /// <param name="responseMessage">The OData response message to be populated by the generator</param>
 /// <param name="entityMap">The map to use to map RDF URIs to OData types and properties</param>
 /// <param name="baseUri">The base URI for the OData feed</param>
 /// <param name="messageWriterSettings">Additional settings to apply to the generated OData output</param>
 public ODataFeedGenerator(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, SparqlMap entityMap, string baseUri, ODataMessageWriterSettings messageWriterSettings)
 {
     _request = requestMessage;
     _response = responseMessage;
     _map = entityMap;
     _baseUri = baseUri;
     _writerSettings = messageWriterSettings;
 }
Пример #36
0
 /// <summary>
 /// Initializes a new instance of <see cref="HeaderCollection"/>.
 /// </summary>
 /// <param name="responseMessage">The response message to pull the headers from.</param>
 internal HeaderCollection(IODataResponseMessage responseMessage)
     : this()
 {
     if (responseMessage != null)
     {
         this.SetHeaders(responseMessage.Headers);
     }
 }
Пример #37
0
        /// <summary>
        /// Constructs an internal wrapper around the <paramref name="responseMessage"/>
        /// that isolates the internal implementation of the ODataLib from the interface.
        /// </summary>
        /// <param name="responseMessage">The response message to wrap.</param>
        /// <param name="writing">true if the message is being written; false when it is read.</param>
        /// <param name="disableMessageStreamDisposal">true if the stream returned should ignore dispose calls.</param>
        /// <param name="maxMessageSize">The maximum size of the message in bytes (or a negative number if no maximum applies).</param>
        internal ODataResponseMessage(IODataResponseMessage responseMessage, bool writing, bool disableMessageStreamDisposal, long maxMessageSize)
            : base(writing, disableMessageStreamDisposal, maxMessageSize)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(responseMessage != null, "responseMessage != null");

            this.responseMessage = responseMessage;
        }
Пример #38
0
 public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
 {
     responseMessage.SetStatusCode(HttpStatusCode.OK);
     using (var writer = this.CreateMessageWriter(responseMessage))
     {
         writer.WriteMetadataDocument();
     }
 }
Пример #39
0
 /// <summary>
 /// Applies headers in the dictionary to a response message.
 /// </summary>
 /// <param name="headers">The dictionary with the headers to apply.</param>
 /// <param name="responseMessage">The request message to apply the headers to.</param>
 private static void ApplyHeadersToResponse(HeaderCollection headers, IODataResponseMessage responseMessage)
 {
     // NetCF bug with how the enumerators for dictionaries work.
     foreach (KeyValuePair <string, string> header in headers.AsEnumerable().ToList())
     {
         responseMessage.SetHeader(header.Key, header.Value);
     }
 }
        /// <summary>
        /// Creates a new the reader for the given response message and settings.
        /// </summary>
        /// <param name="responseMessage">The response message.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>Newly created message reader.</returns>
        internal ODataMessageReader CreateReader(IODataResponseMessage responseMessage, ODataMessageReaderSettings settings)
        {
            Debug.Assert(responseMessage != null, "responseMessage != null");
            Debug.Assert(settings != null, "settings != null");

            this.responseInfo.Context.Format.ValidateCanReadResponseFormat(responseMessage);
            return new ODataMessageReader(responseMessage, settings, this.responseInfo.TypeResolver.ReaderModel);
        }
        /// <summary>
        /// Creates a new the reader for the given response message and settings.
        /// </summary>
        /// <param name="responseMessage">The response message.</param>
        /// <param name="settings">The settings.</param>
        /// <returns>Newly created message reader.</returns>
        internal ODataMessageReader CreateReader(IODataResponseMessage responseMessage, ODataMessageReaderSettings settings)
        {
            Debug.Assert(responseMessage != null, "responseMessage != null");
            Debug.Assert(settings != null, "settings != null");

            this.responseInfo.Context.Format.ValidateCanReadResponseFormat(responseMessage);
            return(new ODataMessageReader(responseMessage, settings, this.responseInfo.TypeResolver.ReaderModel));
        }
Пример #42
0
 internal ResponseBodyWriter(bool hasMoved, IDataService service, IEnumerator queryResults, RequestDescription requestDescription, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind)
 {
     this.hasMoved = hasMoved;
     this.service = service;
     this.queryResults = queryResults;
     this.requestDescription = requestDescription;
     this.responseMessage = responseMessage;
     this.payloadKind = payloadKind;
     this.encoding = HttpProcessUtility.EncodingFromAcceptCharset(this.service.OperationContext.Host.RequestAcceptCharSet);
     if ((((payloadKind == ODataPayloadKind.Entry) || (payloadKind == ODataPayloadKind.Feed)) || ((payloadKind == ODataPayloadKind.Property) || (payloadKind == ODataPayloadKind.Collection))) || (((payloadKind == ODataPayloadKind.EntityReferenceLink) || (payloadKind == ODataPayloadKind.EntityReferenceLinks)) || (((payloadKind == ODataPayloadKind.Error) || (payloadKind == ODataPayloadKind.ServiceDocument)) || (payloadKind == ODataPayloadKind.Parameter))))
     {
         DataServiceHostWrapper host = service.OperationContext.Host;
         if (WebUtil.GetEffectiveMaxResponseVersion(service.Configuration.DataServiceBehavior.MaxProtocolVersion, host.RequestMaxVersion) > RequestDescription.Version2Dot0)
         {
             bool isEntityOrFeed = (payloadKind == ODataPayloadKind.Entry) || (payloadKind == ODataPayloadKind.Feed);
             if (WebUtil.ResponseMediaTypeWouldBeJsonLight(host.RequestAccept, isEntityOrFeed))
             {
                 requestDescription.VerifyAndRaiseResponseVersion(RequestDescription.Version3Dot0, service);
                 host.ResponseVersion = RequestDescription.Version3Dot0.ToString() + ";";
             }
         }
     }
     if (this.requestDescription.TargetKind == RequestTargetKind.MediaResource)
     {
         this.mediaResourceStream = service.StreamProvider.GetReadStream(this.queryResults.Current, RequestDescription.GetStreamProperty(this.requestDescription), this.service.OperationContext);
     }
     else if (payloadKind != ODataPayloadKind.BinaryValue)
     {
         string requestAcceptCharSet = this.service.OperationContext.Host.RequestAcceptCharSet;
         if (string.IsNullOrEmpty(requestAcceptCharSet) || (requestAcceptCharSet == "*"))
         {
             requestAcceptCharSet = "UTF-8";
         }
         if ((payloadKind == ODataPayloadKind.Value) && !string.IsNullOrEmpty(this.requestDescription.MimeType))
         {
             this.messageWriter = CreateMessageWriter(this.AbsoluteServiceUri, this.service, this.requestDescription.ActualResponseVersion, responseMessage, ODataFormat.RawValue);
         }
         else
         {
             this.messageWriter = CreateMessageWriter(this.AbsoluteServiceUri, this.service, this.requestDescription.ActualResponseVersion, responseMessage, this.service.OperationContext.Host.RequestAccept, requestAcceptCharSet);
         }
         try
         {
             this.contentFormat = ODataUtils.SetHeadersForPayload(this.messageWriter, payloadKind);
             if ((payloadKind == ODataPayloadKind.Value) && !string.IsNullOrEmpty(this.requestDescription.MimeType))
             {
                 responseMessage.SetHeader("Content-Type", this.requestDescription.MimeType);
             }
         }
         catch (ODataContentTypeException exception)
         {
             throw new DataServiceException(0x19f, null, System.Data.Services.Strings.DataServiceException_UnsupportedMediaType, null, exception);
         }
         string headerValue = this.requestDescription.ResponseVersion.ToString() + ";";
         responseMessage.SetHeader("DataServiceVersion", headerValue);
     }
 }
Пример #43
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            if (this.TryDispatch(requestMessage, responseMessage))
            {
                return;
            }

            if (this.QueryContext.Target.TypeKind != EdmTypeKind.Collection)
            {
                throw Utility.BuildException(HttpStatusCode.BadRequest, "The new resource can only be created under collection resource.", null);
            }

            if (this.QueryContext.Target.IsReference)
            {
                this.ProcessCreateLink(requestMessage, responseMessage);
                return;
            }

            try
            {
                var targetEntitySet = (IEdmEntitySetBase)this.QueryContext.Target.NavigationSource;

                // TODO: [lianw] Try to remove "targetEntitySet" later.
                var queryResults = this.QueryContext.ResolveQuery(this.DataSource);

                if (!IsAllowInsert(targetEntitySet as IEdmEntitySet))
                {
                    throw new ODataServiceException(HttpStatusCode.BadRequest, "The insert request is not allowed.", null);
                }

                var bodyObject = ProcessPostBody(requestMessage, targetEntitySet, queryResults);

                using (var messageWriter = this.CreateMessageWriter(responseMessage))
                {
                    this.DataSource.UpdateProvider.SaveChanges();

                    // 11.4.2 Create an Entity
                    // Upon successful completion the service MUST respond with either 201 Created, or 204 No Content if the request included a return Prefer header with a value of return=minimal.
                    responseMessage.SetStatusCode(HttpStatusCode.Created);
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.Location, Utility.BuildLocationUri(this.QueryContext, bodyObject).OriginalString);
                    var currentETag = Utility.GetETagValue(bodyObject);
                    // if the current entity has ETag field
                    if (currentETag != null)
                    {
                        responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag);
                    }

                    ResponseWriter.WriteEntry(messageWriter.CreateODataEntryWriter(targetEntitySet), bodyObject, targetEntitySet, ODataVersion.V4, null);
                }
            }
            catch
            {
                this.DataSource.UpdateProvider.ClearChanges();
                throw;
            }
        }
Пример #44
0
        /// <summary>
        /// Prevents a default instance of the <see cref="MessageWriterBuilder"/> class from being created.
        /// </summary>
        /// <param name="serviceUri">The service URI.</param>
        /// <param name="responseVersion">The response version.</param>
        /// <param name="dataService">The data service.</param>
        /// <param name="responseMessage">The response message.</param>
        /// <param name="model">The model to provide to the message writer.</param>
        private MessageWriterBuilder(Uri serviceUri, Version responseVersion, IDataService dataService, IODataResponseMessage responseMessage, IEdmModel model)
        {
            this.writerSettings = CreateMessageWriterSettings();
            ApplyCommonSettings(this.writerSettings, serviceUri, responseVersion, dataService, responseMessage);

            Debug.Assert(responseMessage != null, "responseMessage != null");
            this.responseMessage = responseMessage;

            this.model = model;
        }
Пример #45
0
 internal MaterializeAtom(ResponseInfo responseInfo, QueryComponents queryComponents, ProjectionPlan plan, IODataResponseMessage responseMessage, ODataPayloadKind payloadKind)
 {
     Type type;
     this.responseInfo = responseInfo;
     this.elementType = queryComponents.LastSegmentType;
     this.MergeOptionValue = responseInfo.MergeOption;
     this.expectingPrimitiveValue = PrimitiveType.IsKnownNullableType(this.elementType);
     Type materializerType = GetTypeForMaterializer(this.expectingPrimitiveValue, this.elementType, responseInfo.MaxProtocolVersion, out type);
     this.materializer = ODataMaterializer.CreateMaterializerForMessage(responseMessage, responseInfo, materializerType, queryComponents, plan, payloadKind);
 }
Пример #46
0
        /// <summary>
        /// Detects the payload kinds supported by this format for the specified message payload.
        /// </summary>
        /// <param name="responseMessage">The response message with the payload stream.</param>
        /// <param name="detectionInfo">Additional information available for the payload kind detection.</param>
        /// <returns>The set of <see cref="ODataPayloadKind"/>s that are supported with the specified payload.</returns>
        internal override IEnumerable<ODataPayloadKind> DetectPayloadKind(
            IODataResponseMessage responseMessage,
            ODataPayloadKindDetectionInfo detectionInfo)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(responseMessage, "responseMessage");
            ExceptionUtils.CheckArgumentNotNull(detectionInfo, "detectionInfo");

            return DetectPayloadKindImplementation(detectionInfo.ContentType);
        }
Пример #47
0
        /// <summary>
        /// Constructs a new instance of DataServiceTransportException.
        /// </summary>
        /// <param name="response">ResponseMessage from the exception so that the error payload can be read.</param>
        /// <param name="innerException">Actual exception that this exception is wrapping.</param>
        public DataServiceTransportException(IODataResponseMessage response, Exception innerException)
            : base(innerException.Message, innerException)
        {
            Util.CheckArgumentNull(innerException, "innerException");

            this.state.ResponseMessage = response;

#if !PORTABLELIB
            this.SerializeObjectState += (sender, e) => e.AddSerializedState(this.state);
#endif
        }
Пример #48
0
        /// <summary>
        /// Detects the payload kinds supported by this format for the specified message payload.
        /// </summary>
        /// <param name="responseMessage">The response message with the payload stream.</param>
        /// <param name="detectionInfo">Additional information available for the payload kind detection.</param>
        /// <returns>The set of <see cref="ODataPayloadKind"/>s that are supported with the specified payload.</returns>
        internal override IEnumerable<ODataPayloadKind> DetectPayloadKind(
            IODataResponseMessage responseMessage,
            ODataPayloadKindDetectionInfo detectionInfo)
        {
            DebugUtils.CheckNoExternalCallers();
            ExceptionUtils.CheckArgumentNotNull(responseMessage, "responseMessage");
            ExceptionUtils.CheckArgumentNotNull(detectionInfo, "detectionInfo");

            Stream messageStream = ((ODataMessage)responseMessage).GetStream();
            return this.DetectPayloadKindImplementation(messageStream, /*readingResponse*/ true, /*synchronous*/ true, detectionInfo);
        }
Пример #49
0
 public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
 {
     switch (this.HttpMethod)
     {
         case HttpMethod.POST:
             this.ProcessCreate(requestMessage.GetStream(), responseMessage);
             break;
         case HttpMethod.PUT:
             this.ProcessUpdate(requestMessage.GetStream(), responseMessage);
             break;
     }
 }
Пример #50
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                ODataError error;
                HttpStatusCode statusCode;

                this.BuildODataError(out error, out statusCode);
                responseMessage.SetStatusCode(statusCode);
                messageWriter.WriteError(error, true);
            }
        }
Пример #51
0
        /// <summary>
        /// Create a new instance of ODataMessageWriterSettings for normal requests.
        /// </summary>
        /// <param name="dataService">Data service instance.</param>
        /// <param name="requestDescription">The current request description.</param>
        /// <param name="responseMessage">IODataResponseMessage implementation.</param>
        /// <param name="model">The model to provide to the message writer.</param>
        /// <returns>An instance of a message writer with the appropriate settings.</returns>
        internal static MessageWriterBuilder ForNormalRequest(IDataService dataService, RequestDescription requestDescription, IODataResponseMessage responseMessage, IEdmModel model)
        {
            Debug.Assert(dataService != null, "dataService != null");
            Debug.Assert(dataService.OperationContext != null, "dataService.OperationContext != null");
            Debug.Assert(requestDescription != null, "requestDescription != null");
            Debug.Assert(dataService.OperationContext.RequestMessage != null, "dataService.OperationContext.RequestMessage != null");
            Debug.Assert(responseMessage != null, "responseMessage != null");

            Uri serviceUri = dataService.OperationContext.AbsoluteServiceUri;
            Version responseVersion = requestDescription.ActualResponseVersion;

            MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, responseMessage, model);

            // ODataLib doesn't allow custom MIME types on raw values (must be text/plain for non-binary, and application/octet for binary values).
            // To maintain existing V1/V2 behavior, work around this by setting the format as RawValue (we handle conneg ourself for this, so don't make ODL do its own),
            // and then later manually override the content type header. Conneg is done by Astoria in DataService.CreateResponseBodyWriter.
            if (requestDescription.ResponsePayloadKind == ODataPayloadKind.Value && !string.IsNullOrEmpty(requestDescription.MimeType))
            {
                messageWriterBuilder.WriterSettings.SetContentType(ODataFormat.RawValue);
            }
            else
            {
                string acceptHeaderValue = dataService.OperationContext.RequestMessage.GetAcceptableContentTypes();

                // In V1/V2 we defaulted to charset=utf-8 for the response when there was no specific Accept-Charset.
                // ODataMessageWriter uses a different default in some cases depending on the media type, so we need to override that here.
                string requestAcceptCharSet = dataService.OperationContext.RequestMessage.GetRequestAcceptCharsetHeader();
                if (string.IsNullOrEmpty(requestAcceptCharSet) || requestAcceptCharSet == "*")
                {
                    requestAcceptCharSet = XmlConstants.Utf8Encoding;
                }

                messageWriterBuilder.WriterSettings.SetContentType(acceptHeaderValue, requestAcceptCharSet);
            }

            // always set the metadata document URI. ODataLib will decide whether or not to write it.
            messageWriterBuilder.WriterSettings.ODataUri = new ODataUri()
            {
                ServiceRoot = serviceUri,
                SelectAndExpand = requestDescription.ExpandAndSelect.Clause,
                Path = requestDescription.Path
            };

            messageWriterBuilder.WriterSettings.JsonPCallback = requestDescription.JsonPaddingFunctionName;

            return messageWriterBuilder;
        }
        private ODataAsynchronousWriter TestInit()
        {
            this.userModel = new EdmModel();

            testType = new EdmEntityType("NS", "Test");
            testType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32);
            this.userModel.AddElement(testType);

            var defaultContainer = new EdmEntityContainer("NS", "DefaultContainer");
            this.userModel.AddElement(defaultContainer);

            this.singleton = new EdmSingleton(defaultContainer, "MySingleton", this.testType);
            defaultContainer.AddElement(this.singleton);

            responseStream = new MemoryStream();
            responseMessage = new InMemoryMessage { Stream = responseStream };
            messageWriter = new ODataMessageWriter(responseMessage);
            return messageWriter.CreateODataAsynchronousWriter();
        }
Пример #53
0
        private void ProcessCreate(Stream requestStream, IODataResponseMessage responseMessage)
        {
            try
            {
                // handle insert annotation
                if (!this.IsAllowInsert(this.QueryContext.Target.NavigationSource as IEdmEntitySet))
                {
                    throw new ODataServiceException(HttpStatusCode.BadRequest, "The insert request is not allowed.", null);
                }

                // handle content type
                var contentType = this.HandleContentType((IEdmEntityType)this.QueryContext.Target.ElementType);

                // handle entity
                var entities = this.QueryContext.ResolveQuery(this.DataSource);
                var entity = this.DataSource.UpdateProvider.Create(this.QueryContext.Target.ElementType.FullTypeName(), entities);
                this.DataSource.StreamProvider.CreateStream(entity, requestStream, contentType);

                this.DataSource.UpdateProvider.SaveChanges();

                using (var messageWriter = this.CreateMessageWriter(responseMessage))
                {
                    responseMessage.SetHeader(ServiceConstants.HttpHeaders.Location, Utility.BuildLocationUri(this.QueryContext, entity).OriginalString);

                    if (this.PreferenceContext.Return == ServiceConstants.PreferenceValue_Return_Minimal)
                    {
                        responseMessage.SetStatusCode(HttpStatusCode.NoContent);
                    }
                    else
                    {
                        responseMessage.SetStatusCode(HttpStatusCode.Created);
                        var edmEntitySet = (IEdmEntitySetBase)this.QueryContext.Target.NavigationSource;
                        ResponseWriter.WriteEntry(messageWriter.CreateODataEntryWriter(edmEntitySet), entity, edmEntitySet, ODataVersion.V4, null);
                    }
                }
            }
            catch
            {
                this.DataSource.UpdateProvider.ClearChanges();
                throw;
            }
        }
Пример #54
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            try
            {
                var odataPath = this.QueryContext.QueryPath;

                if (this.QueryContext.Target.IsReference && this.QueryContext.Target.TypeKind != EdmTypeKind.Collection)
                {
                    ProcessUpdateEntityReference(requestMessage, responseMessage, odataPath);
                }
                else
                {
                    ProcessUpdateOrUpsertEntity(requestMessage, responseMessage, odataPath);
                }
            }
            catch
            {
                this.DataSource.UpdateProvider.ClearChanges();
                throw;
            }
        }
Пример #55
0
        public override void Process(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage)
        {
            // TODO: we will need to add server-driven paging for delta link

            object queryResults = this.QueryContext.ResolveQuery(this.DataSource);

            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                IEdmNavigationSource navigationSource = this.QueryContext.Target.NavigationSource;
                IEnumerable iEnumerableResults = queryResults as IEnumerable;

                if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Collection)
                {
                    IEdmEntitySetBase entitySet = navigationSource as IEdmEntitySetBase;
                    IEdmEntityType entityType = this.QueryContext.Target.ElementType as IEdmEntityType;
                    if (entitySet == null || entityType == null)
                    {
                        throw new InvalidOperationException("Invalid target when query feed.");
                    }
                    GenerateDeltaItemsFromFeed(iEnumerableResults, entitySet, ODataVersion.V4, this.QueryContext.QuerySelectExpandClause);

                    Uri newDeltaLink = null;
                    if (this.PreferenceContext.TrackingChanges)
                    {
                        var newDeltaToken = DeltaContext.GenerateDeltaToken(this.QueryContext.QueryUri, iEnumerableResults, entitySet, this.QueryContext.QuerySelectExpandClause);
                        newDeltaLink = new Uri(string.Format("{0}?{1}={2}", this.ServiceRootUri, ServiceConstants.QueryOption_Delta, newDeltaToken));
                        responseMessage.AddPreferenceApplied(ServiceConstants.Preference_TrackChanging);
                    }
                    ODataDeltaWriter resultWriter = messageWriter.CreateODataDeltaWriter(entitySet, entityType);
                    ResponseWriter.WriteDeltaFeed(resultWriter, this.DeltaItems, this.QueryContext.CountOption, newDeltaLink);

                    resultWriter.Flush();
                }
                else
                {
                    throw Utility.BuildException(HttpStatusCode.Gone);
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of ODataResponseContext with the specified responseMessage,
        /// baseAddress and serviceOperationName.
        /// </summary>
        /// <param name="responseMessage">An instance of the IODataResponseMessage.</param>
        /// <param name="format">ODataFormat to be used.</param>
        /// <param name="version">DataServiceversion to be used</param>
        /// <param name="baseAddress">The baseAddress to be used while serializing feed/entry.</param>
        /// <param name="serviceOperationName">The serviceOperationName to use while serializing primitives and complex types.</param>
        public ODataResponseContext(IODataResponseMessage responseMessage, ODataFormat format, ODataVersion version, Uri baseAddress, string serviceOperationName)
        {
            if (responseMessage == null)
            {
                throw Error.ArgumentNull("responseMessage");
            }

            if (baseAddress == null)
            {
                throw Error.ArgumentNull("baseAddress");
            }

            if (String.IsNullOrEmpty(serviceOperationName))
            {
                throw Error.ArgumentNullOrEmpty("serviceOperationName");
            }

            _responseMessage = responseMessage;
            ODataFormat = format;
            ODataVersion = version;
            _baseAddress = baseAddress;
            _serviceOperationName = serviceOperationName;
            IsIndented = true;
        }
Пример #57
0
        private void ProcessUpdateOrUpsertEntity(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath)
        {
            var targetObject = this.QueryContext.ResolveQuery(this.DataSource);
            string targetETag = null;

            if (targetObject != null)
            {
                targetETag = Utility.GetETagValue(targetObject);
            }

            var requestETagKind = RequestETagKind.None;
            string requestETag;
            if (Utility.TryGetIfMatch(this.RequestHeaders, out requestETag))
            {
                requestETagKind = RequestETagKind.IfMatch;
            }
            else if (Utility.TryGetIfNoneMatch(this.RequestHeaders, out requestETag))
            {
                requestETagKind = RequestETagKind.IfNoneMatch;
            }

            switch (requestETagKind)
            {
                case RequestETagKind.None:
                    {
                        if (targetETag == null)
                        {
                            if (targetObject == null)
                            {
                                ProcessUpsertEntity(requestMessage, responseMessage, odataPath);
                            }
                            else
                            {
                                ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false);
                            }
                        }
                        else
                        {
                            ResponseWriter.WriteEmptyResponse(responseMessage, (HttpStatusCode)428);
                        }

                        break;
                    }
                case RequestETagKind.IfMatch:
                    {
                        if (requestETag == ServiceConstants.ETagValueAsterisk || requestETag == targetETag)
                        {
                            if (targetObject == null)
                            {
                                throw Utility.BuildException(HttpStatusCode.NotFound);
                            }

                            ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false);
                        }
                        else
                        {
                            ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.PreconditionFailed);
                        }

                        break;
                    }
                case RequestETagKind.IfNoneMatch:
                    {
                        if (requestETag == ServiceConstants.ETagValueAsterisk)
                        {
                            ProcessUpsertEntity(requestMessage, responseMessage, odataPath);
                        }
                        else if (requestETag != targetETag)
                        {
                            if (targetObject == null)
                            {
                                throw Utility.BuildException(HttpStatusCode.NotFound);
                            }

                            ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, false);
                        }
                        else
                        {
                            ResponseWriter.WriteEmptyResponse(responseMessage, HttpStatusCode.PreconditionFailed);
                        }

                        break;
                    }
            }
        }
Пример #58
0
        private void ProcessUpdateRequestBody(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, object targetObject, bool isUpsert)
        {
            if (this.QueryContext.Target.NavigationSource != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Entity)
            {
                using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model))
                {
                    var entryReader = messageReader.CreateODataEntryReader(this.QueryContext.Target.NavigationSource, (IEdmEntityType)this.QueryContext.Target.Type);

                    while (entryReader.Read())
                    {
                        switch (entryReader.State)
                        {
                            case ODataReaderState.EntryEnd:
                                var entry = (ODataEntry)entryReader.Item;
                                foreach (var property in entry.Properties)
                                {
                                    if (Utility.IsETagProperty(targetObject, property.Name)) continue;
                                    // the property might be an open property, so test null first
                                    var propertyInfo = targetObject.GetType().GetProperty(property.Name);
                                    if (propertyInfo != null)
                                    {
                                        if (!isUpsert && Utility.IsReadOnly(propertyInfo)) continue;
                                    }

                                    this.DataSource.UpdateProvider.Update(targetObject, property.Name, property.Value);
                                }

                                break;
                        }
                    }
                }
            }
            else if (this.QueryContext.Target.Property != null && this.QueryContext.Target.TypeKind == EdmTypeKind.Complex)
            {
                using (var messageReader = new ODataMessageReader(requestMessage, this.GetReaderSettings(), this.DataSource.Model))
                {
                    var property = messageReader.ReadProperty(this.QueryContext.Target.Property);
                    ODataComplexValue complexValue = property.Value as ODataComplexValue;

                    foreach (var p in complexValue.Properties)
                    {
                        if (Utility.IsETagProperty(targetObject, property.Name)) continue;
                        this.DataSource.UpdateProvider.Update(targetObject, p.Name, p.Value);
                    }
                }
            }
            else
            {
                throw Utility.BuildException(
                    HttpStatusCode.NotImplemented,
                    string.Format("PATCH/PUT for '{0}' type is not supported.", this.QueryContext.Target.TypeKind),
                    null);
            }

            var currentETag = Utility.GetETagValue(targetObject);
            // if the current entity has ETag field
            if (currentETag != null)
            {
                if (!isUpsert)
                {
                    this.DataSource.UpdateProvider.UpdateETagValue(targetObject);
                }

                this.DataSource.UpdateProvider.SaveChanges();

                currentETag = Utility.GetETagValue(targetObject);
                responseMessage.SetHeader(ServiceConstants.HttpHeaders.ETag, currentETag);
            }
            else
            {
                this.DataSource.UpdateProvider.SaveChanges();
            }

            ResponseWriter.WriteEmptyResponse(responseMessage);
        }
Пример #59
0
        private void ProcessUpsertEntity(IODataRequestMessage requestMessage, IODataResponseMessage responseMessage, ODataPath odataPath)
        {
            if (this.QueryContext.Target.TypeKind == EdmTypeKind.Entity && !this.QueryContext.Target.IsReference)
            {
                Uri parentUri = this.QueryContext.Target.BuildContainerUri(this.ServiceRootUri);
                QueryContext parentContext = new QueryContext(this.ServiceRootUri, parentUri, this.DataSource.Model);

                if (parentContext.Target.IsEntitySet)
                {
                    // Update a entity under a entity set => Upsert

                    // TODO: Do we need to preserver the key value?
                    new CreateHandler(this, parentContext.QueryUri).Process(requestMessage, responseMessage);
                }
                else
                {
                    // Update Singleton or single value entity from null value.
                    var parent = parentContext.ResolveQuery(this.DataSource);

                    // TODO: It might not correct here, since the last segment could be type segment.
                    NavigationPropertySegment navSegment = (NavigationPropertySegment)odataPath.LastSegment;
                    var targetObject = Utility.CreateResource(this.QueryContext.Target.Type);
                    parent.GetType().GetProperty(navSegment.NavigationProperty.Name).SetValue(parent, targetObject, null);

                    ProcessUpdateRequestBody(requestMessage, responseMessage, targetObject, true);
                }
            }
            else
            {
                throw Utility.BuildException(HttpStatusCode.NotFound);
            }
        }
Пример #60
0
        private void ProcessUpdate(Stream requestStream, IODataResponseMessage responseMessage)
        {
            // handle entity
            var entity = this.HandleEntity();

            // handle content type
            var parentUri = this.QueryContext.Target.BuildContainerUri(this.ServiceRootUri);
            var parentContext = new QueryContext(this.ServiceRootUri, parentUri, this.DataSource.Model);
            var contentType = this.HandleContentType((IEdmEntityType)parentContext.Target.ElementType);

            // handle ETag
            this.HandleETag(entity, true);

            // handle update
            this.DataSource.StreamProvider.UpdateStream(entity, requestStream, contentType);

            using (var messageWriter = this.CreateMessageWriter(responseMessage))
            {
                responseMessage.SetStatusCode(HttpStatusCode.OK);
                var edmEntitySet = (IEdmEntitySetBase)parentContext.Target.NavigationSource;
                ResponseWriter.WriteEntry(messageWriter.CreateODataEntryWriter(edmEntitySet), entity, edmEntitySet, ODataVersion.V4, null);
            }
        }