529 lines
25 KiB
C#
529 lines
25 KiB
C#
|
//----------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System;
|
||
|
using System.Globalization;
|
||
|
using System.IO;
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel.Diagnostics;
|
||
|
using System.Text;
|
||
|
using System.Xml;
|
||
|
using System.Diagnostics;
|
||
|
|
||
|
class WebMessageEncoderFactory : MessageEncoderFactory
|
||
|
{
|
||
|
WebMessageEncoder messageEncoder;
|
||
|
|
||
|
public WebMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, WebContentTypeMapper contentTypeMapper, bool javascriptCallbackEnabled)
|
||
|
{
|
||
|
messageEncoder = new WebMessageEncoder(writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas, contentTypeMapper, javascriptCallbackEnabled);
|
||
|
}
|
||
|
|
||
|
public override MessageEncoder Encoder
|
||
|
{
|
||
|
get { return messageEncoder; }
|
||
|
}
|
||
|
|
||
|
public override MessageVersion MessageVersion
|
||
|
{
|
||
|
get { return messageEncoder.MessageVersion; }
|
||
|
}
|
||
|
|
||
|
internal static string GetContentType(string mediaType, Encoding encoding)
|
||
|
{
|
||
|
string charset = TextEncoderDefaults.EncodingToCharSet(encoding);
|
||
|
if (!string.IsNullOrEmpty(charset))
|
||
|
{
|
||
|
return string.Format(CultureInfo.InvariantCulture, "{0}; charset={1}", mediaType, charset);
|
||
|
}
|
||
|
return mediaType;
|
||
|
}
|
||
|
|
||
|
class WebMessageEncoder : MessageEncoder
|
||
|
{
|
||
|
const string defaultMediaType = "application/xml";
|
||
|
WebContentTypeMapper contentTypeMapper;
|
||
|
string defaultContentType;
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile MessageEncoder jsonMessageEncoder;
|
||
|
int maxReadPoolSize;
|
||
|
int maxWritePoolSize;
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile MessageEncoder rawMessageEncoder;
|
||
|
XmlDictionaryReaderQuotas readerQuotas;
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile MessageEncoder textMessageEncoder;
|
||
|
object thisLock;
|
||
|
Encoding writeEncoding;
|
||
|
bool javascriptCallbackEnabled;
|
||
|
|
||
|
public WebMessageEncoder(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, WebContentTypeMapper contentTypeMapper, bool javascriptCallbackEnabled)
|
||
|
{
|
||
|
if (writeEncoding == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writeEncoding");
|
||
|
}
|
||
|
|
||
|
this.thisLock = new object();
|
||
|
|
||
|
TextEncoderDefaults.ValidateEncoding(writeEncoding);
|
||
|
this.writeEncoding = writeEncoding;
|
||
|
|
||
|
this.maxReadPoolSize = maxReadPoolSize;
|
||
|
this.maxWritePoolSize = maxWritePoolSize;
|
||
|
this.contentTypeMapper = contentTypeMapper;
|
||
|
this.javascriptCallbackEnabled = javascriptCallbackEnabled;
|
||
|
|
||
|
this.readerQuotas = new XmlDictionaryReaderQuotas();
|
||
|
quotas.CopyTo(this.readerQuotas);
|
||
|
|
||
|
this.defaultContentType = GetContentType(defaultMediaType, writeEncoding);
|
||
|
}
|
||
|
|
||
|
public override string ContentType
|
||
|
{
|
||
|
get { return this.defaultContentType; }
|
||
|
}
|
||
|
|
||
|
public override string MediaType
|
||
|
{
|
||
|
get { return defaultMediaType; }
|
||
|
}
|
||
|
|
||
|
public override MessageVersion MessageVersion
|
||
|
{
|
||
|
get { return MessageVersion.None; }
|
||
|
}
|
||
|
|
||
|
MessageEncoder JsonMessageEncoder
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (jsonMessageEncoder == null)
|
||
|
{
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
if (jsonMessageEncoder == null)
|
||
|
{
|
||
|
jsonMessageEncoder = new JsonMessageEncoderFactory(writeEncoding, maxReadPoolSize, maxWritePoolSize, readerQuotas, javascriptCallbackEnabled).Encoder;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return jsonMessageEncoder;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MessageEncoder RawMessageEncoder
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (rawMessageEncoder == null)
|
||
|
{
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
if (rawMessageEncoder == null)
|
||
|
{
|
||
|
rawMessageEncoder = new ByteStreamMessageEncodingBindingElement(readerQuotas).CreateMessageEncoderFactory().Encoder;
|
||
|
((IWebMessageEncoderHelper)rawMessageEncoder).EnableBodyReaderMoveToContent(); // see the comments in IWebMessageEncoderHelper for why this is done
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return rawMessageEncoder;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
MessageEncoder TextMessageEncoder
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (textMessageEncoder == null)
|
||
|
{
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
if (textMessageEncoder == null)
|
||
|
{
|
||
|
textMessageEncoder = new TextMessageEncoderFactory(MessageVersion.None, writeEncoding, maxReadPoolSize, maxWritePoolSize, readerQuotas).Encoder;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return textMessageEncoder;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
object ThisLock
|
||
|
{
|
||
|
get { return thisLock; }
|
||
|
}
|
||
|
|
||
|
public override bool IsContentTypeSupported(string contentType)
|
||
|
{
|
||
|
if (contentType == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contentType");
|
||
|
}
|
||
|
|
||
|
WebContentFormat messageFormat;
|
||
|
if (TryGetContentTypeMapping(contentType, out messageFormat) &&
|
||
|
(messageFormat != WebContentFormat.Default))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return RawMessageEncoder.IsContentTypeSupported(contentType) || JsonMessageEncoder.IsContentTypeSupported(contentType) || TextMessageEncoder.IsContentTypeSupported(contentType);
|
||
|
}
|
||
|
|
||
|
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
|
||
|
{
|
||
|
if (bufferManager == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("bufferManager"));
|
||
|
}
|
||
|
|
||
|
WebContentFormat format = GetFormatForContentType(contentType);
|
||
|
Message message;
|
||
|
|
||
|
switch (format)
|
||
|
{
|
||
|
case WebContentFormat.Json:
|
||
|
message = JsonMessageEncoder.ReadMessage(buffer, bufferManager, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty);
|
||
|
break;
|
||
|
case WebContentFormat.Xml:
|
||
|
message = TextMessageEncoder.ReadMessage(buffer, bufferManager, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
|
||
|
break;
|
||
|
case WebContentFormat.Raw:
|
||
|
message = RawMessageEncoder.ReadMessage(buffer, bufferManager, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
|
||
|
break;
|
||
|
default:
|
||
|
throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw");
|
||
|
}
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
|
||
|
{
|
||
|
if (stream == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
|
||
|
}
|
||
|
|
||
|
WebContentFormat format = GetFormatForContentType(contentType);
|
||
|
Message message;
|
||
|
switch (format)
|
||
|
{
|
||
|
case WebContentFormat.Json:
|
||
|
message = JsonMessageEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty);
|
||
|
break;
|
||
|
case WebContentFormat.Xml:
|
||
|
message = TextMessageEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty);
|
||
|
break;
|
||
|
case WebContentFormat.Raw:
|
||
|
message = RawMessageEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType);
|
||
|
message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty);
|
||
|
break;
|
||
|
default:
|
||
|
throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw");
|
||
|
}
|
||
|
return message;
|
||
|
}
|
||
|
|
||
|
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
|
||
|
{
|
||
|
if (message == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
|
||
|
}
|
||
|
if (bufferManager == null)
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new ArgumentNullException("bufferManager"), message);
|
||
|
}
|
||
|
if (maxMessageSize < 0)
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxMessageSize", maxMessageSize,
|
||
|
SR2.GetString(SR2.ValueMustBeNonNegative)), message);
|
||
|
}
|
||
|
if (messageOffset < 0 || messageOffset > maxMessageSize)
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("messageOffset", messageOffset,
|
||
|
SR2.GetString(SR2.JsonValueMustBeInRange, 0, maxMessageSize)), message);
|
||
|
}
|
||
|
ThrowIfMismatchedMessageVersion(message);
|
||
|
|
||
|
WebContentFormat messageFormat = ExtractFormatFromMessage(message);
|
||
|
JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty;
|
||
|
switch (messageFormat)
|
||
|
{
|
||
|
case WebContentFormat.Json:
|
||
|
return JsonMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset);
|
||
|
case WebContentFormat.Xml:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
return TextMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset);
|
||
|
case WebContentFormat.Raw:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
return RawMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset);
|
||
|
default:
|
||
|
throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void WriteMessage(Message message, Stream stream)
|
||
|
{
|
||
|
if (message == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
|
||
|
}
|
||
|
if (stream == null)
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new ArgumentNullException("stream"), message);
|
||
|
}
|
||
|
ThrowIfMismatchedMessageVersion(message);
|
||
|
|
||
|
WebContentFormat messageFormat = ExtractFormatFromMessage(message);
|
||
|
JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty;
|
||
|
switch (messageFormat)
|
||
|
{
|
||
|
case WebContentFormat.Json:
|
||
|
JsonMessageEncoder.WriteMessage(message, stream);
|
||
|
break;
|
||
|
case WebContentFormat.Xml:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
TextMessageEncoder.WriteMessage(message, stream);
|
||
|
break;
|
||
|
case WebContentFormat.Raw:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
RawMessageEncoder.WriteMessage(message, stream);
|
||
|
break;
|
||
|
default:
|
||
|
throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override IAsyncResult BeginWriteMessage(Message message, Stream stream, AsyncCallback callback, object state)
|
||
|
{
|
||
|
if (message == null)
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("message"));
|
||
|
}
|
||
|
if (stream == null)
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new ArgumentNullException("stream"), message);
|
||
|
}
|
||
|
|
||
|
ThrowIfMismatchedMessageVersion(message);
|
||
|
|
||
|
return new WriteMessageAsyncResult(message, stream, this, callback, state);
|
||
|
}
|
||
|
|
||
|
public override void EndWriteMessage(IAsyncResult result)
|
||
|
{
|
||
|
WriteMessageAsyncResult.End(result);
|
||
|
}
|
||
|
|
||
|
internal override bool IsCharSetSupported(string charSet)
|
||
|
{
|
||
|
Encoding tmp;
|
||
|
return TextEncoderDefaults.TryGetEncoding(charSet, out tmp);
|
||
|
}
|
||
|
|
||
|
WebContentFormat ExtractFormatFromMessage(Message message)
|
||
|
{
|
||
|
object messageFormatProperty;
|
||
|
message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out messageFormatProperty);
|
||
|
if (messageFormatProperty == null)
|
||
|
{
|
||
|
return WebContentFormat.Xml;
|
||
|
}
|
||
|
|
||
|
WebBodyFormatMessageProperty typedMessageFormatProperty = messageFormatProperty as WebBodyFormatMessageProperty;
|
||
|
if ((typedMessageFormatProperty == null) ||
|
||
|
(typedMessageFormatProperty.Format == WebContentFormat.Default))
|
||
|
{
|
||
|
return WebContentFormat.Xml;
|
||
|
}
|
||
|
|
||
|
return typedMessageFormatProperty.Format;
|
||
|
}
|
||
|
|
||
|
WebContentFormat GetFormatForContentType(string contentType)
|
||
|
{
|
||
|
WebContentFormat messageFormat;
|
||
|
|
||
|
if (TryGetContentTypeMapping(contentType, out messageFormat) &&
|
||
|
(messageFormat != WebContentFormat.Default))
|
||
|
{
|
||
|
if (DiagnosticUtility.ShouldTraceInformation)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(contentType))
|
||
|
{
|
||
|
contentType = "<null>";
|
||
|
}
|
||
|
TraceUtility.TraceEvent(TraceEventType.Information,
|
||
|
TraceCode.RequestFormatSelectedFromContentTypeMapper,
|
||
|
SR2.GetString(SR2.TraceCodeRequestFormatSelectedFromContentTypeMapper, messageFormat.ToString(), contentType));
|
||
|
}
|
||
|
return messageFormat;
|
||
|
}
|
||
|
|
||
|
// Don't pass on null content types to IsContentTypeSupported methods -- they might throw.
|
||
|
// If null content type isn't already mapped, return the default format of Raw.
|
||
|
|
||
|
if (contentType == null)
|
||
|
{
|
||
|
messageFormat = WebContentFormat.Raw;
|
||
|
}
|
||
|
else if (JsonMessageEncoder.IsContentTypeSupported(contentType))
|
||
|
{
|
||
|
messageFormat = WebContentFormat.Json;
|
||
|
}
|
||
|
else if (TextMessageEncoder.IsContentTypeSupported(contentType))
|
||
|
{
|
||
|
messageFormat = WebContentFormat.Xml;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
messageFormat = WebContentFormat.Raw;
|
||
|
}
|
||
|
|
||
|
if (DiagnosticUtility.ShouldTraceInformation)
|
||
|
{
|
||
|
TraceUtility.TraceEvent(TraceEventType.Information,
|
||
|
TraceCode.RequestFormatSelectedByEncoderDefaults,
|
||
|
SR2.GetString(SR2.TraceCodeRequestFormatSelectedByEncoderDefaults, messageFormat.ToString(), contentType));
|
||
|
}
|
||
|
|
||
|
return messageFormat;
|
||
|
}
|
||
|
|
||
|
bool TryGetContentTypeMapping(string contentType, out WebContentFormat format)
|
||
|
{
|
||
|
if (contentTypeMapper == null)
|
||
|
{
|
||
|
format = WebContentFormat.Default;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
format = contentTypeMapper.GetMessageFormatForContentType(contentType);
|
||
|
if (!WebContentFormatHelper.IsDefined(format))
|
||
|
{
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR2.GetString(SR2.UnknownWebEncodingFormat, contentType, format)));
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
{
|
||
|
throw;
|
||
|
}
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
|
||
|
SR2.GetString(SR2.ErrorEncounteredInContentTypeMapper), e));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class WriteMessageAsyncResult : ScheduleActionItemAsyncResult
|
||
|
{
|
||
|
Message message;
|
||
|
Stream stream;
|
||
|
MessageEncoder encoder;
|
||
|
WebMessageEncoder webMessageEncoder;
|
||
|
static AsyncCompletion handleEndWriteMessage;
|
||
|
|
||
|
public WriteMessageAsyncResult(Message message, Stream stream, WebMessageEncoder webMessageEncoder, AsyncCallback callback, object state)
|
||
|
: base(callback, state)
|
||
|
{
|
||
|
this.message = message;
|
||
|
this.stream = stream;
|
||
|
this.webMessageEncoder = webMessageEncoder;
|
||
|
|
||
|
WebContentFormat messageFormat = webMessageEncoder.ExtractFormatFromMessage(message);
|
||
|
JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty;
|
||
|
|
||
|
switch (messageFormat)
|
||
|
{
|
||
|
case WebContentFormat.Json:
|
||
|
this.encoder = webMessageEncoder.JsonMessageEncoder;
|
||
|
this.Schedule();
|
||
|
break;
|
||
|
|
||
|
case WebContentFormat.Xml:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
this.encoder = webMessageEncoder.TextMessageEncoder;
|
||
|
this.Schedule();
|
||
|
break;
|
||
|
|
||
|
case WebContentFormat.Raw:
|
||
|
if (message.Properties.TryGetValue<JavascriptCallbackResponseMessageProperty>(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) &&
|
||
|
javascriptResponseMessageProperty != null &&
|
||
|
!String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName))
|
||
|
{
|
||
|
throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR2.JavascriptCallbackNotsupported), message);
|
||
|
}
|
||
|
|
||
|
handleEndWriteMessage = new AsyncCompletion(HandleEndWriteMessage);
|
||
|
IAsyncResult result = webMessageEncoder.RawMessageEncoder.BeginWriteMessage(message, stream, PrepareAsyncCompletion(HandleEndWriteMessage), this);
|
||
|
if (SyncContinue(result))
|
||
|
{
|
||
|
this.Complete(true);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
protected override void OnDoWork()
|
||
|
{
|
||
|
this.encoder.WriteMessage(this.message, this.stream);
|
||
|
}
|
||
|
|
||
|
static bool HandleEndWriteMessage(IAsyncResult result)
|
||
|
{
|
||
|
WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)result.AsyncState;
|
||
|
thisPtr.webMessageEncoder.RawMessageEncoder.EndWriteMessage(result);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|