|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Dispatcher
{
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.Generic;
using System.Xml;
using System.Runtime.Serialization;
using DiagnosticUtility = System.ServiceModel.DiagnosticUtility;
using System.ServiceModel.Web;
abstract class SingleBodyParameterMessageFormatter : IDispatchMessageFormatter, IClientMessageFormatter
{
string contractName;
string contractNs;
bool isRequestFormatter;
string operationName;
string serializerType;
protected SingleBodyParameterMessageFormatter(OperationDescription operation, bool isRequestFormatter, string serializerType)
{
if (operation == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("operation");
}
this.contractName = operation.DeclaringContract.Name;
this.contractNs = operation.DeclaringContract.Namespace;
this.operationName = operation.Name;
this.isRequestFormatter = isRequestFormatter;
this.serializerType = serializerType;
}
protected string ContractName
{
get { return this.contractName; }
}
protected string ContractNs
{
get { return this.contractNs; }
}
protected string OperationName
{
get { return this.operationName; }
}
public static IClientMessageFormatter CreateXmlAndJsonClientFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager)
{
IClientMessageFormatter xmlFormatter = CreateClientFormatter(operation, type, isRequestFormatter, false, xmlSerializerManager);
if (!WebHttpBehavior.SupportsJsonFormat(operation))
{
return xmlFormatter;
}
IClientMessageFormatter jsonFormatter = CreateClientFormatter(operation, type, isRequestFormatter, true, xmlSerializerManager);
Dictionary<WebContentFormat, IClientMessageFormatter> map = new Dictionary<WebContentFormat, IClientMessageFormatter>();
map.Add(WebContentFormat.Xml, xmlFormatter);
map.Add(WebContentFormat.Json, jsonFormatter);
return new DemultiplexingClientMessageFormatter(map, xmlFormatter);
}
public static IDispatchMessageFormatter CreateXmlAndJsonDispatchFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager, string callbackParameterName)
{
IDispatchMessageFormatter xmlFormatter = CreateDispatchFormatter(operation, type, isRequestFormatter, false, xmlSerializerManager, null);
if (!WebHttpBehavior.SupportsJsonFormat(operation))
{
return xmlFormatter;
}
IDispatchMessageFormatter jsonFormatter = CreateDispatchFormatter(operation, type, isRequestFormatter, true, xmlSerializerManager, callbackParameterName);
Dictionary<WebContentFormat, IDispatchMessageFormatter> map = new Dictionary<WebContentFormat, IDispatchMessageFormatter>();
map.Add(WebContentFormat.Xml, xmlFormatter);
map.Add(WebContentFormat.Json, jsonFormatter);
return new DemultiplexingDispatchMessageFormatter(map, xmlFormatter);
}
public object DeserializeReply(Message message, object[] parameters)
{
if (isRequestFormatter)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.FormatterCannotBeUsedForReplyMessages)));
}
return ReadObject(message);
}
public void DeserializeRequest(Message message, object[] parameters)
{
if (!isRequestFormatter)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.FormatterCannotBeUsedForRequestMessages)));
}
parameters[0] = ReadObject(message);
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
if (isRequestFormatter)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.FormatterCannotBeUsedForReplyMessages)));
}
Message message = Message.CreateMessage(messageVersion, (string)null, CreateBodyWriter(result));
if (result == null)
{
SuppressReplyEntityBody(message);
}
AttachMessageProperties(message, false);
return message;
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
if (!isRequestFormatter)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.FormatterCannotBeUsedForRequestMessages)));
}
Message message = Message.CreateMessage(messageVersion, (string)null, CreateBodyWriter(parameters[0]));
if (parameters[0] == null)
{
SuppressRequestEntityBody(message);
}
AttachMessageProperties(message, true);
return message;
}
internal static IClientMessageFormatter CreateClientFormatter(OperationDescription operation, Type type, bool isRequestFormatter, bool useJson, UnwrappedTypesXmlSerializerManager xmlSerializerManager)
{
if (type == null)
{
return new NullMessageFormatter(false, null);
}
else if (useJson)
{
return CreateJsonFormatter(operation, type, isRequestFormatter);
}
else
{
return CreateXmlFormatter(operation, type, isRequestFormatter, xmlSerializerManager);
}
}
internal static IDispatchMessageFormatter CreateDispatchFormatter(OperationDescription operation, Type type, bool isRequestFormatter, bool useJson, UnwrappedTypesXmlSerializerManager xmlSerializerManager, string callbackParameterName)
{
if (type == null)
{
return new NullMessageFormatter(useJson, callbackParameterName);
}
else if (useJson)
{
return CreateJsonFormatter(operation, type, isRequestFormatter);
}
else
{
return CreateXmlFormatter(operation, type, isRequestFormatter, xmlSerializerManager);
}
}
internal static void SuppressReplyEntityBody(Message message)
{
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
OutgoingWebResponseContext responseContext = currentContext.OutgoingResponse;
if (responseContext != null)
{
responseContext.SuppressEntityBody = true;
}
}
else
{
object untypedProp;
message.Properties.TryGetValue(HttpResponseMessageProperty.Name, out untypedProp);
HttpResponseMessageProperty prop = untypedProp as HttpResponseMessageProperty;
if (prop == null)
{
prop = new HttpResponseMessageProperty();
message.Properties[HttpResponseMessageProperty.Name] = prop;
}
prop.SuppressEntityBody = true;
}
}
internal static void SuppressRequestEntityBody(Message message)
{
WebOperationContext currentContext = WebOperationContext.Current;
if (currentContext != null)
{
OutgoingWebRequestContext requestContext = currentContext.OutgoingRequest;
if (requestContext != null)
{
requestContext.SuppressEntityBody = true;
}
}
else
{
object untypedProp;
message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out untypedProp);
HttpRequestMessageProperty prop = untypedProp as HttpRequestMessageProperty;
if (prop == null)
{
prop = new HttpRequestMessageProperty();
message.Properties[HttpRequestMessageProperty.Name] = prop;
}
prop.SuppressEntityBody = true;
}
}
protected virtual void AttachMessageProperties(Message message, bool isRequest)
{
}
protected abstract XmlObjectSerializer[] GetInputSerializers();
protected abstract XmlObjectSerializer GetOutputSerializer(Type type);
protected virtual void ValidateMessageFormatProperty(Message message)
{
}
protected Type GetTypeForSerializer(Type type, Type parameterType, IList<Type> knownTypes)
{
if (type == parameterType)
{
return type;
}
else if (knownTypes != null)
{
for (int i = 0; i < knownTypes.Count; ++i)
{
if (type == knownTypes[i])
{
return type;
}
}
}
return parameterType;
}
public static SingleBodyParameterMessageFormatter CreateXmlFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager)
{
DataContractSerializerOperationBehavior dcsob = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsob != null)
{
return new SingleBodyParameterDataContractMessageFormatter(operation, type, isRequestFormatter, false, dcsob);
}
XmlSerializerOperationBehavior xsob = operation.Behaviors.Find<XmlSerializerOperationBehavior>();
if (xsob != null)
{
return new SingleBodyParameterXmlSerializerMessageFormatter(operation, type, isRequestFormatter, xsob, xmlSerializerManager);
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.OnlyDataContractAndXmlSerializerTypesInUnWrappedMode, operation.Name)));
}
public static SingleBodyParameterMessageFormatter CreateJsonFormatter(OperationDescription operation, Type type, bool isRequestFormatter)
{
DataContractSerializerOperationBehavior dcsob = operation.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsob == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR2.GetString(SR2.JsonFormatRequiresDataContract, operation.Name, operation.DeclaringContract.Name, operation.DeclaringContract.Namespace)));
}
return new SingleBodyParameterDataContractMessageFormatter(operation, type, isRequestFormatter, true, dcsob);
}
BodyWriter CreateBodyWriter(object body)
{
XmlObjectSerializer serializer;
if (body != null)
{
serializer = GetOutputSerializer(body.GetType());
if (serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.CannotSerializeType, body.GetType(), this.operationName, this.contractName, this.contractNs, this.serializerType)));
}
}
else
{
serializer = null;
}
return new SingleParameterBodyWriter(body, serializer);
}
protected virtual object ReadObject(Message message)
{
if (HttpStreamFormatter.IsEmptyMessage(message))
{
return null;
}
XmlObjectSerializer[] inputSerializers = GetInputSerializers();
XmlDictionaryReader reader = message.GetReaderAtBodyContents();
if (inputSerializers != null)
{
for (int i = 0; i < inputSerializers.Length; ++i)
{
if (inputSerializers[i].IsStartObject(reader))
{
return inputSerializers[i].ReadObject(reader, false);
}
}
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR2.GetString(SR2.CannotDeserializeBody, reader.LocalName, reader.NamespaceURI, operationName, contractName, contractNs, this.serializerType)));
}
class NullMessageFormatter : IDispatchMessageFormatter, IClientMessageFormatter
{
bool useJson;
string callbackParameterName;
public NullMessageFormatter(bool useJson, string callbackParameterName)
{
this.useJson = useJson;
this.callbackParameterName = callbackParameterName;
}
public object DeserializeReply(Message message, object[] parameters)
{
return null;
}
public void DeserializeRequest(Message message, object[] parameters)
{
}
public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
{
Message reply = Message.CreateMessage(messageVersion, (string)null);
SuppressReplyEntityBody(reply);
if (useJson && WebHttpBehavior.TrySetupJavascriptCallback(callbackParameterName) != null)
{
reply.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty);
}
return reply;
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
Message request = Message.CreateMessage(messageVersion, (string)null);
SuppressRequestEntityBody(request);
return request;
}
}
class SingleParameterBodyWriter : BodyWriter
{
object body;
XmlObjectSerializer serializer;
public SingleParameterBodyWriter(object body, XmlObjectSerializer serializer)
: base(false)
{
if (body != null && serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
}
this.body = body;
this.serializer = serializer;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
if (body != null)
{
this.serializer.WriteObject(writer, body);
}
}
}
}
}
|