/// <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 errors. /// </summary> /// <param name="serviceUri">Service base uri.</param> /// <param name="dataService">Data service instance.</param> /// <param name="responseVersion">Version of the response payload.</param> /// <param name="responseMessage">IODataResponseMessage implementation.</param> /// <param name="acceptHeaderValue">Accept header value.</param> /// <param name="acceptCharSetHeaderValue">Accept charset header value.</param> /// <returns>An instance of a message writer with the appropriate settings.</returns> internal static MessageWriterBuilder ForError(Uri serviceUri, IDataService dataService, Version responseVersion, IODataResponseMessage responseMessage, string acceptHeaderValue, string acceptCharSetHeaderValue) { MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, responseMessage, null /*model*/); messageWriterBuilder.WriterSettings.SetContentType(acceptHeaderValue, acceptCharSetHeaderValue); 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); }
/// <summary>Handles an exception when processing a batch response.</summary> /// <param name='service'>Data service doing the processing.</param> /// <param name="requestMessage">requestMessage holding information about the request that caused an error</param> /// <param name="responseMessage">responseMessage to which we need to write the exception message</param> /// <param name='exception'>Exception thrown.</param> /// <param name='batchWriter'>Output writer for the batch.</param> /// <param name="responseStream">Underlying response stream.</param> /// <param name="defaultResponseVersion">The data service version to use for response, if it cannot be computed from the requestMessage.</param> internal static void HandleBatchOperationError(IDataService service, AstoriaRequestMessage requestMessage, IODataResponseMessage responseMessage, Exception exception, ODataBatchWriter batchWriter, Stream responseStream, Version defaultResponseVersion) { Debug.Assert(service != null, "service != null"); Debug.Assert(exception != null, "exception != null"); Debug.Assert(batchWriter != null, "batchWriter != null"); Debug.Assert(service.Configuration != null, "service.Configuration != null"); Debug.Assert(CommonUtil.IsCatchableExceptionType(exception), "CommonUtil.IsCatchableExceptionType(exception)"); ErrorHandler handler = CreateHandler(service, requestMessage, exception, defaultResponseVersion); service.InternalHandleException(handler.exceptionArgs); if (requestMessage != null && responseMessage != null) { responseMessage.SetHeader(XmlConstants.HttpODataVersion, handler.responseVersion.ToString(2) + ";"); requestMessage.ProcessException(handler.exceptionArgs); // if ProcessBenignException returns anything, we can safely not write to the stream. if (ProcessBenignException(exception, service) != null) { return; } } if (requestMessage != null) { responseMessage = requestMessage.BatchServiceHost.GetOperationResponseMessage(); WebUtil.SetResponseHeadersForBatchRequests(responseMessage, requestMessage.BatchServiceHost); } else { responseMessage = batchWriter.CreateOperationResponseMessage(null); responseMessage.StatusCode = handler.exceptionArgs.ResponseStatusCode; } MessageWriterBuilder messageWriterBuilder = MessageWriterBuilder.ForError( null, service, handler.responseVersion, responseMessage, handler.contentType, null /*acceptCharsetHeaderValue*/); using (ODataMessageWriter messageWriter = messageWriterBuilder.CreateWriter()) { ODataError error = handler.exceptionArgs.CreateODataError(); WriteErrorWithFallbackForXml(messageWriter, handler.encoding, responseStream, handler.exceptionArgs, error, messageWriterBuilder); } }
/// <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); }
/// <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; }
/// <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); }); }
/// <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> /// Writes the error with fallback logic for XML cases where the writer is in an error state and a new writer must be created. /// </summary> /// <param name="messageWriter">The message writer.</param> /// <param name="encoding">The encoding to use for the error if we have to fallback.</param> /// <param name="responseStream">The response stream to write to in the fallback case.</param> /// <param name="args">The args for the error.</param> /// <param name="error">The error to write.</param> /// <param name="messageWriterBuilder">MessageWriterBuilder to use if a new ODataMessageWriter needs to be constructed.</param> private static void WriteErrorWithFallbackForXml(ODataMessageWriter messageWriter, Encoding encoding, Stream responseStream, HandleExceptionArgs args, ODataError error, MessageWriterBuilder messageWriterBuilder) { Debug.Assert(args != null, "args != null"); #if DEBUG Debug.Assert(args.ProcessExceptionWasCalled, "ProcessException was not called by the time we tried to serialze this error message with ODataLib."); #endif if (messageWriter != null) { try { // If the XmlWriter inside the ODataMessageWriter had entered Error state, ODataMessageWriter.WriteError would throw an InvalidOperationException // when we try to write to it. Note that XmlWriter doesn't always throw an XmlException when it enters Error state. // The right thing to do is we don't write any more because at this point we don't know what's been written to the underlying // stream. However we still should flush the writer to make sure that all the content that was written but is sitting in the buffers actually appears // in the stream before writing the instream error. Otherwise the buffer will be flushed when disposing the writer later and we would end up with // either content written after the instream error (this would also result in having the Xml declaration in the middle of the payload - // [Astoria-ODataLib-Integration] In-stream errors due to XmlExceptions are written out backwards (error before partial valid payload)) or, // hypothetically, the instream error in the middle of the other content that was already partially written. For example we can end up with a payload that // looks like <element attr="val<m:error... The XmlReader would not be able to parse the error payload in this case. Disposing the writer will flush the buffer. // It is fine to do it since the writer is not usable at this point anyways. Also note that the writer will be disposed more than once (e.g. in finally block // in ResponseBodySerializer) but only the first call will have any effect. // However since in the versions we shipped we always create a new XmlWriter to serialize the error payload when the existing // one is in error state, we will continue to do the same to avoid introducing any breaking change here. messageWriter.WriteError(error, args.UseVerboseErrors); } catch (ODataException e) { // Yikes, ODataLib threw while writing the error. This tends to happen if the service author did something invalid during custom // error handling, such as add an custom instance annotation to the error payload. In this dire case, we treat it almost like // an in-stream error, and abort the previous writing. We write out the new error. Note that this will produce an invalid payload like // the situation noted above with XmlWriter errors. WebUtil.Dispose(messageWriter); messageWriterBuilder.SetMessageForErrorInError(); var newErrorWriter = messageWriterBuilder.CreateWriter(); ODataError errorWhileWritingOtherError = new ODataError() { ErrorCode = "500", InnerError = new ODataInnerError(e), Message = Strings.ErrorHandler_ErrorWhileWritingError }; newErrorWriter.WriteError(errorWhileWritingOtherError, args.UseVerboseErrors); } catch (InvalidOperationException) { Debug.Assert(ContentTypeUtil.IsNotJson(args.ResponseContentType), "Should never get here for JSON responses"); WebUtil.Dispose(messageWriter); // if either an InvalidOperationException was encountered (see comment above) or the message writer was null, write the error out manually. Debug.Assert(responseStream != null, "responseStream != null"); using (XmlWriter xmlWriter = XmlWriter.Create(responseStream, XmlUtil.CreateXmlWriterSettings(encoding))) { ErrorUtils.WriteXmlError(xmlWriter, error, args.UseVerboseErrors, MaxInnerErrorDepth); } } } }
/// <summary> /// Handles an exception that occurred while writing a response. /// </summary> /// <param name="service">Data service doing the processing.</param> /// <param name="exception">The exception that was thrown.</param> /// <param name="responseMessage">The response message.</param> /// <param name="messageWriter">The message writer, if null this will fall back to writing a raw XML error to the stream.</param> /// <param name="encoding">The encoding to while writing the error.</param> /// <param name="responseStream">The response stream to write the error to.</param> /// <param name="messageWriterBuilder">MessageWriterBuilder to use in case a new ODataMessageWriter needs to be constructed.</param> internal static void HandleExceptionWhileWriting(IDataService service, Exception exception, IODataResponseMessage responseMessage, ODataMessageWriter messageWriter, Encoding encoding, Stream responseStream, MessageWriterBuilder messageWriterBuilder) { Debug.Assert(service != null, "service != null"); Debug.Assert(service.Configuration != null, "service.Configuration != null"); Debug.Assert(exception != null, "exception != null"); Debug.Assert(CommonUtil.IsCatchableExceptionType(exception), "CommonUtil.IsCatchableExceptionType(exception)"); Debug.Assert(responseMessage != null, "responseMessage != null"); string contentType = responseMessage.GetHeader(XmlConstants.HttpContentType); HandleExceptionArgs args = new HandleExceptionArgs(exception, true, contentType, service.Configuration.UseVerboseErrors); service.InternalHandleException(args); service.OperationContext.RequestMessage.ProcessException(args); ODataError error = args.CreateODataError(); WriteErrorWithFallbackForXml(messageWriter, encoding, responseStream, args, error, messageWriterBuilder); }
/// <summary> /// Create a new instance of ODataMessageWriterSettings for errors. /// </summary> /// <param name="serviceUri">Service base uri.</param> /// <param name="dataService">Data service instance.</param> /// <param name="responseVersion">Version of the response payload.</param> /// <param name="responseMessage">IODataResponseMessage implementation.</param> /// <param name="acceptHeaderValue">Accept header value.</param> /// <param name="acceptCharSetHeaderValue">Accept charset header value.</param> /// <returns>An instance of a message writer with the appropriate settings.</returns> internal static MessageWriterBuilder ForError(Uri serviceUri, IDataService dataService, Version responseVersion, IODataResponseMessage responseMessage, string acceptHeaderValue, string acceptCharSetHeaderValue) { MessageWriterBuilder messageWriterBuilder = new MessageWriterBuilder(serviceUri, responseVersion, dataService, responseMessage, null /*model*/); messageWriterBuilder.WriterSettings.SetContentType(acceptHeaderValue, acceptCharSetHeaderValue); 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; }