Esempio n. 1
0
        public static async Task SerializeAsync(OeQueryContext queryContext, IAsyncEnumerator <Object> asyncEnumerator,
                                                String contentType, Stream stream, OeEntryFactory entryFactory, IServiceProvider?serviceProvider, CancellationToken cancellationToken)
        {
            var settings = new ODataMessageWriterSettings()
            {
                BaseUri = queryContext.ODataUri.ServiceRoot,
                EnableMessageStreamDisposal = false,
                ODataUri    = queryContext.ODataUri,
                Validations = ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            if (serviceProvider != null)
            {
                serviceProvider = new ServiceProvider(serviceProvider, settings);
            }

            IODataResponseMessage responseMessage = new Infrastructure.OeInMemoryMessage(stream, contentType, serviceProvider);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, queryContext.EdmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);
                ODataWriter writer = await messageWriter.CreateODataResourceSetWriterAsync(entryFactory.EntitySet, entryFactory.EdmEntityType);

                var odataWriter = new OeODataWriter(queryContext, writer, cancellationToken);
                await odataWriter.WriteAsync(entryFactory, asyncEnumerator).ConfigureAwait(false);
            }
        }
Esempio n. 2
0
        public static async Task SerializeAsync(Uri baseUri, OeParseUriContext parseUriContext, Db.OeEntityAsyncEnumerator asyncEnumerator, Stream stream)
        {
            IEdmModel      edmModel     = parseUriContext.EdmModel;
            OeEntryFactory entryFactory = parseUriContext.EntryFactory;
            String         contentType  = parseUriContext.Headers.ContentType;

            var settings = new ODataMessageWriterSettings()
            {
                BaseUri = baseUri,
                EnableMessageStreamDisposal = false,
                ODataUri    = parseUriContext.ODataUri,
                Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            IODataResponseMessage responseMessage = new OeInMemoryMessage(stream, contentType);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, edmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);
                ODataWriter writer    = messageWriter.CreateODataResourceSetWriter(entryFactory.EntitySet, entryFactory.EntityType);
                var         getWriter = new GetWriter(baseUri, parseUriContext.Headers.MetadataLevel, writer);
                await getWriter.SerializeAsync(entryFactory, asyncEnumerator, stream);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Determines the response format based on the results of content negotiation.
        /// </summary>
        /// <param name="payloadKind">The payload kind of the response.</param>
        /// <param name="acceptableMediaTypes">
        /// The acceptable media types used to determine the content type of the message.
        /// This is a comma separated list of content types as specified in RFC 2616, Section 14.1
        /// </param>
        /// <param name="acceptableCharSets">
        /// The acceptable charsets to use to the determine the encoding of the message.
        /// This is a comma separated list of charsets as specified in RFC 2616, Section 14.2
        /// </param>
        /// <returns>The format the response should use. </returns>
        internal ODataFormatWithParameters DetermineResponseFormat(ODataPayloadKind payloadKind, string acceptableMediaTypes, string acceptableCharSets)
        {
            Debug.Assert(payloadKind != ODataPayloadKind.Unsupported, "kind != ODataPayloadKind.Unsupported");

            ContentNegotiationResponseMessage responseMessage = new ContentNegotiationResponseMessage();

            ODataMessageWriterSettings settings = new ODataMessageWriterSettings {
                Version = this.responseVersion
            };

            // settings.EnableAtomSupport();
            settings.SetContentType(acceptableMediaTypes, acceptableCharSets);

            try
            {
                using (ODataMessageWriter writer = new ODataMessageWriter(responseMessage, settings))
                {
                    ODataFormat format = ODataUtils.SetHeadersForPayload(writer, payloadKind);
                    return(new ODataFormatWithParameters(format, responseMessage.ContentType));
                }
            }
            catch (ODataContentTypeException exception)
            {
                if (this.throwIfNoMatch)
                {
                    throw new DataServiceException(415, null, Microsoft.OData.Service.Strings.DataServiceException_UnsupportedMediaType, null, exception);
                }

                return(null);
            }
        }
Esempio n. 4
0
        public virtual async Task ExecuteResultAsync(ActionContext context)
        {
            var settings = new ODataMessageWriterSettings()
            {
                BaseUri = _odataUri.ServiceRoot,
                EnableMessageStreamDisposal = false,
                ODataUri    = _odataUri,
                Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            var requestHeaders = OeRequestHeaders.Parse(context.HttpContext.Request.Headers["Accept"], context.HttpContext.Request.Headers["Prefer"]);

            if (requestHeaders.MaxPageSize > 0 && PageSize == 0)
            {
                PageSize = requestHeaders.MaxPageSize;
            }

            IODataResponseMessage responseMessage = new Infrastructure.OeInMemoryMessage(context.HttpContext.Response.Body, context.HttpContext.Request.ContentType);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _edmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);

                IEdmEntityType entityType = _resultEntitySet.EntityType();
                ODataWriter    writer     = messageWriter.CreateODataResourceSetWriter(_resultEntitySet, entityType);
                await SerializeAsync(writer, requestHeaders.MetadataLevel);
            }
        }
Esempio n. 5
0
        private void WriteEntity(Stream stream, OeEntityItem entityItem)
        {
            var settings = new ODataMessageWriterSettings()
            {
                BaseUri  = _baseUri,
                Version  = ODataVersion.V4,
                ODataUri = new ODataUri()
                {
                    ServiceRoot = _baseUri
                },
                EnableMessageStreamDisposal = false
            };

            IODataResponseMessage responseMessage = new OeInMemoryMessage(stream, null);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _model))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.Resource);
                ODataWriter writer = messageWriter.CreateODataResourceWriter(entityItem.EntitySet, entityItem.EntityType);

                entityItem.RefreshEntry();
                writer.WriteStart(entityItem.Entry);
                writer.WriteEnd();
            }
        }
Esempio n. 6
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);
     }
 }
        private void WriteEntity(Stream stream, OeEntityItem entityItem)
        {
            IODataResponseMessage responseMessage = new OeInMemoryMessage(stream, null);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, _settings, _model))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.Resource);
                ODataWriter writer = messageWriter.CreateODataResourceWriter(entityItem.EntitySet, entityItem.EntityType);

                writer.WriteStart(entityItem.Entry);
                writer.WriteEnd();
            }
        }
Esempio n. 8
0
        private async Task WriteEntity(IEdmEntitySet entitySet, ODataResource entry, Stream stream)
        {
            IODataResponseMessage responseMessage = new Infrastructure.OeInMemoryMessage(stream, null);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, _settings, _model.GetEdmModel(entitySet)))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.Resource);
                ODataWriter writer = await messageWriter.CreateODataResourceWriterAsync(entitySet, entitySet.EntityType());

                await writer.WriteStartAsync(entry);

                await writer.WriteEndAsync();
            }
        }
Esempio n. 9
0
        /// <summary>Handles an exception before the response has been written out.</summary>
        /// <param name='exception'>Exception thrown.</param>
        /// <param name='service'>Data service doing the processing.</param>
        /// <returns>An action that can serialize the exception into a stream.</returns>
        internal static Action <Stream> HandleBeforeWritingException(Exception exception, IDataService service)
        {
            Debug.Assert(CommonUtil.IsCatchableExceptionType(exception), "CommonUtil.IsCatchableExceptionType(exception)");
            Debug.Assert(exception != null, "exception != null");
            Debug.Assert(service != null, "service != null");

            AstoriaRequestMessage requestMessage = service.OperationContext.RequestMessage;

            Debug.Assert(requestMessage != null, "requestMessage != null");

            ErrorHandler handler = CreateHandler(service, requestMessage, exception, VersionUtil.DataServiceDefaultResponseVersion);

            service.InternalHandleException(handler.exceptionArgs);

            service.OperationContext.ResponseMessage.SetHeader(XmlConstants.HttpODataVersion, handler.responseVersion.ToString(2) + ";");
            requestMessage.ProcessException(handler.exceptionArgs);

            Action <Stream> action = ProcessBenignException(exception, service);

            if (action != null)
            {
                return(action);
            }

            MessageWriterBuilder messageWriterBuilder = MessageWriterBuilder.ForError(
                service.OperationContext.RequestMessage.AbsoluteServiceUri,
                service,
                handler.responseVersion,
                service.OperationContext.ResponseMessage,
                handler.contentType,
                service.OperationContext.RequestMessage.GetRequestAcceptCharsetHeader());

            ODataMessageWriter messageWriter = messageWriterBuilder.CreateWriter();

            ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.Error);

            return(stream =>
            {
                service.OperationContext.ResponseMessage.SetStream(stream);
                ODataError error = handler.exceptionArgs.CreateODataError();
                WriteErrorWithFallbackForXml(messageWriter, handler.encoding, stream, handler.exceptionArgs, error, messageWriterBuilder);
            });
        }
Esempio n. 10
0
        public async Task ExecuteResultAsync(ActionContext context)
        {
            var settings = new ODataMessageWriterSettings()
            {
                BaseUri = _odataUri.ServiceRoot,
                EnableMessageStreamDisposal = false,
                ODataUri    = _odataUri,
                Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            var requestHeaders = OeRequestHeaders.Parse(context.HttpContext.Request.Headers["Accept"], context.HttpContext.Request.Headers["Prefer"]);

            _metadataLevel = requestHeaders.MetadataLevel;
            if (requestHeaders.MaxPageSize > 0 && PageSize == 0)
            {
                PageSize = requestHeaders.MaxPageSize;
            }

            IODataResponseMessage responseMessage = new OeInMemoryMessage(context.HttpContext.Response.Body, context.HttpContext.Request.ContentType);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, _edmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);

                IEdmEntitySet  edmEntitySet  = null;
                IEdmEntityType edmEntityType = null;
                foreach (IEdmEntitySet element in _edmModel.EntityContainer.EntitySets())
                {
                    edmEntityType = element.EntityType();
                    if (edmEntityType.FullName() == typeof(T).FullName)
                    {
                        edmEntitySet = element;
                        break;
                    }
                }

                ODataWriter writer = messageWriter.CreateODataResourceSetWriter(edmEntitySet, edmEntityType);
                await SerializeAsync(writer);
            }
        }
Esempio n. 11
0
        public static async Task SerializeAsync(OeQueryContext queryContext, Db.OeAsyncEnumerator asyncEnumerator, String contentType, Stream stream)
        {
            OeEntryFactory entryFactory = queryContext.EntryFactory;
            var            settings     = new ODataMessageWriterSettings()
            {
                BaseUri = queryContext.ODataUri.ServiceRoot,
                EnableMessageStreamDisposal = false,
                ODataUri    = queryContext.ODataUri,
                Validations = ValidationKinds.ThrowIfTypeConflictsWithMetadata | ValidationKinds.ThrowOnDuplicatePropertyNames,
                Version     = ODataVersion.V4
            };

            IODataResponseMessage responseMessage = new OeInMemoryMessage(stream, contentType);

            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, settings, queryContext.EdmModel))
            {
                ODataUtils.SetHeadersForPayload(messageWriter, ODataPayloadKind.ResourceSet);
                ODataWriter writer    = messageWriter.CreateODataResourceSetWriter(entryFactory.EntitySet, entryFactory.EntityType);
                var         getWriter = new GetWriter(queryContext, writer);
                await getWriter.SerializeAsync(entryFactory, asyncEnumerator, queryContext).ConfigureAwait(false);
            }
        }
        private IEnumerable <KeyValuePair <string, string> > GetResponseMessageHeaders(Type graphType, ODataFormat odataFormat, ODataVersion version)
        {
            IODataResponseMessage responseMessage = new ODataMessageWrapper();

            ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings()
            {
                BaseUri = new Uri(ODataFormatterConstants.DefaultNamespace),
                Version = version,
                Indent  = false
            };

            writerSettings.SetContentType(odataFormat);
            using (ODataMessageWriter messageWriter = new ODataMessageWriter(responseMessage, writerSettings))
            {
                ODataSerializer serializer = ODataSerializerProvider.GetODataPayloadSerializer(graphType);

                // get the OData specific headers for the payloadkind
                ODataUtils.SetHeadersForPayload(messageWriter, serializer.ODataPayloadKind);
            }

            return(responseMessage.Headers);
        }
Esempio n. 13
0
        /// <summary>Initializes a new <see cref="ResponseBodyWriter"/> that can write the body of a response.</summary>
        /// <param name="service">Service for the request being processed.</param>
        /// <param name="queryResults">Enumerator for results.</param>
        /// <param name="requestDescription">Description of request made to the system.</param>
        /// <param name="actualResponseMessageWhoseHeadersMayBeOverridden">IODataResponseMessage instance for the response.</param>
        internal ResponseBodyWriter(
            IDataService service,
            QueryResultInfo queryResults,
            RequestDescription requestDescription,
            IODataResponseMessage actualResponseMessageWhoseHeadersMayBeOverridden)
        {
            Debug.Assert(service != null, "service != null");
            Debug.Assert(requestDescription != null, "requestDescription != null");
            Debug.Assert(actualResponseMessageWhoseHeadersMayBeOverridden != null, "actualResponseMessageWhoseHeadersMayBeOverridden != null");

            this.service            = service;
            this.queryResults       = queryResults;
            this.requestDescription = requestDescription;
            this.actualResponseMessageWhoseHeadersMayBeOverridden = actualResponseMessageWhoseHeadersMayBeOverridden;

            Debug.Assert(this.PayloadKind != ODataPayloadKind.Unsupported, "payloadKind != ODataPayloadKind.Unsupported");

            this.encoding = ContentTypeUtil.EncodingFromAcceptCharset(this.service.OperationContext.RequestMessage.GetRequestAcceptCharsetHeader());

            if (this.PayloadKind == ODataPayloadKind.Entry ||
                this.PayloadKind == ODataPayloadKind.Feed ||
                this.PayloadKind == ODataPayloadKind.Property ||
                this.PayloadKind == ODataPayloadKind.Collection ||
                this.PayloadKind == ODataPayloadKind.EntityReferenceLink ||
                this.PayloadKind == ODataPayloadKind.EntityReferenceLinks ||
                this.PayloadKind == ODataPayloadKind.Error ||
                this.PayloadKind == ODataPayloadKind.ServiceDocument ||
                this.PayloadKind == ODataPayloadKind.Parameter)
            {
                AstoriaRequestMessage requestMessage = service.OperationContext.RequestMessage;
                IODataResponseMessage responseMessageOnOperationContext = service.OperationContext.ResponseMessage;

                Version effectiveMaxResponseVersion = VersionUtil.GetEffectiveMaxResponseVersion(service.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion(), requestMessage.RequestMaxVersion);
                bool    isEntityOrFeed = this.PayloadKind == ODataPayloadKind.Entry || this.PayloadKind == ODataPayloadKind.Feed;
                if (ContentTypeUtil.IsResponseMediaTypeJsonLight(requestMessage.GetAcceptableContentTypes(), isEntityOrFeed, effectiveMaxResponseVersion))
                {
                    // If JSON light 'wins', then bump the version to V3.
                    requestDescription.VerifyAndRaiseResponseVersion(VersionUtil.Version4Dot0, service);
                    responseMessageOnOperationContext.SetHeader(XmlConstants.HttpODataVersion, XmlConstants.ODataVersion4Dot0 + ";");
                }
            }

            if (this.requestDescription.TargetKind == RequestTargetKind.MediaResource)
            {
                Debug.Assert(this.PayloadKind == ODataPayloadKind.BinaryValue, "payloadKind == ODataPayloadKind.BinaryValue");

                // Note that GetReadStream will set the ResponseETag before it returns
                this.mediaResourceStream = service.StreamProvider.GetReadStream(
                    this.queryResults.Current,
                    this.requestDescription.StreamProperty,
                    this.service.OperationContext);
            }
            else if (this.PayloadKind != ODataPayloadKind.BinaryValue)
            {
                IEdmModel model;
                if (this.PayloadKind == ODataPayloadKind.MetadataDocument)
                {
                    model = MetadataSerializer.PrepareModelForSerialization(this.service.Provider, this.service.Configuration);
                }
                else
                {
                    model = this.GetModelFromService();
                }

                // Create the message writer using which the response needs to be written.
                this.messageWriterBuilder = MessageWriterBuilder.ForNormalRequest(
                    this.service,
                    this.requestDescription,
                    this.actualResponseMessageWhoseHeadersMayBeOverridden,
                    model);

                this.messageWriter = this.messageWriterBuilder.CreateWriter();

                try
                {
                    // Make sure all the headers are written before the method returns.
                    this.contentFormat = ODataUtils.SetHeadersForPayload(this.messageWriter, this.PayloadKind);
                }
                catch (ODataContentTypeException contentTypeException)
                {
                    throw new DataServiceException(415, null, Strings.DataServiceException_UnsupportedMediaType, null, contentTypeException);
                }

                Debug.Assert(requestDescription.ResponseFormat != null, "Response format should already have been determined.");
                Debug.Assert(ReferenceEquals(this.contentFormat, requestDescription.ResponseFormat.Format), "Response format in request description did not match format when writing.");

                if (this.PayloadKind == ODataPayloadKind.Value && !String.IsNullOrEmpty(this.requestDescription.MimeType))
                {
                    this.actualResponseMessageWhoseHeadersMayBeOverridden.SetHeader(XmlConstants.HttpContentType, this.requestDescription.MimeType);
                }

                // EPM is currently removed, but this doesn't seem to be used for EPM only. The old comment was saying:
                // In astoria, there is a bug in V1/V2 that while computing response version, we did not take
                // epm into account. Hence while creating the writer, we need to pass the RequestDescription.ActualResponseVersion
                // so that ODataLib can do the correct payload validation. But we need to write the response version without
                // the epm into the response headers because of backward-compat issue. Hence over-writing the response version
                // header with the wrong version value.
                string responseVersion = this.requestDescription.ResponseVersion.ToString() + ";";
                this.actualResponseMessageWhoseHeadersMayBeOverridden.SetHeader(XmlConstants.HttpODataVersion, responseVersion);
            }
        }
 /// <summary>
 /// Sets the content-type and data service version headers on the message used by the message writer.
 /// This method can be called if it is important to set all the message headers before calling any of the
 /// write methods.
 /// If it is sufficient to set the headers when the write methods on the message writer
 /// are called, you don't have to call this method and setting the headers will happen automatically.
 /// </summary>
 /// <param name="payloadKind">The kind of payload to be written with the message writer.</param>
 /// <returns>The <see cref="ODataFormat"/> used for the specified <paramref name="payloadKind"/>.</returns>
 public ODataFormat SetHeadersForPayload(ODataPayloadKind payloadKind)
 {
     return(ODataUtils.SetHeadersForPayload(this.messageWriter, payloadKind));
 }
Esempio n. 15
0
        private ODataRequestMessageWrapper GenerateBatchRequest()
        {
            if ((base.ChangedEntries.Count == 0) && (this.Queries == null))
            {
                base.SetCompleted();
                return(null);
            }
            ODataRequestMessageWrapper requestMessage = this.CreateBatchRequest();

            using (ODataMessageWriter writer = Serializer.CreateMessageWriter(requestMessage, base.RequestInfo))
            {
                ODataUtils.SetHeadersForPayload(writer, ODataPayloadKind.Batch);
                requestMessage.FireSendingRequest2(null);
                this.batchWriter = writer.CreateODataBatchWriter();
                this.batchWriter.WriteStartBatch();
                if (this.Queries != null)
                {
                    for (int i = 0; i < this.Queries.Length; i++)
                    {
                        Uri requestUri = base.RequestInfo.BaseUriResolver.CreateAbsoluteUriIfNeeded(this.Queries[i].QueryComponents(base.RequestInfo.MaxProtocolVersion).Uri);
                        ODataRequestMessageWrapper wrapper2 = this.CreateRequestMessage(requestUri, "GET");
                        Version requestVersion = this.Queries[i].QueryComponents(base.RequestInfo.MaxProtocolVersion).Version;
                        WebUtil.SetOperationVersionHeaders(wrapper2, requestVersion, base.RequestInfo.MaxProtocolVersionAsVersion);
                        wrapper2.FireSendingRequest2(null);
                    }
                }
                else if (0 < base.ChangedEntries.Count)
                {
                    this.batchWriter.WriteStartChangeset();
                    ClientEdmModel model = ClientEdmModel.GetModel(base.RequestInfo.MaxProtocolVersion);
                    for (int j = 0; j < base.ChangedEntries.Count; j++)
                    {
                        Descriptor descriptor = base.ChangedEntries[j];
                        if (!descriptor.ContentGeneratedForSave)
                        {
                            ODataRequestMessageWrapper wrapper3;
                            EntityDescriptor           entityDescriptor = descriptor as EntityDescriptor;
                            if (descriptor.DescriptorKind == DescriptorKind.Entity)
                            {
                                if (entityDescriptor.State != EntityStates.Added)
                                {
                                    if (((entityDescriptor.State == EntityStates.Unchanged) || (entityDescriptor.State == EntityStates.Modified)) && (entityDescriptor.SaveStream != null))
                                    {
                                        throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForMediaLink);
                                    }
                                }
                                else if (model.GetClientTypeAnnotation(model.GetOrCreateEdmType(entityDescriptor.Entity.GetType())).IsMediaLinkEntry || entityDescriptor.IsMediaLinkEntry)
                                {
                                    throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForMediaLink);
                                }
                            }
                            else if (descriptor.DescriptorKind == DescriptorKind.NamedStream)
                            {
                                throw System.Data.Services.Client.Error.NotSupported(System.Data.Services.Client.Strings.Context_BatchNotSupportedForNamedStreams);
                            }
                            if (descriptor.DescriptorKind == DescriptorKind.Entity)
                            {
                                wrapper3 = base.CreateRequest(entityDescriptor);
                            }
                            else
                            {
                                wrapper3 = base.CreateRequest((LinkDescriptor)descriptor);
                            }
                            wrapper3.FireSendingRequest2(descriptor);
                            base.CreateChangeData(j, wrapper3);
                        }
                    }
                    this.batchWriter.WriteEndChangeset();
                }
                this.batchWriter.WriteEndBatch();
                this.batchWriter.Flush();
            }
            return(requestMessage);
        }
Esempio n. 16
0
        internal void Write(Stream stream)
        {
            Stream     responseMessageStream = null;
            Serializer responseSerializer    = null;

            this.actualResponseMessageWhoseHeadersMayBeOverridden.SetStream(stream);

            try
            {
                switch (this.PayloadKind)
                {
                case ODataPayloadKind.BinaryValue:
                    Debug.Assert(
                        this.requestDescription.TargetKind == RequestTargetKind.OpenPropertyValue ||
                        this.requestDescription.TargetKind == RequestTargetKind.PrimitiveValue ||
                        this.requestDescription.TargetKind == RequestTargetKind.MediaResource,
                        this.requestDescription.TargetKind + " is PrimitiveValue or OpenPropertyValue or StreamPropertyValue");
                    Debug.Assert(this.messageWriter == null, "No Message writer required for writing binary payload");

                    responseMessageStream = this.actualResponseMessageWhoseHeadersMayBeOverridden.GetStream();
                    BinarySerializer binarySerializer = new BinarySerializer(responseMessageStream);
                    if (this.requestDescription.TargetKind == RequestTargetKind.MediaResource)
                    {
                        // If this.mediaResourceStream is null, we will set the status code to 204.
                        // We would not get here on a WCF host, but on other hosts we would.
                        Debug.Assert(this.requestDescription.IsNamedStream || this.mediaResourceStream != null, "this.mediaResourceStream cannot be null for MR request.");
                        if (this.mediaResourceStream != null)
                        {
                            binarySerializer.WriteRequest(this.mediaResourceStream, this.service.StreamProvider.StreamBufferSize);
                        }
                    }
                    else
                    {
                        binarySerializer.WriteRequest(this.queryResults.Current);
                    }

                    break;

                case ODataPayloadKind.Value:
                    Debug.Assert(
                        this.requestDescription.TargetKind == RequestTargetKind.OpenPropertyValue ||
                        this.requestDescription.TargetKind == RequestTargetKind.PrimitiveValue,
                        this.requestDescription.TargetKind + " is PrimitiveValue or OpenPropertyValue");

                    TextSerializer textSerializer = new TextSerializer(this.messageWriter);
                    textSerializer.WriteRequest(this.queryResults.Current);
                    break;

                case ODataPayloadKind.ServiceDocument:
                    Debug.Assert(this.requestDescription.TargetKind == RequestTargetKind.ServiceDirectory, "this.requestDescription.TargetKind == RequestTargetKind.ServiceDirectory");
                    ServiceDocumentSerializer serializer = new ServiceDocumentSerializer(this.messageWriter);
                    serializer.WriteServiceDocument(this.service.Provider);
                    break;

                case ODataPayloadKind.EntityReferenceLink:
                case ODataPayloadKind.EntityReferenceLinks:
                case ODataPayloadKind.Collection:
                case ODataPayloadKind.Property:
                    Debug.Assert(this.requestDescription.TargetKind != RequestTargetKind.Resource || this.requestDescription.LinkUri, "this.requestDescription.TargetKind != RequestTargetKind.Resource || this.requestDescription.LinkUri");
                    NonEntitySerializer nonEntitySerializer = new NonEntitySerializer(this.requestDescription, this.AbsoluteServiceUri, this.service, this.messageWriter);
                    responseSerializer = nonEntitySerializer;
                    if (this.requestDescription.TargetKind == RequestTargetKind.ComplexObject)
                    {
                        ODataUtils.SetHeadersForPayload(this.messageWriter, ODataPayloadKind.Resource);
                    }
                    if (this.requestDescription.TargetKind == RequestTargetKind.Collection &&
                        this.requestDescription.TargetResourceType.ElementType().ResourceTypeKind == ResourceTypeKind.ComplexType)
                    {
                        ODataUtils.SetHeadersForPayload(this.messageWriter, ODataPayloadKind.ResourceSet);
                    }
                    nonEntitySerializer.WriteRequest(this.queryResults);
                    break;

                case ODataPayloadKind.Resource:
                case ODataPayloadKind.ResourceSet:
                    Debug.Assert(this.requestDescription.TargetKind == RequestTargetKind.Resource, "TargetKind " + this.requestDescription.TargetKind + " == Resource");
                    EntitySerializer entitySerializer = new EntitySerializer(
                        this.requestDescription,
                        this.AbsoluteServiceUri,
                        this.service,
                        this.service.OperationContext.ResponseMessage.GetHeader(XmlConstants.HttpResponseETag),
                        this.messageWriter,
                        this.contentFormat);

                    responseSerializer = entitySerializer;
                    entitySerializer.WriteRequest(this.queryResults);
                    break;

                default:
                    Debug.Assert(this.PayloadKind == ODataPayloadKind.MetadataDocument, "this.payloadKind == ODataPayloadKind.MetadataDocument");
                    Debug.Assert(this.requestDescription.TargetKind == RequestTargetKind.Metadata, "this.requestDescription.TargetKind == RequestTargetKind.Metadata");

                    this.messageWriter.WriteMetadataDocument();
                    break;
                }
            }
            catch (Exception exception)
            {
                if (!CommonUtil.IsCatchableExceptionType(exception))
                {
                    throw;
                }

                // Astoria-ODataLib-Integration: Astoria does not call flush before calling the IDataServiceHost.ProcessException method
                // If the request is for an entry/feed and the data source throws an error while these results are being enumerated and written,
                // the server doesn't flush the writer's stream before it calls HandleException and starts writing out the error.
                // To handle this case, we'll make the EntitySerializer expose a method that calls Flush on the underlying ODL writer instance.
                if (responseSerializer != null)
                {
                    responseSerializer.Flush();
                }

                ErrorHandler.HandleExceptionWhileWriting(this.service, exception, this.actualResponseMessageWhoseHeadersMayBeOverridden, this.messageWriter, this.encoding, stream, this.messageWriterBuilder);
            }
            finally
            {
                WebUtil.Dispose(this.messageWriter);
                WebUtil.Dispose(this.queryResults);
                WebUtil.Dispose(this.mediaResourceStream);

                // For batch operations, we need to dispose the stream obtained from calling
                // IODataResponseMessage.GetStream to signal that we are done with the message.
                if (responseMessageStream != null && this.actualResponseMessageWhoseHeadersMayBeOverridden is ODataBatchOperationResponseMessage)
                {
                    responseMessageStream.Dispose();
                }
            }
        }