/// <summary>
        /// Create a new instance of ODataMessageWriterSettings for batch requests.
        /// </summary>
        /// <param name="dataService">Data service instance.</param>
        /// <returns>An instance of a message writer with the appropriate settings.</returns>
        internal static MessageWriterBuilder ForBatch(IDataService dataService)
        {
            Uri     serviceUri      = dataService.OperationContext.RequestMessage.AbsoluteServiceUri;
            Version responseVersion = VersionUtil.GetEffectiveMaxResponseVersion(dataService.OperationContext.RequestMessage.RequestMaxVersion, dataService.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion());

            MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, dataService.OperationContext.ResponseMessage, null /*model*/);

            // Astoria does not do content negotiation for the top level batch payload at all in V1/V2
            // Hence passing */* as the accept header value by default.

            string contentType = XmlConstants.MimeAny;

            if (dataService.OperationContext.RequestMessage != null &&
                string.CompareOrdinal(
                    XmlConstants.ODataVersion4Dot0,
                    dataService.OperationContext.RequestMessage.GetHeader(XmlConstants.HttpODataVersion)) == 0)
            {
                // For V4, batch request & response payload can be in Json format
                string accept = dataService.OperationContext.RequestMessage.GetHeader(XmlConstants.HttpAccept);

                if (accept != null && accept.StartsWith(XmlConstants.MimeApplicationJson))
                {
                    contentType = accept;
                }
            }
            messageWriterBuilder.WriterSettings.SetContentType(contentType, null /*acceptableCharSets*/);

            return(messageWriterBuilder);
        }
        /// <summary>
        /// Create a new instance of ODataMessageWriterSettings for batch requests.
        /// </summary>
        /// <param name="dataService">Data service instance.</param>
        /// <returns>An instance of a message writer with the appropriate settings.</returns>
        internal static MessageWriterBuilder ForBatch(IDataService dataService)
        {
            Uri     serviceUri      = dataService.OperationContext.RequestMessage.AbsoluteServiceUri;
            Version responseVersion = VersionUtil.GetEffectiveMaxResponseVersion(dataService.OperationContext.RequestMessage.RequestMaxVersion, dataService.Configuration.DataServiceBehavior.MaxProtocolVersion.ToVersion());

            MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, dataService.OperationContext.ResponseMessage, null /*model*/);

            // Astoria does not do content negotiation for the top level batch payload at all in V1/V2
            // Hence passing */* as the accept header value.
            messageWriterBuilder.WriterSettings.SetContentType(XmlConstants.MimeAny, null /*acceptableCharSets*/);

            return(messageWriterBuilder);
        }
Beispiel #3
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);
            }
        }